support upgrading existing packages with empty mod get command

Signed-off-by: Tihomir Jovicic <tihomir.jovicic.develop@gmail.com>
This commit is contained in:
Tihomir Jovicic 2021-08-12 10:47:59 +02:00
parent 2102e78c1f
commit 6a0b74416a
2 changed files with 97 additions and 76 deletions

View File

@ -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 {

View File

@ -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
}