Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

enhancement: implement --tags semver to use/install a specific version #107

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 18 additions & 1 deletion cmd/cmd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,35 +23,52 @@ import (
"github.com/rogpeppe/go-internal/testscript"
)

func TestCommands(t *testing.T) {
func TestCommand(t *testing.T) {
testscript.Run(t, testscript.Params{
Dir: "testscripts",
Setup: func(env *testscript.Env) error {
env.Setenv("HVM_GITHUBTOKEN", os.Getenv("HVM_GITHUBTOKEN"))
return nil
},
})
}
func TestCommandConfig(t *testing.T) {
testscript.Run(t, testscript.Params{
Dir: "testscripts/config",
Setup: func(env *testscript.Env) error {
env.Setenv("HVM_GITHUBTOKEN", os.Getenv("HVM_GITHUBTOKEN"))
return nil
},
})
}
func TestCommandInstall(t *testing.T) {
testscript.Run(t, testscript.Params{
Dir: "testscripts/install",
Setup: func(env *testscript.Env) error {
env.Setenv("HVM_GITHUBTOKEN", os.Getenv("HVM_GITHUBTOKEN"))
return nil
},
})
}
func TestCommandRemove(t *testing.T) {
testscript.Run(t, testscript.Params{
Dir: "testscripts/remove",
Setup: func(env *testscript.Env) error {
env.Setenv("HVM_GITHUBTOKEN", os.Getenv("HVM_GITHUBTOKEN"))
return nil
},
})
}
func TestCommandStatus(t *testing.T) {
testscript.Run(t, testscript.Params{
Dir: "testscripts/status",
Setup: func(env *testscript.Env) error {
env.Setenv("HVM_GITHUBTOKEN", os.Getenv("HVM_GITHUBTOKEN"))
return nil
},
})
}
func TestCommandUse(t *testing.T) {
testscript.Run(t, testscript.Params{
Dir: "testscripts/use",
Setup: func(env *testscript.Env) error {
Expand Down
16 changes: 14 additions & 2 deletions cmd/install.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,26 +35,33 @@ to use when version management is disabled in the current directory. It then
downloads, extracts, and caches the release asset for your operating system and
architecture, placing a copy in the cache "default" directory.

You may bypass the selection screen using --latest or --tag

To use this version when version management is disabled in the current
directory, the cache "default" directory must be in your PATH. If it is not,
you will be prompted to add it when installation is complete.`,
Run: func(cmd *cobra.Command, args []string) {
useLatest, err := cmd.Flags().GetBool("latest")
cobra.CheckErr(err)

err = install(useLatest)
useTag, err := cmd.Flags().GetString("tag")
cobra.CheckErr(err)

err = install(useLatest, useTag)
cobra.CheckErr(err)
},
}

func init() {
rootCmd.AddCommand(installCmd)
installCmd.Flags().Bool("latest", false, "Install the latest version")
installCmd.Flags().String("tag", "", "Use specific tag version")
installCmd.MarkFlagsMutuallyExclusive("latest", "tag")
}

// install sets the version of the Hugo executable to use when version
// management is disabled in the current directory.
func install(useLatest bool) error {
func install(useLatest bool, useTag string) error {
asset := newAsset()
repo := newRepository()

Expand All @@ -63,6 +70,11 @@ func install(useLatest bool) error {
if err != nil {
return err
}
} else if useTag != "" {
err := repo.getSpecificTag(asset, useTag)
if err != nil {
return err
}
} else {
msg := "Select a version to use when version management is disabled"
err := repo.selectTag(asset, msg)
Expand Down
2 changes: 1 addition & 1 deletion cmd/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ func status(cmd *cobra.Command) error {
fmt.Printf("Would you like to get it now? (Y/n): ")
fmt.Scanln(&r)
if len(r) == 0 || strings.ToLower(string(r[0])) == "y" {
err = use(true, false)
err = use(true, false, "")
if err != nil {
return err
}
Expand Down
12 changes: 12 additions & 0 deletions cmd/testscripts/install/install_tag_fail_exclusive.txtar
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# User cache and config dirs (we use os.UserCacheDir and os.UserCongfigDir)
[darwin] env HOME=home
[darwin] mkdir "$HOME/Library/Caches"
[darwin] mkdir "$HOME/Library/Application Support"
[linux] env XDG_CACHE_HOME=cache
[linux] env XDG_CONFIG_HOME=config
[windows] env LocalAppData=cache
[windows] env AppData=config

# Test
! exec hvm install --latest --tag x
stderr 'Error: if any flags in the group \[latest tag\] are set none of the others can be; \[latest tag\] were all set\n'
12 changes: 12 additions & 0 deletions cmd/testscripts/install/install_tag_fail_invalid.txtar
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# User cache and config dirs (we use os.UserCacheDir and os.UserCongfigDir)
[darwin] env HOME=home
[darwin] mkdir "$HOME/Library/Caches"
[darwin] mkdir "$HOME/Library/Application Support"
[linux] env XDG_CACHE_HOME=cache
[linux] env XDG_CONFIG_HOME=config
[windows] env LocalAppData=cache
[windows] env AppData=config

# Test
! exec hvm install --tag x1
stderr 'Error: invalid tag: vx1\n'
12 changes: 12 additions & 0 deletions cmd/testscripts/install/install_tag_fail_missing-argument.txtar
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# User cache and config dirs (we use os.UserCacheDir and os.UserCongfigDir)
[darwin] env HOME=home
[darwin] mkdir "$HOME/Library/Caches"
[darwin] mkdir "$HOME/Library/Application Support"
[linux] env XDG_CACHE_HOME=cache
[linux] env XDG_CONFIG_HOME=config
[windows] env LocalAppData=cache
[windows] env AppData=config

# Test
! exec hvm install --tag
stderr 'Error: flag needs an argument: --tag\n'
12 changes: 12 additions & 0 deletions cmd/testscripts/install/install_tag_fail_not-found.txtar
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# User cache and config dirs (we use os.UserCacheDir and os.UserCongfigDir)
[darwin] env HOME=home
[darwin] mkdir "$HOME/Library/Caches"
[darwin] mkdir "$HOME/Library/Application Support"
[linux] env XDG_CACHE_HOME=cache
[linux] env XDG_CONFIG_HOME=config
[windows] env LocalAppData=cache
[windows] env AppData=config

# Test
! exec hvm install --tag v0.1.2
stderr 'Error: tag not found: v0\.1\.2\n'
13 changes: 13 additions & 0 deletions cmd/testscripts/install/install_tag_pass.txtar
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# User cache and config dirs (we use os.UserCacheDir and os.UserCongfigDir)
[darwin] env HOME=home
[darwin] mkdir "$HOME/Library/Caches"
[darwin] mkdir "$HOME/Library/Application Support"
[linux] env XDG_CACHE_HOME=cache
[linux] env XDG_CONFIG_HOME=config
[windows] env LocalAppData=cache
[windows] env AppData=config

# Test
exec hvm install --tag v0.138.0
stdout 'Downloading v.* done.\n'
stdout 'Installation of v.* complete.\n'
12 changes: 12 additions & 0 deletions cmd/testscripts/use/use_tag_fail_exclusive.txtar
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# User cache and config dirs (we use os.UserCacheDir and os.UserCongfigDir)
[darwin] env HOME=home
[darwin] mkdir "$HOME/Library/Caches"
[darwin] mkdir "$HOME/Library/Application Support"
[linux] env XDG_CACHE_HOME=cache
[linux] env XDG_CONFIG_HOME=config
[windows] env LocalAppData=cache
[windows] env AppData=config

# Test
! exec hvm use --latest --tag x
stderr 'Error: if any flags in the group \[latest tag\] are set none of the others can be; \[latest tag\] were all set\n'
12 changes: 12 additions & 0 deletions cmd/testscripts/use/use_tag_fail_invalid.txtar
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# User cache and config dirs (we use os.UserCacheDir and os.UserCongfigDir)
[darwin] env HOME=home
[darwin] mkdir "$HOME/Library/Caches"
[darwin] mkdir "$HOME/Library/Application Support"
[linux] env XDG_CACHE_HOME=cache
[linux] env XDG_CONFIG_HOME=config
[windows] env LocalAppData=cache
[windows] env AppData=config

# Test
! exec hvm use --tag x1
stderr 'Error: invalid tag: vx1\n'
12 changes: 12 additions & 0 deletions cmd/testscripts/use/use_tag_fail_misssing-argument.txtar
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# User cache and config dirs (we use os.UserCacheDir and os.UserCongfigDir)
[darwin] env HOME=home
[darwin] mkdir "$HOME/Library/Caches"
[darwin] mkdir "$HOME/Library/Application Support"
[linux] env XDG_CACHE_HOME=cache
[linux] env XDG_CONFIG_HOME=config
[windows] env LocalAppData=cache
[windows] env AppData=config

# Test
! exec hvm use --tag
stderr 'Error: flag needs an argument: --tag\n'
12 changes: 12 additions & 0 deletions cmd/testscripts/use/use_tag_fail_not-found.txtar
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# User cache and config dirs (we use os.UserCacheDir and os.UserCongfigDir)
[darwin] env HOME=home
[darwin] mkdir "$HOME/Library/Caches"
[darwin] mkdir "$HOME/Library/Application Support"
[linux] env XDG_CACHE_HOME=cache
[linux] env XDG_CONFIG_HOME=config
[windows] env LocalAppData=cache
[windows] env AppData=config

# Test
! exec hvm use --tag v0.1.2
stderr 'Error: tag not found: v0\.1\.2\n'
12 changes: 12 additions & 0 deletions cmd/testscripts/use/use_tag_pass.txtar
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# User cache and config dirs (we use os.UserCacheDir and os.UserCongfigDir)
[darwin] env HOME=home
[darwin] mkdir "$HOME/Library/Caches"
[darwin] mkdir "$HOME/Library/Application Support"
[linux] env XDG_CACHE_HOME=cache
[linux] env XDG_CONFIG_HOME=config
[windows] env LocalAppData=cache
[windows] env AppData=config

# Test
exec hvm use --tag v0.138.0
stdout 'Downloading v.* done.\n'
99 changes: 99 additions & 0 deletions cmd/use-getSpecificTag_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
package cmd

import (
"fmt"
"slices"
"testing"
)

func newMockRepo(reverse bool) *repository {
r := repository{
tags: []string{"v1.2.3", "v1.2.2", "v1.2.1", "v1.2.0", "v1.1.2", "v1.1.1", "v1.1.0", "v1.0.0", "v0.2.2", "v0.2.1", "v0.2.0", "v0.1.2", "v0.1.1", "v0.1.0"},
latestTag: "v1.2.3",
}
if reverse {
slices.Reverse(r.tags)
}
return &r
}

var testCases = []struct {
given string
want string
}{
// invalid strings
{"", ""},
{"abc", ""},
{"a.b", ""},
{"v1.", ""},
{"v1.2.", ""},
{"v1.2.3.", ""},
{"v1.2.3.4", ""},
{"1.", ""},
{"1.2.", ""},
{"1.2.3.", ""},
{"1.2.3.4", ""},
// valid strings
{"v", "v1.2.3"},
{"v1", "v1.2.3"},
{"v1.2", "v1.2.3"},
{"v1.2.3", "v1.2.3"},
{"1", "v1.2.3"},
{"1.2", "v1.2.3"},
{"1.2.3", "v1.2.3"},
// major only use lookup
{"0", "v0.2.2"},
{"v0", "v0.2.2"},
{"1", "v1.2.3"},
{"v1", "v1.2.3"},
{"v1", "v1.2.3"},
// major and minor use lookup
{"0.1", "v0.1.2"},
{"v0.1", "v0.1.2"},
{"1.1", "v1.1.2"},
{"v1.1", "v1.1.2"},
{"0.2", "v0.2.2"},
{"v0.2", "v0.2.2"},
// latest-major, minor and lookup)
{".1", "v1.1.2"},
{"v.1", "v1.1.2"},
{".0", "v1.0.0"},
{"v.0", "v1.0.0"},
// Specific major taken from latestTag (no lookup)
{".2.1", "v1.2.1"},
{"v.2.1", "v1.2.1"},
{".2.1", "v1.2.1"},
{"v.2.1", "v1.2.1"},
}

func TestGetSpecificTagDescending(t *testing.T) {
// mock needed elements and sort config
Config.SortAscending = false
repo := newMockRepo(Config.SortAscending)
asset := newAsset()
for _, tc := range testCases {
t.Run(fmt.Sprintf("[%s] ShouldBe [%s]", tc.given, tc.want), func(t *testing.T) {
asset.tag = ""
err := repo.getSpecificTag(asset, tc.given)
if asset.tag != tc.want {
t.Fatalf("given(%s) -> calculated(%s) -> want(%s) : %s", tc.given, asset.tag, tc.want, err)
}
})
}
}

func TestGetSpecificTagAscending(t *testing.T) {
// mock needed elements and sort config
Config.SortAscending = true
repo := newMockRepo(Config.SortAscending)
asset := newAsset()
for _, tc := range testCases {
t.Run(fmt.Sprintf("[%s] ShouldBe [%s]", tc.given, tc.want), func(t *testing.T) {
asset.tag = ""
err := repo.getSpecificTag(asset, tc.given)
if asset.tag != tc.want {
t.Errorf("given(%s) -> calculated(%s) -> want(%s) : %s", tc.given, asset.tag, tc.want, err)
}
})
}
}
Loading
Loading