diff --git a/debian/remote.go b/debian/remote.go index 1714efd0..18ea5aaa 100644 --- a/debian/remote.go +++ b/debian/remote.go @@ -185,7 +185,7 @@ func (repo *RemoteRepo) Download(d utils.Downloader, packageCollection *PackageC count := 0 list.ForEach(func(p *Package) { - poolPath, err := packageRepo.PoolPath(p.Filename) + poolPath, err := packageRepo.PoolPath(p.Filename, p.HashMD5) if err == nil { if !p.VerifyFile(poolPath) { d.Download(repo.PackageURL(p.Filename).String(), poolPath, ch) diff --git a/debian/repository.go b/debian/repository.go index be17650b..09c548d1 100644 --- a/debian/repository.go +++ b/debian/repository.go @@ -2,10 +2,27 @@ package debian import ( "fmt" + "os" "path/filepath" - "strings" ) +// Repository directory structure: +// +// \- pool +// \- ab +// \- ae +// \- package.deb +// \- public +// \- dists +// \- squeeze +// \- Release +// \- main +// \- binary-i386 +// \- Packages.bz2 +// references packages from pool +// \- pool +// contains symlinks to main pool + // Repository abstract file system with package pool and published package repos type Repository struct { RootPath string @@ -16,22 +33,22 @@ func NewRepository(root string) *Repository { return &Repository{RootPath: root} } -// PoolPath returns full path to package file in pool -// -// PoolPath checks that final path doesn't go out of repository root path -func (r *Repository) PoolPath(filename string) (string, error) { - filename = filepath.Clean(filename) - if strings.HasPrefix(filename, ".") { - return "", fmt.Errorf("filename %s starts with dot", filename) +// PoolPath returns full path to package file in pool givan any name and hash of file contents +func (r *Repository) PoolPath(filename string, hashMD5 string) (string, error) { + filename = filepath.Base(filename) + if filename == "." || filename == "/" { + return "", fmt.Errorf("filename %s is invalid", filename) } - if filepath.IsAbs(filename) { - return "", fmt.Errorf("absolute filename %s not supported", filename) - } - - if strings.HasPrefix(filename, "pool/") { - filename = filename[5:] - } - - return filepath.Join(r.RootPath, "pool", filename), nil + return filepath.Join(r.RootPath, "pool", hashMD5[0:2], hashMD5[2:4], filename), nil +} + +// MkDir creates directory recursively under public path +func (r *Repository) MkDir(path string) error { + return os.MkdirAll(filepath.Join(r.RootPath, "public", path), 0755) +} + +// CreateFile creates file for writing under public path +func (r *Repository) CreateFile(path string) (*os.File, error) { + return os.Create(filepath.Join(r.RootPath, "public", path)) } diff --git a/debian/repository_test.go b/debian/repository_test.go index 588c4be0..ce1300cd 100644 --- a/debian/repository_test.go +++ b/debian/repository_test.go @@ -2,6 +2,7 @@ package debian import ( . "launchpad.net/gocheck" + "os" "path/filepath" ) @@ -16,24 +17,32 @@ func (s *RepositorySuite) SetUpTest(c *C) { } func (s *RepositorySuite) TestPoolPath(c *C) { - path, err := s.repo.PoolPath("a/b/package.deb") + path, err := s.repo.PoolPath("a/b/package.deb", "91b1a1480b90b9e269ca44d897b12575") c.Assert(err, IsNil) - c.Assert(path, Equals, filepath.Join(s.repo.RootPath, "pool", "a/b/package.deb")) + c.Assert(path, Equals, filepath.Join(s.repo.RootPath, "pool", "91/b1/package.deb")) - path, err = s.repo.PoolPath("pool/a/b/package.deb") - c.Assert(err, IsNil) - c.Assert(path, Equals, filepath.Join(s.repo.RootPath, "pool", "a/b/package.deb")) - - _, err = s.repo.PoolPath("/dev/stdin") - c.Assert(err, ErrorMatches, "absolute filename.*") - - _, err = s.repo.PoolPath("../../../etc/passwd") - c.Assert(err, ErrorMatches, ".*starts with dot") - - _, err = s.repo.PoolPath("pool/a/../../../etc/passwd") - c.Assert(err, ErrorMatches, ".*starts with dot") - - path, err = s.repo.PoolPath("./etc/passwd") - c.Assert(err, IsNil) - c.Assert(path, Equals, filepath.Join(s.repo.RootPath, "pool", "etc/passwd")) + _, err = s.repo.PoolPath("/", "91b1a1480b90b9e269ca44d897b12575") + c.Assert(err, ErrorMatches, ".*is invalid") + _, err = s.repo.PoolPath("", "91b1a1480b90b9e269ca44d897b12575") + c.Assert(err, ErrorMatches, ".*is invalid") +} + +func (s *RepositorySuite) TestMkDir(c *C) { + err := s.repo.MkDir("ppa/dists/squeeze/") + c.Assert(err, IsNil) + + _, err = os.Stat(filepath.Join(s.repo.RootPath, "public/ppa/dists/squeeze/")) + c.Assert(err, IsNil) +} + +func (s *RepositorySuite) TestCreateFile(c *C) { + err := s.repo.MkDir("ppa/dists/squeeze/") + c.Assert(err, IsNil) + + file, err := s.repo.CreateFile("ppa/dists/squeeze/Release") + c.Assert(err, IsNil) + defer file.Close() + + _, err = os.Stat(filepath.Join(s.repo.RootPath, "public/ppa/dists/squeeze/Release")) + c.Assert(err, IsNil) }