feat: use the pubgrub algorithm for solving versions (#40)
* refactor: separate resolving tests * feat: use pubgrub to resolve dependencies * feat: show friendly mod name in error message * feat: show single version in error message when only one matches * ci: update go version to match go.mod * feat: format FactoryGame incompatibility and term * chore: fetch all necessary data of the version at once * chore: upgrade pubgrub * chore: upgrade pubgrub * ci: update golangci-lint version for go 1.21 * chore: lint * chore: update go version in readme
This commit is contained in:
parent
72a6094ad3
commit
024b11b1e8
16 changed files with 740 additions and 413 deletions
8
.github/workflows/push.yaml
vendored
8
.github/workflows/push.yaml
vendored
|
@ -10,7 +10,7 @@ jobs:
|
|||
- name: Set up Go
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: 1.18
|
||||
go-version: 1.21
|
||||
|
||||
- name: Check out code into the Go module directory
|
||||
uses: actions/checkout@v2
|
||||
|
@ -33,7 +33,7 @@ jobs:
|
|||
- name: Set up Go
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: 1.18
|
||||
go-version: 1.21
|
||||
|
||||
- name: Check out code into the Go module directory
|
||||
uses: actions/checkout@v2
|
||||
|
@ -47,7 +47,7 @@ jobs:
|
|||
- name: golangci-lint
|
||||
uses: golangci/golangci-lint-action@v2
|
||||
with:
|
||||
version: v1.51
|
||||
version: v1.54
|
||||
skip-pkg-cache: true
|
||||
skip-build-cache: true
|
||||
|
||||
|
@ -62,7 +62,7 @@ jobs:
|
|||
- name: Set up Go
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: 1.18
|
||||
go-version: 1.21
|
||||
|
||||
- name: Check out code into the Go module directory
|
||||
uses: actions/checkout@v2
|
||||
|
|
2
.github/workflows/release.yml
vendored
2
.github/workflows/release.yml
vendored
|
@ -13,7 +13,7 @@ jobs:
|
|||
- name: Set up Go
|
||||
uses: actions/setup-go@v2
|
||||
with:
|
||||
go-version: 1.18
|
||||
go-version: 1.21
|
||||
|
||||
- name: Check out code into the Go module directory
|
||||
uses: actions/checkout@v2
|
||||
|
|
|
@ -76,7 +76,7 @@ Run `ficsit help` to see a list of available commands.
|
|||
|
||||
### Dependencies
|
||||
|
||||
* [Go 1.18](https://go.dev/doc/install)
|
||||
* [Go 1.21](https://go.dev/doc/install)
|
||||
* IDE of Choice. Goland or VSCode suggested.
|
||||
|
||||
## Building
|
||||
|
|
|
@ -47,11 +47,11 @@ func InitCLI(apiOnly bool) (*GlobalContext, error) {
|
|||
|
||||
func (g *GlobalContext) Save() error {
|
||||
if err := g.Installations.Save(); err != nil {
|
||||
return err
|
||||
return errors.Wrap(err, "failed to save installations")
|
||||
}
|
||||
|
||||
if err := g.Profiles.Save(); err != nil {
|
||||
return err
|
||||
return errors.Wrap(err, "failed to save profiles")
|
||||
}
|
||||
|
||||
return nil
|
||||
|
|
|
@ -3,18 +3,19 @@ package cli
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strings"
|
||||
"slices"
|
||||
|
||||
"github.com/Khan/genqlient/graphql"
|
||||
"github.com/Masterminds/semver/v3"
|
||||
"github.com/mircearoata/pubgrub-go/pubgrub"
|
||||
"github.com/mircearoata/pubgrub-go/pubgrub/helpers"
|
||||
"github.com/mircearoata/pubgrub-go/pubgrub/semver"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/viper"
|
||||
|
||||
"github.com/satisfactorymodding/ficsit-cli/ficsit"
|
||||
)
|
||||
|
||||
const smlDownloadTemplate = `https://github.com/satisfactorymodding/SatisfactoryModLoader/releases/download/%s/SML.zip`
|
||||
const smlDownloadTemplate = `https://github.com/satisfactorymodding/SatisfactoryModLoader/releases/download/v%s/SML.zip`
|
||||
|
||||
type DependencyResolver struct {
|
||||
apiClient graphql.Client
|
||||
|
@ -24,320 +25,163 @@ func NewDependencyResolver(apiClient graphql.Client) DependencyResolver {
|
|||
return DependencyResolver{apiClient: apiClient}
|
||||
}
|
||||
|
||||
var (
|
||||
rootPkg = "$$root$$"
|
||||
smlPkg = "SML"
|
||||
factoryGamePkg = "FactoryGame"
|
||||
)
|
||||
|
||||
type ficsitAPISource struct {
|
||||
apiClient graphql.Client
|
||||
lockfile *LockFile
|
||||
toInstall map[string]semver.Constraint
|
||||
modVersionInfo map[string]ficsit.ModVersionsWithDependenciesResponse
|
||||
gameVersion semver.Version
|
||||
smlVersions []ficsit.SMLVersionsSmlVersionsGetSMLVersionsSml_versionsSMLVersion
|
||||
}
|
||||
|
||||
func (f *ficsitAPISource) GetPackageVersions(pkg string) ([]pubgrub.PackageVersion, error) {
|
||||
if pkg == rootPkg {
|
||||
return []pubgrub.PackageVersion{{Version: semver.Version{}, Dependencies: f.toInstall}}, nil
|
||||
}
|
||||
if pkg == factoryGamePkg {
|
||||
return []pubgrub.PackageVersion{{Version: f.gameVersion}}, nil
|
||||
}
|
||||
if pkg == smlPkg {
|
||||
versions := make([]pubgrub.PackageVersion, len(f.smlVersions))
|
||||
for i, smlVersion := range f.smlVersions {
|
||||
v, err := semver.NewVersion(smlVersion.Version)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to parse version %s", smlVersion.Version)
|
||||
}
|
||||
gameConstraint, err := semver.NewConstraint(fmt.Sprintf(">=%d", smlVersion.Satisfactory_version))
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to parse constraint %s", fmt.Sprintf(">=%d", smlVersion.Satisfactory_version))
|
||||
}
|
||||
versions[i] = pubgrub.PackageVersion{
|
||||
Version: v,
|
||||
Dependencies: map[string]semver.Constraint{
|
||||
factoryGamePkg: gameConstraint,
|
||||
},
|
||||
}
|
||||
}
|
||||
return versions, nil
|
||||
}
|
||||
response, err := ficsit.ModVersionsWithDependencies(context.TODO(), f.apiClient, pkg)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to fetch mod %s", pkg)
|
||||
}
|
||||
if response.Mod.Id == "" {
|
||||
return nil, errors.Errorf("mod %s not found", pkg)
|
||||
}
|
||||
f.modVersionInfo[pkg] = *response
|
||||
versions := make([]pubgrub.PackageVersion, len(response.Mod.Versions))
|
||||
for i, modVersion := range response.Mod.Versions {
|
||||
v, err := semver.NewVersion(modVersion.Version)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to parse version %s", modVersion.Version)
|
||||
}
|
||||
dependencies := make(map[string]semver.Constraint)
|
||||
optionalDependencies := make(map[string]semver.Constraint)
|
||||
for _, dependency := range modVersion.Dependencies {
|
||||
c, err := semver.NewConstraint(dependency.Condition)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to parse constraint %s", dependency.Condition)
|
||||
}
|
||||
if dependency.Optional {
|
||||
optionalDependencies[dependency.Mod_id] = c
|
||||
} else {
|
||||
dependencies[dependency.Mod_id] = c
|
||||
}
|
||||
}
|
||||
versions[i] = pubgrub.PackageVersion{
|
||||
Version: v,
|
||||
Dependencies: dependencies,
|
||||
OptionalDependencies: optionalDependencies,
|
||||
}
|
||||
}
|
||||
return versions, nil
|
||||
}
|
||||
|
||||
func (f *ficsitAPISource) PickVersion(pkg string, versions []semver.Version) semver.Version {
|
||||
if f.lockfile != nil {
|
||||
if existing, ok := (*f.lockfile)[pkg]; ok {
|
||||
v, err := semver.NewVersion(existing.Version)
|
||||
if err == nil {
|
||||
if slices.ContainsFunc(versions, func(version semver.Version) bool {
|
||||
return v.Compare(version) == 0
|
||||
}) {
|
||||
return v
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return helpers.StandardVersionPriority(versions)
|
||||
}
|
||||
|
||||
func (d DependencyResolver) ResolveModDependencies(constraints map[string]string, lockFile *LockFile, gameVersion int) (LockFile, error) {
|
||||
smlVersionsDB, err := ficsit.SMLVersions(context.TODO(), d.apiClient)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed fetching SMl versions")
|
||||
return nil, errors.Wrap(err, "failed fetching SML versions")
|
||||
}
|
||||
|
||||
copied := make(map[string][]string, len(constraints))
|
||||
for k, v := range constraints {
|
||||
copied[k] = []string{v}
|
||||
}
|
||||
|
||||
instance := &resolvingInstance{
|
||||
Resolver: d,
|
||||
InputLock: lockFile,
|
||||
ToResolve: copied,
|
||||
OutputLock: make(LockFile),
|
||||
SMLVersions: smlVersionsDB,
|
||||
GameVersion: gameVersion,
|
||||
}
|
||||
|
||||
if err := instance.Step(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return instance.OutputLock, nil
|
||||
}
|
||||
|
||||
type resolvingInstance struct {
|
||||
Resolver DependencyResolver
|
||||
|
||||
InputLock *LockFile
|
||||
|
||||
ToResolve map[string][]string
|
||||
|
||||
OutputLock LockFile
|
||||
|
||||
SMLVersions *ficsit.SMLVersionsResponse
|
||||
GameVersion int
|
||||
}
|
||||
|
||||
func (r *resolvingInstance) Step() error {
|
||||
if len(r.ToResolve) > 0 {
|
||||
if err := r.LockStep(make(map[string]bool)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
converted := make([]ficsit.ModVersionConstraint, 0)
|
||||
for id, constraint := range r.ToResolve {
|
||||
if id != "SML" {
|
||||
converted = append(converted, ficsit.ModVersionConstraint{
|
||||
ModIdOrReference: id,
|
||||
Version: constraint[0],
|
||||
})
|
||||
} else {
|
||||
if existingSML, ok := r.OutputLock[id]; ok {
|
||||
for _, cs := range constraint {
|
||||
smlVersionConstraint, _ := semver.NewConstraint(cs)
|
||||
if !smlVersionConstraint.Check(semver.MustParse(existingSML.Version)) {
|
||||
return errors.Errorf("mod %s version %s does not match constraint %s",
|
||||
id,
|
||||
existingSML.Version,
|
||||
constraint,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var chosenSMLVersion *semver.Version
|
||||
for _, version := range r.SMLVersions.SmlVersions.Sml_versions {
|
||||
if version.Satisfactory_version > r.GameVersion {
|
||||
continue
|
||||
}
|
||||
|
||||
currentVersion := semver.MustParse(version.Version)
|
||||
|
||||
matches := true
|
||||
for _, cs := range constraint {
|
||||
smlVersionConstraint, _ := semver.NewConstraint(cs)
|
||||
|
||||
if !smlVersionConstraint.Check(currentVersion) {
|
||||
matches = false
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if matches {
|
||||
if chosenSMLVersion == nil || currentVersion.GreaterThan(chosenSMLVersion) {
|
||||
chosenSMLVersion = currentVersion
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if chosenSMLVersion == nil {
|
||||
return errors.Errorf("could not find an SML version that matches constraint %s and game version %d", constraint, r.GameVersion)
|
||||
}
|
||||
|
||||
smlVersionStr := chosenSMLVersion.String()
|
||||
if !strings.HasPrefix(smlVersionStr, "v") {
|
||||
smlVersionStr = "v" + smlVersionStr
|
||||
}
|
||||
|
||||
r.OutputLock[id] = LockedMod{
|
||||
Version: chosenSMLVersion.String(),
|
||||
Link: fmt.Sprintf(smlDownloadTemplate, smlVersionStr),
|
||||
Dependencies: map[string]string{},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nextResolve := make(map[string][]string)
|
||||
|
||||
// TODO Cache
|
||||
dependencies, err := ficsit.ResolveModDependencies(context.TODO(), r.Resolver.apiClient, converted)
|
||||
gameVersionSemver, err := semver.NewVersion(fmt.Sprintf("%d", gameVersion))
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed resolving mod dependencies")
|
||||
return nil, errors.Wrap(err, "failed parsing game version")
|
||||
}
|
||||
|
||||
sort.Slice(dependencies.Mods, func(i, j int) bool {
|
||||
return dependencies.Mods[i].Mod_reference < dependencies.Mods[j].Mod_reference
|
||||
})
|
||||
|
||||
for _, mod := range dependencies.Mods {
|
||||
modVersions := make([]ModVersion, len(mod.Versions))
|
||||
for i, version := range mod.Versions {
|
||||
versionDependencies := make([]VersionDependency, len(version.Dependencies))
|
||||
|
||||
for j, dependency := range version.Dependencies {
|
||||
versionDependencies[j] = VersionDependency{
|
||||
ModReference: dependency.Mod_id,
|
||||
Constraint: dependency.Condition,
|
||||
Optional: dependency.Optional,
|
||||
toInstall := make(map[string]semver.Constraint, len(constraints))
|
||||
for k, v := range constraints {
|
||||
c, err := semver.NewConstraint(v)
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to parse constraint %s", v)
|
||||
}
|
||||
toInstall[k] = c
|
||||
}
|
||||
|
||||
modVersions[i] = ModVersion{
|
||||
ID: version.Id,
|
||||
Version: version.Version,
|
||||
Link: viper.GetString("api-base") + version.Link,
|
||||
Hash: version.Hash,
|
||||
Dependencies: versionDependencies,
|
||||
}
|
||||
ficsitSource := &ficsitAPISource{
|
||||
apiClient: d.apiClient,
|
||||
smlVersions: smlVersionsDB.SmlVersions.Sml_versions,
|
||||
gameVersion: gameVersionSemver,
|
||||
lockfile: lockFile,
|
||||
toInstall: toInstall,
|
||||
modVersionInfo: make(map[string]ficsit.ModVersionsWithDependenciesResponse),
|
||||
}
|
||||
|
||||
sort.Slice(modVersions, func(i, j int) bool {
|
||||
a := semver.MustParse(modVersions[i].Version)
|
||||
b := semver.MustParse(modVersions[j].Version)
|
||||
return b.LessThan(a)
|
||||
})
|
||||
result, err := pubgrub.Solve(helpers.NewCachingSource(ficsitSource), rootPkg)
|
||||
if err != nil {
|
||||
finalError := err
|
||||
var solverErr pubgrub.SolvingError
|
||||
if errors.As(err, &solverErr) {
|
||||
finalError = DependencyResolverError{SolvingError: solverErr, apiClient: d.apiClient, smlVersions: smlVersionsDB.SmlVersions.Sml_versions, gameVersion: gameVersion}
|
||||
}
|
||||
return nil, errors.Wrap(finalError, "failed to solve dependencies")
|
||||
}
|
||||
delete(result, rootPkg)
|
||||
delete(result, factoryGamePkg)
|
||||
|
||||
// Pick latest version
|
||||
// TODO Clone and branch
|
||||
var selectedVersion ModVersion
|
||||
for _, version := range modVersions {
|
||||
matches := true
|
||||
|
||||
for _, cs := range r.ToResolve[mod.Mod_reference] {
|
||||
resolvingConstraint, _ := semver.NewConstraint(cs)
|
||||
if !resolvingConstraint.Check(semver.MustParse(version.Version)) {
|
||||
matches = false
|
||||
outputLock := make(LockFile, len(result))
|
||||
for k, v := range result {
|
||||
if k == smlPkg {
|
||||
outputLock[k] = LockedMod{
|
||||
Version: v.String(),
|
||||
Hash: "",
|
||||
Link: fmt.Sprintf(smlDownloadTemplate, v.String()),
|
||||
}
|
||||
continue
|
||||
}
|
||||
versions := ficsitSource.modVersionInfo[k].Mod.Versions
|
||||
for _, ver := range versions {
|
||||
if ver.Version == v.RawString() {
|
||||
outputLock[k] = LockedMod{
|
||||
Version: v.String(),
|
||||
Hash: ver.Hash,
|
||||
Link: viper.GetString("api-base") + ver.Link,
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if matches {
|
||||
selectedVersion = version
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if selectedVersion.Version == "" {
|
||||
return errors.Errorf("no version of %s matches constraints", mod.Mod_reference)
|
||||
}
|
||||
|
||||
if _, ok := r.OutputLock[mod.Mod_reference]; ok {
|
||||
if r.OutputLock[mod.Mod_reference].Version != selectedVersion.Version {
|
||||
return errors.New("failed resolving dependencies. requires different versions of " + mod.Mod_reference)
|
||||
}
|
||||
}
|
||||
|
||||
modDependencies := make(map[string]string)
|
||||
for _, dependency := range selectedVersion.Dependencies {
|
||||
if !dependency.Optional {
|
||||
modDependencies[dependency.ModReference] = dependency.Constraint
|
||||
}
|
||||
}
|
||||
|
||||
r.OutputLock[mod.Mod_reference] = LockedMod{
|
||||
Version: selectedVersion.Version,
|
||||
Hash: selectedVersion.Hash,
|
||||
Link: selectedVersion.Link,
|
||||
Dependencies: modDependencies,
|
||||
}
|
||||
|
||||
for _, dependency := range selectedVersion.Dependencies {
|
||||
if previousSelectedVersion, ok := r.OutputLock[dependency.ModReference]; ok {
|
||||
constraint, _ := semver.NewConstraint(dependency.Constraint)
|
||||
if !constraint.Check(semver.MustParse(previousSelectedVersion.Version)) {
|
||||
return errors.Errorf("mod %s version %s does not match constraint %s",
|
||||
dependency.ModReference,
|
||||
previousSelectedVersion.Version,
|
||||
dependency.Constraint,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
if resolving, ok := nextResolve[dependency.ModReference]; ok {
|
||||
constraint, _ := semver.NewConstraint(dependency.Constraint)
|
||||
|
||||
for _, cs := range resolving {
|
||||
resolvingConstraint, _ := semver.NewConstraint(cs)
|
||||
intersects, _ := constraint.Intersects(resolvingConstraint)
|
||||
if !intersects {
|
||||
return errors.Errorf("mod %s constraint %s does not intersect with %s",
|
||||
dependency.ModReference,
|
||||
resolving,
|
||||
dependency.Constraint,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if dependency.Optional {
|
||||
continue
|
||||
}
|
||||
|
||||
nextResolve[dependency.ModReference] = append(nextResolve[dependency.ModReference], dependency.Constraint)
|
||||
}
|
||||
}
|
||||
|
||||
r.ToResolve = nextResolve
|
||||
|
||||
for _, constraint := range converted {
|
||||
if _, ok := r.OutputLock[constraint.ModIdOrReference]; !ok {
|
||||
return errors.New("failed resolving dependency: " + constraint.ModIdOrReference)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if len(r.ToResolve) > 0 {
|
||||
if err := r.Step(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *resolvingInstance) LockStep(viewed map[string]bool) error {
|
||||
added := false
|
||||
if r.InputLock != nil {
|
||||
for modReference, constraints := range r.ToResolve {
|
||||
if _, ok := viewed[modReference]; ok {
|
||||
continue
|
||||
}
|
||||
|
||||
viewed[modReference] = true
|
||||
|
||||
if locked, ok := (*r.InputLock)[modReference]; ok {
|
||||
passes := true
|
||||
|
||||
for _, cs := range constraints {
|
||||
constraint, _ := semver.NewConstraint(cs)
|
||||
if !constraint.Check(semver.MustParse(locked.Version)) {
|
||||
passes = false
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if passes {
|
||||
delete(r.ToResolve, modReference)
|
||||
r.OutputLock[modReference] = locked
|
||||
for k, v := range locked.Dependencies {
|
||||
if alreadyResolving, ok := r.ToResolve[k]; ok {
|
||||
newConstraint, _ := semver.NewConstraint(v)
|
||||
for _, resolvingConstraint := range alreadyResolving {
|
||||
cs2, _ := semver.NewConstraint(resolvingConstraint)
|
||||
intersects, _ := newConstraint.Intersects(cs2)
|
||||
if !intersects {
|
||||
return errors.Errorf("mod %s constraint %s does not intersect with %s",
|
||||
k,
|
||||
v,
|
||||
alreadyResolving,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
r.ToResolve[k] = append(r.ToResolve[k], v)
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
if outVersion, ok := r.OutputLock[k]; ok {
|
||||
constraint, _ := semver.NewConstraint(v)
|
||||
if !constraint.Check(semver.MustParse(outVersion.Version)) {
|
||||
return errors.Errorf("mod %s version %s does not match constraint %s",
|
||||
k,
|
||||
outVersion.Version,
|
||||
v,
|
||||
)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
r.ToResolve[k] = append(r.ToResolve[k], v)
|
||||
added = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if added {
|
||||
if err := r.LockStep(viewed); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
return outputLock, nil
|
||||
}
|
||||
|
|
134
cli/dependency_resolver_error.go
Normal file
134
cli/dependency_resolver_error.go
Normal file
|
@ -0,0 +1,134 @@
|
|||
package cli
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/Khan/genqlient/graphql"
|
||||
"github.com/mircearoata/pubgrub-go/pubgrub"
|
||||
"github.com/mircearoata/pubgrub-go/pubgrub/semver"
|
||||
|
||||
"github.com/satisfactorymodding/ficsit-cli/ficsit"
|
||||
)
|
||||
|
||||
type DependencyResolverError struct {
|
||||
pubgrub.SolvingError
|
||||
apiClient graphql.Client
|
||||
smlVersions []ficsit.SMLVersionsSmlVersionsGetSMLVersionsSml_versionsSMLVersion
|
||||
gameVersion int
|
||||
}
|
||||
|
||||
func (e DependencyResolverError) Error() string {
|
||||
rootPkg := e.Cause().Terms()[0].Dependency()
|
||||
writer := pubgrub.NewStandardErrorWriter(rootPkg).
|
||||
WithIncompatibilityStringer(
|
||||
MakeDependencyResolverErrorStringer(e.apiClient, e.smlVersions, e.gameVersion),
|
||||
)
|
||||
e.WriteTo(writer)
|
||||
return writer.String()
|
||||
}
|
||||
|
||||
type DependencyResolverErrorStringer struct {
|
||||
pubgrub.StandardIncompatibilityStringer
|
||||
apiClient graphql.Client
|
||||
packageNames map[string]string
|
||||
smlVersions []ficsit.SMLVersionsSmlVersionsGetSMLVersionsSml_versionsSMLVersion
|
||||
gameVersion int
|
||||
}
|
||||
|
||||
func MakeDependencyResolverErrorStringer(apiClient graphql.Client, smlVersions []ficsit.SMLVersionsSmlVersionsGetSMLVersionsSml_versionsSMLVersion, gameVersion int) *DependencyResolverErrorStringer {
|
||||
s := &DependencyResolverErrorStringer{
|
||||
apiClient: apiClient,
|
||||
smlVersions: smlVersions,
|
||||
gameVersion: gameVersion,
|
||||
packageNames: map[string]string{},
|
||||
}
|
||||
s.StandardIncompatibilityStringer = pubgrub.NewStandardIncompatibilityStringer().WithTermStringer(s)
|
||||
return s
|
||||
}
|
||||
|
||||
func (w *DependencyResolverErrorStringer) getPackageName(pkg string) string {
|
||||
if pkg == smlPkg {
|
||||
return "SML"
|
||||
}
|
||||
if pkg == factoryGamePkg {
|
||||
return "Satisfactory"
|
||||
}
|
||||
if name, ok := w.packageNames[pkg]; ok {
|
||||
return name
|
||||
}
|
||||
result, err := ficsit.GetModName(context.Background(), w.apiClient, pkg)
|
||||
if err != nil {
|
||||
return pkg
|
||||
}
|
||||
w.packageNames[pkg] = result.Mod.Name
|
||||
return result.Mod.Name
|
||||
}
|
||||
|
||||
func (w *DependencyResolverErrorStringer) Term(t pubgrub.Term, includeVersion bool) string {
|
||||
name := w.getPackageName(t.Dependency())
|
||||
fullName := fmt.Sprintf("%s (%s)", name, t.Dependency())
|
||||
if name == t.Dependency() {
|
||||
fullName = t.Dependency()
|
||||
}
|
||||
if includeVersion {
|
||||
if t.Constraint().IsAny() {
|
||||
return fmt.Sprintf("every version of %s", fullName)
|
||||
}
|
||||
switch t.Dependency() {
|
||||
case factoryGamePkg:
|
||||
// Remove ".0.0" from the versions mentioned, since only the major is ever used
|
||||
return fmt.Sprintf("%s \"%s\"", fullName, strings.ReplaceAll(t.Constraint().String(), ".0.0", ""))
|
||||
case smlPkg:
|
||||
var matched []semver.Version
|
||||
for _, v := range w.smlVersions {
|
||||
ver, err := semver.NewVersion(v.Version)
|
||||
if err != nil {
|
||||
// Assume it is contained in the constraint
|
||||
matched = append(matched, semver.Version{})
|
||||
continue
|
||||
}
|
||||
if t.Constraint().Contains(ver) {
|
||||
matched = append(matched, ver)
|
||||
}
|
||||
}
|
||||
if len(matched) == 1 {
|
||||
return fmt.Sprintf("%s \"%s\"", fullName, matched[0])
|
||||
}
|
||||
return fmt.Sprintf("%s \"%s\"", fullName, t.Constraint())
|
||||
default:
|
||||
res, err := ficsit.ModVersions(context.Background(), w.apiClient, t.Dependency(), ficsit.VersionFilter{
|
||||
Limit: 100,
|
||||
})
|
||||
if err != nil {
|
||||
return fmt.Sprintf("%s \"%s\"", fullName, t.Constraint())
|
||||
}
|
||||
var matched []semver.Version
|
||||
for _, v := range res.Mod.Versions {
|
||||
ver, err := semver.NewVersion(v.Version)
|
||||
if err != nil {
|
||||
// Assume it is contained in the constraint
|
||||
matched = append(matched, semver.Version{})
|
||||
continue
|
||||
}
|
||||
if t.Constraint().Contains(ver) {
|
||||
matched = append(matched, ver)
|
||||
}
|
||||
}
|
||||
if len(matched) == 1 {
|
||||
return fmt.Sprintf("%s \"%s\"", fullName, matched[0])
|
||||
}
|
||||
return fmt.Sprintf("%s \"%s\"", fullName, t.Constraint())
|
||||
}
|
||||
}
|
||||
return fullName
|
||||
}
|
||||
|
||||
func (w *DependencyResolverErrorStringer) IncompatibilityString(incompatibility *pubgrub.Incompatibility, rootPkg string) string {
|
||||
terms := incompatibility.Terms()
|
||||
if len(terms) == 1 && terms[0].Dependency() == factoryGamePkg {
|
||||
return fmt.Sprintf("Satisfactory CL%d is installed", w.gameVersion)
|
||||
}
|
||||
return w.StandardIncompatibilityStringer.IncompatibilityString(incompatibility, rootPkg)
|
||||
}
|
|
@ -175,7 +175,7 @@ func (l *ftpDisk) IsExist(err error) bool {
|
|||
return strings.Contains(err.Error(), "Create directory operation failed")
|
||||
}
|
||||
|
||||
func (l *ftpDisk) Open(path string, flag int) (io.WriteCloser, error) {
|
||||
func (l *ftpDisk) Open(path string, _ int) (io.WriteCloser, error) {
|
||||
reader, writer := io.Pipe()
|
||||
|
||||
log.Debug().Str("path", path).Str("schema", "ftp").Msg("opening for writing")
|
||||
|
|
|
@ -14,38 +14,38 @@ func newSFTP(path string) (Disk, error) {
|
|||
return sftpDisk{path: path}, nil
|
||||
}
|
||||
|
||||
func (l sftpDisk) Exists(path string) error {
|
||||
func (l sftpDisk) Exists(path string) error { //nolint
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (l sftpDisk) Read(path string) ([]byte, error) {
|
||||
func (l sftpDisk) Read(path string) ([]byte, error) { //nolint
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (l sftpDisk) Write(path string, data []byte) error {
|
||||
func (l sftpDisk) Write(path string, data []byte) error { //nolint
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (l sftpDisk) Remove(path string) error {
|
||||
func (l sftpDisk) Remove(path string) error { //nolint
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (l sftpDisk) MkDir(path string) error {
|
||||
func (l sftpDisk) MkDir(path string) error { //nolint
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (l sftpDisk) ReadDir(path string) ([]Entry, error) {
|
||||
func (l sftpDisk) ReadDir(path string) ([]Entry, error) { //nolint
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (l sftpDisk) IsNotExist(err error) bool {
|
||||
func (l sftpDisk) IsNotExist(err error) bool { //nolint
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (l sftpDisk) IsExist(err error) bool {
|
||||
func (l sftpDisk) IsExist(err error) bool { //nolint
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (l sftpDisk) Open(path string, flag int) (io.WriteCloser, error) {
|
||||
func (l sftpDisk) Open(path string, flag int) (io.WriteCloser, error) { //nolint
|
||||
panic("implement me")
|
||||
}
|
||||
|
|
|
@ -435,11 +435,7 @@ func (i *Installation) Install(ctx *GlobalContext, updates chan InstallUpdate) e
|
|||
completed++
|
||||
}
|
||||
|
||||
if err := i.WriteLockFile(ctx, lockfile); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
return i.WriteLockFile(ctx, lockfile)
|
||||
}
|
||||
|
||||
func (i *Installation) SetProfile(ctx *GlobalContext, profile string) error {
|
||||
|
@ -520,9 +516,8 @@ func (i *Installation) GetPlatform(ctx *GlobalContext) (*Platform, error) {
|
|||
if err != nil {
|
||||
if d.IsNotExist(err) {
|
||||
continue
|
||||
} else {
|
||||
return nil, errors.Wrap(err, "failed detecting version file")
|
||||
}
|
||||
return nil, errors.Wrap(err, "failed detecting version file")
|
||||
}
|
||||
return &platform, nil
|
||||
}
|
||||
|
|
|
@ -7,11 +7,17 @@ import (
|
|||
"github.com/MarvinJWendt/testza"
|
||||
)
|
||||
|
||||
func TestProfileResolution(t *testing.T) {
|
||||
func profilesGetResolver() DependencyResolver {
|
||||
ctx, err := InitCLI(false)
|
||||
testza.AssertNoError(t, err)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
resolver := NewDependencyResolver(ctx.APIClient)
|
||||
return NewDependencyResolver(ctx.APIClient)
|
||||
}
|
||||
|
||||
func TestProfileResolution(t *testing.T) {
|
||||
resolver := profilesGetResolver()
|
||||
|
||||
resolved, err := (&Profile{
|
||||
Name: DefaultProfileName,
|
||||
|
@ -26,8 +32,12 @@ func TestProfileResolution(t *testing.T) {
|
|||
testza.AssertNoError(t, err)
|
||||
testza.AssertNotNil(t, resolved)
|
||||
testza.AssertLen(t, resolved, 4)
|
||||
}
|
||||
|
||||
_, err = (&Profile{
|
||||
func TestProfileRequiredOlderVersion(t *testing.T) {
|
||||
resolver := profilesGetResolver()
|
||||
|
||||
_, err := (&Profile{
|
||||
Name: DefaultProfileName,
|
||||
Mods: map[string]ProfileMod{
|
||||
"RefinedPower": {
|
||||
|
@ -41,9 +51,13 @@ func TestProfileResolution(t *testing.T) {
|
|||
},
|
||||
}).Resolve(resolver, nil, math.MaxInt)
|
||||
|
||||
testza.AssertEqual(t, "failed resolving profile dependencies: failed resolving dependencies. requires different versions of RefinedRDLib", err.Error())
|
||||
testza.AssertEqual(t, "failed resolving profile dependencies: failed to solve dependencies: Because installing Refined Power (RefinedPower) \"3.0.9\" and Refined Power (RefinedPower) \"3.0.9\" depends on RefinedRDLib \"^1.0.7\", installing RefinedRDLib \"^1.0.7\".\nSo, because installing RefinedRDLib \"1.0.6\", version solving failed.", err.Error())
|
||||
}
|
||||
|
||||
_, err = (&Profile{
|
||||
func TestResolutionNonExistentMod(t *testing.T) {
|
||||
resolver := profilesGetResolver()
|
||||
|
||||
_, err := (&Profile{
|
||||
Name: DefaultProfileName,
|
||||
Mods: map[string]ProfileMod{
|
||||
"ThisModDoesNotExist$$$": {
|
||||
|
@ -53,5 +67,5 @@ func TestProfileResolution(t *testing.T) {
|
|||
},
|
||||
}).Resolve(resolver, nil, math.MaxInt)
|
||||
|
||||
testza.AssertEqual(t, "failed resolving profile dependencies: failed resolving dependency: ThisModDoesNotExist$$$", err.Error())
|
||||
testza.AssertEqual(t, "failed resolving profile dependencies: failed to solve dependencies: failed to make decision: failed to get package versions: mod ThisModDoesNotExist$$$ not found", err.Error())
|
||||
}
|
||||
|
|
7
ficsit/queries/mod_name.graphql
Normal file
7
ficsit/queries/mod_name.graphql
Normal file
|
@ -0,0 +1,7 @@
|
|||
query GetModName ($modId: String!) {
|
||||
mod: getModByIdOrReference(modIdOrReference: $modId) {
|
||||
id
|
||||
mod_reference
|
||||
name
|
||||
}
|
||||
}
|
19
ficsit/queries/mod_versions_with_dependencies.graphql
Normal file
19
ficsit/queries/mod_versions_with_dependencies.graphql
Normal file
|
@ -0,0 +1,19 @@
|
|||
# @genqlient(omitempty: true)
|
||||
query ModVersionsWithDependencies (
|
||||
$modId: String!,
|
||||
) {
|
||||
mod: getModByIdOrReference(modIdOrReference: $modId) {
|
||||
id
|
||||
versions (filter: { limit: 100 }) {
|
||||
id
|
||||
version
|
||||
link
|
||||
hash
|
||||
dependencies {
|
||||
mod_id
|
||||
condition
|
||||
optional
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
15
ficsit/queries/version.graphql
Normal file
15
ficsit/queries/version.graphql
Normal file
|
@ -0,0 +1,15 @@
|
|||
# @genqlient(omitempty: true)
|
||||
query Version (
|
||||
$modId: String!,
|
||||
$version: String!
|
||||
) {
|
||||
mod: getModByIdOrReference(modIdOrReference: $modId) {
|
||||
id
|
||||
version(version: $version) {
|
||||
id
|
||||
version
|
||||
link
|
||||
hash
|
||||
}
|
||||
}
|
||||
}
|
333
ficsit/types.go
333
ficsit/types.go
|
@ -209,6 +209,30 @@ type GetModModAuthorsUserModUser struct {
|
|||
// GetUsername returns GetModModAuthorsUserModUser.Username, and is useful for accessing the field via an interface.
|
||||
func (v *GetModModAuthorsUserModUser) GetUsername() string { return v.Username }
|
||||
|
||||
// GetModNameMod includes the requested fields of the GraphQL type Mod.
|
||||
type GetModNameMod struct {
|
||||
Id string `json:"id"`
|
||||
Mod_reference string `json:"mod_reference"`
|
||||
Name string `json:"name"`
|
||||
}
|
||||
|
||||
// GetId returns GetModNameMod.Id, and is useful for accessing the field via an interface.
|
||||
func (v *GetModNameMod) GetId() string { return v.Id }
|
||||
|
||||
// GetMod_reference returns GetModNameMod.Mod_reference, and is useful for accessing the field via an interface.
|
||||
func (v *GetModNameMod) GetMod_reference() string { return v.Mod_reference }
|
||||
|
||||
// GetName returns GetModNameMod.Name, and is useful for accessing the field via an interface.
|
||||
func (v *GetModNameMod) GetName() string { return v.Name }
|
||||
|
||||
// GetModNameResponse is returned by GetModName on success.
|
||||
type GetModNameResponse struct {
|
||||
Mod GetModNameMod `json:"mod"`
|
||||
}
|
||||
|
||||
// GetMod returns GetModNameResponse.Mod, and is useful for accessing the field via an interface.
|
||||
func (v *GetModNameResponse) GetMod() GetModNameMod { return v.Mod }
|
||||
|
||||
// GetModResponse is returned by GetMod on success.
|
||||
type GetModResponse struct {
|
||||
Mod GetModMod `json:"mod"`
|
||||
|
@ -221,51 +245,51 @@ type ModFields string
|
|||
|
||||
const (
|
||||
ModFieldsCreatedAt ModFields = "created_at"
|
||||
ModFieldsUpdatedAt ModFields = "updated_at"
|
||||
ModFieldsName ModFields = "name"
|
||||
ModFieldsViews ModFields = "views"
|
||||
ModFieldsDownloads ModFields = "downloads"
|
||||
ModFieldsHotness ModFields = "hotness"
|
||||
ModFieldsLastVersionDate ModFields = "last_version_date"
|
||||
ModFieldsName ModFields = "name"
|
||||
ModFieldsPopularity ModFields = "popularity"
|
||||
ModFieldsLastVersionDate ModFields = "last_version_date"
|
||||
ModFieldsSearch ModFields = "search"
|
||||
ModFieldsUpdatedAt ModFields = "updated_at"
|
||||
ModFieldsViews ModFields = "views"
|
||||
)
|
||||
|
||||
type ModFilter struct {
|
||||
Hidden bool `json:"hidden,omitempty"`
|
||||
Ids []string `json:"ids,omitempty"`
|
||||
Limit int `json:"limit,omitempty"`
|
||||
Offset int `json:"offset,omitempty"`
|
||||
Order Order `json:"order,omitempty"`
|
||||
Order_by ModFields `json:"order_by,omitempty"`
|
||||
References []string `json:"references,omitempty"`
|
||||
Order Order `json:"order,omitempty"`
|
||||
Search string `json:"search,omitempty"`
|
||||
Ids []string `json:"ids,omitempty"`
|
||||
References []string `json:"references,omitempty"`
|
||||
Hidden bool `json:"hidden,omitempty"`
|
||||
TagIDs []string `json:"tagIDs,omitempty"`
|
||||
}
|
||||
|
||||
// GetHidden returns ModFilter.Hidden, and is useful for accessing the field via an interface.
|
||||
func (v *ModFilter) GetHidden() bool { return v.Hidden }
|
||||
|
||||
// GetIds returns ModFilter.Ids, and is useful for accessing the field via an interface.
|
||||
func (v *ModFilter) GetIds() []string { return v.Ids }
|
||||
|
||||
// GetLimit returns ModFilter.Limit, and is useful for accessing the field via an interface.
|
||||
func (v *ModFilter) GetLimit() int { return v.Limit }
|
||||
|
||||
// GetOffset returns ModFilter.Offset, and is useful for accessing the field via an interface.
|
||||
func (v *ModFilter) GetOffset() int { return v.Offset }
|
||||
|
||||
// GetOrder_by returns ModFilter.Order_by, and is useful for accessing the field via an interface.
|
||||
func (v *ModFilter) GetOrder_by() ModFields { return v.Order_by }
|
||||
|
||||
// GetOrder returns ModFilter.Order, and is useful for accessing the field via an interface.
|
||||
func (v *ModFilter) GetOrder() Order { return v.Order }
|
||||
|
||||
// GetOrder_by returns ModFilter.Order_by, and is useful for accessing the field via an interface.
|
||||
func (v *ModFilter) GetOrder_by() ModFields { return v.Order_by }
|
||||
// GetSearch returns ModFilter.Search, and is useful for accessing the field via an interface.
|
||||
func (v *ModFilter) GetSearch() string { return v.Search }
|
||||
|
||||
// GetIds returns ModFilter.Ids, and is useful for accessing the field via an interface.
|
||||
func (v *ModFilter) GetIds() []string { return v.Ids }
|
||||
|
||||
// GetReferences returns ModFilter.References, and is useful for accessing the field via an interface.
|
||||
func (v *ModFilter) GetReferences() []string { return v.References }
|
||||
|
||||
// GetSearch returns ModFilter.Search, and is useful for accessing the field via an interface.
|
||||
func (v *ModFilter) GetSearch() string { return v.Search }
|
||||
// GetHidden returns ModFilter.Hidden, and is useful for accessing the field via an interface.
|
||||
func (v *ModFilter) GetHidden() bool { return v.Hidden }
|
||||
|
||||
// GetTagIDs returns ModFilter.TagIDs, and is useful for accessing the field via an interface.
|
||||
func (v *ModFilter) GetTagIDs() []string { return v.TagIDs }
|
||||
|
@ -313,6 +337,76 @@ type ModVersionsResponse struct {
|
|||
// GetMod returns ModVersionsResponse.Mod, and is useful for accessing the field via an interface.
|
||||
func (v *ModVersionsResponse) GetMod() ModVersionsMod { return v.Mod }
|
||||
|
||||
// ModVersionsWithDependenciesMod includes the requested fields of the GraphQL type Mod.
|
||||
type ModVersionsWithDependenciesMod struct {
|
||||
Id string `json:"id"`
|
||||
Versions []ModVersionsWithDependenciesModVersionsVersion `json:"versions"`
|
||||
}
|
||||
|
||||
// GetId returns ModVersionsWithDependenciesMod.Id, and is useful for accessing the field via an interface.
|
||||
func (v *ModVersionsWithDependenciesMod) GetId() string { return v.Id }
|
||||
|
||||
// GetVersions returns ModVersionsWithDependenciesMod.Versions, and is useful for accessing the field via an interface.
|
||||
func (v *ModVersionsWithDependenciesMod) GetVersions() []ModVersionsWithDependenciesModVersionsVersion {
|
||||
return v.Versions
|
||||
}
|
||||
|
||||
// ModVersionsWithDependenciesModVersionsVersion includes the requested fields of the GraphQL type Version.
|
||||
type ModVersionsWithDependenciesModVersionsVersion struct {
|
||||
Id string `json:"id"`
|
||||
Version string `json:"version"`
|
||||
Link string `json:"link"`
|
||||
Hash string `json:"hash"`
|
||||
Dependencies []ModVersionsWithDependenciesModVersionsVersionDependenciesVersionDependency `json:"dependencies"`
|
||||
}
|
||||
|
||||
// GetId returns ModVersionsWithDependenciesModVersionsVersion.Id, and is useful for accessing the field via an interface.
|
||||
func (v *ModVersionsWithDependenciesModVersionsVersion) GetId() string { return v.Id }
|
||||
|
||||
// GetVersion returns ModVersionsWithDependenciesModVersionsVersion.Version, and is useful for accessing the field via an interface.
|
||||
func (v *ModVersionsWithDependenciesModVersionsVersion) GetVersion() string { return v.Version }
|
||||
|
||||
// GetLink returns ModVersionsWithDependenciesModVersionsVersion.Link, and is useful for accessing the field via an interface.
|
||||
func (v *ModVersionsWithDependenciesModVersionsVersion) GetLink() string { return v.Link }
|
||||
|
||||
// GetHash returns ModVersionsWithDependenciesModVersionsVersion.Hash, and is useful for accessing the field via an interface.
|
||||
func (v *ModVersionsWithDependenciesModVersionsVersion) GetHash() string { return v.Hash }
|
||||
|
||||
// GetDependencies returns ModVersionsWithDependenciesModVersionsVersion.Dependencies, and is useful for accessing the field via an interface.
|
||||
func (v *ModVersionsWithDependenciesModVersionsVersion) GetDependencies() []ModVersionsWithDependenciesModVersionsVersionDependenciesVersionDependency {
|
||||
return v.Dependencies
|
||||
}
|
||||
|
||||
// ModVersionsWithDependenciesModVersionsVersionDependenciesVersionDependency includes the requested fields of the GraphQL type VersionDependency.
|
||||
type ModVersionsWithDependenciesModVersionsVersionDependenciesVersionDependency struct {
|
||||
Mod_id string `json:"mod_id"`
|
||||
Condition string `json:"condition"`
|
||||
Optional bool `json:"optional"`
|
||||
}
|
||||
|
||||
// GetMod_id returns ModVersionsWithDependenciesModVersionsVersionDependenciesVersionDependency.Mod_id, and is useful for accessing the field via an interface.
|
||||
func (v *ModVersionsWithDependenciesModVersionsVersionDependenciesVersionDependency) GetMod_id() string {
|
||||
return v.Mod_id
|
||||
}
|
||||
|
||||
// GetCondition returns ModVersionsWithDependenciesModVersionsVersionDependenciesVersionDependency.Condition, and is useful for accessing the field via an interface.
|
||||
func (v *ModVersionsWithDependenciesModVersionsVersionDependenciesVersionDependency) GetCondition() string {
|
||||
return v.Condition
|
||||
}
|
||||
|
||||
// GetOptional returns ModVersionsWithDependenciesModVersionsVersionDependenciesVersionDependency.Optional, and is useful for accessing the field via an interface.
|
||||
func (v *ModVersionsWithDependenciesModVersionsVersionDependenciesVersionDependency) GetOptional() bool {
|
||||
return v.Optional
|
||||
}
|
||||
|
||||
// ModVersionsWithDependenciesResponse is returned by ModVersionsWithDependencies on success.
|
||||
type ModVersionsWithDependenciesResponse struct {
|
||||
Mod ModVersionsWithDependenciesMod `json:"mod"`
|
||||
}
|
||||
|
||||
// GetMod returns ModVersionsWithDependenciesResponse.Mod, and is useful for accessing the field via an interface.
|
||||
func (v *ModVersionsWithDependenciesResponse) GetMod() ModVersionsWithDependenciesMod { return v.Mod }
|
||||
|
||||
// ModsModsGetMods includes the requested fields of the GraphQL type GetMods.
|
||||
type ModsModsGetMods struct {
|
||||
Count int `json:"count"`
|
||||
|
@ -627,37 +721,77 @@ type VersionFields string
|
|||
|
||||
const (
|
||||
VersionFieldsCreatedAt VersionFields = "created_at"
|
||||
VersionFieldsDownloads VersionFields = "downloads"
|
||||
VersionFieldsUpdatedAt VersionFields = "updated_at"
|
||||
VersionFieldsDownloads VersionFields = "downloads"
|
||||
)
|
||||
|
||||
type VersionFilter struct {
|
||||
Ids []string `json:"ids,omitempty"`
|
||||
Limit int `json:"limit,omitempty"`
|
||||
Offset int `json:"offset,omitempty"`
|
||||
Order Order `json:"order,omitempty"`
|
||||
Order_by VersionFields `json:"order_by,omitempty"`
|
||||
Order Order `json:"order,omitempty"`
|
||||
Search string `json:"search,omitempty"`
|
||||
Ids []string `json:"ids,omitempty"`
|
||||
}
|
||||
|
||||
// GetIds returns VersionFilter.Ids, and is useful for accessing the field via an interface.
|
||||
func (v *VersionFilter) GetIds() []string { return v.Ids }
|
||||
|
||||
// GetLimit returns VersionFilter.Limit, and is useful for accessing the field via an interface.
|
||||
func (v *VersionFilter) GetLimit() int { return v.Limit }
|
||||
|
||||
// GetOffset returns VersionFilter.Offset, and is useful for accessing the field via an interface.
|
||||
func (v *VersionFilter) GetOffset() int { return v.Offset }
|
||||
|
||||
// GetOrder returns VersionFilter.Order, and is useful for accessing the field via an interface.
|
||||
func (v *VersionFilter) GetOrder() Order { return v.Order }
|
||||
|
||||
// GetOrder_by returns VersionFilter.Order_by, and is useful for accessing the field via an interface.
|
||||
func (v *VersionFilter) GetOrder_by() VersionFields { return v.Order_by }
|
||||
|
||||
// GetOrder returns VersionFilter.Order, and is useful for accessing the field via an interface.
|
||||
func (v *VersionFilter) GetOrder() Order { return v.Order }
|
||||
|
||||
// GetSearch returns VersionFilter.Search, and is useful for accessing the field via an interface.
|
||||
func (v *VersionFilter) GetSearch() string { return v.Search }
|
||||
|
||||
// GetIds returns VersionFilter.Ids, and is useful for accessing the field via an interface.
|
||||
func (v *VersionFilter) GetIds() []string { return v.Ids }
|
||||
|
||||
// VersionMod includes the requested fields of the GraphQL type Mod.
|
||||
type VersionMod struct {
|
||||
Id string `json:"id"`
|
||||
Version VersionModVersion `json:"version"`
|
||||
}
|
||||
|
||||
// GetId returns VersionMod.Id, and is useful for accessing the field via an interface.
|
||||
func (v *VersionMod) GetId() string { return v.Id }
|
||||
|
||||
// GetVersion returns VersionMod.Version, and is useful for accessing the field via an interface.
|
||||
func (v *VersionMod) GetVersion() VersionModVersion { return v.Version }
|
||||
|
||||
// VersionModVersion includes the requested fields of the GraphQL type Version.
|
||||
type VersionModVersion struct {
|
||||
Id string `json:"id"`
|
||||
Version string `json:"version"`
|
||||
Link string `json:"link"`
|
||||
Hash string `json:"hash"`
|
||||
}
|
||||
|
||||
// GetId returns VersionModVersion.Id, and is useful for accessing the field via an interface.
|
||||
func (v *VersionModVersion) GetId() string { return v.Id }
|
||||
|
||||
// GetVersion returns VersionModVersion.Version, and is useful for accessing the field via an interface.
|
||||
func (v *VersionModVersion) GetVersion() string { return v.Version }
|
||||
|
||||
// GetLink returns VersionModVersion.Link, and is useful for accessing the field via an interface.
|
||||
func (v *VersionModVersion) GetLink() string { return v.Link }
|
||||
|
||||
// GetHash returns VersionModVersion.Hash, and is useful for accessing the field via an interface.
|
||||
func (v *VersionModVersion) GetHash() string { return v.Hash }
|
||||
|
||||
// VersionResponse is returned by Version on success.
|
||||
type VersionResponse struct {
|
||||
Mod VersionMod `json:"mod"`
|
||||
}
|
||||
|
||||
// GetMod returns VersionResponse.Mod, and is useful for accessing the field via an interface.
|
||||
func (v *VersionResponse) GetMod() VersionMod { return v.Mod }
|
||||
|
||||
type VersionStabilities string
|
||||
|
||||
const (
|
||||
|
@ -710,6 +844,14 @@ type __GetModInput struct {
|
|||
// GetModId returns __GetModInput.ModId, and is useful for accessing the field via an interface.
|
||||
func (v *__GetModInput) GetModId() string { return v.ModId }
|
||||
|
||||
// __GetModNameInput is used internally by genqlient
|
||||
type __GetModNameInput struct {
|
||||
ModId string `json:"modId"`
|
||||
}
|
||||
|
||||
// GetModId returns __GetModNameInput.ModId, and is useful for accessing the field via an interface.
|
||||
func (v *__GetModNameInput) GetModId() string { return v.ModId }
|
||||
|
||||
// __ModVersionsInput is used internally by genqlient
|
||||
type __ModVersionsInput struct {
|
||||
ModId string `json:"modId,omitempty"`
|
||||
|
@ -722,6 +864,14 @@ func (v *__ModVersionsInput) GetModId() string { return v.ModId }
|
|||
// GetFilter returns __ModVersionsInput.Filter, and is useful for accessing the field via an interface.
|
||||
func (v *__ModVersionsInput) GetFilter() VersionFilter { return v.Filter }
|
||||
|
||||
// __ModVersionsWithDependenciesInput is used internally by genqlient
|
||||
type __ModVersionsWithDependenciesInput struct {
|
||||
ModId string `json:"modId,omitempty"`
|
||||
}
|
||||
|
||||
// GetModId returns __ModVersionsWithDependenciesInput.ModId, and is useful for accessing the field via an interface.
|
||||
func (v *__ModVersionsWithDependenciesInput) GetModId() string { return v.ModId }
|
||||
|
||||
// __ModsInput is used internally by genqlient
|
||||
type __ModsInput struct {
|
||||
Filter ModFilter `json:"filter,omitempty"`
|
||||
|
@ -738,6 +888,18 @@ type __ResolveModDependenciesInput struct {
|
|||
// GetFilter returns __ResolveModDependenciesInput.Filter, and is useful for accessing the field via an interface.
|
||||
func (v *__ResolveModDependenciesInput) GetFilter() []ModVersionConstraint { return v.Filter }
|
||||
|
||||
// __VersionInput is used internally by genqlient
|
||||
type __VersionInput struct {
|
||||
ModId string `json:"modId,omitempty"`
|
||||
Version string `json:"version,omitempty"`
|
||||
}
|
||||
|
||||
// GetModId returns __VersionInput.ModId, and is useful for accessing the field via an interface.
|
||||
func (v *__VersionInput) GetModId() string { return v.ModId }
|
||||
|
||||
// GetVersion returns __VersionInput.Version, and is useful for accessing the field via an interface.
|
||||
func (v *__VersionInput) GetVersion() string { return v.Version }
|
||||
|
||||
func CheckVersionUploadState(
|
||||
ctx context.Context,
|
||||
client graphql.Client,
|
||||
|
@ -884,6 +1046,40 @@ query GetMod ($modId: String!) {
|
|||
return &data, err
|
||||
}
|
||||
|
||||
func GetModName(
|
||||
ctx context.Context,
|
||||
client graphql.Client,
|
||||
modId string,
|
||||
) (*GetModNameResponse, error) {
|
||||
req := &graphql.Request{
|
||||
OpName: "GetModName",
|
||||
Query: `
|
||||
query GetModName ($modId: String!) {
|
||||
mod: getModByIdOrReference(modIdOrReference: $modId) {
|
||||
id
|
||||
mod_reference
|
||||
name
|
||||
}
|
||||
}
|
||||
`,
|
||||
Variables: &__GetModNameInput{
|
||||
ModId: modId,
|
||||
},
|
||||
}
|
||||
var err error
|
||||
|
||||
var data GetModNameResponse
|
||||
resp := &graphql.Response{Data: &data}
|
||||
|
||||
err = client.MakeRequest(
|
||||
ctx,
|
||||
req,
|
||||
resp,
|
||||
)
|
||||
|
||||
return &data, err
|
||||
}
|
||||
|
||||
func ModVersions(
|
||||
ctx context.Context,
|
||||
client graphql.Client,
|
||||
|
@ -922,6 +1118,49 @@ query ModVersions ($modId: String!, $filter: VersionFilter) {
|
|||
return &data, err
|
||||
}
|
||||
|
||||
func ModVersionsWithDependencies(
|
||||
ctx context.Context,
|
||||
client graphql.Client,
|
||||
modId string,
|
||||
) (*ModVersionsWithDependenciesResponse, error) {
|
||||
req := &graphql.Request{
|
||||
OpName: "ModVersionsWithDependencies",
|
||||
Query: `
|
||||
query ModVersionsWithDependencies ($modId: String!) {
|
||||
mod: getModByIdOrReference(modIdOrReference: $modId) {
|
||||
id
|
||||
versions(filter: {limit:100}) {
|
||||
id
|
||||
version
|
||||
link
|
||||
hash
|
||||
dependencies {
|
||||
mod_id
|
||||
condition
|
||||
optional
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`,
|
||||
Variables: &__ModVersionsWithDependenciesInput{
|
||||
ModId: modId,
|
||||
},
|
||||
}
|
||||
var err error
|
||||
|
||||
var data ModVersionsWithDependenciesResponse
|
||||
resp := &graphql.Response{Data: &data}
|
||||
|
||||
err = client.MakeRequest(
|
||||
ctx,
|
||||
req,
|
||||
resp,
|
||||
)
|
||||
|
||||
return &data, err
|
||||
}
|
||||
|
||||
func Mods(
|
||||
ctx context.Context,
|
||||
client graphql.Client,
|
||||
|
@ -1041,3 +1280,43 @@ query SMLVersions {
|
|||
|
||||
return &data, err
|
||||
}
|
||||
|
||||
func Version(
|
||||
ctx context.Context,
|
||||
client graphql.Client,
|
||||
modId string,
|
||||
version string,
|
||||
) (*VersionResponse, error) {
|
||||
req := &graphql.Request{
|
||||
OpName: "Version",
|
||||
Query: `
|
||||
query Version ($modId: String!, $version: String!) {
|
||||
mod: getModByIdOrReference(modIdOrReference: $modId) {
|
||||
id
|
||||
version(version: $version) {
|
||||
id
|
||||
version
|
||||
link
|
||||
hash
|
||||
}
|
||||
}
|
||||
}
|
||||
`,
|
||||
Variables: &__VersionInput{
|
||||
ModId: modId,
|
||||
Version: version,
|
||||
},
|
||||
}
|
||||
var err error
|
||||
|
||||
var data VersionResponse
|
||||
resp := &graphql.Response{Data: &data}
|
||||
|
||||
err = client.MakeRequest(
|
||||
ctx,
|
||||
req,
|
||||
resp,
|
||||
)
|
||||
|
||||
return &data, err
|
||||
}
|
||||
|
|
36
go.mod
36
go.mod
|
@ -1,32 +1,32 @@
|
|||
module github.com/satisfactorymodding/ficsit-cli
|
||||
|
||||
go 1.18
|
||||
go 1.21
|
||||
|
||||
require (
|
||||
github.com/JohannesKaufmann/html-to-markdown v1.3.6
|
||||
github.com/Khan/genqlient v0.5.0
|
||||
github.com/MarvinJWendt/testza v0.4.3
|
||||
github.com/Masterminds/semver/v3 v3.1.1
|
||||
github.com/MarvinJWendt/testza v0.5.2
|
||||
github.com/PuerkitoBio/goquery v1.8.0
|
||||
github.com/charmbracelet/bubbles v0.14.0
|
||||
github.com/charmbracelet/bubbletea v0.22.1
|
||||
github.com/charmbracelet/glamour v0.5.0
|
||||
github.com/charmbracelet/lipgloss v0.6.0
|
||||
github.com/jlaffaye/ftp v0.1.0
|
||||
github.com/mircearoata/pubgrub-go v0.3.2
|
||||
github.com/muesli/reflow v0.3.0
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/pterm/pterm v0.12.49
|
||||
github.com/pterm/pterm v0.12.67
|
||||
github.com/rs/zerolog v1.28.0
|
||||
github.com/sahilm/fuzzy v0.1.0
|
||||
github.com/spf13/cobra v1.6.0
|
||||
github.com/spf13/viper v1.13.0
|
||||
)
|
||||
|
||||
replace github.com/Masterminds/semver/v3 v3.1.1 => github.com/Vilsol/semver/v3 v3.1.2-0.20220414201711-64ef71d40f9a
|
||||
|
||||
require (
|
||||
atomicgo.dev/cursor v0.1.1 // indirect
|
||||
atomicgo.dev/keyboard v0.2.8 // indirect
|
||||
atomicgo.dev/assert v0.0.2 // indirect
|
||||
atomicgo.dev/cursor v0.2.0 // indirect
|
||||
atomicgo.dev/keyboard v0.2.9 // indirect
|
||||
atomicgo.dev/schedule v0.1.0 // indirect
|
||||
github.com/agnivade/levenshtein v1.1.1 // indirect
|
||||
github.com/alecthomas/chroma v0.10.0 // indirect
|
||||
github.com/alexflint/go-arg v1.4.3 // indirect
|
||||
|
@ -41,14 +41,14 @@ require (
|
|||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/dlclark/regexp2 v1.7.0 // indirect
|
||||
github.com/fsnotify/fsnotify v1.6.0 // indirect
|
||||
github.com/gookit/color v1.5.2 // indirect
|
||||
github.com/gookit/color v1.5.4 // indirect
|
||||
github.com/gorilla/css v1.0.0 // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.0.1 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.1.0 // indirect
|
||||
github.com/lithammer/fuzzysearch v1.1.5 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.5 // indirect
|
||||
github.com/lithammer/fuzzysearch v1.1.8 // indirect
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0 // indirect
|
||||
github.com/magiconair/properties v1.8.6 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
|
@ -65,7 +65,7 @@ require (
|
|||
github.com/pelletier/go-toml/v2 v2.0.5 // indirect
|
||||
github.com/rivo/uniseg v0.4.4 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/sergi/go-diff v1.2.0 // indirect
|
||||
github.com/sergi/go-diff v1.3.1 // indirect
|
||||
github.com/spf13/afero v1.9.2 // indirect
|
||||
github.com/spf13/cast v1.5.0 // indirect
|
||||
github.com/spf13/jwalterweatherman v1.1.0 // indirect
|
||||
|
@ -75,12 +75,12 @@ require (
|
|||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
|
||||
github.com/yuin/goldmark v1.5.2 // indirect
|
||||
github.com/yuin/goldmark-emoji v1.0.1 // indirect
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
|
||||
golang.org/x/net v0.0.0-20221014081412-f15817d10f9b // indirect
|
||||
golang.org/x/sys v0.0.0-20221013171732-95e765b1cc43 // indirect
|
||||
golang.org/x/term v0.0.0-20220919170432-7a66f970e087 // indirect
|
||||
golang.org/x/text v0.3.8 // indirect
|
||||
golang.org/x/tools v0.1.12 // indirect
|
||||
golang.org/x/mod v0.8.0 // indirect
|
||||
golang.org/x/net v0.6.0 // indirect
|
||||
golang.org/x/sys v0.12.0 // indirect
|
||||
golang.org/x/term v0.12.0 // indirect
|
||||
golang.org/x/text v0.13.0 // indirect
|
||||
golang.org/x/tools v0.6.0 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
|
|
84
go.sum
84
go.sum
|
@ -1,7 +1,11 @@
|
|||
atomicgo.dev/cursor v0.1.1 h1:0t9sxQomCTRh5ug+hAMCs59x/UmC9QL6Ci5uosINKD4=
|
||||
atomicgo.dev/cursor v0.1.1/go.mod h1:Lr4ZJB3U7DfPPOkbH7/6TOtJ4vFGHlgj1nc+n900IpU=
|
||||
atomicgo.dev/keyboard v0.2.8 h1:Di09BitwZgdTV1hPyX/b9Cqxi8HVuJQwWivnZUEqlj4=
|
||||
atomicgo.dev/keyboard v0.2.8/go.mod h1:BC4w9g00XkxH/f1HXhW2sXmJFOCWbKn9xrOunSFtExQ=
|
||||
atomicgo.dev/assert v0.0.2 h1:FiKeMiZSgRrZsPo9qn/7vmr7mCsh5SZyXY4YGYiYwrg=
|
||||
atomicgo.dev/assert v0.0.2/go.mod h1:ut4NcI3QDdJtlmAxQULOmA13Gz6e2DWbSAS8RUOmNYQ=
|
||||
atomicgo.dev/cursor v0.2.0 h1:H6XN5alUJ52FZZUkI7AlJbUc1aW38GWZalpYRPpoPOw=
|
||||
atomicgo.dev/cursor v0.2.0/go.mod h1:Lr4ZJB3U7DfPPOkbH7/6TOtJ4vFGHlgj1nc+n900IpU=
|
||||
atomicgo.dev/keyboard v0.2.9 h1:tOsIid3nlPLZ3lwgG8KZMp/SFmr7P0ssEN5JUsm78K8=
|
||||
atomicgo.dev/keyboard v0.2.9/go.mod h1:BC4w9g00XkxH/f1HXhW2sXmJFOCWbKn9xrOunSFtExQ=
|
||||
atomicgo.dev/schedule v0.1.0 h1:nTthAbhZS5YZmgYbb2+DH8uQIZcTlIrd4eYr3UQxEjs=
|
||||
atomicgo.dev/schedule v0.1.0/go.mod h1:xeUa3oAkiuHYh8bKiQBRojqAMq3PXXbJujjb0hw8pEU=
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
|
||||
|
@ -54,12 +58,10 @@ github.com/MarvinJWendt/testza v0.2.10/go.mod h1:pd+VWsoGUiFtq+hRKSU1Bktnn+DMCSr
|
|||
github.com/MarvinJWendt/testza v0.2.12/go.mod h1:JOIegYyV7rX+7VZ9r77L/eH6CfJHHzXjB69adAhzZkI=
|
||||
github.com/MarvinJWendt/testza v0.3.0/go.mod h1:eFcL4I0idjtIx8P9C6KkAuLgATNKpX4/2oUqKc6bF2c=
|
||||
github.com/MarvinJWendt/testza v0.4.2/go.mod h1:mSdhXiKH8sg/gQehJ63bINcCKp7RtYewEjXsvsVUPbE=
|
||||
github.com/MarvinJWendt/testza v0.4.3 h1:u2XaM4IqGp9dsdUmML8/Z791fu4yjQYzOiufOtJwTII=
|
||||
github.com/MarvinJWendt/testza v0.4.3/go.mod h1:CpXaOfceNEYnLDtNIyTrPPcCpDJYqzZnu2aiA2Wp33U=
|
||||
github.com/MarvinJWendt/testza v0.5.2 h1:53KDo64C1z/h/d/stCYCPY69bt/OSwjq5KpFNwi+zB4=
|
||||
github.com/MarvinJWendt/testza v0.5.2/go.mod h1:xu53QFE5sCdjtMCKk8YMQ2MnymimEctc4n3EjyIYvEY=
|
||||
github.com/PuerkitoBio/goquery v1.8.0 h1:PJTF7AmFCFKk1N6V6jmKfrNH9tV5pNE6lZMkG0gta/U=
|
||||
github.com/PuerkitoBio/goquery v1.8.0/go.mod h1:ypIiRMtY7COPGk+I/YbZLbxsxn9g5ejnI2HSMtkjZvI=
|
||||
github.com/Vilsol/semver/v3 v3.1.2-0.20220414201711-64ef71d40f9a h1:Z443bc6RS9J5qRi7KGqWpStbNYxhDWtSqK/mPQNsIO4=
|
||||
github.com/Vilsol/semver/v3 v3.1.2-0.20220414201711-64ef71d40f9a/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs=
|
||||
github.com/agnivade/levenshtein v1.0.1/go.mod h1:CURSv5d9Uaml+FovSIICkLbAUZ9S4RqaHDIsdSBg7lM=
|
||||
github.com/agnivade/levenshtein v1.1.0/go.mod h1:veldBMzWxcCG2ZvUTKD2kJNRdCk5hVbJomOvKkmgYbo=
|
||||
github.com/agnivade/levenshtein v1.1.1 h1:QY8M92nrzkmr798gCo3kmMyqXFzdQVpxLlGPRBij0P8=
|
||||
|
@ -131,6 +133,7 @@ github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5y
|
|||
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/frankban/quicktest v1.14.3 h1:FJKSZTDHjyhriyC81FLQ0LY93eSai0ZyR/ZIkd3ZUKE=
|
||||
github.com/frankban/quicktest v1.14.3/go.mod h1:mgiwOwqx65TmIk1wJ6Q7wvnVMocbUorkibMOrVTHZps=
|
||||
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
|
||||
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
|
||||
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
|
||||
|
@ -174,6 +177,7 @@ github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
|||
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
|
||||
github.com/google/go-cmp v0.5.8/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
|
||||
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||
github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
|
||||
|
@ -194,8 +198,8 @@ github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5m
|
|||
github.com/googleapis/google-cloud-go-testing v0.0.0-20200911160855-bcd43fbb19e8/go.mod h1:dvDLG8qkwmyD9a/MJJN3XJcT3xFxOKAvTZGvuZmac9g=
|
||||
github.com/gookit/color v1.4.2/go.mod h1:fqRyamkC1W8uxl+lxCQxOT09l/vYfZ+QeiX3rKQHCoQ=
|
||||
github.com/gookit/color v1.5.0/go.mod h1:43aQb+Zerm/BWh2GnrgOQm7ffz7tvQXEKV6BFMl7wAo=
|
||||
github.com/gookit/color v1.5.2 h1:uLnfXcaFjlrDnQDT+NCBcfhrXqYTx/rcCa6xn01Y8yI=
|
||||
github.com/gookit/color v1.5.2/go.mod h1:w8h4bGiHeeBpvQVePTutdbERIUf3oJE5lZ8HM0UgXyg=
|
||||
github.com/gookit/color v1.5.4 h1:FZmqs7XOyGgCAxmWyPslpiok1k05wmY3SJTytgvYFs0=
|
||||
github.com/gookit/color v1.5.4/go.mod h1:pZJOeOS8DM43rXbp4AZo1n9zCU2qjpcRko0b6/QJi9w=
|
||||
github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY=
|
||||
github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c=
|
||||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||
|
@ -221,18 +225,20 @@ github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+o
|
|||
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||
github.com/klauspost/cpuid/v2 v2.0.10/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c=
|
||||
github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c=
|
||||
github.com/klauspost/cpuid/v2 v2.1.0 h1:eyi1Ad2aNJMW95zcSbmGg7Cg6cq3ADwLpMAP96d8rF0=
|
||||
github.com/klauspost/cpuid/v2 v2.1.0/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
|
||||
github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg=
|
||||
github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
|
||||
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
|
||||
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
|
||||
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
|
||||
github.com/lithammer/fuzzysearch v1.1.5 h1:Ag7aKU08wp0R9QCfF4GoGST9HbmAIeLP7xwMrOBEp1c=
|
||||
github.com/lithammer/fuzzysearch v1.1.5/go.mod h1:1R1LRNk7yKid1BaQkmuLQaHruxcC4HmAH30Dh61Ih1Q=
|
||||
github.com/lithammer/fuzzysearch v1.1.8 h1:/HIuJnjHuXS8bKaiTMeeDlW2/AyIWk2brx1V8LFgLN4=
|
||||
github.com/lithammer/fuzzysearch v1.1.8/go.mod h1:IdqeyBClc3FFqSzYq/MXESsS4S0FsZ5ajtkr5xPLts4=
|
||||
github.com/logrusorgru/aurora/v3 v3.0.0/go.mod h1:vsR12bk5grlLvLXAYrBsb5Oc/N+LxAlxggSjiwMnCUc=
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY=
|
||||
github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0=
|
||||
|
@ -255,13 +261,14 @@ github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m
|
|||
github.com/mattn/go-runewidth v0.0.10/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
|
||||
github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk=
|
||||
github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU=
|
||||
github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
|
||||
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||
github.com/microcosm-cc/bluemonday v1.0.17/go.mod h1:Z0r70sCuXHig8YpBzCc5eGHAap2K7e/u082ZUpDRRqM=
|
||||
github.com/microcosm-cc/bluemonday v1.0.21 h1:dNH3e4PSyE4vNX+KlRGHT5KrSvjeUkoNPwEORjffHJg=
|
||||
github.com/microcosm-cc/bluemonday v1.0.21/go.mod h1:ytNkv4RrDrLJ2pqlsSI46O6IVXmZOBBD4SaJyDwwTkM=
|
||||
github.com/mircearoata/pubgrub-go v0.3.2 h1:AeC2bvHebii6YrfyN+AST06WiQUENKQkREA7Xoi4/HY=
|
||||
github.com/mircearoata/pubgrub-go v0.3.2/go.mod h1:9oWL9ZXdjFYvnGl95qiM1dTciFNx1MN8fUnG3SUwDi8=
|
||||
github.com/mitchellh/mapstructure v1.2.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
|
@ -299,16 +306,15 @@ github.com/pterm/pterm v0.12.31/go.mod h1:32ZAWZVXD7ZfG0s8qqHXePte42kdz8ECtRyEej
|
|||
github.com/pterm/pterm v0.12.33/go.mod h1:x+h2uL+n7CP/rel9+bImHD5lF3nM9vJj80k9ybiiTTE=
|
||||
github.com/pterm/pterm v0.12.36/go.mod h1:NjiL09hFhT/vWjQHSj1athJpx6H8cjpHXNAK5bUw8T8=
|
||||
github.com/pterm/pterm v0.12.40/go.mod h1:ffwPLwlbXxP+rxT0GsgDTzS3y3rmpAO1NMjUkGTYf8s=
|
||||
github.com/pterm/pterm v0.12.49 h1:qeNm0wTWawy6WhKoY8ZKq6qTXFr0s2UtUyRW0yVztEg=
|
||||
github.com/pterm/pterm v0.12.49/go.mod h1:D4OBoWNqAfXkm5QLTjIgjNiMXPHemLJHnIreGUsWzWg=
|
||||
github.com/pterm/pterm v0.12.67 h1:5iB7ajIQROYfxYD7+sFJ4+KJhFJ+xn7QOVBm4s6RUF0=
|
||||
github.com/pterm/pterm v0.12.67/go.mod h1:nFuT9ZVkkCi8o4L1dtWuYPwDQxggLh4C263qG5nTLpQ=
|
||||
github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||
github.com/rivo/uniseg v0.4.2 h1:YwD0ulJSJytLpiaWua0sBDusfsCZohxjxzVTYjwxfV8=
|
||||
github.com/rivo/uniseg v0.4.2/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||
github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis=
|
||||
github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k=
|
||||
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||
github.com/rs/xid v1.4.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
|
||||
github.com/rs/zerolog v1.28.0 h1:MirSo27VyNi7RJYP3078AA1+Cyzd2GB66qy3aUHvsWY=
|
||||
github.com/rs/zerolog v1.28.0/go.mod h1:NILgTygv/Uej1ra5XxGf82ZFSLk58MFGAUS2o6usyD0=
|
||||
|
@ -321,8 +327,9 @@ github.com/sebdah/goldie/v2 v2.5.3 h1:9ES/mNN+HNUbNWpVAlrzuZ7jE+Nrczbj8uFRjM7624
|
|||
github.com/sebdah/goldie/v2 v2.5.3/go.mod h1:oZ9fp0+se1eapSRjfYbsV/0Hqhbuu3bJVvKI/NNtssI=
|
||||
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
|
||||
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
||||
github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ=
|
||||
github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
||||
github.com/sergi/go-diff v1.3.1 h1:xkr+Oxo4BOQKmkn/B9eMK0g5Kg/983T9DqqPHwYqD+8=
|
||||
github.com/sergi/go-diff v1.3.1/go.mod h1:aMJSSKb2lpPvRNec0+w3fl7LP9IOFzdc9Pa4NFbPK1I=
|
||||
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
|
||||
github.com/spf13/afero v1.9.2 h1:j49Hj62F0n+DaZ1dDCvhABaPNSGNkt32oRFxI33IEMw=
|
||||
github.com/spf13/afero v1.9.2/go.mod h1:iUV7ddyEEZPO5gA3zD4fJt6iStLlL+Lg4m2cihcDf8Y=
|
||||
|
@ -346,8 +353,9 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5
|
|||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/subosito/gotenv v1.4.1 h1:jyEFiXpy21Wm81FBN71l9VoMMV8H8jG+qIK3GCpY6Qs=
|
||||
github.com/subosito/gotenv v1.4.1/go.mod h1:ayKnFf/c6rvx/2iiLrJUk1e6plDbT3edrFNGqEflhK0=
|
||||
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
|
||||
|
@ -364,6 +372,7 @@ github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
|
|||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
github.com/yuin/goldmark v1.4.4/go.mod h1:rmuwmfZ0+bvzB24eSC//bk1R1Zp3hM0OXYv/G2LIilg=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
github.com/yuin/goldmark v1.4.14/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
github.com/yuin/goldmark v1.5.2 h1:ALmeCk/px5FSm1MAcFBAsVKZjDuMVj8Tm7FFIlMJnqU=
|
||||
github.com/yuin/goldmark v1.5.2/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
|
@ -394,6 +403,7 @@ golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u0
|
|||
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
|
||||
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
|
||||
golang.org/x/exp v0.0.0-20220909182711-5c715a9e8561 h1:MDc5xs78ZrZr3HMQugiXOAkSZtfTpbJLDr/lwfgO53E=
|
||||
golang.org/x/exp v0.0.0-20220909182711-5c715a9e8561/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE=
|
||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
|
@ -419,8 +429,9 @@ golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
|||
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
|
@ -455,9 +466,10 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
|
|||
golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20210916014120-12bc252f5db8/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.0.0-20220909164309-bea034e7d591/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
|
||||
golang.org/x/net v0.0.0-20221014081412-f15817d10f9b h1:tvrvnPFcdzp294diPnrdZZZ8XUt2Tyj7svb7X52iDuU=
|
||||
golang.org/x/net v0.0.0-20221014081412-f15817d10f9b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
|
||||
golang.org/x/net v0.6.0 h1:L4ZwwTvKW9gr0ZMS1yrHD9GZhIuVjOBBnaKH+SPQK0Q=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
|
@ -478,6 +490,8 @@ golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJ
|
|||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
|
@ -524,18 +538,21 @@ golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||
golang.org/x/sys v0.0.0-20220204135822-1c1b9b1eba6a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20221013171732-95e765b1cc43 h1:OK7RB6t2WQX54srQQYSXMW8dF5C6/8+oA/s5QBmmto4=
|
||||
golang.org/x/sys v0.0.0-20221013171732-95e765b1cc43/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o=
|
||||
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.0.0-20220919170432-7a66f970e087 h1:tPwmk4vmvVCMdr98VgL4JH+qZxPL8fqlUOHnyOM8N3w=
|
||||
golang.org/x/term v0.0.0-20220919170432-7a66f970e087/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/term v0.12.0 h1:/ZfYdc3zq+q02Rv9vGqTeSItdzZTSNDmfTi0mBAuidU=
|
||||
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
|
||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
|
@ -544,8 +561,10 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
|||
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.3.8 h1:nAL+RVCQ9uMn3vJZbV+MRnydTJFPf8qqY42YiA6MrqY=
|
||||
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
|
||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||
|
@ -599,8 +618,9 @@ golang.org/x/tools v0.0.0-20210108195828-e2f9c7f1fc8e/go.mod h1:emZCQorbCU4vsT4f
|
|||
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
||||
golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
|
||||
golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E=
|
||||
golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.6.0 h1:BOw41kyTf3PuCW1pVQf8+Cyg8pMlkYB1oo9iJ6D/lKM=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
|
|
Loading…
Reference in a new issue