Skip to content

Commit

Permalink
cmd: Make the hvm dot file independent of OS and environment
Browse files Browse the repository at this point in the history
Closes #19
  • Loading branch information
jmooring authored Sep 19, 2023
1 parent 2d38547 commit 463412b
Show file tree
Hide file tree
Showing 6 changed files with 86 additions and 52 deletions.
36 changes: 10 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,26 +53,18 @@ Add this function to $HOME/.zshrc
```zsh
# Hugo Version Manager: override path to the hugo executable.
hugo() {
hvm_common_msg="Run 'hvm use' to fix or 'hvm disable' to disable version management."
hvm_show_status=true
if [ -f ".hvm" ]; then
hugo_bin=$(cat ".hvm" 2> /dev/null)
if ! echo "${hugo_bin}" | grep -q "hugo$"; then
>&2 printf "The .hvm file in this directory is invalid.\\n"
>&2 printf "%s\\n" "${hvm_common_msg}"
return 1
fi
if [ ! -f "${hugo_bin}" ]; then
>&2 printf "Unable to find %s.\\n" "${hugo_bin}"
>&2 printf "%s\\n" "${hvm_common_msg}"
hugo_bin=$(hvm status --printExecPath 2> /dev/null)
if [ -z "${hugo_bin}" ]; then
if ! hugo_bin=$(which hugo); then
>&2 printf "Command not found.\\n"
return 1
fi
else
if [ "${hvm_show_status}" == true ]; then
>&2 printf "Hugo version management is enabled in this directory.\\n"
>&2 printf "Run 'hvm status' for details, or 'hvm disable' to disable.\\n\\n"
fi
else
hugo_bin=$(which hugo)
fi
"${hugo_bin}" "$@"
}
Expand All @@ -87,26 +79,18 @@ Add this function to $HOME/.bashrc
```bash
# Hugo Version Manager: override path to the hugo executable.
hugo() {
hvm_common_msg="Run 'hvm use' to fix or 'hvm disable' to disable version management."
hvm_show_status=true
if [ -f ".hvm" ]; then
hugo_bin=$(cat ".hvm" 2> /dev/null)
if ! echo "${hugo_bin}" | grep -q "hugo$"; then
>&2 printf "The .hvm file in this directory is invalid.\\n"
>&2 printf "%s\\n" "${hvm_common_msg}"
return 1
fi
if [ ! -f "${hugo_bin}" ]; then
>&2 printf "Unable to find %s.\\n" "${hugo_bin}"
>&2 printf "%s\\n" "${hvm_common_msg}"
hugo_bin=$(hvm status --printExecPath 2> /dev/null)
if [ -z "${hugo_bin}" ]; then
if ! hugo_bin=$(which hugo); then
>&2 printf "Command not found.\\n"
return 1
fi
else
if [ "${hvm_show_status}" == true ]; then
>&2 printf "Hugo version management is enabled in this directory.\\n"
>&2 printf "Run 'hvm status' for details, or 'hvm disable' to disable.\\n\\n"
fi
else
hugo_bin=$(which hugo)
fi
"${hugo_bin}" "$@"
}
Expand Down
56 changes: 39 additions & 17 deletions cmd/hvm/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (

"github.com/jmooring/hvm/pkg/helpers"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"golang.org/x/mod/semver"
)

