Skip to content

Allow to ignore files during diff generation #18814

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

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 40 additions & 13 deletions services/gitdiff/gitdiff.go
Original file line number Diff line number Diff line change
Expand Up @@ -1307,6 +1307,7 @@ type DiffOptions struct {
MaxFiles int
WhitespaceBehavior string
DirectComparison bool
IgnoredFiles []string
}

// GetDiff builds a Diff between two commits of a repository.
Expand All @@ -1327,33 +1328,44 @@ func GetDiff(gitRepo *git.Repository, opts *DiffOptions, files ...string) (*Diff
if len(opts.SkipTo) > 0 {
argsLength++
}
if len(files) > 0 {
argsLength += len(files) + 1
argsLength += len(files)

// git 1.9.0 added pathspec exclusion of files
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now the minimal git version is 2.0, so version check is unnecessary.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, true.
I'd still like to add some tests before allowing this PR to be merged.
However, I'm still unsure how to do that in this case:
I know there are former git repositories in our codebase that are used for testing somehow, but I have no idea how or where to add tests.

I'll fix it when I add the tests as well.

gitVersionGreater190 := git.CheckGitVersionAtLeast("1.9.0") == nil
if gitVersionGreater190 {
argsLength += len(opts.IgnoredFiles)
}

// If either included files or ignored files are present, we have to insert "--"
needsOptionEscaping := len(files) > 0 || (gitVersionGreater190 && len(opts.IgnoredFiles) > 0)
if needsOptionEscaping {
argsLength++
}

// If we only have ignored files, then we have to explicitly query everything ('.'), otherwise simply nothing will be queried
if needsOptionEscaping && len(files) == 0 {
argsLength++
}

diffArgs := make([]string, 0, argsLength)
diffArgs = append(diffArgs, "diff", "--src-prefix=\\a/", "--dst-prefix=\\b/", "-M")
if len(opts.WhitespaceBehavior) != 0 {
diffArgs = append(diffArgs, opts.WhitespaceBehavior)
}

if (len(opts.BeforeCommitID) == 0 || opts.BeforeCommitID == git.EmptySHA) && commit.ParentCount() == 0 {
diffArgs = append(diffArgs, "diff", "--src-prefix=\\a/", "--dst-prefix=\\b/", "-M")
if len(opts.WhitespaceBehavior) != 0 {
diffArgs = append(diffArgs, opts.WhitespaceBehavior)
}
// append empty tree ref
diffArgs = append(diffArgs, "4b825dc642cb6eb9a060e54bf8d69288fbee4904")
diffArgs = append(diffArgs, opts.AfterCommitID)
} else {
actualBeforeCommitID := opts.BeforeCommitID
if len(actualBeforeCommitID) == 0 {
parentCommit, _ := commit.Parent(0)
actualBeforeCommitID = parentCommit.ID.String()
}
diffArgs = append(diffArgs, "diff", "--src-prefix=\\a/", "--dst-prefix=\\b/", "-M")
if len(opts.WhitespaceBehavior) != 0 {
diffArgs = append(diffArgs, opts.WhitespaceBehavior)
}
diffArgs = append(diffArgs, actualBeforeCommitID)
diffArgs = append(diffArgs, opts.AfterCommitID)
opts.BeforeCommitID = actualBeforeCommitID
}
diffArgs = append(diffArgs, opts.AfterCommitID)

// In git 2.31, git diff learned --skip-to which we can use to shortcut skip to file
// so if we are using at least this version of git we don't have to tell ParsePatch to do
Expand All @@ -1364,9 +1376,24 @@ func GetDiff(gitRepo *git.Repository, opts *DiffOptions, files ...string) (*Diff
parsePatchSkipToFile = ""
}

if len(files) > 0 {
if needsOptionEscaping {
diffArgs = append(diffArgs, "--")
diffArgs = append(diffArgs, files...)

// Exclude all files where requested - see git pathspecs for the syntax
if gitVersionGreater190 {
for _, ignoredFile := range opts.IgnoredFiles {
if ignoredFile == "" {
continue
}
diffArgs = append(diffArgs, fmt.Sprintf("':(exclude,literal)%s'", ignoredFile)) // TODO: Will this break on Windows because of no single quote escaping in command prompt?
}
}
}

// If we only have ignored files, then we have to explicitly query everything, otherwise simply nothing will be queried
if needsOptionEscaping && len(files) == 0 {
diffArgs = append(diffArgs, ".")
}

reader, writer := io.Pipe()
Expand Down