From a6e0ea8bd2a36ac2b731171486554b6d437b380f Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Mon, 17 Jun 2013 22:09:07 -0700 Subject: [PATCH] Don't depend on os/user anymore, which requires cgo --- configfile.go | 9 +++++++++ configfile_unix.go | 45 +++++++++++++++++++++++++++++++++++++++++++ configfile_windows.go | 37 +++++++++++++++++++++++++++++++++++ packer.go | 26 +++++++++++++------------ 4 files changed, 105 insertions(+), 12 deletions(-) create mode 100644 configfile.go create mode 100644 configfile_unix.go create mode 100644 configfile_windows.go diff --git a/configfile.go b/configfile.go new file mode 100644 index 000000000..8b0e8eff1 --- /dev/null +++ b/configfile.go @@ -0,0 +1,9 @@ +package main + +// ConfigFile returns the default path to the configuration file. On +// Unix-like systems this is the ".packerconfig" file in the home directory. +// On Windows, this is the "packer.config" file in the application data +// directory. +func ConfigFile() (string, error) { + return configFile() +} diff --git a/configfile_unix.go b/configfile_unix.go new file mode 100644 index 000000000..b0b28109f --- /dev/null +++ b/configfile_unix.go @@ -0,0 +1,45 @@ +// +build darwin freebsd linux netbsd openbsd + +package main + +import ( + "bytes" + "errors" + "log" + "os" + "os/exec" + "path/filepath" + "strings" +) + +func configFile() (string, error) { + dir, err := configDir() + if err != nil { + return "", err + } + + return filepath.Join(dir, ".packerconfig"), nil +} + +func configDir() (string, error) { + // First prefer the HOME environmental variable + if home := os.Getenv("HOME"); home != "" { + log.Printf("Detected home directory from env var: %s", home) + return home, nil + } + + // If that fails, try the shell + var stdout bytes.Buffer + cmd := exec.Command("sh", "-c", "eval echo ~$USER") + cmd.Stdout = &stdout + if err := cmd.Run(); err != nil { + return "", err + } + + result := strings.TrimSpace(stdout.String()) + if result == "" { + return "", errors.New("blank output") + } + + return result, nil +} diff --git a/configfile_windows.go b/configfile_windows.go new file mode 100644 index 000000000..c59359dd9 --- /dev/null +++ b/configfile_windows.go @@ -0,0 +1,37 @@ +// +build windows + +package main + +import ( + "path/filepath" + "syscall" + "unsafe" +) + +var ( + shell = syscall.MustLoadDLL("Shell32.dll") + getFolderPath = shell.MustFindProc("SHGetFolderPathW") +) + +const CSIDL_APPDATA = 26 + +func configFile() (string, error) { + dir, err := configDir() + if err != nil { + return "", err + } + + return filepath.Join(dir, "packer.config"), nil +} + +func configDir() (string, error) { + b := make([]uint16, syscall.MAX_PATH) + + // See: http://msdn.microsoft.com/en-us/library/windows/desktop/bb762181(v=vs.85).aspx + r, _, err := getFolderPath.Call(0, CSIDL_APPDATA, 0, 0, uintptr(unsafe.Pointer(&b[0]))) + if uint32(r) != 0 { + return "", err + } + + return syscall.UTF16ToString(b), nil +} diff --git a/packer.go b/packer.go index 60e21421c..c9d9a9015 100644 --- a/packer.go +++ b/packer.go @@ -9,8 +9,6 @@ import ( "io/ioutil" "log" "os" - "os/user" - "path/filepath" "runtime" ) @@ -82,19 +80,23 @@ func loadConfig() (*config, error) { } mustExist := true - configFile := os.Getenv("PACKER_CONFIG") - if configFile == "" { - u, err := user.Current() - if err != nil { - return nil, err - } - - configFile = filepath.Join(u.HomeDir, ".packerconfig") + configFilePath := os.Getenv("PACKER_CONFIG") + if configFilePath == "" { + var err error + configFilePath, err = configFile() mustExist = false + + if err != nil { + log.Printf("Error detecing default config file path: %s", err) + } } - log.Printf("Attempting to open config file: %s", configFile) - f, err := os.Open(configFile) + if configFilePath == "" { + return &config, nil + } + + log.Printf("Attempting to open config file: %s", configFilePath) + f, err := os.Open(configFilePath) if err != nil { if !os.IsNotExist(err) { return nil, err