From 312023090f952b8c80d2e027c5965d33b6f936f7 Mon Sep 17 00:00:00 2001 From: l3uddz Date: Sat, 13 Jun 2020 10:40:41 +0100 Subject: [PATCH] change(config): check if current binary path is writeable, use alternative if not when binary path is not writeable, .config/crop will be used within user home directory --- cmd/root.go | 8 ++++--- go.mod | 2 +- pathutils/file.go | 58 ++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 63 insertions(+), 5 deletions(-) diff --git a/cmd/root.go b/cmd/root.go index da8cdde..33aab37 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -20,7 +20,7 @@ import ( var ( // Global flags flagLogLevel = 0 - flagConfigFolder = pathutils.GetCurrentBinaryPath() + flagConfigFolder = pathutils.GetDefaultConfigPath() flagConfigFile = "config.yaml" flagCachePath = "cache" flagLogFile = "activity.log" @@ -55,6 +55,7 @@ func init() { rootCmd.PersistentFlags().StringVarP(&flagConfigFile, "config", "c", flagConfigFile, "Config file") rootCmd.PersistentFlags().StringVarP(&flagCachePath, "cache", "d", flagCachePath, "Cache path") rootCmd.PersistentFlags().StringVarP(&flagLogFile, "log", "l", flagLogFile, "Log file") + rootCmd.PersistentFlags().StringVarP(&flagLockFile, "lock", "f", flagLockFile, "Lock file") rootCmd.PersistentFlags().CountVarP(&flagLogLevel, "verbose", "v", "Verbose level") rootCmd.PersistentFlags().BoolVar(&flagDryRun, "dry-run", false, "Dry run mode") @@ -71,8 +72,9 @@ func initCore(showAppInfo bool) { if !rootCmd.PersistentFlags().Changed("log") { flagLogFile = filepath.Join(flagConfigFolder, flagLogFile) } - - flagLockFile = filepath.Join(flagConfigFolder, flagLockFile) + if !rootCmd.PersistentFlags().Changed("lock") { + flagLockFile = filepath.Join(flagConfigFolder, flagLockFile) + } // Init Logging if err := logger.Init(flagLogLevel, flagLogFile); err != nil { diff --git a/go.mod b/go.mod index dd1e75f..8f5175f 100644 --- a/go.mod +++ b/go.mod @@ -40,7 +40,7 @@ require ( golang.org/x/crypto v0.0.0-20200604202706-70a84ac30bf9 // indirect golang.org/x/net v0.0.0-20200602114024-627f9648deb9 // indirect golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d // indirect - golang.org/x/sys v0.0.0-20200610111108-226ff32320da // indirect + golang.org/x/sys v0.0.0-20200610111108-226ff32320da google.golang.org/appengine v1.6.6 // indirect google.golang.org/protobuf v1.24.0 // indirect gopkg.in/ini.v1 v1.57.0 // indirect diff --git a/pathutils/file.go b/pathutils/file.go index f383924..49a18ad 100644 --- a/pathutils/file.go +++ b/pathutils/file.go @@ -1,19 +1,75 @@ package pathutils import ( + "github.com/pkg/errors" + "golang.org/x/sys/unix" "os" "path/filepath" + "runtime" ) /* Public */ func GetCurrentBinaryPath() string { + // get current binary path dir, err := filepath.Abs(filepath.Dir(os.Args[0])) if err != nil { // get current working dir if dir, err = os.Getwd(); err != nil { - os.Exit(1) + panic("failed to determine current binary location") } } + return dir } + +func GetDefaultConfigPath() string { + // get binary path + bp := GetCurrentBinaryPath() + if dirIsWriteable(bp) == nil { + return bp + } + + // binary path is not write-able, use alternative path + uhp, err := os.UserHomeDir() + if err != nil { + panic("failed to determine current user home directory") + } + + // set crop path inside user home dir + chp := filepath.Join(uhp, ".config", "crop") + if _, err := os.Stat(chp); os.IsNotExist(err) { + if e := os.MkdirAll(chp, os.ModePerm); e != nil { + panic("failed to create crop config directory") + } + } + + return chp +} + +/* Private */ + +func dirIsWriteable(dir string) error { + // credits: https://stackoverflow.com/questions/20026320/how-to-tell-if-folder-exists-and-is-writable + var err error + + if runtime.GOOS != "windows" { + err = unix.Access(dir, unix.W_OK) + } else { + f, e := os.Stat(dir) + if e != nil { + return e + } + + switch { + case !f.IsDir(): + err = errors.New("dir is not a directory") + case f.Mode().Perm()&(1<<(uint(7))) == 0: + err = errors.New("dir is not writeable") + default: + break + } + } + + return err +}