diff --git a/aur_install_test.go b/aur_install_test.go index e850ab66..a9ee1ea6 100644 --- a/aur_install_test.go +++ b/aur_install_test.go @@ -116,7 +116,7 @@ func TestInstaller_InstallNeeded(t *testing.T) { return tc.isInstalled } - mockDB := &mock.DBExecutor{IsCorrectVersionInstalledFunc: isCorrectInstalledOverride} + mockDB := &mock.DBExecutor{IsCorrectVersionInstalledFn: isCorrectInstalledOverride} mockRunner := &exe.MockRunner{CaptureFn: captureOverride, ShowFn: showOverride} cmdBuilder := &exe.CmdBuilder{ MakepkgBin: makepkgBin, @@ -391,7 +391,7 @@ func TestInstaller_InstallMixedSourcesAndLayers(t *testing.T) { return false } - mockDB := &mock.DBExecutor{IsCorrectVersionInstalledFunc: isCorrectInstalledOverride} + mockDB := &mock.DBExecutor{IsCorrectVersionInstalledFn: isCorrectInstalledOverride} mockRunner := &exe.MockRunner{CaptureFn: captureOverride, ShowFn: showOverride} cmdBuilder := &exe.CmdBuilder{ MakepkgBin: makepkgBin, @@ -548,7 +548,7 @@ func TestInstaller_CompileFailed(t *testing.T) { return false } - mockDB := &mock.DBExecutor{IsCorrectVersionInstalledFunc: isCorrectInstalledOverride} + mockDB := &mock.DBExecutor{IsCorrectVersionInstalledFn: isCorrectInstalledOverride} mockRunner := &exe.MockRunner{CaptureFn: captureOverride, ShowFn: showOverride} cmdBuilder := &exe.CmdBuilder{ MakepkgBin: makepkgBin, @@ -706,7 +706,7 @@ func TestInstaller_InstallSplitPackage(t *testing.T) { return false } - mockDB := &mock.DBExecutor{IsCorrectVersionInstalledFunc: isCorrectInstalledOverride} + mockDB := &mock.DBExecutor{IsCorrectVersionInstalledFn: isCorrectInstalledOverride} mockRunner := &exe.MockRunner{CaptureFn: captureOverride, ShowFn: showOverride} cmdBuilder := &exe.CmdBuilder{ MakepkgBin: makepkgBin, diff --git a/local_install.go b/local_install.go index 7cd5ee1c..b24c6ada 100644 --- a/local_install.go +++ b/local_install.go @@ -6,6 +6,7 @@ import ( "context" "os" "path/filepath" + "strings" "github.com/Jguer/yay/v11/pkg/db" "github.com/Jguer/yay/v11/pkg/dep" @@ -27,12 +28,13 @@ func installLocalPKGBUILD( dbExecutor db.Executor, ) error { aurCache := config.Runtime.AURCache + noCheck := strings.Contains(config.MFlags, "--nocheck") if len(cmdArgs.Targets) < 1 { return errors.New(gotext.Get("no target directories specified")) } - grapher := dep.NewGrapher(dbExecutor, aurCache, false, settings.NoConfirm, os.Stdout) + grapher := dep.NewGrapher(dbExecutor, aurCache, false, settings.NoConfirm, os.Stdout, cmdArgs.ExistsDouble("d", "nodeps"), noCheck) graph := topo.New[string, *dep.InstallInfo]() for _, target := range cmdArgs.Targets { var errG error diff --git a/pkg/cmd/graph/main.go b/pkg/cmd/graph/main.go index 77ed1290..ae0bd0f9 100644 --- a/pkg/cmd/graph/main.go +++ b/pkg/cmd/graph/main.go @@ -45,7 +45,7 @@ func handleCmd() error { return errors.Wrap(err, gotext.Get("failed to retrieve aur Cache")) } - grapher := dep.NewGrapher(dbExecutor, aurCache, true, settings.NoConfirm, os.Stdout) + grapher := dep.NewGrapher(dbExecutor, aurCache, true, settings.NoConfirm, os.Stdout, cmdArgs.ExistsDouble("d", "nodeps"), false) return graphPackage(context.Background(), grapher, cmdArgs.Targets) } diff --git a/pkg/db/mock/executor.go b/pkg/db/mock/executor.go index cd22c405..b72ef2d0 100644 --- a/pkg/db/mock/executor.go +++ b/pkg/db/mock/executor.go @@ -16,65 +16,76 @@ type ( type DBExecutor struct { db.Executor - IsCorrectVersionInstalledFunc func(string, string) bool + IsCorrectVersionInstalledFn func(string, string) bool + SyncPackageFn func(string) IPackage + PackagesFromGroupFn func(string) []IPackage + LocalSatisfierExistsFn func(string) bool + SyncSatisfierFn func(string) IPackage } -func (t DBExecutor) AlpmArchitectures() ([]string, error) { +func (t *DBExecutor) AlpmArchitectures() ([]string, error) { panic("implement me") } -func (t DBExecutor) BiggestPackages() []IPackage { +func (t *DBExecutor) BiggestPackages() []IPackage { panic("implement me") } -func (t DBExecutor) Cleanup() { +func (t *DBExecutor) Cleanup() { panic("implement me") } -func (t DBExecutor) IsCorrectVersionInstalled(s, s2 string) bool { - if t.IsCorrectVersionInstalledFunc != nil { - return t.IsCorrectVersionInstalledFunc(s, s2) +func (t *DBExecutor) IsCorrectVersionInstalled(s, s2 string) bool { + if t.IsCorrectVersionInstalledFn != nil { + return t.IsCorrectVersionInstalledFn(s, s2) } panic("implement me") } -func (t DBExecutor) LastBuildTime() time.Time { +func (t *DBExecutor) LastBuildTime() time.Time { panic("implement me") } -func (t DBExecutor) LocalPackage(s string) IPackage { +func (t *DBExecutor) LocalPackage(s string) IPackage { return nil } -func (t DBExecutor) LocalPackages() []IPackage { +func (t *DBExecutor) LocalPackages() []IPackage { panic("implement me") } -func (t DBExecutor) LocalSatisfierExists(s string) bool { +func (t *DBExecutor) LocalSatisfierExists(s string) bool { + if t.LocalSatisfierExistsFn != nil { + return t.LocalSatisfierExistsFn(s) + } panic("implement me") } -func (t DBExecutor) PackageConflicts(iPackage IPackage) []Depend { +func (t *DBExecutor) PackageConflicts(iPackage IPackage) []Depend { panic("implement me") } -func (t DBExecutor) PackageDepends(iPackage IPackage) []Depend { +func (t *DBExecutor) PackageDepends(iPackage IPackage) []Depend { panic("implement me") } -func (t DBExecutor) PackageGroups(iPackage IPackage) []string { +func (t *DBExecutor) PackageGroups(iPackage IPackage) []string { return []string{} } -func (t DBExecutor) PackageOptionalDepends(iPackage IPackage) []Depend { +func (t *DBExecutor) PackageOptionalDepends(iPackage IPackage) []Depend { panic("implement me") } -func (t DBExecutor) PackageProvides(iPackage IPackage) []Depend { +func (t *DBExecutor) PackageProvides(iPackage IPackage) []Depend { panic("implement me") } -func (t DBExecutor) PackagesFromGroup(s string) []IPackage { +func (t *DBExecutor) PackagesFromGroup(s string) []IPackage { + if t.PackagesFromGroupFn != nil { + return t.PackagesFromGroupFn(s) + } + panic("implement me") } @@ -95,6 +106,9 @@ func (t DBExecutor) SatisfierFromDB(s, s2 string) IPackage { } func (t DBExecutor) SyncPackage(s string) IPackage { + if t.SyncPackageFn != nil { + return t.SyncPackageFn(s) + } panic("implement me") } @@ -103,6 +117,9 @@ func (t DBExecutor) SyncPackages(s ...string) []IPackage { } func (t DBExecutor) SyncSatisfier(s string) IPackage { + if t.SyncSatisfierFn != nil { + return t.SyncSatisfierFn(s) + } panic("implement me") } diff --git a/pkg/db/mock/repo.go b/pkg/db/mock/repo.go index f9445c16..29bbd77d 100644 --- a/pkg/db/mock/repo.go +++ b/pkg/db/mock/repo.go @@ -88,7 +88,7 @@ func (p *Package) Conflicts() alpm.DependList { // Depends returns the package's dependency list. func (p *Package) Depends() alpm.DependList { - panic("not implemented") // TODO: Implement + return alpm.DependList{} } // Depends returns the package's optional dependency list. diff --git a/pkg/dep/depGraph.go b/pkg/dep/dep_graph.go similarity index 94% rename from pkg/dep/depGraph.go rename to pkg/dep/dep_graph.go index 142a5d6f..84175bd5 100644 --- a/pkg/dep/depGraph.go +++ b/pkg/dep/dep_graph.go @@ -89,18 +89,24 @@ var colorMap = map[Reason]string{ CheckDep: "forestgreen", } +type AURCache interface { + Get(ctx context.Context, query *metadata.AURQuery) ([]*aurc.Pkg, error) +} + type Grapher struct { - dbExecutor db.Executor - aurCache *metadata.Client - fullGraph bool // If true, the graph will include all dependencies including already installed ones or repo - noConfirm bool - w io.Writer // output writer + dbExecutor db.Executor + aurCache AURCache + fullGraph bool // If true, the graph will include all dependencies including already installed ones or repo + noConfirm bool + noDeps bool // If true, the graph will not include dependencies + noCheckDeps bool // If true, the graph will not include dependencies + w io.Writer // output writer providerCache map[string]*aur.Pkg } -func NewGrapher(dbExecutor db.Executor, aurCache *metadata.Client, - fullGraph, noConfirm bool, output io.Writer, +func NewGrapher(dbExecutor db.Executor, aurCache AURCache, + fullGraph, noConfirm bool, output io.Writer, noDeps bool, noCheckDeps bool, ) *Grapher { return &Grapher{ dbExecutor: dbExecutor, @@ -108,6 +114,8 @@ func NewGrapher(dbExecutor db.Executor, aurCache *metadata.Client, fullGraph: fullGraph, noConfirm: noConfirm, w: output, + noDeps: noDeps, + noCheckDeps: noCheckDeps, providerCache: make(map[string]*aurc.Pkg, 5), } } @@ -226,11 +234,11 @@ func (g *Grapher) addDepNodes(ctx context.Context, pkg *aur.Pkg, graph *topo.Gra g.addNodes(ctx, graph, pkg.Name, pkg.MakeDepends, MakeDep) } - if !false && len(pkg.Depends) > 0 { + if !g.noDeps && len(pkg.Depends) > 0 { g.addNodes(ctx, graph, pkg.Name, pkg.Depends, Dep) } - if !false && len(pkg.CheckDepends) > 0 { + if !g.noCheckDeps && !g.noDeps && len(pkg.CheckDepends) > 0 { g.addNodes(ctx, graph, pkg.Name, pkg.CheckDepends, CheckDep) } } diff --git a/pkg/dep/dep_graph_test.go b/pkg/dep/dep_graph_test.go new file mode 100644 index 00000000..dc72d859 --- /dev/null +++ b/pkg/dep/dep_graph_test.go @@ -0,0 +1,217 @@ +package dep + +import ( + "context" + "encoding/json" + "io" + "os" + "testing" + + "github.com/Jguer/yay/v11/pkg/db" + "github.com/Jguer/yay/v11/pkg/db/mock" + aur "github.com/Jguer/yay/v11/pkg/query" + + "github.com/Jguer/aur/metadata" + "github.com/stretchr/testify/require" +) + +func ptrString(s string) *string { + return &s +} + +type getFunc func(ctx context.Context, query *metadata.AURQuery) ([]*aur.Pkg, error) + +type MockAUR struct { + GetFn getFunc +} + +func (m *MockAUR) Get(ctx context.Context, query *metadata.AURQuery) ([]*aur.Pkg, error) { + if m.GetFn != nil { + return m.GetFn(ctx, query) + } + + panic("implement me") +} + +func getFromFile(t *testing.T, filePath string) getFunc { + f, err := os.Open(filePath) + require.NoError(t, err) + + fBytes, err := io.ReadAll(f) + require.NoError(t, err) + + pkgs := []*aur.Pkg{} + err = json.Unmarshal(fBytes, &pkgs) + require.NoError(t, err) + + return func(ctx context.Context, query *metadata.AURQuery) ([]*aur.Pkg, error) { + return pkgs, nil + } +} + +func TestGrapher_GraphFromTargets_jellyfin(t *testing.T) { + mockDB := &mock.DBExecutor{ + SyncPackageFn: func(string) mock.IPackage { return nil }, + SyncSatisfierFn: func(s string) mock.IPackage { + switch s { + case "jellyfin": + return nil + case "dotnet-runtime-6.0": + return &mock.Package{ + PName: "dotnet-runtime-6.0", + PBase: "dotnet-runtime-6.0", + PVersion: "6.0.100-1", + PDB: mock.NewDB("community"), + } + case "dotnet-sdk-6.0": + return &mock.Package{ + PName: "dotnet-sdk-6.0", + PBase: "dotnet-sdk-6.0", + PVersion: "6.0.100-1", + PDB: mock.NewDB("community"), + } + } + + return nil + }, + PackagesFromGroupFn: func(string) []mock.IPackage { return nil }, + LocalSatisfierExistsFn: func(s string) bool { + switch s { + case "dotnet-sdk-6.0", "dotnet-runtime-6.0", "jellyfin-server=10.8.8", "jellyfin-web=10.8.8": + return false + } + + return true + }, + } + + mockAUR := &MockAUR{GetFn: func(ctx context.Context, query *metadata.AURQuery) ([]*aur.Pkg, error) { + if query.Needles[0] == "jellyfin" { + jfinFn := getFromFile(t, "testdata/jellyfin.json") + return jfinFn(ctx, query) + } + + if query.Needles[0] == "jellyfin-web" { + jfinWebFn := getFromFile(t, "testdata/jellyfin-web.json") + return jfinWebFn(ctx, query) + } + + if query.Needles[0] == "jellyfin-server" { + jfinServerFn := getFromFile(t, "testdata/jellyfin-server.json") + return jfinServerFn(ctx, query) + } + + panic("implement me") + }} + + type fields struct { + dbExecutor db.Executor + aurCache AURCache + noDeps bool + noCheckDeps bool + } + type args struct { + targets []string + } + tests := []struct { + name string + fields fields + args args + want []map[string]*InstallInfo + wantErr bool + }{ + { + name: "noDeps", + fields: fields{ + dbExecutor: mockDB, + aurCache: mockAUR, + noDeps: true, + noCheckDeps: false, + }, + args: args{ + targets: []string{"jellyfin"}, + }, + want: []map[string]*InstallInfo{ + { + "jellyfin": { + Source: AUR, + Reason: Explicit, + Version: "10.8.8-1", + AURBase: ptrString("jellyfin"), + }, + }, + { + "dotnet-sdk-6.0": { + Source: Sync, + Reason: MakeDep, + Version: "6.0.100-1", + SyncDBName: ptrString("community"), + }, + }, + }, + wantErr: false, + }, + { + name: "deps", + fields: fields{ + dbExecutor: mockDB, + aurCache: mockAUR, + noDeps: false, + noCheckDeps: false, + }, + args: args{ + targets: []string{"jellyfin"}, + }, + want: []map[string]*InstallInfo{ + { + "jellyfin": { + Source: AUR, + Reason: Explicit, + Version: "10.8.8-1", + AURBase: ptrString("jellyfin"), + }, + }, + { + "jellyfin-web": { + Source: AUR, + Reason: Dep, + Version: "10.8.8-1", + AURBase: ptrString("jellyfin"), + }, + "jellyfin-server": { + Source: AUR, + Reason: Dep, + Version: "10.8.8-1", + AURBase: ptrString("jellyfin"), + }, + }, + { + "dotnet-sdk-6.0": { + Source: Sync, + Reason: MakeDep, + Version: "6.0.100-1", + SyncDBName: ptrString("community"), + }, + "dotnet-runtime-6.0": { + Source: Sync, + Reason: Dep, + Version: "6.0.100-1", + SyncDBName: ptrString("community"), + }, + }, + }, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + g := NewGrapher(tt.fields.dbExecutor, + tt.fields.aurCache, false, true, os.Stdout, + tt.fields.noDeps, tt.fields.noCheckDeps) + got, err := g.GraphFromTargets(context.Background(), nil, tt.args.targets) + require.NoError(t, err) + layers := got.TopoSortedLayerMap() + require.EqualValues(t, tt.want, layers, layers) + }) + } +} diff --git a/pkg/dep/testdata/jellyfin-server.json b/pkg/dep/testdata/jellyfin-server.json new file mode 100644 index 00000000..b492a92a --- /dev/null +++ b/pkg/dep/testdata/jellyfin-server.json @@ -0,0 +1,3 @@ +[ + {"ID":1176791,"Name":"jellyfin-server","PackageBaseID":138631,"PackageBase":"jellyfin","Version":"10.8.8-1","Description":"Jellyfin server component","URL":"https://github.com/jellyfin/jellyfin","NumVotes":84,"Popularity":1.272964,"OutOfDate":null,"Maintainer":"z3ntu","Submitter":"z3ntu","FirstSubmitted":1547053171,"LastModified":1669830147,"URLPath":"/cgit/aur.git/snapshot/jellyfin-server.tar.gz","Depends":["dotnet-runtime-6.0","aspnet-runtime-6.0","ffmpeg","sqlite"],"MakeDepends":["dotnet-sdk-6.0","nodejs","npm","git"],"License":["GPL2"]} +] \ No newline at end of file diff --git a/pkg/dep/testdata/jellyfin-web.json b/pkg/dep/testdata/jellyfin-web.json new file mode 100644 index 00000000..83912bae --- /dev/null +++ b/pkg/dep/testdata/jellyfin-web.json @@ -0,0 +1,3 @@ +[ +{"ID":1176790,"Name":"jellyfin-web","PackageBaseID":138631,"PackageBase":"jellyfin","Version":"10.8.8-1","Description":"Jellyfin web client","URL":"https://github.com/jellyfin/jellyfin","NumVotes":84,"Popularity":1.272964,"OutOfDate":null,"Maintainer":"z3ntu","Submitter":"z3ntu","FirstSubmitted":1547053171,"LastModified":1669830147,"URLPath":"/cgit/aur.git/snapshot/jellyfin-web.tar.gz","MakeDepends":["dotnet-sdk-6.0","nodejs","npm","git"],"License":["GPL2"]} +] \ No newline at end of file diff --git a/pkg/dep/testdata/jellyfin.json b/pkg/dep/testdata/jellyfin.json new file mode 100644 index 00000000..d73354b5 --- /dev/null +++ b/pkg/dep/testdata/jellyfin.json @@ -0,0 +1,3 @@ +[ + {"ID":1176789,"Name":"jellyfin","PackageBaseID":138631,"PackageBase":"jellyfin","Version":"10.8.8-1","Description":"The Free Software Media System","URL":"https://github.com/jellyfin/jellyfin","NumVotes":84,"Popularity":1.272964,"OutOfDate":null,"Maintainer":"z3ntu","Submitter":"z3ntu","FirstSubmitted":1547053171,"LastModified":1669830147,"URLPath":"/cgit/aur.git/snapshot/jellyfin.tar.gz","Depends":["jellyfin-web=10.8.8","jellyfin-server=10.8.8"],"MakeDepends":["dotnet-sdk-6.0","nodejs","npm","git"],"License":["GPL2"]} +] \ No newline at end of file diff --git a/pkg/query/types_test.go b/pkg/query/types_test.go index c83de0d7..69a3c6a8 100644 --- a/pkg/query/types_test.go +++ b/pkg/query/types_test.go @@ -134,7 +134,7 @@ func Test_aurQuery_printSearch(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { w := &strings.Builder{} - executor := mock.DBExecutor{} + executor := &mock.DBExecutor{} text.UseColor = tt.useColor // Fire @@ -236,7 +236,7 @@ func Test_repoQuery_printSearch(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { w := &strings.Builder{} - executor := mock.DBExecutor{} + executor := &mock.DBExecutor{} text.UseColor = tt.useColor // Fire diff --git a/sync.go b/sync.go index b67224a4..1c79067d 100644 --- a/sync.go +++ b/sync.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "os" + "strings" "github.com/Jguer/yay/v11/pkg/completion" "github.com/Jguer/yay/v11/pkg/db" @@ -23,6 +24,11 @@ func syncInstall(ctx context.Context, ) error { aurCache := config.Runtime.AURCache refreshArg := cmdArgs.ExistsArg("y", "refresh") + noDeps := cmdArgs.ExistsArg("d", "nodeps") + noCheck := strings.Contains(config.MFlags, "--nocheck") + if noDeps { + config.Runtime.CmdBuilder.AddMakepkgFlag("-d") + } if refreshArg && config.Runtime.Mode.AtLeastRepo() { if errR := earlyRefresh(ctx, cmdArgs); errR != nil { @@ -36,7 +42,7 @@ func syncInstall(ctx context.Context, } } - grapher := dep.NewGrapher(dbExecutor, aurCache, false, settings.NoConfirm, os.Stdout) + grapher := dep.NewGrapher(dbExecutor, aurCache, false, settings.NoConfirm, os.Stdout, noDeps, noCheck) graph, err := grapher.GraphFromTargets(ctx, nil, cmdArgs.Targets) if err != nil {