diff --git a/cmd/dagger/cmd/mod/file.go b/cmd/dagger/cmd/mod/file.go index 6d905f09..13c869d8 100644 --- a/cmd/dagger/cmd/mod/file.go +++ b/cmd/dagger/cmd/mod/file.go @@ -10,6 +10,8 @@ import ( "path/filepath" "regexp" "strings" + + "github.com/spf13/viper" ) const filePath = "./cue.mod/dagger.mod.cue" @@ -20,6 +22,8 @@ const tmpBasePath = "./cue.mod/tmp" type file struct { module string require []*require + + workspacePath string } func readPath(workspacePath string) (*file, error) { @@ -33,6 +37,8 @@ func readPath(workspacePath string) (*file, error) { return nil, err } + modFile.workspacePath = workspacePath + return modFile, nil } @@ -93,8 +99,75 @@ func nonEmptyLines(b []byte) []string { return lines } -func (f *file) write(workspacePath string) error { - return ioutil.WriteFile(path.Join(workspacePath, filePath), f.contents().Bytes(), 0600) +func (f *file) processRequire(req *require, upgrade bool) (bool, error) { + var isNew bool + + tmpPath := path.Join(f.workspacePath, tmpBasePath, req.repo) + if err := os.MkdirAll(tmpPath, 0755); err != nil { + return false, fmt.Errorf("error creating tmp dir for cloning package") + } + defer os.RemoveAll(tmpPath) + + // clone the repo + privateKeyFile := viper.GetString("private-key-file") + privateKeyPassword := viper.GetString("private-key-password") + r, err := clone(req, tmpPath, privateKeyFile, privateKeyPassword) + if err != nil { + return isNew, fmt.Errorf("error downloading package %s: %w", req, err) + } + + existing := f.search(req) + destPath := path.Join(f.workspacePath, destBasePath) + + // requirement is new, so we should move the files and add it to the mod file + if existing == nil { + if err := move(req, tmpPath, destPath); err != nil { + return isNew, err + } + f.require = append(f.require, req) + isNew = true + return isNew, nil + } + + if upgrade { + latestTag, err := r.latestTag() + if err != nil { + return isNew, err + } + + if latestTag == "" { + return isNew, fmt.Errorf("repo does not have a tag") + } + + req.version = latestTag + } + + c, err := compareVersions(existing.version, req.version) + if err != nil { + return isNew, err + } + + // the existing requirement is newer so we skip installation + if c > 0 { + return isNew, nil + } + + // the new requirement is newer so we checkout the cloned repo to that tag, change the version in the existing + // requirement and replace the code in the /pkg folder + existing.version = req.version + if err = r.checkout(req.version); err != nil { + return isNew, err + } + if err = replace(req, tmpPath, destPath); err != nil { + return isNew, err + } + isNew = true + + return isNew, nil +} + +func (f *file) write() error { + return ioutil.WriteFile(path.Join(f.workspacePath, filePath), f.contents().Bytes(), 0600) } func (f *file) contents() *bytes.Buffer { diff --git a/cmd/dagger/cmd/mod/get.go b/cmd/dagger/cmd/mod/get.go index b1b73228..30638764 100644 --- a/cmd/dagger/cmd/mod/get.go +++ b/cmd/dagger/cmd/mod/get.go @@ -1,10 +1,6 @@ package mod import ( - "fmt" - "os" - "path" - "github.com/hashicorp/go-version" "github.com/spf13/cobra" "github.com/spf13/viper" @@ -29,10 +25,6 @@ var getCmd = &cobra.Command{ lg := logger.New() ctx := lg.WithContext(cmd.Context()) - if len(args) == 0 { - lg.Fatal().Msg("need to specify package name in command argument") - } - workspace := common.CurrentWorkspace(ctx) st := common.CurrentEnvironmentState(ctx, workspace) doneCh := common.TrackWorkspaceCommand(ctx, cmd, workspace, st, &telemetry.Property{ @@ -48,21 +40,28 @@ var getCmd = &cobra.Command{ // parse packages to install var packages []*require - for _, arg := range args { - p, err := parseArgument(arg) - if err != nil { - lg.Error().Err(err).Msgf("error parsing package %s", arg) - continue - } + var upgrade bool - packages = append(packages, p) + if len(args) == 0 { + lg.Info().Msg("upgrading installed packages...") + packages = modFile.require + upgrade = true + } else { + for _, arg := range args { + p, err := parseArgument(arg) + if err != nil { + lg.Error().Err(err).Msgf("error parsing package %s", arg) + continue + } + packages = append(packages, p) + } } // download packages for _, p := range packages { - isNew, err := processRequire(workspace.Path, p, modFile) + isNew, err := modFile.processRequire(p, upgrade) if err != nil { - lg.Error().Err(err).Msg("error processing package") + lg.Error().Err(err).Msgf("error processing package %s", p.repo) } if isNew { @@ -71,70 +70,14 @@ var getCmd = &cobra.Command{ } // write to mod file in the current dir - if err = modFile.write(workspace.Path); err != nil { + if err = modFile.write(); err != nil { lg.Error().Err(err).Msg("error writing to mod file") } - lg.Info().Msg("checking for new versions...") - <-doneCh }, } -func processRequire(workspacePath string, req *require, modFile *file) (bool, error) { - var isNew bool - - tmpPath := path.Join(workspacePath, tmpBasePath, req.repo) - if err := os.MkdirAll(tmpPath, 0755); err != nil { - return false, fmt.Errorf("error creating tmp dir for cloning package") - } - defer os.RemoveAll(tmpPath) - - // clone the repo - privateKeyFile := viper.GetString("private-key-file") - privateKeyPassword := viper.GetString("private-key-password") - r, err := clone(req, tmpPath, privateKeyFile, privateKeyPassword) - if err != nil { - return isNew, fmt.Errorf("error downloading package %s: %w", req, err) - } - - existing := modFile.search(req) - destPath := path.Join(workspacePath, destBasePath) - - // requirement is new, so we should move the files and add it to the mod file - if existing == nil { - if err := move(req, tmpPath, destPath); err != nil { - return isNew, err - } - modFile.require = append(modFile.require, req) - isNew = true - return isNew, nil - } - - c, err := compareVersions(existing.version, req.version) - if err != nil { - return isNew, err - } - - // the existing requirement is newer so we skip installation - if c > 0 { - return isNew, nil - } - - // the new requirement is newer so we checkout the cloned repo to that tag, change the version in the existing - // requirement and replace the code in the /pkg folder - existing.version = req.version - if err = r.checkout(req.version); err != nil { - return isNew, err - } - if err = replace(req, tmpPath, destPath); err != nil { - return isNew, err - } - isNew = true - - return isNew, nil -} - func compareVersions(reqV1, reqV2 string) (int, error) { v1, err := version.NewVersion(reqV1) if err != nil { @@ -145,10 +88,15 @@ func compareVersions(reqV1, reqV2 string) (int, error) { if err != nil { return 0, err } + if v1.LessThan(v2) { return -1, nil } + if v1.Equal(v2) { + return 0, nil + } + return 1, nil }