-
Notifications
You must be signed in to change notification settings - Fork 1.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Scan GitHub and GitLab refs that aren't cloned by default #1918
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -108,7 +108,9 @@ func (d *Diff) finalize() error { return d.contentWriter.CloseForWriting() } | |
|
||
// Commit contains commit header info and diffs. | ||
type Commit struct { | ||
Hash string | ||
Hash string | ||
// The source of a commit, if it doesn't exist in the repository's history. | ||
Source string | ||
Author string | ||
Committer string | ||
Date time.Time | ||
|
@@ -231,19 +233,23 @@ func (c *Parser) RepoPath( | |
) (chan *Diff, error) { | ||
args := []string{ | ||
"-C", source, | ||
"--no-replace-objects", | ||
"log", | ||
"--patch", // https://git-scm.com/docs/git-log#Documentation/git-log.txt---patch | ||
"--full-history", | ||
"--date=format:%a %b %d %H:%M:%S %Y %z", | ||
"--pretty=fuller", // https://git-scm.com/docs/git-log#_pretty_formats | ||
"--notes", // https://git-scm.com/docs/git-log#Documentation/git-log.txt---notesltrefgt | ||
"--source", // https://git-scm.com/docs/git-log#Documentation/git-log.txt---source | ||
} | ||
if abbreviatedLog { | ||
// https://git-scm.com/docs/git-log#Documentation/git-log.txt---diff-filterACDMRTUXB82308203 | ||
args = append(args, "--diff-filter=AM") | ||
} | ||
if head != "" { | ||
args = append(args, head) | ||
} else { | ||
// https://git-scm.com/docs/git-log#Documentation/git-log.txt---all | ||
args = append(args, "--all") | ||
} | ||
for _, glob := range excludedGlobs { | ||
|
@@ -332,10 +338,9 @@ func (c *Parser) FromReader(ctx context.Context, stdOut io.Reader, diffChan chan | |
outReader := bufio.NewReader(stdOut) | ||
var ( | ||
currentCommit *Commit | ||
|
||
totalLogSize int | ||
totalLogSize int | ||
latestState = Initial | ||
) | ||
var latestState = Initial | ||
|
||
diff := func(c *Commit, opts ...diffOption) *Diff { | ||
opts = append(opts, withCustomContentWriter(bufferwriter.New())) | ||
|
@@ -395,10 +400,18 @@ func (c *Parser) FromReader(ctx context.Context, stdOut io.Reader, diffChan chan | |
// Create a new currentDiff and currentCommit | ||
currentCommit = &Commit{Message: strings.Builder{}} | ||
currentDiff = diff(currentCommit) | ||
// Check that the commit line contains a hash and set it. | ||
if len(line) >= 47 { | ||
currentCommit.Hash = string(line[7:47]) | ||
|
||
hash, ref := parseCommitLine(line) | ||
if hash == nil || ref == nil { | ||
ctx.Logger().Error( | ||
fmt.Errorf(`expected line to match 'commit <hash> <ref>', got %q`, line), | ||
"Failed to parse CommitLine") | ||
latestState = ParseFailure | ||
continue | ||
} | ||
|
||
currentCommit.Hash = string(hash) | ||
currentCommit.Source = parseSourceRef(ref) | ||
case isMergeLine(isStaged, latestState, line): | ||
latestState = MergeLine | ||
case isAuthorLine(isStaged, latestState, line): | ||
|
@@ -614,6 +627,47 @@ func isCommitLine(isStaged bool, latestState ParseState, line []byte) bool { | |
return false | ||
} | ||
|
||
func parseCommitLine(line []byte) (hash []byte, ref []byte) { | ||
// Check that the commit line contains a 40-character hash and set it. | ||
// `commit e5575cd6f2d21d3a1a604287c7bf4a7eab2266e0\n` | ||
if len(line) >= 47 { | ||
hash = line[7:47] | ||
} | ||
|
||
// Check if the commit line includes branch references. | ||
// `commit 2dbbb28727c7c2954438666dafba57bb8c714d3b refs/heads/fix/github-enterprise-gist\n` | ||
if len(line) > 48 { | ||
ref = line[48 : len(line)-1] | ||
} | ||
|
||
return | ||
} | ||
|
||
// ParseCommitSource s | ||
// https://git-scm.com/docs/git-log#Documentation/git-log.txt---source | ||
func parseSourceRef(ref []byte) string { | ||
// We don't care about 'normal' refs. | ||
if bytes.HasPrefix(ref, []byte("refs/heads/")) || bytes.HasPrefix(ref, []byte("refs/tags/")) { | ||
return "" | ||
} | ||
|
||
// Handle GitHub pull requests. | ||
// e.g., `refs/pull/238/head` or `refs/pull/1234/merge` | ||
if after, ok := bytes.CutPrefix(ref, []byte("refs/pull/")); ok { | ||
prNumber := after[:bytes.Index(after, []byte("/"))] | ||
return "Pull request #" + string(prNumber) | ||
} | ||
|
||
// Handle GitLab merge requests | ||
// e.g., `refs/merge-requests/238/head` or `refs/merge-requests/1234/merge` | ||
if after, ok := bytes.CutPrefix(ref, []byte("refs/merge-requests/")); ok { | ||
mrNumber := after[:bytes.Index(after, []byte("/"))] | ||
return "Merge request #" + string(mrNumber) | ||
} | ||
|
||
return fmt.Sprintf("%s (hidden ref)", string(ref)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does "hidden" just mean "not visible via the respective web UI?" My small concern here is that this also happens if we simply fail to parse the relevant ref because we made a mistake somewhere. What do you think of just returning the ref as-is in that case - would it be confusing? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
It means "not visible with default Git behaviour"; sometimes these refs are only discoverable via the web UI or API. The term is inspired by this blog post. The Git ref namespace ( Two examples of this are:
I think it's worth signaling that these refs are special and don't technically exist in the repository. Returning the ref as-is is already a source of confusion (#3493). |
||
} | ||
|
||
// Author: Bill Rich <[email protected]> | ||
func isAuthorLine(isStaged bool, latestState ParseState, line []byte) bool { | ||
if isStaged || !(latestState == CommitLine || latestState == MergeLine) { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why did you add this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's from this hidden comment thread. GitHub's PR UI is a nightmare.