diff --git a/mod/file.go b/mod/file.go index 947ea583..733d1051 100644 --- a/mod/file.go +++ b/mod/file.go @@ -98,7 +98,8 @@ func read(fMod, fSum io.Reader) (*file, error) { return nil, fmt.Errorf("repos in mod and sum line don't match: %s and %s", modSplit[0], sumSplit[0]) } - require, err := newRequire(modSplit[0]) + // FIXME: if we want to add support for version constraints in the mod file, it would be here + require, err := newRequire(modSplit[0], "") if err != nil { return nil, err } @@ -204,7 +205,7 @@ func (f *file) updateToLatest(req *Require) (*Require, error) { } // checkout the latest tag - latestTag, err := gitRepo.latestTag() + latestTag, err := gitRepo.latestTag(req.versionConstraint) if err != nil { return nil, err } diff --git a/mod/mod.go b/mod/mod.go index 6e7902db..85aec33e 100644 --- a/mod/mod.go +++ b/mod/mod.go @@ -6,14 +6,8 @@ import ( "github.com/gofrs/flock" ) -func InstallStdlib(workspace string) error { - _, err := Install(workspace, "alpha.dagger.io@v0.1") - - return err -} - -func Install(workspace, repoName string) (*Require, error) { - require, err := newRequire(repoName) +func Install(workspace, repoName, versionConstraint string) (*Require, error) { + require, err := newRequire(repoName, versionConstraint) if err != nil { return nil, err } @@ -51,7 +45,7 @@ func InstallAll(workspace string, repoNames []string) ([]*Require, error) { for _, repoName := range repoNames { var require *Require - if require, err = Install(workspace, repoName); err != nil { + if require, err = Install(workspace, repoName, ""); err != nil { continue } @@ -61,8 +55,8 @@ func InstallAll(workspace string, repoNames []string) ([]*Require, error) { return installedRequires, err } -func Update(workspace, repoName string) (*Require, error) { - require, err := newRequire(repoName) +func Update(workspace, repoName, versionConstraint string) (*Require, error) { + require, err := newRequire(repoName, versionConstraint) if err != nil { return nil, err } @@ -100,7 +94,7 @@ func UpdateAll(workspace string, repoNames []string) ([]*Require, error) { for _, repoName := range repoNames { var require *Require - if require, err = Update(workspace, repoName); err != nil { + if require, err = Update(workspace, repoName, ""); err != nil { continue } diff --git a/mod/repo.go b/mod/repo.go index 96182a64..09257054 100644 --- a/mod/repo.go +++ b/mod/repo.go @@ -49,7 +49,7 @@ func clone(require *Require, dir string, privateKeyFile, privateKeyPassword stri } if require.version == "" { - latestTag, err := rr.latestTag() + latestTag, err := rr.latestTag(require.versionConstraint) if err != nil { return nil, err } @@ -85,25 +85,53 @@ func (r *repo) checkout(version string) error { return nil } -func (r *repo) listTags() ([]string, error) { +func (r *repo) listTagVersions(versionConstraint string) ([]string, error) { + if versionConstraint == "" { + versionConstraint = ">= 0" + } + + constraint, err := version.NewConstraint(versionConstraint) + if err != nil { + return nil, err + } + iter, err := r.contents.Tags() if err != nil { return nil, err } var tags []string - if err := iter.ForEach(func(ref *plumbing.Reference) error { - tags = append(tags, ref.Name().Short()) + err = iter.ForEach(func(ref *plumbing.Reference) error { + tagV := ref.Name().Short() + + if !strings.HasPrefix(tagV, "v") { + // ignore wrong formatted tags + return nil + } + + v, err := version.NewVersion(tagV) + if err != nil { + // ignore invalid tag + return nil + } + + if constraint.Check(v) { + // Add tag if it matches the version constraint + tags = append(tags, ref.Name().Short()) + } + return nil - }); err != nil { + }) + + if err != nil { return nil, err } return tags, nil } -func (r *repo) latestTag() (string, error) { - versionsRaw, err := r.listTags() +func (r *repo) latestTag(versionConstraint string) (string, error) { + versionsRaw, err := r.listTagVersions(versionConstraint) if err != nil { return "", err } @@ -115,10 +143,9 @@ func (r *repo) latestTag() (string, error) { } if len(versions) == 0 { - return "", fmt.Errorf("repo doesn't have any tags") + return "", fmt.Errorf("repo doesn't have any tags matching the required version") } - sort.Sort(version.Collection(versions)) - - return versions[len(versions)-1].Original(), nil + sort.Sort(sort.Reverse(version.Collection(versions))) + return versions[0].Original(), nil } diff --git a/mod/repo_test.go b/mod/repo_test.go index cbf01fbd..1f107506 100644 --- a/mod/repo_test.go +++ b/mod/repo_test.go @@ -74,7 +74,7 @@ func TestListTags(t *testing.T) { t.Fatal(err) } - tags, err := r.listTags() + tags, err := r.listTagVersions("") if err != nil { t.Error(err) } diff --git a/mod/require.go b/mod/require.go index fb113692..50f13aba 100644 --- a/mod/require.go +++ b/mod/require.go @@ -15,16 +15,17 @@ type Require struct { cloneRepo string clonePath string - version string - checksum string + version string + versionConstraint string + checksum string } -func newRequire(repoName string) (*Require, error) { +func newRequire(repoName, versionConstraint string) (*Require, error) { switch { case strings.HasPrefix(repoName, "github.com"): - return parseGithubRepoName(repoName) + return parseGithubRepoName(repoName, versionConstraint) case strings.HasPrefix(repoName, "alpha.dagger.io"): - return parseDaggerRepoName(repoName) + return parseDaggerRepoName(repoName, versionConstraint) default: return nil, fmt.Errorf("repo name does not match suported providers") } @@ -32,7 +33,7 @@ func newRequire(repoName string) (*Require, error) { var githubRepoNameRegex = regexp.MustCompile(`(github.com/[a-zA-Z0-9_.-]+/[a-zA-Z0-9_.-]+)([a-zA-Z0-9/_.-]*)@?([0-9a-zA-Z.-]*)`) -func parseGithubRepoName(repoName string) (*Require, error) { +func parseGithubRepoName(repoName, versionConstraint string) (*Require, error) { repoMatches := githubRepoNameRegex.FindStringSubmatch(repoName) if len(repoMatches) < 4 { @@ -40,9 +41,10 @@ func parseGithubRepoName(repoName string) (*Require, error) { } return &Require{ - repo: repoMatches[1], - path: repoMatches[2], - version: repoMatches[3], + repo: repoMatches[1], + path: repoMatches[2], + version: repoMatches[3], + versionConstraint: versionConstraint, cloneRepo: repoMatches[1], clonePath: repoMatches[2], @@ -51,7 +53,7 @@ func parseGithubRepoName(repoName string) (*Require, error) { var daggerRepoNameRegex = regexp.MustCompile(`alpha.dagger.io([a-zA-Z0-9/_.-]*)@?([0-9a-zA-Z.-]*)`) -func parseDaggerRepoName(repoName string) (*Require, error) { +func parseDaggerRepoName(repoName, versionConstraint string) (*Require, error) { repoMatches := daggerRepoNameRegex.FindStringSubmatch(repoName) if len(repoMatches) < 3 { @@ -59,9 +61,10 @@ func parseDaggerRepoName(repoName string) (*Require, error) { } return &Require{ - repo: "alpha.dagger.io", - path: repoMatches[1], - version: repoMatches[2], + repo: "alpha.dagger.io", + path: repoMatches[1], + version: repoMatches[2], + versionConstraint: versionConstraint, cloneRepo: "github.com/dagger/universe", clonePath: path.Join("/stdlib", repoMatches[1]), diff --git a/mod/require_test.go b/mod/require_test.go index e455456e..bdc3857a 100644 --- a/mod/require_test.go +++ b/mod/require_test.go @@ -98,7 +98,7 @@ func TestParseArgument(t *testing.T) { for _, c := range cases { t.Run(c.name, func(t *testing.T) { - got, err := newRequire(c.in) + got, err := newRequire(c.in, "") if err != nil && c.hasError { return } diff --git a/state/project.go b/state/project.go index 274a4961..5f61d8be 100644 --- a/state/project.go +++ b/state/project.go @@ -12,6 +12,7 @@ import ( "github.com/rs/zerolog/log" "go.dagger.io/dagger/keychain" + "go.dagger.io/dagger/mod" "go.dagger.io/dagger/stdlib" "gopkg.in/yaml.v3" ) @@ -24,12 +25,13 @@ var ( ) const ( - daggerDir = ".dagger" - envDir = "env" - stateDir = "state" - planDir = "plan" - manifestFile = "values.yaml" - computedFile = "computed.json" + daggerDir = ".dagger" + envDir = "env" + stateDir = "state" + planDir = "plan" + manifestFile = "values.yaml" + computedFile = "computed.json" + universeVersionConstraint = ">= 0.1, < 0.2" ) type Project struct { @@ -396,9 +398,7 @@ func vendorUniverse(ctx context.Context, p string) error { } log.Ctx(ctx).Debug().Str("mod", p).Msg("vendoring universe") - // FIXME(samalba): disabled install remote stdlib temporarily - // if err := mod.InstallStdlib(p); err != nil { - if err := stdlib.Vendor(ctx, p); err != nil { + if _, err := mod.Install(p, "alpha.dagger.io", universeVersionConstraint); err != nil { return err }