Expand All @@ -44,6 +45,8 @@ location. The "default" directory created by the "install" command is excluded.`

func init() {
rootCmd.AddCommand(statusCmd)
statusCmd.Flags().Bool("printExecPath", false, "Print the path to the Hugo executable if version\nmanagement is enabled in the current directory")
viper.BindPFlag("printExecPath", statusCmd.Flags().Lookup("printExecPath"))
}

// status displays a list of cached assets, the size of the cache, and the
Expand All @@ -59,10 +62,20 @@ func status() error {
if err != nil {
return err
}
if version == "" {
fmt.Println("Version management is disabled in the current directory.")

if viper.GetBool("printExecPath") {
if version == "" {
fmt.Fprintf(os.Stderr, "Version management is disabled in the current directory.\n")
return nil
}
fmt.Println(filepath.Join(App.CacheDirPath, version, getExecName()))
return nil
} else {
fmt.Printf("The current directory is configured to use Hugo %s.\n", version)
if version == "" {
fmt.Println("Version management is disabled in the current directory.")
} else {
fmt.Printf("The current directory is configured to use Hugo %s.\n", version)
}
}

// Get tags; ignore App.DefaultDirName.
Expand Down Expand Up @@ -91,9 +104,21 @@ func status() error {
}
fmt.Println()

// Determine cache size; ignore file in App.DefaultDirName.
var size int64
err = fs.WalkDir(os.DirFS(App.CacheDirPath), ".", func(path string, d fs.DirEntry, err error) error {
size, err := getCacheSize()
if err != nil {
return err
}
fmt.Println("Cache size:", size/1000000, "MB")
fmt.Println("Cache directory:", App.CacheDirPath)

return nil
}

// getCacheSize returns the size of the cache directory, in bytes, excluding
// the App.DefaultDirName subdirectory.
func getCacheSize() (int64, error) {
var size int64 = 0
err := fs.WalkDir(os.DirFS(App.CacheDirPath), ".", func(path string, d fs.DirEntry, err error) error {
if err != nil {
return err
}
Expand All @@ -109,13 +134,10 @@ func status() error {
})

if err != nil {
return err
return 0, err
}

fmt.Println("Cache size:", size/1000000, "MB")
fmt.Println("Cache directory:", App.CacheDirPath)

return nil
return size, nil
}

// getVersionFromDotFile returns the semver string from the app dot file in the
Expand Down Expand Up @@ -149,19 +171,19 @@ func getVersionFromDotFile(path string) (string, error) {
return "", fmt.Errorf("the %s file in the current directory is empty: %s", App.DotFileName, theFix)
}

re := regexp.MustCompile(`.+(v\d+\.\d+\.\d+).+`)
match := re.FindStringSubmatch(dotHvmContent)
if match == nil {
re := regexp.MustCompile(`^v\d+\.\d+\.\d+$`)
match := re.MatchString(dotHvmContent)
if !match {
return "", fmt.Errorf("the %s file in the current directory has an invalid format: %s", App.DotFileName, theFix)
}

exists, err = helpers.Exists(dotHvmContent)
exists, err = helpers.Exists(filepath.Join(App.CacheDirPath, dotHvmContent, getExecName()))
if err != nil {
return "", err
}
if !exists {
return "", fmt.Errorf("the %s file in the current directory points to an invalid path (%s): %s", App.DotFileName, dotHvmContent, theFix)
return "", fmt.Errorf("the %s file in the current directory contains an invalid version (%s): %s", App.DotFileName, dotHvmContent, theFix)
}

return (match[1]), nil
return (dotHvmContent), nil
}
24 changes: 24 additions & 0 deletions cmd/hvm/testscripts/status-print-execpath.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# 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 status --printExecPath
[darwin] stdout '^home/Library/Caches/hvm/v0.117.0/hugo\n$'
[linux] stdout '^cache/hvm/v0.117.0/hugo\n$'
[windows] stdout '^cache\\hvm\\v0.117.0\\hugo.exe\n$'

# Files
-- .hvm --
v0.117.0
-- home/Library/Caches/hvm/v0.117.0/hugo --
darwin-exec-bytes
-- cache/hvm/v0.117.0/hugo --
linux-exec-bytes
-- cache/hvm/v0.117.0/hugo.exe --
windows-exec-bytes
2 changes: 1 addition & 1 deletion cmd/hvm/testscripts/status.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ stdout 'v0.117.0\n'

# Files
-- .hvm --
cache/hvm/v0.117.0/hugo
v0.117.0
-- home/Library/Caches/hvm/v0.117.0/hugo --
darwin-exec-bytes
-- cache/hvm/v0.117.0/hugo --
Expand Down
4 changes: 2 additions & 2 deletions cmd/hvm/testscripts/status_err_3.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

# Test
! exec hvm status
stderr 'the \.hvm file in the current directory points to an invalid path'
stderr 'the \.hvm file in the current directory has an invalid format'

-- .hvm --
xxx/v0.118.2/xxx
xxx
16 changes: 10 additions & 6 deletions cmd/hvm/use.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,12 +162,8 @@ func newRepository() *repository {

// newAsset creates a new asset object, returning a pointer to same.
func newAsset() *asset {
execName := "hugo"
if runtime.GOOS == "windows" {
execName = "hugo.exe"
}
a := asset{
execName: execName,
execName: getExecName(),
}

return &a
Expand Down Expand Up @@ -376,6 +372,14 @@ func (a *asset) downloadAsset() error {
return nil
}

// getExecName returns the name of the Hugo executable file.
func getExecName() string {
if runtime.GOOS == "windows" {
return "hugo.exe"
}
return "hugo"
}

// getExecPath returns the path of the Hugo executable file.
func (a *asset) getExecPath() string {
return filepath.Join(App.CacheDirPath, a.tag, a.execName)
Expand All @@ -388,7 +392,7 @@ func (a *asset) createDotFile() error {
return err
}

err = os.WriteFile(filepath.Join(wd, App.DotFileName), []byte(a.getExecPath()+"\n"), 0644)
err = os.WriteFile(filepath.Join(wd, App.DotFileName), []byte(a.tag), 0644)
if err != nil {
return err
}
Expand Down

0 comments on commit 463412b

Please sign in to comment.