// cmdInstall first calls cmdInstallPrereq() then install the // .git/hooks/pre-commit and pre-push hooks. // // Silently ignore installing the hooks when running under a CI. In // particular, circleci.com doesn't create the directory .git/hooks. func (a *application) cmdInstall(repo scm.ReadOnlyRepo, modes []checks.Mode, noUpdate bool, prereqReady *sync.WaitGroup) (err error) { errCh := make(chan error, 1) go func() { defer prereqReady.Done() errCh <- a.cmdInstallPrereq(repo, modes, noUpdate) }() defer func() { if err2 := <-errCh; err == nil { err = err2 } }() if checks.IsContinuousIntegration() { log.Printf("Running under CI; not installing hooks") return nil } log.Printf("Installing hooks") hookDir, err2 := repo.HookPath() if err2 != nil { return err2 } for _, t := range []string{"pre-commit", "pre-push"} { // Always remove hook first if it exists, in case it's a symlink. p := filepath.Join(hookDir, t) _ = os.Remove(p) if err = ioutil.WriteFile(p, []byte(fmt.Sprintf(hookContent, t)), 0777); err != nil { return err } } log.Printf("Installation done") return nil }
// loadConfig loads the on disk configuration or use the default configuration // if none is found. See CONFIGURATION.md for the logic. func loadConfig(repo scm.ReadOnlyRepo, path string) (string, *checks.Config) { if filepath.IsAbs(path) { if config := loadConfigFile(path); config != nil { return path, config } } else { // <repo root>/.git/<path> if scmDir, err := repo.ScmDir(); err == nil { file := filepath.Join(scmDir, path) if config := loadConfigFile(file); config != nil { return file, config } } // <repo root>/<path> file := filepath.Join(repo.Root(), path) if config := loadConfigFile(file); config != nil { return file, config } if user, err := user.Current(); err == nil && user.HomeDir != "" { if runtime.GOOS == "windows" { // ~/<path> file = filepath.Join(user.HomeDir, path) } else { // ~/.config/<path> file = filepath.Join(user.HomeDir, ".config", path) } if config := loadConfigFile(file); config != nil { return file, config } } } return "<N/A>", checks.New(version) }
// Capture sets GOPATH and executes a subprocess. func (o *Options) Capture(r scm.ReadOnlyRepo, args ...string) (string, int, time.Duration, error) { o.LeaseRunToken() defer o.ReturnRunToken() start := time.Now() out, exitCode, err := internal.Capture(r.Root(), []string{"GOPATH=" + r.GOPATH()}, args...) return out, exitCode, time.Since(start), err }
// cmdInfo displays the current configuration used. func (a *application) cmdInfo(repo scm.ReadOnlyRepo, modes []checks.Mode, configPath string) error { fmt.Printf("File: %s\n", configPath) fmt.Printf("Repo: %s\n", repo.Root()) fmt.Printf("MinVersion: %s\n", a.config.MinVersion) content, err := yaml.Marshal(a.config.IgnorePatterns) if err != nil { return err } fmt.Printf("IgnorePatterns:\n%s", content) if len(modes) == 0 { modes = checks.AllModes } for _, mode := range modes { settings := a.config.Modes[mode] maxLen := 0 for _, checks := range settings.Checks { for _, check := range checks { if l := len(check.GetName()); l > maxLen { maxLen = l } } } fmt.Printf("\n%s:\n %-*s %d seconds\n", mode, maxLen+1, "Limit:", settings.Options.MaxDuration) for _, checks := range settings.Checks { for _, check := range checks { name := check.GetName() fmt.Printf(" %s:%s %s\n", name, strings.Repeat(" ", maxLen-len(name)), check.GetDescription()) content, err := yaml.Marshal(check) if err != nil { return err } options := strings.TrimSpace(string(content)) if options == "{}" { // It means there's no options. options = "<no option>" } lines := strings.Join(strings.Split(options, "\n"), "\n ") fmt.Printf(" %s\n", lines) } } } return nil }
// cmdRun runs all the enabled checks. func (a *application) cmdRun(repo scm.ReadOnlyRepo, modes []checks.Mode, against string, prereqReady *sync.WaitGroup) error { var err error var old scm.Commit if against != "" { if old = repo.Eval(against); old == scm.Invalid { return errors.New("invalid commit 'against'") } } else { if old = repo.Eval(string(scm.Upstream)); old == scm.Invalid { return errors.New("no upstream") } } change, err := repo.Between(scm.Current, old, a.config.IgnorePatterns) if err != nil { return err } return a.runChecks(change, modes, prereqReady) }
// cmdRun runs all the enabled checks. func cmdRun(repo scm.ReadOnlyRepo, config *checks.Config, modes []checks.Mode, against string, prereqReady *sync.WaitGroup) error { var err error var old scm.Commit if against != "" { if old, err = repo.Eval(against); err != nil { return err } } else { if old, err = repo.Upstream(); err != nil { return err } } change, err := repo.Between(scm.Current, old, config.IgnorePatterns) if err != nil { return err } return runChecks(config, change, modes, prereqReady) }
// capture sets GOPATH. func capture(r scm.ReadOnlyRepo, args ...string) (string, int, error) { return internal.Capture(r.Root(), []string{"GOPATH=" + r.GOPATH()}, args...) }