// getArgs parses given parameters and returns target, repo, module and // mode. If mode is "files", then target is optional. func goGetArgs(args []string) (string, string, string, goDepsMode) { f, target := standardFlags(goCmd) repo := f.String("repo", "", "Go repo (example: github.com/coreos/rkt)") module := f.String("module", "", "Module inside Go repo (example: stage1)") mode := f.String("mode", "make", "Mode to use (make - print deps as makefile [default], files - print a list of files)") f.Parse(args) if *repo == "" { common.Die("--repo parameter must be specified and cannot be empty") } if *module == "" { common.Die("--module parameter must be specified and cannot be empty") } var dMode goDepsMode switch *mode { case "make": dMode = goMakeMode if *target == "" { common.Die("--target parameter must be specified and cannot be empty when using 'make' mode") } case "files": dMode = goFilesMode default: common.Die("unknown --mode parameter %q - expected either 'make' or 'files'", *mode) } return *target, *repo, *module, dMode }
// globGetArgs parses given parameters and returns a target, a suffix // and a list of files. func globGetArgs(args []string) globArgs { f, target := standardFlags(globCmd) suffix := f.String("suffix", "", "File suffix (example: .go)") globbingMode := f.String("glob-mode", "all", "Which files to glob (normal, dot-files, all [default])") filelist := f.String("filelist", "", "Read all the files from this file") var mapTo []string mapToWrapper := common.StringSliceWrapper{Slice: &mapTo} f.Var(&mapToWrapper, "map-to", "Map contents of filelist to this directory, can be used multiple times") f.Parse(args) if *target == "" { common.Die("--target parameter must be specified and cannot be empty") } mode := globModeFromString(*globbingMode) if *filelist == "" { common.Die("--filelist parameter must be specified and cannot be empty") } if len(mapTo) < 1 { common.Die("--map-to parameter must be specified at least once") } return globArgs{ target: *target, suffix: *suffix, mode: mode, filelist: *filelist, mapTo: mapTo, } }
func getValidArgs() (string, []string) { filename := "" mapTo := []string{} mapToWrapper := common.StringSliceWrapper{ Slice: &mapTo, } flag.StringVar(&filename, "filelist", "", "Name of the source (path to the directory or to the filelist") flag.Var(&mapToWrapper, "map-to", "Map contents of traversed source to this directory, can be used multiple times") flag.Parse() if filename == "" { common.Die("No --filelist parameter passed") } if len(mapTo) < 1 { common.Die("No --map-to parameter passed, at least one is required") os.Exit(1) } filename = common.MustAbs(filename) for i := 0; i < len(mapTo); i++ { mapTo[i] = common.MustAbs(mapTo[i]) } return filename, mapTo }
func getListing(filename string) *filelist.Lists { fl, err := os.Open(filename) if err != nil { common.Die("Failed to open filelist %q: %v", filename, err) } defer fl.Close() list := &filelist.Lists{} if err := list.ParseFilelist(fl); err != nil { common.Die("Error during getting listing from filelist %q: %v\n", filename, err) } return list }
// goGetFiles returns a list of files that are in given packages. File // paths are relative to a given directory. func goGetFiles(dir string, pkgs []string) []string { params := []string{ "Dir", "GoFiles", "CgoFiles", } var allFiles []string rawTuples := goRun(goList(params, pkgs)) for _, raw := range rawTuples { tuple := goSliceRawTuple(raw) moduleDir := filepath.Clean(tuple[0]) dirSep := fmt.Sprintf("%s%c", dir, filepath.Separator) moduleDirSep := fmt.Sprintf("%s%c", moduleDir, filepath.Separator) if !strings.HasPrefix(moduleDirSep, dirSep) { continue } relModuleDir, err := filepath.Rel(dir, moduleDir) if err != nil { common.Die("Could not make a relative path from %q to %q, even if they have the same prefix", moduleDir, dir) } files := append(goSliceRawSlice(tuple[1]), goSliceRawSlice(tuple[2])...) for i := 0; i < len(files); i++ { files[i] = filepath.Join(relModuleDir, files[i]) } allFiles = append(allFiles, files...) } return allFiles }
func globGetFiles(args globArgs) []string { f, err := globGetFilesFromFilelist(args.filelist) if err != nil { common.Die("Failed to get files from filelist %q: %v", args.filelist, err) } return common.MapFilesToDirectories(f, args.mapTo) }
func main() { depTypes := getAllDepTypes() depTypesString := fmt.Sprintf("'%s'", strings.Join(depTypes, "', '")) if len(os.Args) < 2 { common.Die("Expected a deps type (possible values: %s)", depTypesString) } depType := os.Args[1] cmdArgs := os.Args[2:] if f, ok := cmds[depType]; ok { fmt.Print(f(cmdArgs)) } else if depType == "--help" || depType == "-help" { common.Warn("Run %s with one of the following commands: %s\nE.g. %s %s --help", appName(), depTypesString, os.Args[0], depTypes[0]) } else { common.Die("Unknown deps type: %q, expected one of %s", depType, depTypesString) } }
func getDeepListing(dir string) *filelist.Lists { walker := newFsWalker(common.MustAbs(dir)) list, err := walker.getListing() if err != nil { common.Die("Error during getting listing from directory %q: %v", dir, err) } return list }
func kvGetArgs(args []string) (string, map[string]string) { f, target := standardFlags(kvCmd) f.Parse(args) if *target == "" { common.Die("--target parameter must be specified and cannot be empty") } return *target, toMap(f.Args()...) }
func main() { dir := "" suffix := "" empty := false flag.StringVar(&dir, "directory", "", "Directory path") flag.StringVar(&suffix, "suffix", "", "Suffix for files in directory, when passed it basically does ${--dir}/*${suffix} (dotfiles are ignored)") flag.BoolVar(&empty, "empty", false, "Generate empty filelist") flag.Parse() if !empty && dir == "" { common.Die("No --directory parameter passed") } list := getListing(empty, dir, suffix) if err := list.GenerateFilelist(os.Stdout); err != nil { common.Die("Failed to generate a filelist: %v", err) } }
func getShallowListing(dir, suffix string) *filelist.Lists { list := &filelist.Lists{} fiList, err := ioutil.ReadDir(dir) if err != nil { common.Die("Failed to read directory %q: %v", dir, err) } for _, fi := range fiList { name := fi.Name() if !strings.HasSuffix(name, suffix) { continue } if strings.HasPrefix(name, ".") { continue } if err := categorizeEntry(name, fi.Mode(), list); err != nil { common.Die("%v", err) } } return list }
// globGetArgs parses given parameters and returns a target, a suffix // and a list of files. func globGetArgs(args []string) globArgs { f, target := standardFlags(globCmd) suffix := f.String("suffix", "", "File suffix (example: .go)") globbingMode := f.String("glob-mode", "all", "Which files to glob (normal, dot-files, all [default])") filesMode := f.String("mode", "args", "How to get files, either 'filelist' mode or 'args' [default]") filelist := f.String("filelist", "", "For filelist mode, read all the files from this file") mapTo := []string{} mapToWrapper := common.StringSliceWrapper{Slice: &mapTo} f.Var(&mapToWrapper, "map-to", "Map contents of filelist to this directory, can be used multiple times") f.Parse(args) if *target == "" { common.Die("--target parameter must be specified and cannot be empty") } mode := globModeFromString(*globbingMode) switch *filesMode { case "filelist": if *filelist == "" { common.Die("--filelist parameter must be specified and cannot be empty") } if len(mapTo) < 1 { common.Die("--map-to parameter must be specified at least once") } case "args": if *filelist != "" { common.Warn("--filelist parameter is ignored in args mode") } if len(mapTo) > 0 { common.Warn("--map-to parameter is ignored in args mode") } } return globArgs{ target: *target, suffix: *suffix, files: f.Args(), mode: mode, fMode: *filesMode, filelist: *filelist, mapTo: mapTo, } }
func getItems() []items { kinds := []*kindData{ &kindData{ option: "files", proc: &fileProcessor{}, }, &kindData{ option: "symlinks", proc: &symlinkProcessor{}, }, &kindData{ option: "dirs", proc: &dirProcessor{}, }, } for _, k := range kinds { flag.StringVar(&k.filename, k.option, "", fmt.Sprintf("List of %s", k.option)) } flag.Parse() for _, k := range kinds { if k.filename == "" { common.Die("No --%s parameter passed", k.option) } } allItems := make([]items, 0, len(kinds)) for _, k := range kinds { l, err := getList(k.filename, k.proc) if err != nil { common.Die("Failed to get %s list: %v", k.proc.kind(), err) } allItems = append(allItems, items{ kind: k.proc.kind(), list: l, }) } return allItems }
func globModeFromString(mode string) globMode { switch mode { case "normal": return globNormal case "dot-files": return globDotFiles case "all": return globAll default: common.Die("Unknown glob mode %q", mode) } panic("Should not happen") }
// toMap creates a map from passed strings. This function expects an // even number of strings, otherwise it will bail out. Odd (first, // third and so on) strings are keys, even (second, fourth and so on) // strings are values. func toMap(kv ...string) map[string]string { if len(kv)%2 != 0 { common.Die("Expected even number of strings in toMap") } r := make(map[string]string, len(kv)) lastKey := "" for i, kv := range kv { if i%2 == 0 { lastKey = kv } else { r[lastKey] = kv } } return r }
// goRun executes given argument list and captures its output. The // output is sliced into lines with empty lines being discarded. func goRun(argv []string) []string { cmd := exec.Command(argv[0], argv[1:]...) stdout := new(bytes.Buffer) stderr := new(bytes.Buffer) cmd.Stdout = stdout cmd.Stderr = stderr if err := cmd.Run(); err != nil { common.Die("Error running %s: %v: %s", strings.Join(argv, " "), err, stderr.String()) } rawLines := strings.Split(stdout.String(), "\n") lines := make([]string, 0, len(rawLines)) for _, line := range rawLines { if trimmed := strings.TrimSpace(line); trimmed != "" { lines = append(lines, trimmed) } } return lines }
// goGetDeps gets the directory of a given repo and the all // dependencies, direct or indirect, of a given module in the repo. func goGetDeps(repo, module string) (string, []string) { pkg := path.Join(repo, module) rawTuples := goRun(goList([]string{"Dir", "Deps"}, []string{pkg})) if len(rawTuples) != 1 { common.Die("Expected to get only one line from go list for a single package") } tuple := goSliceRawTuple(rawTuples[0]) dir := tuple[0] if module != "." { dirsToStrip := 1 + strings.Count(module, "/") for i := 0; i < dirsToStrip; i++ { dir = filepath.Dir(dir) } } dir = filepath.Clean(dir) deps := goSliceRawSlice(tuple[1]) return dir, append([]string{pkg}, deps...) }