From 8f370861751e9f1b6711bdbc022c4e7a2481a08d Mon Sep 17 00:00:00 2001 From: Hoang Nguyen Date: Mon, 6 Jan 2025 00:00:00 +0700 Subject: [PATCH 1/3] Replace the usage of go-homedir with os.UserHomeDir() Ref: https://github.com/mitchellh/go-homedir/issues/34 --- cmd/pro/start.go | 3 +-- go.mod | 2 +- pkg/agent/workspace.go | 3 +-- pkg/command/user.go | 5 ++--- pkg/config/dir.go | 4 +--- pkg/encoding/encoding.go | 4 ++-- pkg/ide/fleet/fleet.go | 3 +-- pkg/ide/jetbrains/generic.go | 3 +-- pkg/ide/openvscode/openvscode.go | 3 +-- pkg/ide/vscode/vscode.go | 3 +-- pkg/platform/client/client.go | 3 +-- pkg/ssh/config.go | 3 +-- pkg/ssh/keys.go | 3 +-- pkg/ssh/ssh_add.go | 3 +-- pkg/telemetry/helpers.go | 4 ++-- 15 files changed, 18 insertions(+), 31 deletions(-) diff --git a/cmd/pro/start.go b/cmd/pro/start.go index 86653b234..161cfad79 100644 --- a/cmd/pro/start.go +++ b/cmd/pro/start.go @@ -21,7 +21,6 @@ import ( "github.com/denisbrodbeck/machineid" jsonpatch "github.com/evanphx/json-patch" "github.com/mgutz/ansi" - "github.com/mitchellh/go-homedir" "github.com/skratchdot/open-golang/open" storagev1 "github.com/loft-sh/api/v4/pkg/apis/storage/v1" @@ -1693,7 +1692,7 @@ func getMachineUID(log log.Logger) string { } // get $HOME to distinguish two users on the same machine // will be hashed later together with the ID - home, err := homedir.Dir() + home, err := os.UserHomeDir() if err != nil { home = "error" if log != nil { diff --git a/go.mod b/go.mod index a29c76ced..d55256fe2 100644 --- a/go.mod +++ b/go.mod @@ -29,7 +29,6 @@ require ( github.com/loft-sh/ssh v0.0.4 github.com/mattn/go-isatty v0.0.20 github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d - github.com/mitchellh/go-homedir v1.1.0 github.com/moby/buildkit v0.18.0 github.com/onsi/ginkgo/v2 v2.20.2 github.com/onsi/gomega v1.34.2 @@ -160,6 +159,7 @@ require ( github.com/lucasb-eyer/go-colorful v1.2.0 // indirect github.com/mailru/easyjson v0.7.7 // indirect github.com/mattn/go-localereader v0.0.1 // indirect + github.com/mitchellh/go-homedir v1.1.0 // indirect github.com/mitchellh/go-wordwrap v1.0.1 // indirect github.com/mitchellh/hashstructure/v2 v2.0.2 // indirect github.com/moby/docker-image-spec v1.3.1 // indirect diff --git a/pkg/agent/workspace.go b/pkg/agent/workspace.go index 5b15dd50c..8e0a4ac13 100644 --- a/pkg/agent/workspace.go +++ b/pkg/agent/workspace.go @@ -16,7 +16,6 @@ import ( "github.com/loft-sh/devpod/pkg/gitcredentials" provider2 "github.com/loft-sh/devpod/pkg/provider" "github.com/loft-sh/log" - "github.com/mitchellh/go-homedir" "github.com/moby/patternmatcher/ignorefile" ) @@ -50,7 +49,7 @@ func findDir(agentFolder string, validate func(path string) bool) string { } // check home folder first - homeDir, _ := homedir.Dir() + homeDir, _ := os.UserHomeDir() if homeDir != "" { homeDir = filepath.Join(homeDir, ".devpod", "agent") if validate(homeDir) { diff --git a/pkg/command/user.go b/pkg/command/user.go index 410c8c6da..74f5cd716 100644 --- a/pkg/command/user.go +++ b/pkg/command/user.go @@ -1,14 +1,13 @@ package command import ( + "os" "os/user" - - "github.com/mitchellh/go-homedir" ) func GetHome(userName string) (string, error) { if userName == "" { - return homedir.Dir() + return os.UserHomeDir() } u, err := user.Lookup(userName) diff --git a/pkg/config/dir.go b/pkg/config/dir.go index 85035fa4e..550337965 100644 --- a/pkg/config/dir.go +++ b/pkg/config/dir.go @@ -3,8 +3,6 @@ package config import ( "os" "path/filepath" - - homedir "github.com/mitchellh/go-homedir" ) // Override devpod home @@ -19,7 +17,7 @@ func GetConfigDir() (string, error) { return homeDir, nil } - homeDir, err := homedir.Dir() + homeDir, err := os.UserHomeDir() if err != nil { return "", err } diff --git a/pkg/encoding/encoding.go b/pkg/encoding/encoding.go index cce2df736..2f164cfab 100644 --- a/pkg/encoding/encoding.go +++ b/pkg/encoding/encoding.go @@ -5,12 +5,12 @@ import ( "crypto/sha256" "encoding/hex" "fmt" + "os" "strings" "github.com/denisbrodbeck/machineid" "github.com/google/uuid" "github.com/loft-sh/log" - "github.com/mitchellh/go-homedir" ) const ( @@ -81,7 +81,7 @@ func GetMachineUID(log log.Logger) string { } // get $HOME to distinguish two users on the same machine // will be hashed later together with the ID - home, err := homedir.Dir() + home, err := os.UserHomeDir() if err != nil { home = "error" if log != nil { diff --git a/pkg/ide/fleet/fleet.go b/pkg/ide/fleet/fleet.go index e47feea17..e554be422 100644 --- a/pkg/ide/fleet/fleet.go +++ b/pkg/ide/fleet/fleet.go @@ -18,7 +18,6 @@ import ( "github.com/loft-sh/devpod/pkg/single" "github.com/loft-sh/log" "github.com/loft-sh/log/scanner" - "github.com/mitchellh/go-homedir" "github.com/pkg/errors" ) @@ -215,7 +214,7 @@ func prepareFleetServerLocation(userName string) (string, error) { if userName != "" { homeFolder, err = command.GetHome(userName) } else { - homeFolder, err = homedir.Dir() + homeFolder, err = os.UserHomeDir() } if err != nil { return "", err diff --git a/pkg/ide/jetbrains/generic.go b/pkg/ide/jetbrains/generic.go index 06d7c9e54..4a26083a5 100644 --- a/pkg/ide/jetbrains/generic.go +++ b/pkg/ide/jetbrains/generic.go @@ -18,7 +18,6 @@ import ( devpodhttp "github.com/loft-sh/devpod/pkg/http" "github.com/loft-sh/devpod/pkg/ide" "github.com/loft-sh/log" - "github.com/mitchellh/go-homedir" "github.com/pkg/errors" "github.com/skratchdot/open-golang/open" ) @@ -134,7 +133,7 @@ func getBaseFolder(userName string) (string, error) { if userName != "" { homeFolder, err = command.GetHome(userName) } else { - homeFolder, err = homedir.Dir() + homeFolder, err = os.UserHomeDir() } if err != nil { return "", err diff --git a/pkg/ide/openvscode/openvscode.go b/pkg/ide/openvscode/openvscode.go index 43ad96aed..2470dbb47 100644 --- a/pkg/ide/openvscode/openvscode.go +++ b/pkg/ide/openvscode/openvscode.go @@ -17,7 +17,6 @@ import ( "github.com/loft-sh/devpod/pkg/ide/vscode" "github.com/loft-sh/devpod/pkg/single" "github.com/loft-sh/log" - "github.com/mitchellh/go-homedir" "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -280,7 +279,7 @@ func prepareOpenVSCodeServerLocation(userName string) (string, error) { if userName != "" { homeFolder, err = command.GetHome(userName) } else { - homeFolder, err = homedir.Dir() + homeFolder, err = os.UserHomeDir() } if err != nil { return "", err diff --git a/pkg/ide/vscode/vscode.go b/pkg/ide/vscode/vscode.go index 462d3a947..fb9ab959b 100644 --- a/pkg/ide/vscode/vscode.go +++ b/pkg/ide/vscode/vscode.go @@ -14,7 +14,6 @@ import ( copy2 "github.com/loft-sh/devpod/pkg/copy" "github.com/loft-sh/devpod/pkg/ide" "github.com/loft-sh/log" - "github.com/mitchellh/go-homedir" "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -421,7 +420,7 @@ func prepareServerLocation(userName string, create bool, flavor Flavor) (string, if userName != "" { homeFolder, err = command.GetHome(userName) } else { - homeFolder, err = homedir.Dir() + homeFolder, err = os.UserHomeDir() } if err != nil { return "", err diff --git a/pkg/platform/client/client.go b/pkg/platform/client/client.go index f96956b9b..d26c02ed6 100644 --- a/pkg/platform/client/client.go +++ b/pkg/platform/client/client.go @@ -26,7 +26,6 @@ import ( "github.com/loft-sh/devpod/pkg/platform/project" "github.com/loft-sh/devpod/pkg/version" "github.com/loft-sh/log" - "github.com/mitchellh/go-homedir" perrors "github.com/pkg/errors" "github.com/skratchdot/open-golang/open" "k8s.io/client-go/rest" @@ -48,7 +47,7 @@ const ( ) func init() { - hd, _ := homedir.Dir() + hd, _ := os.UserHomeDir() if folder, ok := os.LookupEnv("LOFT_CACHE_FOLDER"); ok { CacheFolder = filepath.Join(hd, folder) } else { diff --git a/pkg/ssh/config.go b/pkg/ssh/config.go index e7ee2329a..778f93f2c 100644 --- a/pkg/ssh/config.go +++ b/pkg/ssh/config.go @@ -13,7 +13,6 @@ import ( "github.com/loft-sh/log" "github.com/loft-sh/log/scanner" - "github.com/mitchellh/go-homedir" "github.com/pkg/errors" ) @@ -186,7 +185,7 @@ func writeSSHConfig(path, content string, log log.Logger) error { } func ResolveSSHConfigPath(sshConfigPath string) (string, error) { - homeDir, err := homedir.Dir() + homeDir, err := os.UserHomeDir() if err != nil { return "", errors.Wrap(err, "get home dir") } diff --git a/pkg/ssh/keys.go b/pkg/ssh/keys.go index fabeeaab3..3bc10cf12 100644 --- a/pkg/ssh/keys.go +++ b/pkg/ssh/keys.go @@ -12,7 +12,6 @@ import ( "sync" "github.com/loft-sh/devpod/pkg/provider" - "github.com/mitchellh/go-homedir" "github.com/pkg/errors" "golang.org/x/crypto/ssh" @@ -80,7 +79,7 @@ func GetPrivateKeyRaw(context, workspaceID string) ([]byte, error) { } func GetDevPodKeysDir() string { - dir, err := homedir.Dir() + dir, err := os.UserHomeDir() if err == nil { tempDir := filepath.Join(dir, ".devpod", "keys") err = os.MkdirAll(tempDir, 0755) diff --git a/pkg/ssh/ssh_add.go b/pkg/ssh/ssh_add.go index 6072928a4..27fb0650d 100644 --- a/pkg/ssh/ssh_add.go +++ b/pkg/ssh/ssh_add.go @@ -11,7 +11,6 @@ import ( "github.com/loft-sh/devpod/pkg/command" devsshagent "github.com/loft-sh/devpod/pkg/ssh/agent" "github.com/loft-sh/log" - "github.com/mitchellh/go-homedir" "golang.org/x/crypto/ssh" ) @@ -41,7 +40,7 @@ func AddPrivateKeysToAgent(ctx context.Context, log log.Logger) error { } func FindPrivateKeys() ([]string, error) { - homeDir, err := homedir.Dir() + homeDir, err := os.UserHomeDir() if err != nil { return nil, err } diff --git a/pkg/telemetry/helpers.go b/pkg/telemetry/helpers.go index e3e61fe9d..823433802 100644 --- a/pkg/telemetry/helpers.go +++ b/pkg/telemetry/helpers.go @@ -4,9 +4,9 @@ import ( "crypto/hmac" "crypto/sha256" "fmt" + "os" "github.com/denisbrodbeck/machineid" - "github.com/mitchellh/go-homedir" ) // GetMachineID retrieves machine ID and encodes it together with users $HOME path and @@ -19,7 +19,7 @@ func GetMachineID() string { // get $HOME to distinguish two users on the same machine // will be hashed later together with the ID - home, err := homedir.Dir() + home, err := os.UserHomeDir() if err != nil { home = "error" } From 744b32da4713b5af00a0a8d45bff9e4961813040 Mon Sep 17 00:00:00 2001 From: Hoang Nguyen Date: Wed, 8 Jan 2025 00:00:00 +0700 Subject: [PATCH 2/3] Implement UserHomeDir() based on the archived go-homedir package --- cmd/agent/workspace/up.go | 3 +- cmd/pro/start.go | 3 +- pkg/agent/workspace.go | 3 +- pkg/command/user.go | 5 +- pkg/config/dir.go | 4 +- pkg/encoding/encoding.go | 4 +- pkg/ide/fleet/fleet.go | 3 +- pkg/ide/jetbrains/generic.go | 3 +- pkg/ide/openvscode/openvscode.go | 3 +- pkg/ide/vscode/vscode.go | 3 +- pkg/platform/client/client.go | 3 +- pkg/ssh/config.go | 3 +- pkg/ssh/keys.go | 3 +- pkg/ssh/ssh_add.go | 3 +- pkg/telemetry/helpers.go | 4 +- pkg/util/homedir.go | 90 ++++++++++++++++++++++++++++++++ pkg/util/homedir_test.go | 63 ++++++++++++++++++++++ 17 files changed, 185 insertions(+), 18 deletions(-) create mode 100644 pkg/util/homedir.go create mode 100644 pkg/util/homedir_test.go diff --git a/cmd/agent/workspace/up.go b/cmd/agent/workspace/up.go index 9dab9e938..888e13f15 100644 --- a/cmd/agent/workspace/up.go +++ b/cmd/agent/workspace/up.go @@ -24,6 +24,7 @@ import ( "github.com/loft-sh/devpod/pkg/dockercredentials" "github.com/loft-sh/devpod/pkg/extract" provider2 "github.com/loft-sh/devpod/pkg/provider" + "github.com/loft-sh/devpod/pkg/util" "github.com/loft-sh/devpod/scripts" "github.com/loft-sh/log" "github.com/pkg/errors" @@ -451,7 +452,7 @@ func configureDockerDaemon(ctx context.Context, log log.Logger) (err error) { } }`) // Check rootless docker - homeDir, err := os.UserHomeDir() + homeDir, err := util.UserHomeDir() if err != nil { return err } diff --git a/cmd/pro/start.go b/cmd/pro/start.go index 161cfad79..f108d2137 100644 --- a/cmd/pro/start.go +++ b/cmd/pro/start.go @@ -29,6 +29,7 @@ import ( proflags "github.com/loft-sh/devpod/cmd/pro/flags" "github.com/loft-sh/devpod/pkg/platform" "github.com/loft-sh/devpod/pkg/platform/client" + "github.com/loft-sh/devpod/pkg/util" "github.com/loft-sh/log" "github.com/loft-sh/log/hash" "github.com/loft-sh/log/scanner" @@ -1692,7 +1693,7 @@ func getMachineUID(log log.Logger) string { } // get $HOME to distinguish two users on the same machine // will be hashed later together with the ID - home, err := os.UserHomeDir() + home, err := util.UserHomeDir() if err != nil { home = "error" if log != nil { diff --git a/pkg/agent/workspace.go b/pkg/agent/workspace.go index 8e0a4ac13..4c11ed522 100644 --- a/pkg/agent/workspace.go +++ b/pkg/agent/workspace.go @@ -15,6 +15,7 @@ import ( "github.com/loft-sh/devpod/pkg/git" "github.com/loft-sh/devpod/pkg/gitcredentials" provider2 "github.com/loft-sh/devpod/pkg/provider" + "github.com/loft-sh/devpod/pkg/util" "github.com/loft-sh/log" "github.com/moby/patternmatcher/ignorefile" ) @@ -49,7 +50,7 @@ func findDir(agentFolder string, validate func(path string) bool) string { } // check home folder first - homeDir, _ := os.UserHomeDir() + homeDir, _ := util.UserHomeDir() if homeDir != "" { homeDir = filepath.Join(homeDir, ".devpod", "agent") if validate(homeDir) { diff --git a/pkg/command/user.go b/pkg/command/user.go index 74f5cd716..5c00a1a93 100644 --- a/pkg/command/user.go +++ b/pkg/command/user.go @@ -1,13 +1,14 @@ package command import ( - "os" "os/user" + + "github.com/loft-sh/devpod/pkg/util" ) func GetHome(userName string) (string, error) { if userName == "" { - return os.UserHomeDir() + return util.UserHomeDir() } u, err := user.Lookup(userName) diff --git a/pkg/config/dir.go b/pkg/config/dir.go index 550337965..fe844c74c 100644 --- a/pkg/config/dir.go +++ b/pkg/config/dir.go @@ -3,6 +3,8 @@ package config import ( "os" "path/filepath" + + "github.com/loft-sh/devpod/pkg/util" ) // Override devpod home @@ -17,7 +19,7 @@ func GetConfigDir() (string, error) { return homeDir, nil } - homeDir, err := os.UserHomeDir() + homeDir, err := util.UserHomeDir() if err != nil { return "", err } diff --git a/pkg/encoding/encoding.go b/pkg/encoding/encoding.go index 2f164cfab..4b3b3af0c 100644 --- a/pkg/encoding/encoding.go +++ b/pkg/encoding/encoding.go @@ -5,11 +5,11 @@ import ( "crypto/sha256" "encoding/hex" "fmt" - "os" "strings" "github.com/denisbrodbeck/machineid" "github.com/google/uuid" + "github.com/loft-sh/devpod/pkg/util" "github.com/loft-sh/log" ) @@ -81,7 +81,7 @@ func GetMachineUID(log log.Logger) string { } // get $HOME to distinguish two users on the same machine // will be hashed later together with the ID - home, err := os.UserHomeDir() + home, err := util.UserHomeDir() if err != nil { home = "error" if log != nil { diff --git a/pkg/ide/fleet/fleet.go b/pkg/ide/fleet/fleet.go index e554be422..df7e95731 100644 --- a/pkg/ide/fleet/fleet.go +++ b/pkg/ide/fleet/fleet.go @@ -16,6 +16,7 @@ import ( devpodhttp "github.com/loft-sh/devpod/pkg/http" "github.com/loft-sh/devpod/pkg/ide" "github.com/loft-sh/devpod/pkg/single" + "github.com/loft-sh/devpod/pkg/util" "github.com/loft-sh/log" "github.com/loft-sh/log/scanner" "github.com/pkg/errors" @@ -214,7 +215,7 @@ func prepareFleetServerLocation(userName string) (string, error) { if userName != "" { homeFolder, err = command.GetHome(userName) } else { - homeFolder, err = os.UserHomeDir() + homeFolder, err = util.UserHomeDir() } if err != nil { return "", err diff --git a/pkg/ide/jetbrains/generic.go b/pkg/ide/jetbrains/generic.go index 4a26083a5..606b629b6 100644 --- a/pkg/ide/jetbrains/generic.go +++ b/pkg/ide/jetbrains/generic.go @@ -17,6 +17,7 @@ import ( "github.com/loft-sh/devpod/pkg/extract" devpodhttp "github.com/loft-sh/devpod/pkg/http" "github.com/loft-sh/devpod/pkg/ide" + "github.com/loft-sh/devpod/pkg/util" "github.com/loft-sh/log" "github.com/pkg/errors" "github.com/skratchdot/open-golang/open" @@ -133,7 +134,7 @@ func getBaseFolder(userName string) (string, error) { if userName != "" { homeFolder, err = command.GetHome(userName) } else { - homeFolder, err = os.UserHomeDir() + homeFolder, err = util.UserHomeDir() } if err != nil { return "", err diff --git a/pkg/ide/openvscode/openvscode.go b/pkg/ide/openvscode/openvscode.go index 2470dbb47..d209d3cf0 100644 --- a/pkg/ide/openvscode/openvscode.go +++ b/pkg/ide/openvscode/openvscode.go @@ -16,6 +16,7 @@ import ( "github.com/loft-sh/devpod/pkg/ide" "github.com/loft-sh/devpod/pkg/ide/vscode" "github.com/loft-sh/devpod/pkg/single" + "github.com/loft-sh/devpod/pkg/util" "github.com/loft-sh/log" "github.com/pkg/errors" "github.com/sirupsen/logrus" @@ -279,7 +280,7 @@ func prepareOpenVSCodeServerLocation(userName string) (string, error) { if userName != "" { homeFolder, err = command.GetHome(userName) } else { - homeFolder, err = os.UserHomeDir() + homeFolder, err = util.UserHomeDir() } if err != nil { return "", err diff --git a/pkg/ide/vscode/vscode.go b/pkg/ide/vscode/vscode.go index fb9ab959b..641600089 100644 --- a/pkg/ide/vscode/vscode.go +++ b/pkg/ide/vscode/vscode.go @@ -13,6 +13,7 @@ import ( "github.com/loft-sh/devpod/pkg/config" copy2 "github.com/loft-sh/devpod/pkg/copy" "github.com/loft-sh/devpod/pkg/ide" + "github.com/loft-sh/devpod/pkg/util" "github.com/loft-sh/log" "github.com/pkg/errors" "github.com/sirupsen/logrus" @@ -420,7 +421,7 @@ func prepareServerLocation(userName string, create bool, flavor Flavor) (string, if userName != "" { homeFolder, err = command.GetHome(userName) } else { - homeFolder, err = os.UserHomeDir() + homeFolder, err = util.UserHomeDir() } if err != nil { return "", err diff --git a/pkg/platform/client/client.go b/pkg/platform/client/client.go index d26c02ed6..397e71c3c 100644 --- a/pkg/platform/client/client.go +++ b/pkg/platform/client/client.go @@ -24,6 +24,7 @@ import ( "github.com/loft-sh/devpod/pkg/platform/kube" "github.com/loft-sh/devpod/pkg/platform/project" + "github.com/loft-sh/devpod/pkg/util" "github.com/loft-sh/devpod/pkg/version" "github.com/loft-sh/log" perrors "github.com/pkg/errors" @@ -47,7 +48,7 @@ const ( ) func init() { - hd, _ := os.UserHomeDir() + hd, _ := util.UserHomeDir() if folder, ok := os.LookupEnv("LOFT_CACHE_FOLDER"); ok { CacheFolder = filepath.Join(hd, folder) } else { diff --git a/pkg/ssh/config.go b/pkg/ssh/config.go index 778f93f2c..3535baf60 100644 --- a/pkg/ssh/config.go +++ b/pkg/ssh/config.go @@ -11,6 +11,7 @@ import ( "strings" "sync" + "github.com/loft-sh/devpod/pkg/util" "github.com/loft-sh/log" "github.com/loft-sh/log/scanner" "github.com/pkg/errors" @@ -185,7 +186,7 @@ func writeSSHConfig(path, content string, log log.Logger) error { } func ResolveSSHConfigPath(sshConfigPath string) (string, error) { - homeDir, err := os.UserHomeDir() + homeDir, err := util.UserHomeDir() if err != nil { return "", errors.Wrap(err, "get home dir") } diff --git a/pkg/ssh/keys.go b/pkg/ssh/keys.go index 3bc10cf12..edd5e072c 100644 --- a/pkg/ssh/keys.go +++ b/pkg/ssh/keys.go @@ -12,6 +12,7 @@ import ( "sync" "github.com/loft-sh/devpod/pkg/provider" + "github.com/loft-sh/devpod/pkg/util" "github.com/pkg/errors" "golang.org/x/crypto/ssh" @@ -79,7 +80,7 @@ func GetPrivateKeyRaw(context, workspaceID string) ([]byte, error) { } func GetDevPodKeysDir() string { - dir, err := os.UserHomeDir() + dir, err := util.UserHomeDir() if err == nil { tempDir := filepath.Join(dir, ".devpod", "keys") err = os.MkdirAll(tempDir, 0755) diff --git a/pkg/ssh/ssh_add.go b/pkg/ssh/ssh_add.go index 27fb0650d..572b56fc5 100644 --- a/pkg/ssh/ssh_add.go +++ b/pkg/ssh/ssh_add.go @@ -10,6 +10,7 @@ import ( "github.com/loft-sh/devpod/pkg/command" devsshagent "github.com/loft-sh/devpod/pkg/ssh/agent" + "github.com/loft-sh/devpod/pkg/util" "github.com/loft-sh/log" "golang.org/x/crypto/ssh" ) @@ -40,7 +41,7 @@ func AddPrivateKeysToAgent(ctx context.Context, log log.Logger) error { } func FindPrivateKeys() ([]string, error) { - homeDir, err := os.UserHomeDir() + homeDir, err := util.UserHomeDir() if err != nil { return nil, err } diff --git a/pkg/telemetry/helpers.go b/pkg/telemetry/helpers.go index 823433802..82a819d87 100644 --- a/pkg/telemetry/helpers.go +++ b/pkg/telemetry/helpers.go @@ -4,9 +4,9 @@ import ( "crypto/hmac" "crypto/sha256" "fmt" - "os" "github.com/denisbrodbeck/machineid" + "github.com/loft-sh/devpod/pkg/util" ) // GetMachineID retrieves machine ID and encodes it together with users $HOME path and @@ -19,7 +19,7 @@ func GetMachineID() string { // get $HOME to distinguish two users on the same machine // will be hashed later together with the ID - home, err := os.UserHomeDir() + home, err := util.UserHomeDir() if err != nil { home = "error" } diff --git a/pkg/util/homedir.go b/pkg/util/homedir.go new file mode 100644 index 000000000..eec98fd9e --- /dev/null +++ b/pkg/util/homedir.go @@ -0,0 +1,90 @@ +package util + +import ( + "bytes" + "errors" + "os" + "os/exec" + "runtime" + "strconv" + "strings" +) + +// UserHomeDir returns the home directory for the executing user. +// +// This extends the logic of os.UserHomeDir() with the now archived package +// github.com/mitchellh/go-homedir for compatibility. +func UserHomeDir() (string, error) { + // Always try the HOME environment variable first + homeEnv := "HOME" + if runtime.GOOS == "plan9" { + homeEnv = "home" + } + if home := os.Getenv(homeEnv); home != "" { + return home, nil + } + + // Rely on os.UserHomeDir() here, as it's the standard method moving forward + if home, _ := os.UserHomeDir(); home != "" { + return home, nil + } + + var stdout bytes.Buffer + + // Finally, handle cases existed in go-homedir but not in the current + // os.UserHomeDir() implementation + switch runtime.GOOS { + case "windows": + drive := os.Getenv("HOMEDRIVE") + path := os.Getenv("HOMEPATH") + if drive == "" || path == "" { + return "", errors.New("HOMEDRIVE, HOMEPATH, or USERPROFILE are blank") + } + return drive + path, nil + case "darwin": + cmd := exec.Command("sh", "-c", `dscl -q . -read /Users/"$(whoami)" NFSHomeDirectory | sed 's/^[^ ]*: //'`) + cmd.Stdout = &stdout + if err := cmd.Run(); err == nil { + result := strings.TrimSpace(stdout.String()) + if result != "" { + return result, nil + } + } + default: + cmd := exec.Command("getent", "passwd", strconv.Itoa(os.Getuid())) + cmd.Stdout = &stdout + if err := cmd.Run(); err != nil { + // If the error is ErrNotFound, we ignore it. Otherwise, return it. + if err != exec.ErrNotFound { + return "", err + } + } else { + if passwd := strings.TrimSpace(stdout.String()); passwd != "" { + // username:password:uid:gid:gecos:home:shell + passwdParts := strings.SplitN(passwd, ":", 7) + if len(passwdParts) > 5 { + return passwdParts[5], nil + } + } + } + } + + // If all else fails, try the shell + if runtime.GOOS != "windows" { + stdout.Reset() + cmd := exec.Command("sh", "-c", "cd && pwd") + cmd.Stdout = &stdout + if err := cmd.Run(); err != nil { + return "", err + } + + result := strings.TrimSpace(stdout.String()) + if result == "" { + return "", errors.New("blank output when reading home directory") + } + + return result, nil + } + + return "", errors.New("can't determine the home directory") +} diff --git a/pkg/util/homedir_test.go b/pkg/util/homedir_test.go new file mode 100644 index 000000000..b7a32f8e0 --- /dev/null +++ b/pkg/util/homedir_test.go @@ -0,0 +1,63 @@ +package util + +import ( + "os" + "runtime" + "testing" + + "gotest.tools/assert" +) + +func TestUserHomeDir(t *testing.T) { + // Remember to reset environment variables after the test + origHome := os.Getenv("HOME") + origUserProfile := os.Getenv("USERPROFILE") + t.Cleanup(func() { + os.Setenv("HOME", origHome) + os.Setenv("USERPROFILE", origUserProfile) + }) + + type input struct { + home, userProfile string + } + + type testCase struct { + Name string + Input input + Expect string + } + + testCases := []testCase{ + { + // $HOME is preferred on every platform + Name: "both HOME and USERPROFILE are set", + Input: input{ + home: "home", + userProfile: "userProfile", + }, + Expect: "home", + }, + } + if runtime.GOOS == "windows" { + // On Windows, after $HOME, %userprofile% value is checked + testCases = append(testCases, testCase{ + Name: "HOME is unset and USERPROFILE is set", + Input: input{ + home: "", + userProfile: "userProfile", + }, + Expect: "userProfile", + }) + } + + for _, test := range testCases { + t.Run(test.Name, func(t *testing.T) { + os.Setenv("HOME", test.Input.home) + os.Setenv("USERPROFILE", test.Input.userProfile) + + got, err := UserHomeDir() + assert.NilError(t, err, test.Name) + assert.Equal(t, test.Expect, got) + }) + } +} From 18bedc54d2ab0baef88d23d501b4e77eb95b67d5 Mon Sep 17 00:00:00 2001 From: Pascal Breuninger Date: Wed, 8 Jan 2025 16:15:59 +0100 Subject: [PATCH 3/3] chore(cli): address ci linting issue --- pkg/util/homedir.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/util/homedir.go b/pkg/util/homedir.go index eec98fd9e..ff6f34f3b 100644 --- a/pkg/util/homedir.go +++ b/pkg/util/homedir.go @@ -55,7 +55,7 @@ func UserHomeDir() (string, error) { cmd.Stdout = &stdout if err := cmd.Run(); err != nil { // If the error is ErrNotFound, we ignore it. Otherwise, return it. - if err != exec.ErrNotFound { + if errors.Is(err, exec.ErrNotFound) { return "", err } } else {