diff --git a/AUTHORS b/AUTHORS index 2a42fb9a47..d2311eb3a6 100644 --- a/AUTHORS +++ b/AUTHORS @@ -64,3 +64,4 @@ List of contributors, in chronological order: * Golf Hu (https://github.com/hudeng-go) * Cookie Fei (https://github.com/wuhuang26) * Andrey Loukhnov (https://github.com/aol-nnov) +* Malte Swart (https://github.com/mswart) diff --git a/api/api.go b/api/api.go index a52406d800..cc8f1fa824 100644 --- a/api/api.go +++ b/api/api.go @@ -228,7 +228,7 @@ func showPackages(c *gin.Context, reflist *deb.PackageRefList, collectionFactory list.PrepareIndex() list, err = list.Filter([]deb.PackageQuery{q}, withDeps, - nil, context.DependencyOptions(), architecturesList) + nil, nil, context.DependencyOptions(), architecturesList) if err != nil { AbortWithJSONError(c, 500, fmt.Errorf("unable to search: %s", err)) return @@ -244,7 +244,7 @@ func showPackages(c *gin.Context, reflist *deb.PackageRefList, collectionFactory fmt.Println("filter packages by version, query string parse err: ", err) c.AbortWithError(500, fmt.Errorf("unable to parse %s maximum version query string: %s", p.Name, err)) } else { - tmpList, err := list.Filter([]deb.PackageQuery{versionQ}, false, + tmpList, err := list.Filter([]deb.PackageQuery{versionQ}, false, nil, nil, 0, []string{}) if err == nil { diff --git a/api/mirror.go b/api/mirror.go index 0052f2a59c..e90c386a66 100644 --- a/api/mirror.go +++ b/api/mirror.go @@ -306,7 +306,7 @@ func apiMirrorsPackages(c *gin.Context) { list.PrepareIndex() - list, err = list.Filter([]deb.PackageQuery{q}, withDeps, + list, err = list.Filter([]deb.PackageQuery{q}, withDeps, nil, nil, context.DependencyOptions(), architecturesList) if err != nil { AbortWithJSONError(c, 500, fmt.Errorf("unable to search: %s", err)) @@ -468,7 +468,7 @@ func apiMirrorsUpdate(c *gin.Context) { return &task.ProcessReturnValue{Code: http.StatusInternalServerError, Value: nil}, fmt.Errorf("unable to update: %s", err) } - _, _, err = remote.ApplyFilter(context.DependencyOptions(), filterQuery, out) + _, _, err = remote.ApplyFilter(context.DependencyOptions(), filterQuery, nil, out) if err != nil { return &task.ProcessReturnValue{Code: http.StatusInternalServerError, Value: nil}, fmt.Errorf("unable to update: %s", err) } diff --git a/api/repos.go b/api/repos.go index 005c2aaa15..d17e429af8 100644 --- a/api/repos.go +++ b/api/repos.go @@ -586,7 +586,7 @@ func apiReposCopyPackage(c *gin.Context) { return &task.ProcessReturnValue{Code: http.StatusUnprocessableEntity, Value: nil}, fmt.Errorf("unable to parse query '%s': %s", fileName, err) } - toProcess, err := srcList.FilterWithProgress(queries, jsonBody.WithDeps, dstList, context.DependencyOptions(), architecturesList, context.Progress()) + toProcess, err := srcList.FilterWithProgress(queries, jsonBody.WithDeps, dstList, nil, context.DependencyOptions(), architecturesList, context.Progress()) if err != nil { return &task.ProcessReturnValue{Code: http.StatusInternalServerError, Value: nil}, fmt.Errorf("filter error: %s", err) } diff --git a/api/snapshot.go b/api/snapshot.go index 18aa644045..bb7ef165b7 100644 --- a/api/snapshot.go +++ b/api/snapshot.go @@ -636,7 +636,7 @@ func apiSnapshotsPull(c *gin.Context) { } // Filter with dependencies as requested - destinationPackageList, err := sourcePackageList.FilterWithProgress(queries, !noDeps, toPackageList, context.DependencyOptions(), architecturesList, context.Progress()) + destinationPackageList, err := sourcePackageList.FilterWithProgress(queries, !noDeps, toPackageList, nil, context.DependencyOptions(), architecturesList, context.Progress()) if err != nil { return &task.ProcessReturnValue{Code: http.StatusInternalServerError, Value: nil}, err } diff --git a/cmd/mirror_create.go b/cmd/mirror_create.go index 022a5cf202..3be895f357 100644 --- a/cmd/mirror_create.go +++ b/cmd/mirror_create.go @@ -51,6 +51,15 @@ func aptlyMirrorCreate(cmd *commander.Command, args []string) error { repo.SkipComponentCheck = context.Flags().Lookup("force-components").Value.Get().(bool) repo.SkipArchitectureCheck = context.Flags().Lookup("force-architectures").Value.Get().(bool) + extraDepsFromMirrors := context.Flags().Lookup("deps-from-mirrors").Value.String() + if extraDepsFromMirrors != "" { + repo.DepsFromMirrors = strings.Split(extraDepsFromMirrors, ",") + } + extraDepsFromRepos := context.Flags().Lookup("deps-from-repos").Value.String() + if extraDepsFromRepos != "" { + repo.DepsFromRepos = strings.Split(extraDepsFromRepos, ",") + } + if repo.Filter != "" { _, err = query.Parse(repo.Filter) if err != nil { @@ -109,6 +118,8 @@ Example: cmd.Flag.Bool("force-architectures", false, "(only with architecture list) skip check that requested architectures are listed in Release file") cmd.Flag.Int("max-tries", 1, "max download tries till process fails with download error") cmd.Flag.Var(&keyRingsFlag{}, "keyring", "gpg keyring to use when verifying Release file (could be specified multiple times)") + cmd.Flag.String("deps-from-mirrors", "", "list of mirrors thats packages's dependencies should be fulfilled (comma-separated), default to none") + cmd.Flag.String("deps-from-repos", "", "list of repositories thats packages's dependencies should be fulfilled (comma-separated), default to none") return cmd } diff --git a/cmd/mirror_edit.go b/cmd/mirror_edit.go index 5adf504b89..37555ac278 100644 --- a/cmd/mirror_edit.go +++ b/cmd/mirror_edit.go @@ -2,6 +2,7 @@ package cmd import ( "fmt" + "strings" "github.com/aptly-dev/aptly/pgp" "github.com/aptly-dev/aptly/query" @@ -46,6 +47,20 @@ func aptlyMirrorEdit(cmd *commander.Command, args []string) error { fetchMirror = true case "ignore-signatures": ignoreSignatures = true + case "deps-from-repos": + repoNames := flag.Value.String() + if repoNames != "" { + repo.DepsFromRepos = strings.Split(repoNames, ",") + } else { + repo.DepsFromRepos = make([]string, 0) + } + case "deps-from-mirrors": + mirrorNames := flag.Value.String() + if mirrorNames != "" { + repo.DepsFromMirrors = strings.Split(mirrorNames, ",") + } else { + repo.DepsFromMirrors = make([]string, 0) + } } }) @@ -111,6 +126,8 @@ Example: cmd.Flag.Bool("with-sources", false, "download source packages in addition to binary packages") cmd.Flag.Bool("with-udebs", false, "download .udeb packages (Debian installer support)") cmd.Flag.Var(&keyRingsFlag{}, "keyring", "gpg keyring to use when verifying Release file (could be specified multiple times)") + cmd.Flag.String("deps-from-mirrors", "", "list of mirrors thats packages's dependencies should be fulfilled (comma-separated), default to none") + cmd.Flag.String("deps-from-repos", "", "list of repositories thats packages's dependencies should be fulfilled (comma-separated), default to none") return cmd } diff --git a/cmd/mirror_show.go b/cmd/mirror_show.go index 03179161a3..dfd5a64388 100644 --- a/cmd/mirror_show.go +++ b/cmd/mirror_show.go @@ -68,6 +68,14 @@ func aptlyMirrorShowTxt(_ *commander.Command, args []string) error { filterWithDeps = Yes } fmt.Printf("Filter With Deps: %s\n", filterWithDeps) + if repo.FilterWithDeps { + if len(repo.DepsFromMirrors) > 0 { + fmt.Printf("Include Dependencies Of Mirrors: %s\n", strings.Join(repo.DepsFromMirrors, ", ")) + } + if len(repo.DepsFromRepos) > 0 { + fmt.Printf("Include Dependencies Of Repositories: %s\n", strings.Join(repo.DepsFromRepos, ", ")) + } + } } if repo.LastDownloadDate.IsZero() { fmt.Printf("Last update: never\n") diff --git a/cmd/mirror_update.go b/cmd/mirror_update.go index 2e6df4397e..ce03587a5b 100644 --- a/cmd/mirror_update.go +++ b/cmd/mirror_update.go @@ -67,14 +67,51 @@ func aptlyMirrorUpdate(cmd *commander.Command, args []string) error { if repo.Filter != "" { context.Progress().Printf("Applying filter...\n") var filterQuery deb.PackageQuery + var packagesWithExtraDeps *deb.PackageList filterQuery, err = query.Parse(repo.Filter) if err != nil { return fmt.Errorf("unable to update: %s", err) } + collectionFactory := context.NewCollectionFactory() + if len(repo.DepsFromMirrors)+len(repo.DepsFromRepos) > 0 { + packagesWithExtraDeps = deb.NewPackageList() + for _, mirrorName := range repo.DepsFromMirrors { + extraMirror, lerr := collectionFactory.RemoteRepoCollection().ByName(mirrorName) + if lerr != nil { + return fmt.Errorf("unable to update: %s", lerr) + } + lerr = collectionFactory.RemoteRepoCollection().LoadComplete(extraMirror) + if lerr != nil { + return fmt.Errorf("unable to update: %s", lerr) + } + packageList, lerr := deb.NewPackageListFromRefList(extraMirror.RefList(), collectionFactory.PackageCollection(), context.Progress()) + if lerr != nil { + return fmt.Errorf("unable to update: %s", lerr) + } + packagesWithExtraDeps.Append(packageList) + } + for _, repoName := range repo.DepsFromRepos { + extraRepo, lerr := collectionFactory.LocalRepoCollection().ByName(repoName) + if lerr != nil { + return fmt.Errorf("unable to update: %s", lerr) + } + lerr = collectionFactory.LocalRepoCollection().LoadComplete(extraRepo) + if lerr != nil { + return fmt.Errorf("unable to update: %s", lerr) + } + packageList, lerr := deb.NewPackageListFromRefList(extraRepo.RefList(), collectionFactory.PackageCollection(), context.Progress()) + if lerr != nil { + return fmt.Errorf("unable to update: %s", lerr) + } + packagesWithExtraDeps.Append(packageList) + } + context.Progress().Printf("Extra packages with deps: %d\n", packagesWithExtraDeps.Len()) + } + var oldLen, newLen int - oldLen, newLen, err = repo.ApplyFilter(context.DependencyOptions(), filterQuery, context.Progress()) + oldLen, newLen, err = repo.ApplyFilter(context.DependencyOptions(), filterQuery, packagesWithExtraDeps, context.Progress()) if err != nil { return fmt.Errorf("unable to update: %s", err) } diff --git a/cmd/repo_move.go b/cmd/repo_move.go index 8be6698b6b..4c5aa43405 100644 --- a/cmd/repo_move.go +++ b/cmd/repo_move.go @@ -116,7 +116,7 @@ func aptlyRepoMoveCopyImport(cmd *commander.Command, args []string) error { } } - toProcess, err := srcList.FilterWithProgress(queries, withDeps, dstList, context.DependencyOptions(), architecturesList, context.Progress()) + toProcess, err := srcList.FilterWithProgress(queries, withDeps, dstList, nil, context.DependencyOptions(), architecturesList, context.Progress()) if err != nil { return fmt.Errorf("unable to %s: %s", command, err) } diff --git a/cmd/repo_remove.go b/cmd/repo_remove.go index 93e8535c71..c355d87613 100644 --- a/cmd/repo_remove.go +++ b/cmd/repo_remove.go @@ -45,7 +45,7 @@ func aptlyRepoRemove(cmd *commander.Command, args []string) error { } list.PrepareIndex() - toRemove, err := list.Filter(queries, false, nil, 0, nil) + toRemove, err := list.Filter(queries, false, nil, nil, 0, nil) if err != nil { return fmt.Errorf("unable to remove: %s", err) } diff --git a/cmd/snapshot_filter.go b/cmd/snapshot_filter.go index b81a9cfc23..519db66367 100644 --- a/cmd/snapshot_filter.go +++ b/cmd/snapshot_filter.go @@ -67,7 +67,7 @@ func aptlySnapshotFilter(cmd *commander.Command, args []string) error { } // Filter with dependencies as requested - result, err := packageList.FilterWithProgress(queries, withDeps, nil, context.DependencyOptions(), architecturesList, context.Progress()) + result, err := packageList.FilterWithProgress(queries, withDeps, nil, nil, context.DependencyOptions(), architecturesList, context.Progress()) if err != nil { return fmt.Errorf("unable to filter: %s", err) } diff --git a/cmd/snapshot_pull.go b/cmd/snapshot_pull.go index 884b50ffb2..96f256339a 100644 --- a/cmd/snapshot_pull.go +++ b/cmd/snapshot_pull.go @@ -97,7 +97,7 @@ func aptlySnapshotPull(cmd *commander.Command, args []string) error { } // Filter with dependencies as requested - result, err := sourcePackageList.FilterWithProgress(queries, !noDeps, packageList, context.DependencyOptions(), architecturesList, context.Progress()) + result, err := sourcePackageList.FilterWithProgress(queries, !noDeps, packageList, nil, context.DependencyOptions(), architecturesList, context.Progress()) if err != nil { return fmt.Errorf("unable to pull: %s", err) } diff --git a/cmd/snapshot_search.go b/cmd/snapshot_search.go index d771af7ce5..e3efca25af 100644 --- a/cmd/snapshot_search.go +++ b/cmd/snapshot_search.go @@ -104,7 +104,7 @@ func aptlySnapshotMirrorRepoSearch(cmd *commander.Command, args []string) error } result, err := list.FilterWithProgress([]deb.PackageQuery{q}, withDeps, - nil, context.DependencyOptions(), architecturesList, context.Progress()) + nil, nil, context.DependencyOptions(), architecturesList, context.Progress()) if err != nil { return fmt.Errorf("unable to search: %s", err) } diff --git a/completion.d/aptly b/completion.d/aptly index 8caf47f856..cc84388398 100644 --- a/completion.d/aptly +++ b/completion.d/aptly @@ -154,7 +154,7 @@ _aptly() "create") if [[ $numargs -eq 0 ]]; then if [[ "$cur" == -* ]]; then - COMPREPLY=($(compgen -W "-filter= -filter-with-deps -force-components -ignore-signatures -keyring= -with-installer -with-sources -with-udebs" -- ${cur})) + COMPREPLY=($(compgen -W "-filter= -filter-with-deps -force-components -ignore-signatures -keyring= -with-installer -with-sources -with-udebs -deps-from-mirrors= -deps-from-repos=" -- ${cur})) return 0 fi fi @@ -162,7 +162,7 @@ _aptly() "edit") if [[ $numargs -eq 0 ]]; then if [[ "$cur" == -* ]]; then - COMPREPLY=($(compgen -W "-archive-url= -filter= -filter-with-deps -ignore-signatures -keyring= -with-installer -with-sources -with-udebs" -- ${cur})) + COMPREPLY=($(compgen -W "-archive-url= -filter= -filter-with-deps -ignore-signatures -keyring= -with-installer -with-sources -with-udebs -deps-from-mirrors= -deps-from-repos=" -- ${cur})) else COMPREPLY=($(compgen -W "$(__aptly_mirror_list)" -- ${cur})) fi diff --git a/deb/list.go b/deb/list.go index f9a8244ac1..a692bef905 100644 --- a/deb/list.go +++ b/deb/list.go @@ -499,12 +499,12 @@ func (l *PackageList) Search(dep Dependency, allMatches bool) (searchResults []* } // Filter filters package index by specified queries (ORed together), possibly pulling dependencies -func (l *PackageList) Filter(queries []PackageQuery, withDependencies bool, source *PackageList, dependencyOptions int, architecturesList []string) (*PackageList, error) { - return l.FilterWithProgress(queries, withDependencies, source, dependencyOptions, architecturesList, nil) +func (l *PackageList) Filter(queries []PackageQuery, withDependencies bool, source, extraDeps *PackageList, dependencyOptions int, architecturesList []string) (*PackageList, error) { + return l.FilterWithProgress(queries, withDependencies, source, extraDeps, dependencyOptions, architecturesList, nil) } // FilterWithProgress filters package index by specified queries (ORed together), possibly pulling dependencies and displays progress -func (l *PackageList) FilterWithProgress(queries []PackageQuery, withDependencies bool, source *PackageList, dependencyOptions int, architecturesList []string, progress aptly.Progress) (*PackageList, error) { +func (l *PackageList) FilterWithProgress(queries []PackageQuery, withDependencies bool, source, extraDeps *PackageList, dependencyOptions int, architecturesList []string, progress aptly.Progress) (*PackageList, error) { if !l.indexed { panic("list not indexed, can't filter") } @@ -520,18 +520,43 @@ func (l *PackageList) FilterWithProgress(queries []PackageQuery, withDependencie result.PrepareIndex() dependencySource := NewPackageList() + validationSet := NewPackageList() if source != nil { dependencySource.Append(source) } + if extraDeps != nil { + added += extraDeps.Len() + dependencySource.Append(extraDeps) + validationSet.Append(extraDeps) + if dependencyOptions&DepFollowAllVariants > 0 { + // keep all packages that are also present in extraDeps + // --> they are updates + extraDeps.ForEachIndexed(func(p *Package) error { + var err error + searchResults := l.Search(Dependency{Pkg: p.Name, Relation: VersionDontCare}, true) + if searchResults != nil { + for _, p := range searchResults { + if dependencyOptions&DepVerboseResolve == DepVerboseResolve && progress != nil { + progress.ColoredPrintf("@{g}Include package as update@|: %s", p) + } + result.Add(p) + added++ + } + } + return err + }) + } + } dependencySource.Append(result) + validationSet.Append(result) dependencySource.PrepareIndex() + validationSet.PrepareIndex() // while some new dependencies were discovered for added > 0 { added = 0 - // find missing dependencies - missing, err := result.VerifyDependencies(dependencyOptions, architecturesList, dependencySource, progress) + missing, err := validationSet.VerifyDependencies(dependencyOptions, architecturesList, dependencySource, progress) if err != nil { return nil, err } @@ -564,6 +589,7 @@ func (l *PackageList) FilterWithProgress(queries []PackageQuery, withDependencie } result.Add(p) dependencySource.Add(p) + validationSet.Add(p) added++ if dependencyOptions&DepFollowAllVariants == 0 { break @@ -573,7 +599,27 @@ func (l *PackageList) FilterWithProgress(queries []PackageQuery, withDependencie if dependencyOptions&DepVerboseResolve == DepVerboseResolve && progress != nil { progress.ColoredPrintf("@{r}Unsatisfied dependency@|: %s", dep.String()) } + } + if extraDeps == nil { + continue + } + // the missing dependency might come from the extraDeps package list + // if we can fulfil the dependency from extraDeps, include these packages + // within the validationSet -> we want to satisfy their dependencies as well + extraSearchResults := extraDeps.Search(dep, true) + if extraSearchResults != nil { + for _, p := range extraSearchResults { + if dependencyOptions&DepVerboseResolve == DepVerboseResolve && progress != nil { + progress.ColoredPrintf("@{g}Injecting extra package@|: %s", p) + } + dependencySource.Add(p) + validationSet.Add(p) + added++ + if dependencyOptions&DepFollowAllVariants == 0 { + break + } + } } } } diff --git a/deb/list_test.go b/deb/list_test.go index 0cb04b76c3..e4c66b78f8 100644 --- a/deb/list_test.go +++ b/deb/list_test.go @@ -53,9 +53,11 @@ type PackageListSuite struct { // Mocked packages in list packages []*Package packages2 []*Package + packages3 []*Package sourcePackages []*Package il *PackageList il2 *PackageList + il3 *PackageList } var _ = Suite(&PackageListSuite{}) @@ -114,6 +116,15 @@ func (s *PackageListSuite) SetUpTest(c *C) { } s.il2.PrepareIndex() + s.il3 = NewPackageList() + s.packages3 = []*Package{ + {Name: "data", Version: "1.0", Architecture: "all", Source: "data", deps: &PackageDependencies{PreDepends: []string{"dpkg (>= 1.6)"}}}, + } + for _, p := range s.packages3 { + s.il3.Add(p) + } + s.il3.PrepareIndex() + s.sourcePackages = []*Package{ {Name: "postfix", Version: "1.3", Architecture: "source", SourceArchitecture: "any", IsSource: true, deps: &PackageDependencies{}}, {Name: "app", Version: "1.1~bp1", Architecture: "source", SourceArchitecture: "any", IsSource: true, deps: &PackageDependencies{}}, @@ -311,7 +322,7 @@ func (s *PackageListSuite) TestSearch(c *C) { } func (s *PackageListSuite) TestFilter(c *C) { - c.Check(func() { s.list.Filter([]PackageQuery{&PkgQuery{"abcd", "0.3", "i386"}}, false, nil, 0, nil) }, Panics, "list not indexed, can't filter") + c.Check(func() { s.list.Filter([]PackageQuery{&PkgQuery{"abcd", "0.3", "i386"}}, false, nil, nil, 0, nil) }, Panics, "list not indexed, can't filter") plString := func(l *PackageList) string { list := make([]string, 0, l.Len()) @@ -324,12 +335,12 @@ func (s *PackageListSuite) TestFilter(c *C) { return strings.Join(list, " ") } - result, err := s.il.Filter([]PackageQuery{&PkgQuery{"app", "1.1~bp1", "i386"}}, false, nil, 0, nil) + result, err := s.il.Filter([]PackageQuery{&PkgQuery{"app", "1.1~bp1", "i386"}}, false, nil, nil, 0, nil) c.Check(err, IsNil) c.Check(plString(result), Equals, "app_1.1~bp1_i386") result, err = s.il.Filter([]PackageQuery{&PkgQuery{"app", "1.1~bp1", "i386"}, &PkgQuery{"dpkg", "1.7", "source"}, - &PkgQuery{"dpkg", "1.8", "amd64"}}, false, nil, 0, nil) + &PkgQuery{"dpkg", "1.8", "amd64"}}, false, nil, nil, 0, nil) c.Check(err, IsNil) c.Check(plString(result), Equals, "app_1.1~bp1_i386 dpkg_1.7_source") @@ -338,69 +349,73 @@ func (s *PackageListSuite) TestFilter(c *C) { &DependencyQuery{Dep: Dependency{Pkg: "dpkg", Relation: VersionGreater, Version: "1.6.1-3"}}, &DependencyQuery{Dep: Dependency{Pkg: "app", Relation: VersionGreaterOrEqual, Version: "1.0"}}, &DependencyQuery{Dep: Dependency{Pkg: "xyz"}}, - &DependencyQuery{Dep: Dependency{Pkg: "aa", Relation: VersionGreater, Version: "3.0"}}}, false, nil, 0, nil) + &DependencyQuery{Dep: Dependency{Pkg: "aa", Relation: VersionGreater, Version: "3.0"}}}, false, nil, nil, 0, nil) c.Check(err, IsNil) c.Check(plString(result), Equals, "app_1.0_s390 app_1.1~bp1_amd64 app_1.1~bp1_arm app_1.1~bp1_i386 dpkg_1.7_i386 dpkg_1.7_source") - result, err = s.il.Filter([]PackageQuery{&DependencyQuery{Dep: Dependency{Pkg: "app", Architecture: "i386"}}}, true, NewPackageList(), 0, []string{"i386"}) + result, err = s.il.Filter([]PackageQuery{&DependencyQuery{Dep: Dependency{Pkg: "app", Architecture: "i386"}}}, true, NewPackageList(), nil, 0, []string{"i386"}) c.Check(err, IsNil) c.Check(plString(result), Equals, "app_1.1~bp1_i386 data_1.1~bp1_all dpkg_1.7_i386 lib_1.0_i386 mailer_3.5.8_i386") result, err = s.il.Filter([]PackageQuery{ &DependencyQuery{Dep: Dependency{Pkg: "app", Relation: VersionGreaterOrEqual, Version: "0.9"}}, &DependencyQuery{Dep: Dependency{Pkg: "lib"}}, - &DependencyQuery{Dep: Dependency{Pkg: "data"}}}, true, NewPackageList(), 0, []string{"i386", "amd64"}) + &DependencyQuery{Dep: Dependency{Pkg: "data"}}}, true, NewPackageList(), nil, 0, []string{"i386", "amd64"}) c.Check(err, IsNil) c.Check(plString(result), Equals, "app_1.0_s390 app_1.1~bp1_amd64 app_1.1~bp1_arm app_1.1~bp1_i386 data_1.1~bp1_all dpkg_1.6.1-3_amd64 dpkg_1.7_i386 lib_1.0_i386 mailer_3.5.8_i386") result, err = s.il.Filter([]PackageQuery{&OrQuery{&PkgQuery{"app", "1.1~bp1", "i386"}, - &DependencyQuery{Dep: Dependency{Pkg: "dpkg", Relation: VersionGreater, Version: "1.6.1-3"}}}}, false, nil, 0, nil) + &DependencyQuery{Dep: Dependency{Pkg: "dpkg", Relation: VersionGreater, Version: "1.6.1-3"}}}}, false, nil, nil, 0, nil) c.Check(err, IsNil) c.Check(plString(result), Equals, "app_1.1~bp1_i386 dpkg_1.7_i386 dpkg_1.7_source") result, err = s.il.Filter([]PackageQuery{&AndQuery{&PkgQuery{"app", "1.1~bp1", "i386"}, - &DependencyQuery{Dep: Dependency{Pkg: "dpkg", Relation: VersionGreater, Version: "1.6.1-3"}}}}, false, nil, 0, nil) + &DependencyQuery{Dep: Dependency{Pkg: "dpkg", Relation: VersionGreater, Version: "1.6.1-3"}}}}, false, nil, nil, 0, nil) c.Check(err, IsNil) c.Check(plString(result), Equals, "") result, err = s.il.Filter([]PackageQuery{&OrQuery{&PkgQuery{"app", "1.1~bp1", "i386"}, - &FieldQuery{Field: "$Architecture", Relation: VersionEqual, Value: "s390"}}}, false, nil, 0, nil) + &FieldQuery{Field: "$Architecture", Relation: VersionEqual, Value: "s390"}}}, false, nil, nil, 0, nil) c.Check(err, IsNil) c.Check(plString(result), Equals, "app_1.0_s390 app_1.1~bp1_i386 data_1.1~bp1_all") result, err = s.il.Filter([]PackageQuery{&AndQuery{&FieldQuery{Field: "Version", Relation: VersionGreaterOrEqual, Value: "1.0"}, - &FieldQuery{Field: "$Architecture", Relation: VersionEqual, Value: "s390"}}}, false, nil, 0, nil) + &FieldQuery{Field: "$Architecture", Relation: VersionEqual, Value: "s390"}}}, false, nil, nil, 0, nil) c.Check(err, IsNil) c.Check(plString(result), Equals, "app_1.0_s390 data_1.1~bp1_all") result, err = s.il.Filter([]PackageQuery{&AndQuery{ - &FieldQuery{Field: "$Architecture", Relation: VersionPatternMatch, Value: "i*6"}, &PkgQuery{"app", "1.1~bp1", "i386"}}}, false, nil, 0, nil) + &FieldQuery{Field: "$Architecture", Relation: VersionPatternMatch, Value: "i*6"}, &PkgQuery{"app", "1.1~bp1", "i386"}}}, false, nil, nil, 0, nil) c.Check(err, IsNil) c.Check(plString(result), Equals, "app_1.1~bp1_i386") result, err = s.il.Filter([]PackageQuery{&NotQuery{ - &FieldQuery{Field: "$Architecture", Relation: VersionPatternMatch, Value: "i*6"}}}, false, nil, 0, nil) + &FieldQuery{Field: "$Architecture", Relation: VersionPatternMatch, Value: "i*6"}}}, false, nil, nil, 0, nil) c.Check(err, IsNil) c.Check(plString(result), Equals, "app_1.0_s390 app_1.1~bp1_amd64 app_1.1~bp1_arm data_1.1~bp1_all dpkg_1.6.1-3_amd64 dpkg_1.6.1-3_arm dpkg_1.6.1-3_source dpkg_1.7_source libx_1.5_arm") result, err = s.il.Filter([]PackageQuery{&AndQuery{ - &FieldQuery{Field: "$Architecture", Relation: VersionRegexp, Value: "i.*6", Regexp: regexp.MustCompile("i.*6")}, &PkgQuery{"app", "1.1~bp1", "i386"}}}, false, nil, 0, nil) + &FieldQuery{Field: "$Architecture", Relation: VersionRegexp, Value: "i.*6", Regexp: regexp.MustCompile("i.*6")}, &PkgQuery{"app", "1.1~bp1", "i386"}}}, false, nil, nil, 0, nil) c.Check(err, IsNil) c.Check(plString(result), Equals, "app_1.1~bp1_i386") result, err = s.il.Filter([]PackageQuery{&AndQuery{ &FieldQuery{Field: "Name", Relation: VersionRegexp, Value: "a", Regexp: regexp.MustCompile("a")}, &NotQuery{Q: &FieldQuery{Field: "Name", Relation: VersionEqual, Value: "data"}}, - }}, false, nil, 0, nil) + }}, false, nil, nil, 0, nil) c.Check(err, IsNil) c.Check(plString(result), Equals, "aa_2.0-1_i386 app_1.0_s390 app_1.1~bp1_amd64 app_1.1~bp1_arm app_1.1~bp1_i386 mailer_3.5.8_i386") result, err = s.il.Filter([]PackageQuery{&AndQuery{ &NotQuery{Q: &FieldQuery{Field: "Name", Relation: VersionEqual, Value: "data"}}, &FieldQuery{Field: "Name", Relation: VersionRegexp, Value: "a", Regexp: regexp.MustCompile("a")}, - }}, false, nil, 0, nil) + }}, false, nil, nil, 0, nil) c.Check(err, IsNil) c.Check(plString(result), Equals, "aa_2.0-1_i386 app_1.0_s390 app_1.1~bp1_amd64 app_1.1~bp1_arm app_1.1~bp1_i386 mailer_3.5.8_i386") + + result, err = s.il.Filter([]PackageQuery{&DependencyQuery{Dep: Dependency{Pkg: "aa"}}}, true, nil, s.il3, DepVerboseResolve|DepFollowAllVariants, []string{"i386", "amd64"}) + c.Check(err, IsNil) + c.Check(plString(result), Equals, "aa_2.0-1_i386 data_1.1~bp1_all dpkg_1.6.1-3_amd64 dpkg_1.7_i386") } func (s *PackageListSuite) TestVerifyDependencies(c *C) { diff --git a/deb/remote.go b/deb/remote.go index 6ecb7e8098..24d3e0514a 100644 --- a/deb/remote.go +++ b/deb/remote.go @@ -72,6 +72,10 @@ type RemoteRepo struct { DownloadInstaller bool // Packages for json output Packages []string `codec:"-" json:",omitempty"` + // List of mirror names with additional dependencies + DepsFromMirrors []string + // List of repository names with additional dependencies + DepsFromRepos []string // "Snapshot" of current list of packages packageRefs *PackageRefList // Parsed archived root @@ -584,14 +588,15 @@ func (repo *RemoteRepo) DownloadPackageIndexes(progress aptly.Progress, d aptly. } // ApplyFilter applies filtering to already built PackageList -func (repo *RemoteRepo) ApplyFilter(dependencyOptions int, filterQuery PackageQuery, progress aptly.Progress) (oldLen, newLen int, err error) { +func (repo *RemoteRepo) ApplyFilter(dependencyOptions int, filterQuery PackageQuery, extraDeps *PackageList, progress aptly.Progress) (oldLen, newLen int, err error) { repo.packageList.PrepareIndex() - emptyList := NewPackageList() - emptyList.PrepareIndex() + if extraDeps != nil { + extraDeps.PrepareIndex() + } oldLen = repo.packageList.Len() - repo.packageList, err = repo.packageList.FilterWithProgress([]PackageQuery{filterQuery}, repo.FilterWithDeps, emptyList, dependencyOptions, repo.Architectures, progress) + repo.packageList, err = repo.packageList.FilterWithProgress([]PackageQuery{filterQuery}, repo.FilterWithDeps, nil, extraDeps, dependencyOptions, repo.Architectures, progress) if repo.packageList != nil { newLen = repo.packageList.Len() } diff --git a/man/aptly.1 b/man/aptly.1 index fe986f0ff9..4c353805a1 100644 --- a/man/aptly.1 +++ b/man/aptly.1 @@ -483,6 +483,14 @@ $ aptly mirror create wheezy\-main http://mirror\.yandex\.ru/debian/ wheezy main Options: . .TP +\-\fBdeps\-from\-mirrors\fR= +list of mirrors thats packages\(cqs dependencies should be fulfilled (comma\-separated), default to none +. +.TP +\-\fBdeps\-from\-repos\fR= +list of repositories thats packages\(cqs dependencies should be fulfilled (comma\-separated), default to none +. +.TP \-\fBfilter\fR= filter packages in mirror . @@ -660,6 +668,12 @@ Options: .TP \-\fBarchive\-url\fR= archive url is the root of archive +\-\fBdeps\-from\-mirrors\fR= +list of mirrors thats packages\(cqs dependencies should be fulfilled (comma\-separated), default to none +. +.TP +\-\fBdeps\-from\-repos\fR= +list of repositories thats packages\(cqs dependencies should be fulfilled (comma\-separated), default to none . .TP \-\fBfilter\fR= @@ -2113,6 +2127,7 @@ Clemens Rabe (https://github\.com/seeraven) TJ Merritt (https://github\.com/tjmerritt) . .IP "\[ci]" 4 +<<<<<<< HEAD Matt Martyn (https://github\.com/MMartyn) . .IP "\[ci]" 4 @@ -2160,5 +2175,8 @@ Lorenzo Bolla (https://github\.com/lbolla) .IP "\[ci]" 4 Benj Fassbind (https://github\.com/randombenj) . +.IP "\[ci]" 4 +Malte Swart (https://github\.com/mswart) +. .IP "" 0 diff --git a/system/t03_help/MirrorCreateHelpTest_gold b/system/t03_help/MirrorCreateHelpTest_gold index 1816e6d31c..f202ab05e0 100644 --- a/system/t03_help/MirrorCreateHelpTest_gold +++ b/system/t03_help/MirrorCreateHelpTest_gold @@ -21,6 +21,8 @@ Options: -dep-follow-source: when processing dependencies, follow from binary to Source packages -dep-follow-suggests: when processing dependencies, follow Suggests -dep-verbose-resolve: when processing dependencies, print detailed logs + -deps-from-mirrors="": list of mirrors thats packages's dependencies should be fulfilled (comma-separated), default to none + -deps-from-repos="": list of repositories thats packages's dependencies should be fulfilled (comma-separated), default to none -filter="": filter packages in mirror -filter-with-deps: when filtering, include dependencies of matching packages as well -force-architectures: (only with architecture list) skip check that requested architectures are listed in Release file diff --git a/system/t03_help/MirrorCreateTest_gold b/system/t03_help/MirrorCreateTest_gold index 7450221628..9bd814c70b 100644 --- a/system/t03_help/MirrorCreateTest_gold +++ b/system/t03_help/MirrorCreateTest_gold @@ -12,6 +12,8 @@ Options: -dep-follow-source: when processing dependencies, follow from binary to Source packages -dep-follow-suggests: when processing dependencies, follow Suggests -dep-verbose-resolve: when processing dependencies, print detailed logs + -deps-from-mirrors="": list of mirrors thats packages's dependencies should be fulfilled (comma-separated), default to none + -deps-from-repos="": list of repositories thats packages's dependencies should be fulfilled (comma-separated), default to none -filter="": filter packages in mirror -filter-with-deps: when filtering, include dependencies of matching packages as well -force-architectures: (only with architecture list) skip check that requested architectures are listed in Release file diff --git a/system/t03_help/WrongFlagTest_gold b/system/t03_help/WrongFlagTest_gold index 4dc0cb1946..3dfb470bce 100644 --- a/system/t03_help/WrongFlagTest_gold +++ b/system/t03_help/WrongFlagTest_gold @@ -13,6 +13,8 @@ Options: -dep-follow-source: when processing dependencies, follow from binary to Source packages -dep-follow-suggests: when processing dependencies, follow Suggests -dep-verbose-resolve: when processing dependencies, print detailed logs + -deps-from-mirrors="": list of mirrors thats packages's dependencies should be fulfilled (comma-separated), default to none + -deps-from-repos="": list of repositories thats packages's dependencies should be fulfilled (comma-separated), default to none -filter="": filter packages in mirror -filter-with-deps: when filtering, include dependencies of matching packages as well -force-architectures: (only with architecture list) skip check that requested architectures are listed in Release file diff --git a/system/t04_mirror/ListMirror6Test_gold b/system/t04_mirror/ListMirror6Test_gold index bed19fa244..fe0500c9b5 100644 --- a/system/t04_mirror/ListMirror6Test_gold +++ b/system/t04_mirror/ListMirror6Test_gold @@ -42,7 +42,9 @@ "SkipArchitectureCheck": false, "DownloadSources": false, "DownloadUdebs": false, - "DownloadInstaller": false + "DownloadInstaller": false, + "DepsFromMirrors": null, + "DepsFromRepos": null }, { "Name": "mirror2", @@ -85,7 +87,9 @@ "SkipArchitectureCheck": false, "DownloadSources": true, "DownloadUdebs": false, - "DownloadInstaller": false + "DownloadInstaller": false, + "DepsFromMirrors": null, + "DepsFromRepos": null }, { "Name": "mirror3", @@ -119,7 +123,9 @@ "SkipArchitectureCheck": false, "DownloadSources": false, "DownloadUdebs": false, - "DownloadInstaller": false + "DownloadInstaller": false, + "DepsFromMirrors": null, + "DepsFromRepos": null }, { "Name": "mirror4", @@ -145,6 +151,8 @@ "SkipArchitectureCheck": false, "DownloadSources": false, "DownloadUdebs": false, - "DownloadInstaller": false + "DownloadInstaller": false, + "DepsFromMirrors": null, + "DepsFromRepos": null } ] diff --git a/system/t04_mirror/ShowMirror5Test_gold b/system/t04_mirror/ShowMirror5Test_gold index d8ba1780ca..5140ba5b9e 100644 --- a/system/t04_mirror/ShowMirror5Test_gold +++ b/system/t04_mirror/ShowMirror5Test_gold @@ -41,5 +41,7 @@ "SkipArchitectureCheck": false, "DownloadSources": false, "DownloadUdebs": false, - "DownloadInstaller": false + "DownloadInstaller": false, + "DepsFromMirrors": null, + "DepsFromRepos": null } diff --git a/system/t04_mirror/ShowMirror7Test_gold b/system/t04_mirror/ShowMirror7Test_gold index d454a9599f..430127324b 100644 --- a/system/t04_mirror/ShowMirror7Test_gold +++ b/system/t04_mirror/ShowMirror7Test_gold @@ -357,5 +357,7 @@ "xvba-va-driver_0.8.0-5_i386", "ydpdict_1.0.0-2_amd64", "ydpdict_1.0.0-2_i386" - ] + ], + "DepsFromMirrors": null, + "DepsFromRepos": null } diff --git a/system/t04_mirror/ShowMirror8Test_gold b/system/t04_mirror/ShowMirror8Test_gold index 9d3f70c5db..beffe347d5 100644 --- a/system/t04_mirror/ShowMirror8Test_gold +++ b/system/t04_mirror/ShowMirror8Test_gold @@ -33,5 +33,7 @@ "SkipArchitectureCheck": false, "DownloadSources": false, "DownloadUdebs": false, - "DownloadInstaller": false + "DownloadInstaller": false, + "DepsFromMirrors": null, + "DepsFromRepos": null } diff --git a/system/t05_snapshot/ShowSnapshot4Test_gold b/system/t05_snapshot/ShowSnapshot4Test_gold index 11ea4f8739..29e4fd6e55 100644 --- a/system/t05_snapshot/ShowSnapshot4Test_gold +++ b/system/t05_snapshot/ShowSnapshot4Test_gold @@ -34,7 +34,9 @@ "SkipArchitectureCheck": false, "DownloadSources": false, "DownloadUdebs": false, - "DownloadInstaller": false + "DownloadInstaller": false, + "DepsFromMirrors": null, + "DepsFromRepos": null } ], "Description": "Snapshot from mirror [wheezy-non-free]: http://mirror.yandex.ru/debian/ wheezy", diff --git a/system/t05_snapshot/ShowSnapshot5Test_gold b/system/t05_snapshot/ShowSnapshot5Test_gold index 6d6a42c453..ae1deede47 100644 --- a/system/t05_snapshot/ShowSnapshot5Test_gold +++ b/system/t05_snapshot/ShowSnapshot5Test_gold @@ -36,7 +36,9 @@ "SkipArchitectureCheck": false, "DownloadSources": false, "DownloadUdebs": false, - "DownloadInstaller": false + "DownloadInstaller": false, + "DepsFromMirrors": null, + "DepsFromRepos": null } ], "Packages": [