From a041fe84ae1c1a794e30d10ac26ca0a2b7771e2e Mon Sep 17 00:00:00 2001 From: Vincent Batts Date: Tue, 14 Mar 2023 22:56:57 -0400 Subject: [PATCH] commits: add a fallback if rev-list fails due to shallow depth Fixes: #53 When CI only fetches some shallow depth of commits in a repo, don't fail on `git rev-list` on commits that are outside that range. Signed-off-by: Vincent Batts --- git/commits.go | 41 ++++++++++++++++++++++++++++++++++++++++- main.go | 9 +++++---- 2 files changed, 45 insertions(+), 5 deletions(-) diff --git a/git/commits.go b/git/commits.go index 2bdc5d7..8bef00f 100644 --- a/git/commits.go +++ b/git/commits.go @@ -15,13 +15,19 @@ import ( // If commitrange is a single commit, all ancestor commits up through the hash provided. // If commitrange is an empty commit range, then nil is returned. func Commits(commitrange string) ([]CommitEntry, error) { + // TEST if it has _enough_ of a range from rev-list + commitrange, err := checkRevList(commitrange) + if err != nil { + logrus.Errorf("failed to validate the git commit range: %s", err) + return nil, err + } cmdArgs := []string{"git", "rev-list", commitrange} if debug() { logrus.Infof("[git] cmd: %q", strings.Join(cmdArgs, " ")) } output, err := exec.Command(cmdArgs[0], cmdArgs[1:]...).Output() if err != nil { - logrus.Errorf("mm[git] cmd: %q", strings.Join(cmdArgs, " ")) + logrus.Errorf("[git] cmd: %q", strings.Join(cmdArgs, " ")) return nil, err } if len(output) == 0 { @@ -39,6 +45,39 @@ func Commits(commitrange string) ([]CommitEntry, error) { return commits, nil } +// Since the commitrange requested may be longer than the depth being cloned in CI, +// check for an error, if so do a git log to get the oldest available commit for a reduced range. +func checkRevList(commitrange string) (string, error) { + cmdArgs := []string{"git", "rev-list", commitrange} + if debug() { + logrus.Infof("[git] cmd: %q", strings.Join(cmdArgs, " ")) + } + _, err := exec.Command(cmdArgs[0], cmdArgs[1:]...).Output() + if err == nil { + // no issues, return now + return commitrange, nil + } + cmdArgs = []string{"git", "log", "--pretty=oneline"} + if debug() { + logrus.Infof("[git] cmd: %q", strings.Join(cmdArgs, " ")) + } + output, err := exec.Command(cmdArgs[0], cmdArgs[1:]...).Output() + if err != nil { + logrus.Errorf("[git] cmd: %q", strings.Join(cmdArgs, " ")) + return "", err + } + // This "output" is now the list of available commits and short description. + // We want the last commit hash only.. (i.e. `| tail -n1 | awk '{ print $1 }'`) + chunks := strings.Split(strings.TrimSpace(string(output)), "\n") + if len(chunks) == 1 { + return strings.Split(chunks[0], " ")[0], nil + } + last := chunks[len(chunks)-1] + lastCommit := strings.Split(last, " ")[0] + + return fmt.Sprintf("%s..HEAD", lastCommit), nil +} + // FieldNames are for the formating and rendering of the CommitEntry structs. // Keys here are from git log pretty format "format:..." var FieldNames = map[string]string{ diff --git a/main.go b/main.go index 1a34d7f..2109915 100644 --- a/main.go +++ b/main.go @@ -3,10 +3,10 @@ package main import ( "flag" "fmt" - "log" "os" "strings" + "github.com/sirupsen/logrus" _ "github.com/vbatts/git-validation/rules/danglingwhitespace" _ "github.com/vbatts/git-validation/rules/dco" _ "github.com/vbatts/git-validation/rules/messageregexp" @@ -62,7 +62,7 @@ func main() { rules = validate.FilterRules(validate.RegisteredRules, validate.SanitizeFilters(*flRun)) } if os.Getenv("DEBUG") != "" { - log.Printf("%#v", rules) // XXX maybe reduce this list + logrus.Printf("%#v", rules) // XXX maybe reduce this list } var commitRange = *flCommitRange @@ -80,13 +80,14 @@ func main() { } } + logrus.Infof("using commit range: %s", commitRange) runner, err := validate.NewRunner(*flDir, rules, commitRange, *flVerbose) if err != nil { - log.Fatal(err) + logrus.Fatal(err) } if err := runner.Run(); err != nil { - log.Fatal(err) + logrus.Fatal(err) } _, fail := runner.Results.PassFail() if fail > 0 {