From 3333a643cb26dc60601880857559d6f406e5fd4b Mon Sep 17 00:00:00 2001 From: Pierig Le Saux Date: Thu, 16 Apr 2026 16:21:18 -0400 Subject: [PATCH] fix(jfrog): fix LinkFromPool source path handling and restore YAML config tests --- jfrog/public.go | 42 ++++++++++++++++- jfrog/public_test.go | 109 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 150 insertions(+), 1 deletion(-) diff --git a/jfrog/public.go b/jfrog/public.go index f478ee30..ec12decc 100644 --- a/jfrog/public.go +++ b/jfrog/public.go @@ -2,6 +2,8 @@ package jfrog import ( "fmt" + "io" + "os" "path/filepath" "strings" @@ -122,7 +124,45 @@ func (storage *PublishedStorage) RemoveDirs(path string, progress aptly.Progress } func (storage *PublishedStorage) LinkFromPool(publishedPrefix, publishedRelPath, fileName string, sourcePool aptly.PackagePool, sourcePath string, sourceMD5 aptly_utils.ChecksumInfo, force bool) error { - return storage.PutFile(filepath.Join(publishedPrefix, publishedRelPath, fileName), sourcePath) + sourceFilename := sourcePath + cleanup := func() {} + + if sourcePool != nil { + if localPool, ok := sourcePool.(aptly.LocalPackagePool); ok { + sourceFilename = localPool.FullPath(sourcePath) + } else { + src, err := sourcePool.Open(sourcePath) + if err != nil { + return err + } + defer func() { _ = src.Close() }() + + tmpFile, err := os.CreateTemp("", "aptly-jfrog-pool-*") + if err != nil { + return err + } + + if _, err := io.Copy(tmpFile, src); err != nil { + _ = tmpFile.Close() + _ = os.Remove(tmpFile.Name()) + return err + } + + if err := tmpFile.Close(); err != nil { + _ = os.Remove(tmpFile.Name()) + return err + } + + sourceFilename = tmpFile.Name() + cleanup = func() { + _ = os.Remove(sourceFilename) + } + } + } + + defer cleanup() + + return storage.PutFile(filepath.Join(publishedPrefix, publishedRelPath, fileName), sourceFilename) } func (storage *PublishedStorage) Filelist(prefix string) ([]string, error) { diff --git a/jfrog/public_test.go b/jfrog/public_test.go index d92b6471..5600983f 100644 --- a/jfrog/public_test.go +++ b/jfrog/public_test.go @@ -102,6 +102,92 @@ type resultFixture struct { Results []jfrogutils.ResultItem `json:"results"` } +type fakeLocalPool struct{} + +func (p *fakeLocalPool) Verify(string, string, *aptly_utils.ChecksumInfo, aptly.ChecksumStorage) (string, bool, error) { + return "", false, nil +} + +func (p *fakeLocalPool) Import(string, string, *aptly_utils.ChecksumInfo, bool, aptly.ChecksumStorage) (string, error) { + return "", nil +} + +func (p *fakeLocalPool) LegacyPath(string, *aptly_utils.ChecksumInfo) (string, error) { + return "", nil +} + +func (p *fakeLocalPool) Size(string) (int64, error) { + return 0, nil +} + +func (p *fakeLocalPool) Open(string) (aptly.ReadSeekerCloser, error) { + return nil, errors.New("not implemented") +} + +func (p *fakeLocalPool) FilepathList(aptly.Progress) ([]string, error) { + return nil, nil +} + +func (p *fakeLocalPool) Remove(string) (int64, error) { + return 0, nil +} + +func (p *fakeLocalPool) Stat(string) (os.FileInfo, error) { + return nil, errors.New("not implemented") +} + +func (p *fakeLocalPool) GenerateTempPath(string) (string, error) { + return "", nil +} + +func (p *fakeLocalPool) Link(string, string) error { + return nil +} + +func (p *fakeLocalPool) Symlink(string, string) error { + return nil +} + +func (p *fakeLocalPool) FullPath(path string) string { + return filepath.Join("/var/lib/aptly/pool", path) +} + +type fakeRemotePool struct { + openPath string + openErr error +} + +func (p *fakeRemotePool) Verify(string, string, *aptly_utils.ChecksumInfo, aptly.ChecksumStorage) (string, bool, error) { + return "", false, nil +} + +func (p *fakeRemotePool) Import(string, string, *aptly_utils.ChecksumInfo, bool, aptly.ChecksumStorage) (string, error) { + return "", nil +} + +func (p *fakeRemotePool) LegacyPath(string, *aptly_utils.ChecksumInfo) (string, error) { + return "", nil +} + +func (p *fakeRemotePool) Size(string) (int64, error) { + return 0, nil +} + +func (p *fakeRemotePool) Open(string) (aptly.ReadSeekerCloser, error) { + if p.openErr != nil { + return nil, p.openErr + } + return os.Open(p.openPath) +} + +func (p *fakeRemotePool) FilepathList(aptly.Progress) ([]string, error) { + return nil, nil +} + +func (p *fakeRemotePool) Remove(string) (int64, error) { + return 0, nil +} + func createReader(c *C, results []jfrogutils.ResultItem) *content.ContentReader { filePath := filepath.Join(c.MkDir(), "results.json") data, err := json.Marshal(resultFixture{Results: results}) @@ -192,6 +278,29 @@ func (s *PublishedStorageSuite) TestLinkFromPoolDelegatesToPutFile(c *C) { c.Assert(s.manager.uploadParams[0].Target, Equals, filepath.Join("repo", "prefix", "pool/main/p", "pkg.deb")) } +func (s *PublishedStorageSuite) TestLinkFromPoolUsesLocalPoolFullPath(c *C) { + pool := &fakeLocalPool{} + poolPath := "e3/48/84d71bb98002bf0c775479aa31ee_accountsservice_0.6.55-0ubuntu11_amd64.deb" + + err := s.storage.LinkFromPool("", "pool/main/p", "pkg.deb", pool, poolPath, aptly_utils.ChecksumInfo{}, false) + c.Assert(err, IsNil) + c.Assert(s.manager.uploadParams[0].Pattern, Equals, filepath.Join("/var/lib/aptly/pool", poolPath)) +} + +func (s *PublishedStorageSuite) TestLinkFromPoolCopiesFromRemotePool(c *C) { + tmpFile := filepath.Join(c.MkDir(), "source.deb") + c.Assert(os.WriteFile(tmpFile, []byte("package-bytes"), 0o644), IsNil) + + pool := &fakeRemotePool{openPath: tmpFile} + err := s.storage.LinkFromPool("", "pool/main/p", "pkg.deb", pool, "hash/path/pkg.deb", aptly_utils.ChecksumInfo{}, false) + c.Assert(err, IsNil) + + uploadPath := s.manager.uploadParams[0].Pattern + c.Assert(uploadPath, Not(Equals), "hash/path/pkg.deb") + _, statErr := os.Stat(uploadPath) + c.Assert(os.IsNotExist(statErr), Equals, true) +} + func (s *PublishedStorageSuite) TestFilelist(c *C) { s.manager.searchReader = createReader(c, []jfrogutils.ResultItem{ {Path: "repo/prefix/pool/main/a", Name: "a.deb", Actual_Md5: "m1"},