diff --git a/debian/repository.go b/debian/repository.go index ed109873..794a3218 100644 --- a/debian/repository.go +++ b/debian/repository.go @@ -3,6 +3,7 @@ package debian import ( "fmt" "github.com/smira/aptly/utils" + "io/ioutil" "os" "path/filepath" ) @@ -34,14 +35,28 @@ func NewRepository(root string) *Repository { return &Repository{RootPath: root} } -// 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) { +// RelativePoolPath returns path relative to pool's root +func (r *Repository) RelativePoolPath(filename string, hashMD5 string) (string, error) { filename = filepath.Base(filename) if filename == "." || filename == "/" { return "", fmt.Errorf("filename %s is invalid", filename) } - return filepath.Join(r.RootPath, "pool", hashMD5[0:2], hashMD5[2:4], filename), nil + if len(hashMD5) < 4 { + return "", fmt.Errorf("unable to compute pool location for filename %v, MD5 is missing", filename) + } + + return filepath.Join(hashMD5[0:2], hashMD5[2:4], filename), nil +} + +// PoolPath returns full path to package file in pool given any name and hash of file contents +func (r *Repository) PoolPath(filename string, hashMD5 string) (string, error) { + relative, err := r.RelativePoolPath(filename, hashMD5) + if err != nil { + return "", err + } + + return filepath.Join(r.RootPath, "pool", relative), nil } // PublicPath returns root of public part of repository @@ -91,3 +106,48 @@ func (r *Repository) LinkFromPool(prefix string, component string, sourcePath st func (r *Repository) ChecksumsForFile(path string) (utils.ChecksumInfo, error) { return utils.ChecksumsForFile(filepath.Join(r.RootPath, "public", path)) } + +// PoolFilepathList returns file paths of all the files in the pool +func (r *Repository) PoolFilepathList(progress *utils.Progress) ([]string, error) { + poolPath := filepath.Join(r.RootPath, "pool") + + dirs, err := ioutil.ReadDir(poolPath) + if err != nil { + if os.IsNotExist(err) { + return nil, nil + } + return nil, err + } + + if len(dirs) == 0 { + return nil, nil + } + + if progress != nil { + progress.InitBar(int64(len(dirs)), false) + defer progress.ShutdownBar() + } + + result := []string{} + + for _, dir := range dirs { + err = filepath.Walk(filepath.Join(poolPath, dir.Name()), func(path string, info os.FileInfo, err error) error { + if err != nil { + return err + } + if !info.IsDir() { + result = append(result, path[len(poolPath)+1:]) + } + return nil + }) + if err != nil { + return nil, err + } + + if progress != nil { + progress.AddBar(1) + } + } + + return result, nil +} diff --git a/debian/repository_test.go b/debian/repository_test.go index 26f063f9..8b71865e 100644 --- a/debian/repository_test.go +++ b/debian/repository_test.go @@ -18,6 +18,19 @@ func (s *RepositorySuite) SetUpTest(c *C) { s.repo = NewRepository(c.MkDir()) } +func (s *RepositorySuite) TestRelativePoolPath(c *C) { + path, err := s.repo.RelativePoolPath("a/b/package.deb", "91b1a1480b90b9e269ca44d897b12575") + c.Assert(err, IsNil) + c.Assert(path, Equals, "91/b1/package.deb") + + _, err = s.repo.RelativePoolPath("/", "91b1a1480b90b9e269ca44d897b12575") + c.Assert(err, ErrorMatches, ".*is invalid") + _, err = s.repo.RelativePoolPath("", "91b1a1480b90b9e269ca44d897b12575") + c.Assert(err, ErrorMatches, ".*is invalid") + _, err = s.repo.RelativePoolPath("a/b/package.deb", "9") + c.Assert(err, ErrorMatches, ".*MD5 is missing") +} + func (s *RepositorySuite) TestPoolPath(c *C) { path, err := s.repo.PoolPath("a/b/package.deb", "91b1a1480b90b9e269ca44d897b12575") c.Assert(err, IsNil) @@ -25,8 +38,6 @@ func (s *RepositorySuite) TestPoolPath(c *C) { _, 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) TestPublicPath(c *C) { @@ -126,3 +137,26 @@ func (s *RepositorySuite) TestLinkFromPool(c *C) { c.Check(int(info.Nlink), Equals, 2) } } + +func (s *RepositorySuite) TestPoolFilepathList(c *C) { + list, err := s.repo.PoolFilepathList(nil) + c.Check(err, IsNil) + c.Check(list, IsNil) + + os.MkdirAll(filepath.Join(s.repo.RootPath, "pool", "bd", "0b"), 0755) + os.MkdirAll(filepath.Join(s.repo.RootPath, "pool", "bd", "0a"), 0755) + os.MkdirAll(filepath.Join(s.repo.RootPath, "pool", "ae", "0c"), 0755) + + list, err = s.repo.PoolFilepathList(nil) + c.Check(err, IsNil) + c.Check(list, DeepEquals, []string{}) + + ioutil.WriteFile(filepath.Join(s.repo.RootPath, "pool", "ae", "0c", "1.deb"), nil, 0644) + ioutil.WriteFile(filepath.Join(s.repo.RootPath, "pool", "ae", "0c", "2.deb"), nil, 0644) + ioutil.WriteFile(filepath.Join(s.repo.RootPath, "pool", "bd", "0a", "3.deb"), nil, 0644) + ioutil.WriteFile(filepath.Join(s.repo.RootPath, "pool", "bd", "0b", "4.deb"), nil, 0644) + + list, err = s.repo.PoolFilepathList(nil) + c.Check(err, IsNil) + c.Check(list, DeepEquals, []string{"ae/0c/1.deb", "ae/0c/2.deb", "bd/0a/3.deb", "bd/0b/4.deb"}) +}