From dab494ecf3c1d5077decd40cdf9b20eddf4823bd Mon Sep 17 00:00:00 2001 From: Hansjoerg Maurer Date: Fri, 11 Sep 2026 21:41:33 +0200 Subject: [PATCH] Fix API snapshot pull destination loading --- api/snapshot_test.go | 61 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/api/snapshot_test.go b/api/snapshot_test.go index 9eb68a2b..02f8bca6 100644 --- a/api/snapshot_test.go +++ b/api/snapshot_test.go @@ -1,7 +1,14 @@ package api import ( + "bytes" "encoding/json" + "os" + "path/filepath" + + ctx "github.com/aptly-dev/aptly/context" + "github.com/aptly-dev/aptly/utils" + "github.com/smira/flag" "github.com/aptly-dev/aptly/deb" . "gopkg.in/check.v1" @@ -64,3 +71,57 @@ func (s *SnapshotsSuite) TestGetSnapshotsHandlesConcurrentDeletion(c *C) { c.Assert(response.Code, Equals, 200) } +// Pull must load the destination references before inferring architectures or +// preserving existing packages. Both fixtures are ordinary amd64 packages. +func (_ *SnapshotsSuite) TestPullPreservesDestinationPackages(c *C) { + savedConfig, savedContext := utils.Config, context + defer func() { utils.Config, context = savedConfig, savedContext }() + dir := c.MkDir() + configPath := filepath.Join(dir, "aptly.conf") + configData, err := json.Marshal(map[string]interface{}{"rootDir": dir, "architectures": []string{}}) + c.Assert(err, IsNil) + c.Assert(os.WriteFile(configPath, configData, 0600), IsNil) + flags := flag.NewFlagSet("pull-test", flag.ContinueOnError) + flags.String("config", configPath, "") + flags.String("architectures", "", "") + flags.Bool("no-lock", false, "") + flags.Int("db-open-attempts", 1, "") + testContext, err := ctx.NewContext(flags) + c.Assert(err, IsNil) + defer testContext.Shutdown() + s := &APISuite{context: testContext, router: Router(testContext)} + factory := s.context.NewCollectionFactory() + for _, mode := range []string{"inferred", "explicit"} { + a := &deb.Package{Name: "package-a", Version: "1", Architecture: "amd64"} + b := &deb.Package{Name: "package-b", Version: "1", Architecture: "amd64"} + for name, pkg := range map[string]*deb.Package{"base": a, "source": b} { + c.Assert(factory.PackageCollection().Update(pkg), IsNil) + list := deb.NewPackageList() + c.Assert(list.Add(pkg), IsNil) + snapshot := deb.NewSnapshotFromPackageList("pull-"+name+"-"+mode, nil, list, "") + c.Assert(factory.SnapshotCollection().Add(snapshot), IsNil) + } + params := snapshotsPullParams{ + Source: "pull-source-" + mode, + Destination: "pull-result-" + mode, + Queries: []string{"package-b"}, + } + if mode == "explicit" { + params.Architectures = []string{"amd64"} + } + body, err := json.Marshal(params) + c.Assert(err, IsNil) + response, err := s.HTTPRequest("POST", "/api/snapshots/pull-base-"+mode+"/pull?no-remove=1&no-deps=1", bytes.NewReader(body)) + c.Assert(err, IsNil) + if !c.Check(response.Code, Equals, 201, Commentf("%s: %s", mode, response.Body.String())) { + continue + } + snapshots := s.context.NewCollectionFactory().SnapshotCollection() + result, err := snapshots.ByName(params.Destination) + c.Assert(err, IsNil) + c.Assert(snapshots.LoadComplete(result), IsNil) + c.Check(result.RefList().Strings(), DeepEquals, []string{ + string(a.Key("")), string(b.Key("")), + }, Commentf("%s: preserve A and add B", mode)) + } +}