Skip to content

Commit 8169dfb

Browse files
committed
Merge branch 'ivanvc-ruby/fix-already-installed-return-code'
2 parents 45c31c9 + df5e283 commit 8169dfb

File tree

4 files changed

+123
-7
lines changed

4 files changed

+123
-7
lines changed

internal/cli/cli.go

+19-1
Original file line numberDiff line numberDiff line change
@@ -1092,11 +1092,18 @@ func installCommand(logger *log.Logger, toolName, version string, keepDownload b
10921092
if version == "" {
10931093
err = versions.Install(conf, plugin, dir, os.Stdout, os.Stderr)
10941094
if err != nil {
1095+
var vaiErr versions.VersionAlreadyInstalledError
1096+
if errors.As(err, &vaiErr) {
1097+
logger.Println(err)
1098+
return nil
1099+
}
1100+
10951101
if _, ok := err.(versions.NoVersionSetError); ok {
10961102
logger.Printf("No versions specified for %s in config files or environment", toolName)
10971103
os.Exit(1)
10981104
}
10991105

1106+
logger.Printf("error installing version: %v", err)
11001107
return err
11011108
}
11021109
} else {
@@ -1112,7 +1119,13 @@ func installCommand(logger *log.Logger, toolName, version string, keepDownload b
11121119
}
11131120

11141121
if err != nil {
1115-
logger.Printf("error installing version: %s", err)
1122+
var vaiErr versions.VersionAlreadyInstalledError
1123+
if errors.As(err, &vaiErr) {
1124+
logger.Println(err)
1125+
return nil
1126+
}
1127+
1128+
logger.Printf("error installing version: %v", err)
11161129
}
11171130
}
11181131
}
@@ -1123,6 +1136,11 @@ func installCommand(logger *log.Logger, toolName, version string, keepDownload b
11231136
func filterInstallErrors(errs []error) []error {
11241137
var filtered []error
11251138
for _, err := range errs {
1139+
var vaiErr versions.VersionAlreadyInstalledError
1140+
if errors.As(err, &vaiErr) {
1141+
continue
1142+
}
1143+
11261144
if _, ok := err.(versions.NoVersionSetError); !ok {
11271145
filtered = append(filtered, err)
11281146
}

internal/versions/versions.go

+19-5
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,17 @@ func (e NoVersionSetError) Error() string {
5151
return "no version set"
5252
}
5353

54+
// VersionAlreadyInstalledError is returned whenever a version is already
55+
// installed.
56+
type VersionAlreadyInstalledError struct {
57+
toolName string
58+
version toolversions.Version
59+
}
60+
61+
func (e VersionAlreadyInstalledError) Error() string {
62+
return fmt.Sprintf("version %s of %s is already installed", e.version.Value, e.toolName)
63+
}
64+
5465
// InstallAll installs all specified versions of every tool for the current
5566
// directory. Typically this will just be a single version, if not already
5667
// installed, but it may be multiple versions if multiple versions for the tool
@@ -94,13 +105,16 @@ func Install(conf config.Config, plugin plugins.Plugin, dir string, stdOut io.Wr
94105
}
95106

96107
for _, version := range versions.Versions {
97-
err := InstallOneVersion(conf, plugin, version, false, stdOut, stdErr)
98-
if err != nil {
99-
return err
108+
iErr := InstallOneVersion(conf, plugin, version, false, stdOut, stdErr)
109+
var vaiErr VersionAlreadyInstalledError
110+
if errors.As(iErr, &vaiErr) {
111+
err = errors.Join(err, iErr)
112+
} else if iErr != nil {
113+
return iErr
100114
}
101115
}
102116

103-
return nil
117+
return err
104118
}
105119

106120
// InstallVersion installs a version of a specific tool, the version may be an
@@ -143,7 +157,7 @@ func InstallOneVersion(conf config.Config, plugin plugins.Plugin, versionStr str
143157
installDir := installs.InstallPath(conf, plugin, version)
144158

145159
if installs.IsInstalled(conf, plugin, version) {
146-
return fmt.Errorf("version %s of %s is already installed", version, plugin.Name)
160+
return VersionAlreadyInstalledError{version: version, toolName: plugin.Name}
147161
}
148162

149163
env := map[string]string{

internal/versions/versions_test.go

+28-1
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,30 @@ func TestInstall(t *testing.T) {
122122
assertVersionInstalled(t, conf.DataDir, plugin.Name, "1.0.0")
123123
assertVersionInstalled(t, conf.DataDir, plugin.Name, "2.0.0")
124124
})
125+
126+
t.Run("if multiple versions are defined and installed returns an error", func(t *testing.T) {
127+
conf, plugin := generateConfig(t)
128+
stdout, stderr := buildOutputs()
129+
currentDir := t.TempDir()
130+
131+
versions := "1.0.0 2.0.0"
132+
// write a version file
133+
data := []byte(fmt.Sprintf("%s %s", plugin.Name, versions))
134+
err := os.WriteFile(filepath.Join(currentDir, ".tool-versions"), data, 0o666)
135+
assert.NoError(t, err)
136+
137+
err = Install(conf, plugin, currentDir, &stdout, &stderr)
138+
assert.NoError(t, err)
139+
140+
assertVersionInstalled(t, conf.DataDir, plugin.Name, "1.0.0")
141+
assertVersionInstalled(t, conf.DataDir, plugin.Name, "2.0.0")
142+
143+
err = Install(conf, plugin, currentDir, &stdout, &stderr)
144+
assert.Error(t, err)
145+
// Expect a VersionAlreadyInstalledError
146+
var eerr VersionAlreadyInstalledError
147+
assert.ErrorAs(t, err, &eerr)
148+
})
125149
}
126150

127151
func TestInstallVersion(t *testing.T) {
@@ -204,7 +228,10 @@ func TestInstallOneVersion(t *testing.T) {
204228

205229
// Install a second time
206230
err = InstallOneVersion(conf, plugin, "1.0.0", false, &stdout, &stderr)
207-
assert.NotNil(t, err)
231+
assert.Error(t, err)
232+
// Expect a VersionAlreadyInstalledError
233+
var eerr VersionAlreadyInstalledError
234+
assert.ErrorAs(t, err, &eerr)
208235
})
209236

210237
t.Run("creates download directory", func(t *testing.T) {

test/install_command.bats

+57
Original file line numberDiff line numberDiff line change
@@ -321,3 +321,60 @@ EOM
321321
# [ "$status" -eq 0 ]
322322
# [[ "$output" == *'asdf: Warn:'*'not be preserved'* ]]
323323
#}
324+
325+
@test "install command without arguments installs version a second time without errors" {
326+
cd "$PROJECT_DIR"
327+
echo -n 'dummy 1.2.0' >".tool-versions"
328+
run asdf install
329+
[ "$status" -eq 0 ]
330+
[ "$(cat "$ASDF_DIR/installs/dummy/1.2.0/version")" = "1.2.0" ]
331+
332+
run asdf install
333+
[ "$status" -eq 0 ]
334+
}
335+
336+
@test "install command with tool installs version a second time without errors" {
337+
cd "$PROJECT_DIR"
338+
echo -n 'dummy 1.2.0' >".tool-versions"
339+
run asdf install dummy
340+
[ "$status" -eq 0 ]
341+
[ "$(cat "$ASDF_DIR/installs/dummy/1.2.0/version")" = "1.2.0" ]
342+
343+
run asdf install dummy
344+
[ "$status" -eq 0 ]
345+
}
346+
347+
@test "install command with tool and version installs version a second time without errors" {
348+
run asdf install dummy 1.0.0
349+
[ "$status" -eq 0 ]
350+
[ "$(cat "$ASDF_DIR/installs/dummy/1.0.0/version")" = "1.0.0" ]
351+
352+
run asdf install dummy 1.0.0
353+
[ "$status" -eq 0 ]
354+
}
355+
356+
@test "install command with tool and different version installs version a second time without errors" {
357+
cd "$PROJECT_DIR"
358+
echo -n 'dummy 1.0.0 1.1.0' >".tool-versions"
359+
360+
run asdf install dummy 1.0.0
361+
[ "$status" -eq 0 ]
362+
[ "$(cat "$ASDF_DIR/installs/dummy/1.0.0/version")" = "1.0.0" ]
363+
364+
run asdf install
365+
[ "$status" -eq 0 ]
366+
[ "$(cat "$ASDF_DIR/installs/dummy/1.1.0/version")" = "1.1.0" ]
367+
}
368+
369+
@test "install command with two tools installs tool version a second time without errors" {
370+
cd "$PROJECT_DIR"
371+
printf "dummy 1.0.0\nlegacy-dummy 1.0.0" >"$PROJECT_DIR/.tool-versions"
372+
373+
run asdf install dummy 1.0.0
374+
[ "$status" -eq 0 ]
375+
[ "$(cat "$ASDF_DIR/installs/dummy/1.0.0/version")" = "1.0.0" ]
376+
377+
run asdf install
378+
[ "$status" -eq 0 ]
379+
[ "$(cat "$ASDF_DIR/installs/legacy-dummy/1.0.0/version")" = "1.0.0" ]
380+
}

0 commit comments

Comments
 (0)