Refactor Filter options into a struct

It was already a lot of options for one method and I am going to add
another one in the next commit.
This commit is contained in:
Gordian Schoenherr
2024-11-26 16:19:23 +09:00
parent 88ef8efba5
commit 3b785e4165
12 changed files with 167 additions and 71 deletions

View File

@@ -227,8 +227,13 @@ func showPackages(c *gin.Context, reflist *deb.PackageRefList, collectionFactory
list.PrepareIndex()
list, err = list.Filter([]deb.PackageQuery{q}, withDeps,
nil, context.DependencyOptions(), architecturesList)
list, err = list.Filter(deb.FilterOptions{
Queries: []deb.PackageQuery{q},
WithDependencies: withDeps,
Source: nil,
DependencyOptions: context.DependencyOptions(),
Architectures: architecturesList,
})
if err != nil {
AbortWithJSONError(c, 500, fmt.Errorf("unable to search: %s", err))
return
@@ -244,8 +249,9 @@ 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,
nil, 0, []string{})
tmpList, err := list.Filter(deb.FilterOptions{
Queries: []deb.PackageQuery{versionQ},
})
if err == nil {
if tmpList.Len() > 0 {

View File

@@ -306,8 +306,12 @@ func apiMirrorsPackages(c *gin.Context) {
list.PrepareIndex()
list, err = list.Filter([]deb.PackageQuery{q}, withDeps,
nil, context.DependencyOptions(), architecturesList)
list, err = list.Filter(deb.FilterOptions{
Queries: []deb.PackageQuery{q},
WithDependencies: withDeps,
DependencyOptions: context.DependencyOptions(),
Architectures: architecturesList,
})
if err != nil {
AbortWithJSONError(c, 500, fmt.Errorf("unable to search: %s", err))
}

View File

@@ -586,7 +586,14 @@ 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.Filter(deb.FilterOptions{
Queries: queries,
WithDependencies: jsonBody.WithDeps,
Source: dstList,
DependencyOptions: context.DependencyOptions(),
Architectures: architecturesList,
Progress: context.Progress(),
})
if err != nil {
return &task.ProcessReturnValue{Code: http.StatusInternalServerError, Value: nil}, fmt.Errorf("filter error: %s", err)
}

View File

@@ -636,7 +636,14 @@ 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.Filter(deb.FilterOptions{
Queries: queries,
WithDependencies: !noDeps,
Source: toPackageList,
DependencyOptions: context.DependencyOptions(),
Architectures: architecturesList,
Progress: context.Progress(),
})
if err != nil {
return &task.ProcessReturnValue{Code: http.StatusInternalServerError, Value: nil}, err
}

View File

@@ -116,7 +116,14 @@ func aptlyRepoMoveCopyImport(cmd *commander.Command, args []string) error {
}
}
toProcess, err := srcList.FilterWithProgress(queries, withDeps, dstList, context.DependencyOptions(), architecturesList, context.Progress())
toProcess, err := srcList.Filter(deb.FilterOptions{
Queries: queries,
WithDependencies: withDeps,
Source: dstList,
DependencyOptions: context.DependencyOptions(),
Architectures: architecturesList,
Progress: context.Progress(),
})
if err != nil {
return fmt.Errorf("unable to %s: %s", command, err)
}

View File

@@ -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(deb.FilterOptions{Queries: queries})
if err != nil {
return fmt.Errorf("unable to remove: %s", err)
}

View File

@@ -67,7 +67,14 @@ 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.Filter(deb.FilterOptions{
Queries: queries,
WithDependencies: withDeps,
Source: nil,
DependencyOptions: context.DependencyOptions(),
Architectures: architecturesList,
Progress: context.Progress(),
})
if err != nil {
return fmt.Errorf("unable to filter: %s", err)
}

View File

@@ -97,7 +97,14 @@ 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.Filter(deb.FilterOptions{
Queries: queries,
WithDependencies: !noDeps,
Source: packageList,
DependencyOptions: context.DependencyOptions(),
Architectures: architecturesList,
Progress: context.Progress(),
})
if err != nil {
return fmt.Errorf("unable to pull: %s", err)
}

View File

@@ -103,8 +103,13 @@ func aptlySnapshotMirrorRepoSearch(cmd *commander.Command, args []string) error
}
}
result, err := list.FilterWithProgress([]deb.PackageQuery{q}, withDeps,
nil, context.DependencyOptions(), architecturesList, context.Progress())
result, err := list.Filter(deb.FilterOptions{
Queries: []deb.PackageQuery{q},
WithDependencies: withDeps,
DependencyOptions: context.DependencyOptions(),
Architectures: architecturesList,
Progress: context.Progress(),
})
if err != nil {
return fmt.Errorf("unable to search: %s", err)
}

View File

@@ -503,32 +503,37 @@ func (l *PackageList) Search(dep Dependency, allMatches bool, searchProvided boo
return
}
// 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)
// FilterOptions specifies options for Filter()
type FilterOptions struct {
Queries []PackageQuery
WithDependencies bool
Source *PackageList
DependencyOptions int
Architectures []string
Progress aptly.Progress // set to non-nil to report progress
}
// 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) {
// Filter filters package index by specified queries (ORed together), possibly pulling dependencies
func (l *PackageList) Filter(options FilterOptions) (*PackageList, error) {
if !l.indexed {
panic("list not indexed, can't filter")
}
result := NewPackageList()
for _, query := range queries {
result.Append(query.Query(l))
for _, query := range options.Queries {
_ = result.Append(query.Query(l))
}
if withDependencies {
if options.WithDependencies {
added := result.Len()
result.PrepareIndex()
dependencySource := NewPackageList()
if source != nil {
dependencySource.Append(source)
if options.Source != nil {
_ = dependencySource.Append(options.Source)
}
dependencySource.Append(result)
_ = dependencySource.Append(result)
dependencySource.PrepareIndex()
// while some new dependencies were discovered
@@ -536,22 +541,22 @@ func (l *PackageList) FilterWithProgress(queries []PackageQuery, withDependencie
added = 0
// find missing dependencies
missing, err := result.VerifyDependencies(dependencyOptions, architecturesList, dependencySource, progress)
missing, err := result.VerifyDependencies(options.DependencyOptions, options.Architectures, dependencySource, options.Progress)
if err != nil {
return nil, err
}
// try to satisfy dependencies
for _, dep := range missing {
if dependencyOptions&DepFollowAllVariants == 0 {
if options.DependencyOptions&DepFollowAllVariants == 0 {
// dependency might have already been satisfied
// with packages already been added
//
// when follow-all-variants is enabled, we need to try to expand anyway,
// as even if dependency is satisfied now, there might be other ways to satisfy dependency
if result.Search(dep, false, true) != nil {
if dependencyOptions&DepVerboseResolve == DepVerboseResolve && progress != nil {
progress.ColoredPrintf("@{y}Already satisfied dependency@|: %s with %s", &dep, result.Search(dep, true, true))
if options.DependencyOptions&DepVerboseResolve == DepVerboseResolve && options.Progress != nil {
options.Progress.ColoredPrintf("@{y}Already satisfied dependency@|: %s with %s", &dep, result.Search(dep, true, true))
}
continue
}
@@ -564,19 +569,19 @@ func (l *PackageList) FilterWithProgress(queries []PackageQuery, withDependencie
continue
}
if dependencyOptions&DepVerboseResolve == DepVerboseResolve && progress != nil {
progress.ColoredPrintf("@{g}Injecting package@|: %s", p)
if options.DependencyOptions&DepVerboseResolve == DepVerboseResolve && options.Progress != nil {
options.Progress.ColoredPrintf("@{g}Injecting package@|: %s", p)
}
result.Add(p)
dependencySource.Add(p)
_ = result.Add(p)
_ = dependencySource.Add(p)
added++
if dependencyOptions&DepFollowAllVariants == 0 {
if options.DependencyOptions&DepFollowAllVariants == 0 {
break
}
}
} else {
if dependencyOptions&DepVerboseResolve == DepVerboseResolve && progress != nil {
progress.ColoredPrintf("@{r}Unsatisfied dependency@|: %s", dep.String())
if options.DependencyOptions&DepVerboseResolve == DepVerboseResolve && options.Progress != nil {
options.Progress.ColoredPrintf("@{r}Unsatisfied dependency@|: %s", dep.String())
}
}

View File

@@ -131,7 +131,7 @@ func (s *PackageListSuite) TestAddLen(c *C) {
c.Check(s.list.Len(), Equals, 1)
c.Check(s.list.Add(s.p3), IsNil)
c.Check(s.list.Len(), Equals, 2)
c.Check(s.list.Add(s.p4), ErrorMatches, "package already exists and is different: .*")
c.Check(s.list.Add(s.p4), ErrorMatches, "package already exists and is different: .*")
}
func (s *PackageListSuite) TestRemove(c *C) {
@@ -311,7 +311,11 @@ 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(FilterOptions{
Queries: []PackageQuery{&PkgQuery{"abcd", "0.3", "i386"}},
})
}, Panics, "list not indexed, can't filter")
plString := func(l *PackageList) string {
list := make([]string, 0, l.Len())
@@ -324,81 +328,111 @@ 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(FilterOptions{Queries: []PackageQuery{&PkgQuery{"app", "1.1~bp1", "i386"}}})
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)
result, err = s.il.Filter(FilterOptions{Queries: []PackageQuery{&PkgQuery{"app", "1.1~bp1", "i386"}, &PkgQuery{"dpkg", "1.7", "source"},
&PkgQuery{"dpkg", "1.8", "amd64"}}})
c.Check(err, IsNil)
c.Check(plString(result), Equals, "app_1.1~bp1_i386 dpkg_1.7_source")
result, err = s.il.Filter([]PackageQuery{
result, err = s.il.Filter(FilterOptions{Queries: []PackageQuery{
&DependencyQuery{Dep: Dependency{Pkg: "app"}},
&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"}}}})
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(FilterOptions{
Queries: []PackageQuery{&DependencyQuery{Dep: Dependency{Pkg: "app", Architecture: "i386"}}},
WithDependencies: true,
Source: NewPackageList(),
Architectures: []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"})
result, err = s.il.Filter(FilterOptions{
Queries: []PackageQuery{
&DependencyQuery{Dep: Dependency{Pkg: "app", Relation: VersionGreaterOrEqual, Version: "0.9"}},
&DependencyQuery{Dep: Dependency{Pkg: "lib"}},
&DependencyQuery{Dep: Dependency{Pkg: "data"}}},
WithDependencies: true,
Source: NewPackageList(),
Architectures: []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)
result, err = s.il.Filter(FilterOptions{
Queries: []PackageQuery{&OrQuery{&PkgQuery{"app", "1.1~bp1", "i386"},
&DependencyQuery{Dep: Dependency{Pkg: "dpkg", Relation: VersionGreater, Version: "1.6.1-3"}}}},
})
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)
result, err = s.il.Filter(FilterOptions{
Queries: []PackageQuery{&AndQuery{&PkgQuery{"app", "1.1~bp1", "i386"},
&DependencyQuery{Dep: Dependency{Pkg: "dpkg", Relation: VersionGreater, Version: "1.6.1-3"}}}},
})
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)
//result, err = s.il.Filter([]PackageQuery{&OrQuery{&PkgQuery{"app", "1.1~bp1", "i386"},
// &FieldQuery{Field: "$Architecture", Relation: VersionEqual, Value: "s390"}}}, false, nil, 0, nil)
result, err = s.il.Filter(FilterOptions{
Queries: []PackageQuery{&OrQuery{&PkgQuery{"app", "1.1~bp1", "i386"},
&FieldQuery{Field: "$Architecture", Relation: VersionEqual, Value: "s390"}}},
})
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)
result, err = s.il.Filter(FilterOptions{
Queries: []PackageQuery{&AndQuery{&FieldQuery{Field: "Version", Relation: VersionGreaterOrEqual, Value: "1.0"},
&FieldQuery{Field: "$Architecture", Relation: VersionEqual, Value: "s390"}}},
})
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)
result, err = s.il.Filter(FilterOptions{
Queries: []PackageQuery{&AndQuery{
&FieldQuery{Field: "$Architecture", Relation: VersionPatternMatch, Value: "i*6"}, &PkgQuery{"app", "1.1~bp1", "i386"}}},
})
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)
result, err = s.il.Filter(FilterOptions{
Queries: []PackageQuery{&NotQuery{
&FieldQuery{Field: "$Architecture", Relation: VersionPatternMatch, Value: "i*6"}}},
})
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)
result, err = s.il.Filter(FilterOptions{
Queries: []PackageQuery{&AndQuery{
&FieldQuery{Field: "$Architecture", Relation: VersionRegexp, Value: "i.*6", Regexp: regexp.MustCompile("i.*6")}, &PkgQuery{"app", "1.1~bp1", "i386"}}},
})
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)
result, err = s.il.Filter(FilterOptions{
Queries: []PackageQuery{&AndQuery{
&FieldQuery{Field: "Name", Relation: VersionRegexp, Value: "a", Regexp: regexp.MustCompile("a")},
&NotQuery{Q: &FieldQuery{Field: "Name", Relation: VersionEqual, Value: "data"}},
}},
})
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)
result, err = s.il.Filter(FilterOptions{
Queries: []PackageQuery{&AndQuery{
&NotQuery{Q: &FieldQuery{Field: "Name", Relation: VersionEqual, Value: "data"}},
&FieldQuery{Field: "Name", Relation: VersionRegexp, Value: "a", Regexp: regexp.MustCompile("a")},
}},
})
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")
}

View File

@@ -596,7 +596,14 @@ func (repo *RemoteRepo) ApplyFilter(dependencyOptions int, filterQuery PackageQu
emptyList.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.Filter(FilterOptions{
Queries: []PackageQuery{filterQuery},
WithDependencies: repo.FilterWithDeps,
Source: emptyList,
DependencyOptions: dependencyOptions,
Architectures: repo.Architectures,
Progress: progress,
})
if repo.packageList != nil {
newLen = repo.packageList.Len()
}