mirror of https://github.com/ethereum/go-ethereum
commit
c6b25a4046
@ -0,0 +1,133 @@ |
||||
package utils |
||||
|
||||
import ( |
||||
"flag" |
||||
"fmt" |
||||
"os" |
||||
"os/user" |
||||
"path/filepath" |
||||
"strings" |
||||
|
||||
"github.com/codegangsta/cli" |
||||
) |
||||
|
||||
// Custom type which is registered in the flags library which cli uses for
|
||||
// argument parsing. This allows us to expand Value to an absolute path when
|
||||
// the argument is parsed
|
||||
type DirectoryString struct { |
||||
Value string |
||||
} |
||||
|
||||
func (self DirectoryString) String() string { |
||||
return self.Value |
||||
} |
||||
|
||||
func (self DirectoryString) Set(value string) error { |
||||
self.Value = expandPath(value) |
||||
return nil |
||||
} |
||||
|
||||
// Custom cli.Flag type which expand the received string to an absolute path.
|
||||
// e.g. ~/.ethereum -> /home/username/.ethereum
|
||||
type DirectoryFlag struct { |
||||
cli.GenericFlag |
||||
Name string |
||||
Value DirectoryString |
||||
Usage string |
||||
EnvVar string |
||||
} |
||||
|
||||
func (self DirectoryFlag) String() string { |
||||
var fmtString string |
||||
fmtString = "%s %v\t%v" |
||||
|
||||
if len(self.Value.Value) > 0 { |
||||
fmtString = "%s \"%v\"\t%v" |
||||
} else { |
||||
fmtString = "%s %v\t%v" |
||||
} |
||||
|
||||
return withEnvHint(self.EnvVar, fmt.Sprintf(fmtString, prefixedNames(self.Name), self.Value.Value, self.Usage)) |
||||
} |
||||
|
||||
func eachName(longName string, fn func(string)) { |
||||
parts := strings.Split(longName, ",") |
||||
for _, name := range parts { |
||||
name = strings.Trim(name, " ") |
||||
fn(name) |
||||
} |
||||
} |
||||
|
||||
// called by cli library, grabs variable from environment (if in env)
|
||||
// and adds variable to flag set for parsing.
|
||||
func (self DirectoryFlag) Apply(set *flag.FlagSet) { |
||||
if self.EnvVar != "" { |
||||
for _, envVar := range strings.Split(self.EnvVar, ",") { |
||||
envVar = strings.TrimSpace(envVar) |
||||
if envVal := os.Getenv(envVar); envVal != "" { |
||||
self.Value.Value = envVal |
||||
break |
||||
} |
||||
} |
||||
} |
||||
|
||||
eachName(self.Name, func(name string) { |
||||
set.Var(self.Value, self.Name, "a: "+self.Usage) |
||||
}) |
||||
|
||||
} |
||||
|
||||
func prefixFor(name string) (prefix string) { |
||||
if len(name) == 1 { |
||||
prefix = "-" |
||||
} else { |
||||
prefix = "--" |
||||
} |
||||
|
||||
return |
||||
} |
||||
|
||||
func prefixedNames(fullName string) (prefixed string) { |
||||
parts := strings.Split(fullName, ",") |
||||
for i, name := range parts { |
||||
name = strings.Trim(name, " ") |
||||
prefixed += prefixFor(name) + name |
||||
if i < len(parts)-1 { |
||||
prefixed += ", " |
||||
} |
||||
} |
||||
return |
||||
} |
||||
|
||||
func withEnvHint(envVar, str string) string { |
||||
envText := "" |
||||
if envVar != "" { |
||||
envText = fmt.Sprintf(" [$%s]", strings.Join(strings.Split(envVar, ","), ", $")) |
||||
} |
||||
return str + envText |
||||
} |
||||
|
||||
func (self DirectoryFlag) getName() string { |
||||
return self.Name |
||||
} |
||||
|
||||
func (self *DirectoryFlag) Set(value string) { |
||||
self.Value.Value = value |
||||
} |
||||
|
||||
// Expands a file path
|
||||
// 1. replace tilde with users home dir
|
||||
// 2. expands embedded environment variables
|
||||
// 3. cleans the path, e.g. /a/b/../c -> /a/c
|
||||
// Note, it has limitations, e.g. ~someuser/tmp will not be expanded
|
||||
func expandPath(p string) string { |
||||
if strings.HasPrefix(p, "~/") || strings.HasPrefix(p, "~\\") { |
||||
if user, err := user.Current(); err == nil { |
||||
if err == nil { |
||||
p = strings.Replace(p, "~", user.HomeDir, 1) |
||||
} |
||||
} |
||||
} |
||||
|
||||
return filepath.Clean(os.ExpandEnv(p)) |
||||
} |
@ -0,0 +1,28 @@ |
||||
package utils |
||||
|
||||
import ( |
||||
"os" |
||||
"os/user" |
||||
"testing" |
||||
) |
||||
|
||||
func TestPathExpansion(t *testing.T) { |
||||
|
||||
user, _ := user.Current() |
||||
|
||||
tests := map[string]string{ |
||||
"/home/someuser/tmp": "/home/someuser/tmp", |
||||
"~/tmp": user.HomeDir + "/tmp", |
||||
"$DDDXXX/a/b": "/tmp/a/b", |
||||
"/a/b/": "/a/b", |
||||
} |
||||
|
||||
os.Setenv("DDDXXX", "/tmp") |
||||
|
||||
for test, expected := range tests { |
||||
got := expandPath(test) |
||||
if got != expected { |
||||
t.Errorf("test %s, got %s, expected %s\n", test, got, expected) |
||||
} |
||||
} |
||||
} |
Loading…
Reference in new issue