Add support for LocalAppData and .local/state/ fallback

This commit is contained in:
Sam Coe 2021-06-01 15:40:08 -04:00
parent 602167c0c7
commit 1d7ffc2013
No known key found for this signature in database
GPG key ID: 8E322C20F811D086
3 changed files with 54 additions and 22 deletions

View file

@ -18,6 +18,7 @@ const (
XDG_CONFIG_HOME = "XDG_CONFIG_HOME"
XDG_STATE_HOME = "XDG_STATE_HOME"
APP_DATA = "AppData"
LOCAL_APP_DATA = "LocalAppData"
)
// Config path precedence
@ -39,24 +40,34 @@ func ConfigDir() string {
}
// If the path does not exist try migrating config from default paths
if _, err := os.Stat(path); errors.Is(err, os.ErrNotExist) {
if !dirExists(path) {
_ = autoMigrateConfigDir(path)
}
return path
}
// State path precedence
// 1. XDG_CONFIG_HOME
// 2. LocalAppData (windows only)
// 3. HOME
func StateDir() string {
if path := os.Getenv(XDG_STATE_HOME); path != "" {
path = filepath.Join(path, "gh")
if !dirExists(path) {
_ = os.MkdirAll(path, 0755)
_ = autoMigrateStateDir(path)
}
return path
var path string
if a := os.Getenv(XDG_STATE_HOME); a != "" {
path = filepath.Join(a, "gh")
} else if b := os.Getenv(LOCAL_APP_DATA); runtime.GOOS == "windows" && b != "" {
path = filepath.Join(b, "GitHub CLI")
} else {
c, _ := os.UserHomeDir()
path = filepath.Join(c, ".local", "state", "gh")
}
return ConfigDir()
// If the path does not exist try migrating state from default paths
if !dirExists(path) {
_ = autoMigrateStateDir(path)
}
return path
}
var errSamePath = errors.New("same path")

View file

@ -346,9 +346,10 @@ func Test_StateDir(t *testing.T) {
tempDir := t.TempDir()
tests := []struct {
name string
env map[string]string
output string
name string
onlyWindows bool
env map[string]string
output string
}{
{
name: "HOME/USERPROFILE specified",
@ -356,11 +357,11 @@ func Test_StateDir(t *testing.T) {
"XDG_STATE_HOME": "",
"GH_CONFIG_DIR": "",
"XDG_CONFIG_HOME": "",
"AppData": "",
"LocalAppData": "",
"USERPROFILE": tempDir,
"HOME": tempDir,
},
output: filepath.Join(tempDir, ".config", "gh"),
output: filepath.Join(tempDir, ".local", "state", "gh"),
},
{
name: "XDG_STATE_HOME specified",
@ -370,15 +371,28 @@ func Test_StateDir(t *testing.T) {
output: filepath.Join(tempDir, "gh"),
},
{
name: "GH_CONFIG_DIR specified",
name: "LocalAppData specified",
onlyWindows: true,
env: map[string]string{
"GH_CONFIG_DIR": filepath.Join(tempDir, "gh_config_dir"),
"LocalAppData": tempDir,
},
output: filepath.Join(tempDir, "gh_config_dir"),
output: filepath.Join(tempDir, "GitHub CLI"),
},
{
name: "XDG_STATE_HOME and LocalAppData specified",
onlyWindows: true,
env: map[string]string{
"XDG_STATE_HOME": tempDir,
"LocalAppData": tempDir,
},
output: filepath.Join(tempDir, "gh"),
},
}
for _, tt := range tests {
if tt.onlyWindows && runtime.GOOS != "windows" {
continue
}
t.Run(tt.name, func(t *testing.T) {
if tt.env != nil {
for k, v := range tt.env {
@ -443,7 +457,7 @@ func Test_autoMigrateStateDir_migration(t *testing.T) {
homeDir := t.TempDir()
migrateDir := t.TempDir()
homeConfigDir := filepath.Join(homeDir, ".config", "gh")
migrateConfigDir := filepath.Join(migrateDir, ".config", "gh")
migrateStateDir := filepath.Join(migrateDir, ".local", "state", "gh")
homeEnvVar := "HOME"
if runtime.GOOS == "windows" {
@ -458,14 +472,14 @@ func Test_autoMigrateStateDir_migration(t *testing.T) {
err = ioutil.WriteFile(filepath.Join(homeConfigDir, "state.yml"), nil, 0755)
assert.NoError(t, err)
err = autoMigrateStateDir(migrateConfigDir)
err = autoMigrateStateDir(migrateStateDir)
assert.NoError(t, err)
files, err := ioutil.ReadDir(homeConfigDir)
assert.NoError(t, err)
assert.Equal(t, 0, len(files))
files, err = ioutil.ReadDir(migrateConfigDir)
files, err = ioutil.ReadDir(migrateStateDir)
assert.NoError(t, err)
assert.Equal(t, 1, len(files))
assert.Equal(t, "state.yml", files[0].Name())

View file

@ -3,6 +3,8 @@ package update
import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
"regexp"
"strconv"
"strings"
@ -83,9 +85,14 @@ func setStateEntry(stateFilePath string, t time.Time, r ReleaseInfo) error {
if err != nil {
return err
}
_ = ioutil.WriteFile(stateFilePath, content, 0600)
return nil
err = os.MkdirAll(filepath.Dir(stateFilePath), 0755)
if err != nil {
return err
}
err = ioutil.WriteFile(stateFilePath, content, 0600)
return err
}
func versionGreaterThan(v, w string) bool {