github.com/devfans/go-ethereum@v1.5.10-0.20170326212234-7419d0c38291/cmd/utils/customflags.go (about) 1 // Copyright 2015 The go-ethereum Authors 2 // This file is part of go-ethereum. 3 // 4 // go-ethereum is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // go-ethereum is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. 16 17 package utils 18 19 import ( 20 "errors" 21 "flag" 22 "fmt" 23 "math/big" 24 "os" 25 "os/user" 26 "path" 27 "strings" 28 29 "github.com/ethereum/go-ethereum/common/math" 30 "gopkg.in/urfave/cli.v1" 31 ) 32 33 // Custom type which is registered in the flags library which cli uses for 34 // argument parsing. This allows us to expand Value to an absolute path when 35 // the argument is parsed 36 type DirectoryString struct { 37 Value string 38 } 39 40 func (self *DirectoryString) String() string { 41 return self.Value 42 } 43 44 func (self *DirectoryString) Set(value string) error { 45 self.Value = expandPath(value) 46 return nil 47 } 48 49 // Custom cli.Flag type which expand the received string to an absolute path. 50 // e.g. ~/.ethereum -> /home/username/.ethereum 51 type DirectoryFlag struct { 52 Name string 53 Value DirectoryString 54 Usage string 55 } 56 57 func (self DirectoryFlag) String() string { 58 fmtString := "%s %v\t%v" 59 if len(self.Value.Value) > 0 { 60 fmtString = "%s \"%v\"\t%v" 61 } 62 return fmt.Sprintf(fmtString, prefixedNames(self.Name), self.Value.Value, self.Usage) 63 } 64 65 func eachName(longName string, fn func(string)) { 66 parts := strings.Split(longName, ",") 67 for _, name := range parts { 68 name = strings.Trim(name, " ") 69 fn(name) 70 } 71 } 72 73 // called by cli library, grabs variable from environment (if in env) 74 // and adds variable to flag set for parsing. 75 func (self DirectoryFlag) Apply(set *flag.FlagSet) { 76 eachName(self.Name, func(name string) { 77 set.Var(&self.Value, self.Name, self.Usage) 78 }) 79 } 80 81 // BigFlag is a command line flag that accepts 256 bit big integers in decimal or 82 // hexadecimal syntax. 83 type BigFlag struct { 84 Name string 85 Value *big.Int 86 Usage string 87 } 88 89 // bigValue turns *big.Int into a flag.Value 90 type bigValue big.Int 91 92 func (b *bigValue) String() string { 93 if b == nil { 94 return "" 95 } 96 return (*big.Int)(b).String() 97 } 98 99 func (b *bigValue) Set(s string) error { 100 int, ok := math.ParseBig256(s) 101 if !ok { 102 return errors.New("invalid integer syntax") 103 } 104 *b = (bigValue)(*int) 105 return nil 106 } 107 108 func (f BigFlag) GetName() string { 109 return f.Name 110 } 111 112 func (f BigFlag) String() string { 113 fmtString := "%s %v\t%v" 114 if f.Value != nil { 115 fmtString = "%s \"%v\"\t%v" 116 } 117 return fmt.Sprintf(fmtString, prefixedNames(f.Name), f.Value, f.Usage) 118 } 119 120 func (f BigFlag) Apply(set *flag.FlagSet) { 121 eachName(f.Name, func(name string) { 122 set.Var((*bigValue)(f.Value), f.Name, f.Usage) 123 }) 124 } 125 126 // GlobalBig returns the value of a BigFlag from the global flag set. 127 func GlobalBig(ctx *cli.Context, name string) *big.Int { 128 val := ctx.GlobalGeneric(name) 129 if val == nil { 130 return nil 131 } 132 return (*big.Int)(val.(*bigValue)) 133 } 134 135 func prefixFor(name string) (prefix string) { 136 if len(name) == 1 { 137 prefix = "-" 138 } else { 139 prefix = "--" 140 } 141 142 return 143 } 144 145 func prefixedNames(fullName string) (prefixed string) { 146 parts := strings.Split(fullName, ",") 147 for i, name := range parts { 148 name = strings.Trim(name, " ") 149 prefixed += prefixFor(name) + name 150 if i < len(parts)-1 { 151 prefixed += ", " 152 } 153 } 154 return 155 } 156 157 func (self DirectoryFlag) GetName() string { 158 return self.Name 159 } 160 161 func (self *DirectoryFlag) Set(value string) { 162 self.Value.Value = value 163 } 164 165 // Expands a file path 166 // 1. replace tilde with users home dir 167 // 2. expands embedded environment variables 168 // 3. cleans the path, e.g. /a/b/../c -> /a/c 169 // Note, it has limitations, e.g. ~someuser/tmp will not be expanded 170 func expandPath(p string) string { 171 if strings.HasPrefix(p, "~/") || strings.HasPrefix(p, "~\\") { 172 if home := homeDir(); home != "" { 173 p = home + p[1:] 174 } 175 } 176 return path.Clean(os.ExpandEnv(p)) 177 } 178 179 func homeDir() string { 180 if home := os.Getenv("HOME"); home != "" { 181 return home 182 } 183 if usr, err := user.Current(); err == nil { 184 return usr.HomeDir 185 } 186 return "" 187 }