func setup(t *testing.T, td string, files map[string]string) scm.Change { fooDir := filepath.Join(td, "src", "foo") ut.AssertEqual(t, nil, os.MkdirAll(fooDir, 0700)) for f, c := range files { p := filepath.Join(fooDir, f) ut.AssertEqual(t, nil, os.MkdirAll(filepath.Dir(p), 0700)) ut.AssertEqual(t, nil, ioutil.WriteFile(p, []byte(c), 0600)) } _, code, err := internal.Capture(fooDir, nil, "git", "init") ut.AssertEqual(t, 0, code) ut.AssertEqual(t, nil, err) // It's important to add the files to the index, otherwise they will be // ignored. _, code, err = internal.Capture(fooDir, nil, "git", "add", ".") ut.AssertEqual(t, 0, code) ut.AssertEqual(t, nil, err) repo, err := scm.GetRepo(fooDir, td) ut.AssertEqual(t, nil, err) change, err := repo.Between(scm.Current, scm.GitInitialCommit, nil) ut.AssertEqual(t, nil, err) ut.AssertEqual(t, true, change != nil) return change }
// mainImpl implements pcg. func mainImpl() error { a := application{} exec, args := os.Args[0], os.Args[1:] var commands, flags []string for i, arg := range args { if strings.HasPrefix(arg, "-") { flags = args[i:] break } commands = append(commands, arg) } if len(commands) == 0 { if checks.IsContinuousIntegration() { commands = []string{"run-hook", "continuous-integration"} } else { commands = []string{"installrun"} } } fs := flag.NewFlagSet(exec, flag.ExitOnError) verboseFlag := fs.Bool("v", checks.IsContinuousIntegration() || os.Getenv("VERBOSE") != "", "enables verbose logging output") allFlag := fs.Bool("a", false, "runs checks as if all files had been modified") againstFlag := fs.String("r", "", "runs checks on files modified since this revision, as evaluated by your scm repo") noUpdateFlag := fs.Bool("n", false, "disallow using go get even if a prerequisite is missing; bail out instead") configPathFlag := fs.String("c", "pre-commit-go.yml", "file name of the config to load") modeFlag := fs.String("m", "", "comma separated list of modes to process; default depends on the command") fs.IntVar(&a.maxConcurrent, "C", 0, "maximum number of concurrent processes") fs.Parse(flags) if *allFlag { if *againstFlag != "" { return errors.New("-a can't be used with -r") } *againstFlag = string(scm.Initial) } log.SetFlags(log.Lmicroseconds) if !*verboseFlag { log.SetOutput(ioutil.Discard) } modes, err := processModes(*modeFlag) if err != nil { return err } cwd, err := os.Getwd() if err != nil { return err } repo, err := scm.GetRepo(cwd, "") if err != nil { return err } var configPath string configPath, a.config = loadConfig(repo, *configPathFlag) log.Printf("config: %s", configPath) if a.maxConcurrent > 0 { log.Printf("using %d maximum concurrent goroutines", a.maxConcurrent) a.config.MaxConcurrent = a.maxConcurrent } switch cmd := commands[0]; cmd { case "help", "-help", "-h": cmd = "help" if *allFlag != false { return fmt.Errorf("-a can't be used with %s", cmd) } if *againstFlag != "" { return fmt.Errorf("-r can't be used with %s", cmd) } if *noUpdateFlag != false { return fmt.Errorf("-n can't be used with %s", cmd) } if *configPathFlag != "pre-commit-go.yml" { return fmt.Errorf("-m can't be used with %s", cmd) } if *modeFlag != "" { return fmt.Errorf("-m can't be used with %s", cmd) } b := &bytes.Buffer{} fs.SetOutput(b) fs.PrintDefaults() return a.cmdHelp(repo, b.String()) case "info": if *allFlag != false { return fmt.Errorf("-a can't be used with %s", cmd) } if *againstFlag != "" { return fmt.Errorf("-r can't be used with %s", cmd) } if *noUpdateFlag != false { return fmt.Errorf("-n can't be used with %s", cmd) } return a.cmdInfo(repo, modes, configPath) case "install", "i": cmd = "install" if *allFlag != false { return fmt.Errorf("-a can't be used with %s", cmd) } if *againstFlag != "" { return fmt.Errorf("-r can't be used with %s", cmd) } if len(modes) == 0 { modes = checks.AllModes } var prereqReady sync.WaitGroup prereqReady.Add(1) return a.cmdInstall(repo, modes, *noUpdateFlag, &prereqReady) case "installrun": if len(modes) == 0 { modes = []checks.Mode{checks.PrePush} } // Start running all checks that do not have a prerequisite before // installation is completed. var prereqReady sync.WaitGroup prereqReady.Add(1) errCh := make(chan error, 1) go func() { errCh <- a.cmdInstall(repo, modes, *noUpdateFlag, &prereqReady) }() err := a.cmdRun(repo, modes, *againstFlag, &prereqReady) if err2 := <-errCh; err2 != nil { return err2 } return err case "prereq", "p": cmd = "prereq" if *allFlag != false { return fmt.Errorf("-a can't be used with %s", cmd) } if *againstFlag != "" { return fmt.Errorf("-r can't be used with %s", cmd) } if len(modes) == 0 { modes = checks.AllModes } return a.cmdInstallPrereq(repo, modes, *noUpdateFlag) case "run", "r": cmd = "run" if *noUpdateFlag != false { return fmt.Errorf("-n can't be used with %s", cmd) } if len(modes) == 0 { modes = []checks.Mode{checks.PrePush} } return a.cmdRun(repo, modes, *againstFlag, &sync.WaitGroup{}) case "run-hook": if modes != nil { return fmt.Errorf("-m can't be used with %s", cmd) } if *allFlag != false { return fmt.Errorf("-a can't be used with %s", cmd) } if *againstFlag != "" { return fmt.Errorf("-r can't be used with %s", cmd) } if len(commands) < 2 { return errors.New("run-hook is only meant to be used by hooks") } return a.cmdRunHook(repo, commands[1], *noUpdateFlag) case "version": if modes != nil { return fmt.Errorf("-m can't be used with %s", cmd) } if *allFlag != false { return fmt.Errorf("-a can't be used with %s", cmd) } if *againstFlag != "" { return fmt.Errorf("-r can't be used with %s", cmd) } if *noUpdateFlag != false { return fmt.Errorf("-n can't be used with %s", cmd) } fmt.Println(version) return nil case "writeconfig", "w": if modes != nil { return fmt.Errorf("-m can't be used with %s", cmd) } if *allFlag != false { return fmt.Errorf("-a can't be used with %s", cmd) } if *againstFlag != "" { return fmt.Errorf("-r can't be used with %s", cmd) } // Note that in that case, configPath is ignored and not overritten. return a.cmdWriteConfig(repo, *configPathFlag) default: return fmt.Errorf("unknown command %q, try 'help'", cmd) } }
// mainImpl implements pcg. func mainImpl() error { if len(os.Args) == 1 { if checks.IsContinuousIntegration() { os.Args = append(os.Args, "run-hook", "continuous-integration") } else { os.Args = append(os.Args, "installrun") } } cmd := os.Args[1] copy(os.Args[1:], os.Args[2:]) os.Args = os.Args[:len(os.Args)-1] verboseFlag := flag.Bool("v", checks.IsContinuousIntegration() || os.Getenv("VERBOSE") != "", "enables verbose logging output") allFlag := flag.Bool("a", false, "runs checks as if all files had been modified") againstFlag := flag.String("r", "", "runs checks on files modified since this revision, as evaluated by your scm repo") noUpdateFlag := flag.Bool("n", false, "disallow using go get even if a prerequisite is missing; bail out instead") configPathFlag := flag.String("c", "pre-commit-go.yml", "file name of the config to load") modeFlag := flag.String("m", "", "coma separated list of modes to process; default depends on the command") flag.Parse() if *allFlag { if *againstFlag != "" { return errors.New("-a can't be used with -r") } *againstFlag = string(scm.GitInitialCommit) } log.SetFlags(log.Lmicroseconds) if !*verboseFlag { log.SetOutput(ioutil.Discard) } modes, err := processModes(*modeFlag) if err != nil { return err } cwd, err := os.Getwd() if err != nil { return err } repo, err := scm.GetRepo(cwd, "") if err != nil { return err } configPath, config := loadConfig(repo, *configPathFlag) log.Printf("config: %s", configPath) switch cmd { case "help", "-help", "-h": cmd = "help" if *allFlag != false { return fmt.Errorf("-a can't be used with %s", cmd) } if *againstFlag != "" { return fmt.Errorf("-r can't be used with %s", cmd) } if *noUpdateFlag != false { return fmt.Errorf("-n can't be used with %s", cmd) } if *configPathFlag != "pre-commit-go.yml" { return fmt.Errorf("-m can't be used with %s", cmd) } if *modeFlag != "" { return fmt.Errorf("-m can't be used with %s", cmd) } b := &bytes.Buffer{} flag.CommandLine.SetOutput(b) flag.CommandLine.PrintDefaults() return cmdHelp(repo, config, b.String()) case "info": if *allFlag != false { return fmt.Errorf("-a can't be used with %s", cmd) } if *againstFlag != "" { return fmt.Errorf("-r can't be used with %s", cmd) } if *noUpdateFlag != false { return fmt.Errorf("-n can't be used with %s", cmd) } return cmdInfo(repo, config, modes, configPath) case "install", "i": cmd = "install" if *allFlag != false { return fmt.Errorf("-a can't be used with %s", cmd) } if *againstFlag != "" { return fmt.Errorf("-r can't be used with %s", cmd) } if len(modes) == 0 { modes = checks.AllModes } var prereqReady sync.WaitGroup prereqReady.Add(1) return cmdInstall(repo, config, modes, *noUpdateFlag, &prereqReady) case "installrun": if len(modes) == 0 { modes = []checks.Mode{checks.PrePush} } // Start running all checks that do not have a prerequisite before // installation is completed. var prereqReady sync.WaitGroup prereqReady.Add(1) errCh := make(chan error, 1) go func() { errCh <- cmdInstall(repo, config, modes, *noUpdateFlag, &prereqReady) }() err := cmdRun(repo, config, modes, *againstFlag, &prereqReady) if err2 := <-errCh; err2 != nil { return err2 } return err case "prereq", "p": cmd = "prereq" if *allFlag != false { return fmt.Errorf("-a can't be used with %s", cmd) } if *againstFlag != "" { return fmt.Errorf("-r can't be used with %s", cmd) } if len(modes) == 0 { modes = checks.AllModes } return cmdInstallPrereq(repo, config, modes, *noUpdateFlag) case "run", "r": cmd = "run" if *noUpdateFlag != false { return fmt.Errorf("-n can't be used with %s", cmd) } if len(modes) == 0 { modes = []checks.Mode{checks.PrePush} } return cmdRun(repo, config, modes, *againstFlag, &sync.WaitGroup{}) case "run-hook": if modes != nil { return fmt.Errorf("-m can't be used with %s", cmd) } if *allFlag != false { return fmt.Errorf("-a can't be used with %s", cmd) } if *againstFlag != "" { return fmt.Errorf("-r can't be used with %s", cmd) } if flag.NArg() != 1 { return errors.New("run-hook is only meant to be used by hooks") } return cmdRunHook(repo, config, flag.Arg(0), *noUpdateFlag) case "version": if modes != nil { return fmt.Errorf("-m can't be used with %s", cmd) } if *allFlag != false { return fmt.Errorf("-a can't be used with %s", cmd) } if *againstFlag != "" { return fmt.Errorf("-r can't be used with %s", cmd) } if *noUpdateFlag != false { return fmt.Errorf("-n can't be used with %s", cmd) } fmt.Println(version) return nil case "writeconfig", "w": if modes != nil { return fmt.Errorf("-m can't be used with %s", cmd) } if *allFlag != false { return fmt.Errorf("-a can't be used with %s", cmd) } if *againstFlag != "" { return fmt.Errorf("-r can't be used with %s", cmd) } // Note that in that case, configPath is ignored and not overritten. return cmdWriteConfig(repo, config, *configPathFlag) default: return errors.New("unknown command, try 'help'") } }
func mainImpl() error { minFlag := flag.Float64("min", 1, "minimum expected coverage in %") maxFlag := flag.Float64("max", 100, "maximum expected coverage in %") globalFlag := flag.Bool("g", false, "use global coverage") verboseFlag := flag.Bool("v", false, "enable logging") ignoreFlag := scm.IgnorePatterns{} flag.Var(&ignoreFlag, "i", "glob to ignore, use multiple times") flag.Parse() log.SetFlags(log.Lmicroseconds) if !*verboseFlag { log.SetOutput(ioutil.Discard) } cwd, err := os.Getwd() if err != nil { return err } repo, err := scm.GetRepo(cwd, "") if err != nil { return err } c := checks.Coverage{ UseGlobalInference: *globalFlag, Global: checks.CoverageSettings{ MinCoverage: *minFlag, MaxCoverage: *maxFlag, }, PerDirDefault: checks.CoverageSettings{ MinCoverage: *minFlag, MaxCoverage: *maxFlag, }, } // TODO(maruel): Run tests ala pcg; e.g. determine what diff to use. // TODO(maruel): Run only tests down the current directory when // *globalFlag == false. change, err := repo.Between(scm.Current, scm.Initial, ignoreFlag) if err != nil { return err } log.Printf("Packages: %s\n", change.All().TestPackages()) profile, err := c.RunProfile(change, &checks.Options{MaxDuration: 999}) if err != nil { return err } if *globalFlag { if !printProfile(&c.Global, profile, "") { return errSilent } } else { for _, pkg := range change.All().TestPackages() { d := pkgToDir(pkg) subset := profile.Subset(d) if len(subset) != 0 { fmt.Printf("%s\n", d) if !printProfile(&c.Global, subset, " ") { err = errSilent } } else { log.Printf("%s is empty", pkg) } } } return nil }