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
}
Exemple #2
0
// 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)
	}
}
Exemple #3
0
// 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'")
	}
}
Exemple #4
0
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
}