github.com/VMitov/casper@v0.4.0/cmd/casper/flags.go (about)

     1  package main
     2  
     3  import (
     4  	"flag"
     5  	"net/url"
     6  	"path/filepath"
     7  	"strings"
     8  	"syscall"
     9  
    10  	"github.com/pkg/errors"
    11  	cli "gopkg.in/urfave/cli.v2"
    12  	"gopkg.in/urfave/cli.v2/altsrc"
    13  )
    14  
    15  // sourcesSliceFlag is the flag type that wraps cli.sourcesSliceFlag to allow
    16  // for other values to be specified
    17  type sourcesSliceFlag struct {
    18  	*cli.StringSliceFlag
    19  	set *flag.FlagSet
    20  }
    21  
    22  // newSourcesSliceFlag creates a new StringSliceFlag
    23  func newSourcesSliceFlag(fl *cli.StringSliceFlag) *sourcesSliceFlag {
    24  	return &sourcesSliceFlag{StringSliceFlag: fl, set: nil}
    25  }
    26  
    27  // Apply saves the flagSet for later usage calls, then calls the
    28  // wrapped StringSliceFlag.Apply
    29  func (f *sourcesSliceFlag) Apply(set *flag.FlagSet) {
    30  	f.set = set
    31  	f.StringSliceFlag.Apply(set)
    32  }
    33  
    34  // ApplyWithError saves the flagSet for later usage calls, then calls the
    35  // wrapped StringSliceFlag.ApplyWithError
    36  func (f *sourcesSliceFlag) ApplyWithError(set *flag.FlagSet) error {
    37  	f.set = set
    38  	return f.StringSliceFlag.ApplyWithError(set)
    39  }
    40  
    41  // ApplyInputSourceValue applies a StringSlice value to the flagSet if required
    42  func (f *sourcesSliceFlag) ApplyInputSourceValue(context *cli.Context, isc altsrc.InputSourceContext) error {
    43  	if f.set != nil {
    44  		if !context.IsSet(f.Name) && !isEnvVarSet(f.EnvVars) {
    45  			value, err := isc.StringSlice(f.StringSliceFlag.Name)
    46  			if err != nil {
    47  				return err
    48  			}
    49  
    50  			dir, err := getConfigDir(context)
    51  			if err != nil {
    52  				return err
    53  			}
    54  
    55  			value, err = fixPathsForSources(dir, value)
    56  			if err != nil {
    57  				return err
    58  			}
    59  
    60  			if value != nil {
    61  				sliceValue := *(cli.NewStringSlice(value...))
    62  				for _, name := range f.Names() {
    63  					underlyingFlag := f.set.Lookup(name)
    64  					if underlyingFlag != nil {
    65  						underlyingFlag.Value = &sliceValue
    66  					}
    67  				}
    68  			}
    69  		}
    70  	}
    71  	return nil
    72  }
    73  
    74  func getConfigDir(context *cli.Context) (string, error) {
    75  	configPath := context.String(configFlag)
    76  	inputSourcePath, err := filepath.Abs(configPath)
    77  	if err != nil {
    78  		return "", errors.Wrapf(err, "resolving absolute path for config %v failed", configPath)
    79  	}
    80  
    81  	return filepath.Dir(inputSourcePath), nil
    82  }
    83  
    84  func fixPathsForSources(dir string, value []string) ([]string, error) {
    85  	for i, v := range value {
    86  		fixed, err := fixPathsForSource(dir, v)
    87  		if err != nil {
    88  			return value, err
    89  		}
    90  		if fixed != v {
    91  			value[i] = fixed
    92  		}
    93  	}
    94  	return value, nil
    95  }
    96  
    97  func fixPathsForSource(dir, value string) (string, error) {
    98  	u, err := url.Parse(value)
    99  	if err != nil {
   100  		return "", errors.Wrapf(err, "parsing source %v failed", value)
   101  	}
   102  
   103  	if u.Scheme == "file" {
   104  		fixed, err := fixPathsForFileSource(dir, u)
   105  		if err != nil {
   106  			return "", errors.Wrapf(err, "converting file source path %v to absolute failed", u)
   107  		}
   108  
   109  		return fixed, nil
   110  	}
   111  
   112  	return value, nil
   113  }
   114  
   115  func fixPathsForFileSource(dir string, u *url.URL) (string, error) {
   116  	path := u.Host + u.Path
   117  	if strings.HasPrefix(path, "/") {
   118  		return u.String(), nil
   119  	}
   120  
   121  	var err error
   122  	u.Path, err = url.PathUnescape(filepath.Join(dir, path))
   123  	if err != nil {
   124  		return "", err
   125  	}
   126  
   127  	u.Host = ""
   128  	return u.String(), nil
   129  }
   130  
   131  func isEnvVarSet(envVars []string) bool {
   132  	for _, envVar := range envVars {
   133  		if _, ok := syscall.Getenv(envVar); ok {
   134  			// TODO: Can't use this for bools as
   135  			// set means that it was true or false based on
   136  			// Bool flag type, should work for other types
   137  			return true
   138  		}
   139  	}
   140  
   141  	return false
   142  }