Add whitespace handling to PR-comparsion (#4683)

* Add whitespace handling to PR-comparsion

In a PR we have to keep an eye on a lot of different things. But sometimes the
bare code is the key-thing we want to care about and just don't want to care
about fixed indention on some places. Especially if we follow the pathfinder
rule we face a lot of these situations because these changes don't break the
code in many languages but improve the readability a lot.

So this change introduce a fine graned button to adjust the way how the
reviewer want to see whitespace-changes within the code.

The possibilities reflect the possibilities from git itself except of the
`--ignore-blank-lines` flag because that one is also handled by `-b` and is
really rare.

Signed-off-by: Felix Nehrke <felix@nehrke.info>
This commit is contained in:
nemoinho 2018-08-14 19:49:33 +02:00 committed by techknowlogick
parent 03e558c29b
commit ca112f0a04
7 changed files with 91 additions and 15 deletions

View file

@ -633,6 +633,13 @@ func ParsePatch(maxLines, maxLineCharacters, maxFiles int, reader io.Reader) (*D
// passing the empty string as beforeCommitID returns a diff from the // passing the empty string as beforeCommitID returns a diff from the
// parent commit. // parent commit.
func GetDiffRange(repoPath, beforeCommitID, afterCommitID string, maxLines, maxLineCharacters, maxFiles int) (*Diff, error) { func GetDiffRange(repoPath, beforeCommitID, afterCommitID string, maxLines, maxLineCharacters, maxFiles int) (*Diff, error) {
return GetDiffRangeWithWhitespaceBehavior(repoPath, beforeCommitID, afterCommitID, maxLines, maxLineCharacters, maxFiles, "")
}
// GetDiffRangeWithWhitespaceBehavior builds a Diff between two commits of a repository.
// Passing the empty string as beforeCommitID returns a diff from the parent commit.
// The whitespaceBehavior is either an empty string or a git flag
func GetDiffRangeWithWhitespaceBehavior(repoPath, beforeCommitID, afterCommitID string, maxLines, maxLineCharacters, maxFiles int, whitespaceBehavior string) (*Diff, error) {
gitRepo, err := git.OpenRepository(repoPath) gitRepo, err := git.OpenRepository(repoPath)
if err != nil { if err != nil {
return nil, err return nil, err
@ -644,17 +651,21 @@ func GetDiffRange(repoPath, beforeCommitID, afterCommitID string, maxLines, maxL
} }
var cmd *exec.Cmd var cmd *exec.Cmd
// if "after" commit given if len(beforeCommitID) == 0 && commit.ParentCount() == 0 {
if len(beforeCommitID) == 0 { cmd = exec.Command("git", "show", afterCommitID)
// First commit of repository.
if commit.ParentCount() == 0 {
cmd = exec.Command("git", "show", afterCommitID)
} else {
c, _ := commit.Parent(0)
cmd = exec.Command("git", "diff", "-M", c.ID.String(), afterCommitID)
}
} else { } else {
cmd = exec.Command("git", "diff", "-M", beforeCommitID, afterCommitID) actualBeforeCommitID := beforeCommitID
if len(actualBeforeCommitID) == 0 {
parentCommit, _ := commit.Parent(0)
actualBeforeCommitID = parentCommit.ID.String()
}
diffArgs := []string{"diff", "-M"}
if len(whitespaceBehavior) != 0 {
diffArgs = append(diffArgs, whitespaceBehavior)
}
diffArgs = append(diffArgs, actualBeforeCommitID)
diffArgs = append(diffArgs, afterCommitID)
cmd = exec.Command("git", diffArgs...)
} }
cmd.Dir = repoPath cmd.Dir = repoPath
cmd.Stderr = os.Stderr cmd.Stderr = os.Stderr

View file

@ -1152,6 +1152,11 @@ diff.data_not_available = Diff Content Not Available
diff.show_diff_stats = Show Diff Stats diff.show_diff_stats = Show Diff Stats
diff.show_split_view = Split View diff.show_split_view = Split View
diff.show_unified_view = Unified View diff.show_unified_view = Unified View
diff.whitespace_button = Whitespace
diff.whitespace_show_everything = Show all changes
diff.whitespace_ignore_all_whitespace = Ignore whitespace when comparing lines
diff.whitespace_ignore_amount_changes = Ignore changes in amount of whitespace
diff.whitespace_ignore_at_eol = Ignore changes in whitespace at EOL
diff.stats_desc = <strong> %d changed files</strong> with <strong>%d additions</strong> and <strong>%d deletions</strong> diff.stats_desc = <strong> %d changed files</strong> with <strong>%d additions</strong> and <strong>%d deletions</strong>
diff.bin = BIN diff.bin = BIN
diff.view_file = View File diff.view_file = View File

View file

@ -50,3 +50,14 @@ func SetDiffViewStyle(ctx *context.Context) {
ctx.ServerError("ErrUpdateDiffViewStyle", err) ctx.ServerError("ErrUpdateDiffViewStyle", err)
} }
} }
// SetWhitespaceBehavior set whitespace behavior as render variable
func SetWhitespaceBehavior(ctx *context.Context) {
whitespaceBehavior := ctx.Query("whitespace")
switch whitespaceBehavior {
case "ignore-all", "ignore-eol", "ignore-change":
ctx.Data["WhitespaceBehavior"] = whitespaceBehavior
default:
ctx.Data["WhitespaceBehavior"] = ""
}
}

View file

@ -390,6 +390,12 @@ func ViewPullFiles(ctx *context.Context) {
} }
pull := issue.PullRequest pull := issue.PullRequest
whitespaceFlags := map[string]string{
"ignore-all": "-w",
"ignore-change": "-b",
"ignore-eol": "--ignore-space-at-eol",
"": ""}
var ( var (
diffRepoPath string diffRepoPath string
startCommitID string startCommitID string
@ -455,11 +461,12 @@ func ViewPullFiles(ctx *context.Context) {
ctx.Data["Reponame"] = pull.HeadRepo.Name ctx.Data["Reponame"] = pull.HeadRepo.Name
} }
diff, err := models.GetDiffRange(diffRepoPath, diff, err := models.GetDiffRangeWithWhitespaceBehavior(diffRepoPath,
startCommitID, endCommitID, setting.Git.MaxGitDiffLines, startCommitID, endCommitID, setting.Git.MaxGitDiffLines,
setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles) setting.Git.MaxGitDiffLineCharacters, setting.Git.MaxGitDiffFiles,
whitespaceFlags[ctx.Data["WhitespaceBehavior"].(string)])
if err != nil { if err != nil {
ctx.ServerError("GetDiffRange", err) ctx.ServerError("GetDiffRangeWithWhitespaceBehavior", err)
return return
} }

View file

@ -674,7 +674,7 @@ func RegisterRoutes(m *macaron.Macaron) {
m.Post("/merge", reqRepoWriter, bindIgnErr(auth.MergePullRequestForm{}), repo.MergePullRequest) m.Post("/merge", reqRepoWriter, bindIgnErr(auth.MergePullRequestForm{}), repo.MergePullRequest)
m.Post("/cleanup", context.RepoRef(), repo.CleanUpPullRequest) m.Post("/cleanup", context.RepoRef(), repo.CleanUpPullRequest)
m.Group("/files", func() { m.Group("/files", func() {
m.Get("", context.RepoRef(), repo.SetEditorconfigIfExists, repo.SetDiffViewStyle, repo.ViewPullFiles) m.Get("", context.RepoRef(), repo.SetEditorconfigIfExists, repo.SetDiffViewStyle, repo.SetWhitespaceBehavior, repo.ViewPullFiles)
m.Group("/reviews", func() { m.Group("/reviews", func() {
m.Post("/comments", bindIgnErr(auth.CodeCommentForm{}), repo.CreateCodeComment) m.Post("/comments", bindIgnErr(auth.CodeCommentForm{}), repo.CreateCodeComment)
m.Post("/submit", bindIgnErr(auth.SubmitReviewForm{}), repo.SubmitReview) m.Post("/submit", bindIgnErr(auth.SubmitReviewForm{}), repo.SubmitReview)

View file

@ -1,4 +1,19 @@
{{if .DiffNotAvailable}} {{if .DiffNotAvailable}}
<div class="diff-detail-box diff-box ui sticky">
<div>
<div class="ui right">
{{if .PageIsPullFiles}}
{{template "repo/diff/whitespace_dropdown" .}}
{{else}}
<a class="ui tiny basic toggle button" href="?style={{if .IsSplitStyle}}unified{{else}}split{{end}}">{{ if .IsSplitStyle }}{{.i18n.Tr "repo.diff.show_unified_view"}}{{else}}{{.i18n.Tr "repo.diff.show_split_view"}}{{end}}</a>
{{end}}
<a class="ui tiny basic toggle button" data-target="#diff-files">{{.i18n.Tr "repo.diff.show_diff_stats"}}</a>
{{if and .PageIsPullFiles $.SignedUserID}}
{{template "repo/diff/new_review" .}}
{{end}}
</div>
</div>
</div>
<h4>{{.i18n.Tr "repo.diff.data_not_available"}}</h4> <h4>{{.i18n.Tr "repo.diff.data_not_available"}}</h4>
{{else}} {{else}}
<div class="diff-detail-box diff-box ui sticky"> <div class="diff-detail-box diff-box ui sticky">
@ -6,7 +21,11 @@
<i class="fa fa-retweet"></i> <i class="fa fa-retweet"></i>
{{.i18n.Tr "repo.diff.stats_desc" .Diff.NumFiles .Diff.TotalAddition .Diff.TotalDeletion | Str2html}} {{.i18n.Tr "repo.diff.stats_desc" .Diff.NumFiles .Diff.TotalAddition .Diff.TotalDeletion | Str2html}}
<div class="ui right"> <div class="ui right">
<a class="ui tiny basic toggle button" href="?style={{if .IsSplitStyle}}unified{{else}}split{{end}}">{{ if .IsSplitStyle }}{{.i18n.Tr "repo.diff.show_unified_view"}}{{else}}{{.i18n.Tr "repo.diff.show_split_view"}}{{end}}</a> {{if .PageIsPullFiles}}
{{template "repo/diff/whitespace_dropdown" .}}
{{else}}
<a class="ui tiny basic toggle button" href="?style={{if .IsSplitStyle}}unified{{else}}split{{end}}">{{ if .IsSplitStyle }}{{.i18n.Tr "repo.diff.show_unified_view"}}{{else}}{{.i18n.Tr "repo.diff.show_split_view"}}{{end}}</a>
{{end}}
<a class="ui tiny basic toggle button" data-target="#diff-files">{{.i18n.Tr "repo.diff.show_diff_stats"}}</a> <a class="ui tiny basic toggle button" data-target="#diff-files">{{.i18n.Tr "repo.diff.show_diff_stats"}}</a>
{{if and .PageIsPullFiles $.SignedUserID}} {{if and .PageIsPullFiles $.SignedUserID}}
{{template "repo/diff/new_review" .}} {{template "repo/diff/new_review" .}}

View file

@ -0,0 +1,23 @@
<div class="ui dropdown tiny button">
{{.i18n.Tr "repo.diff.whitespace_button"}}
<i class="dropdown icon"></i>
<div class="menu">
<a class="item" href="?style={{if .IsSplitStyle}}split{{else}}unified{{end}}&whitespace=">
<i class="circle {{ if eq .WhitespaceBehavior "" }}dot{{else}}outline{{end}} icon"></i>
{{.i18n.Tr "repo.diff.whitespace_show_everything"}}
</a>
<a class="item" href="?style={{if .IsSplitStyle}}split{{else}}unified{{end}}&whitespace=ignore-all">
<i class="circle {{ if eq .WhitespaceBehavior "ignore-all" }}dot{{else}}outline{{end}} icon"></i>
{{.i18n.Tr "repo.diff.whitespace_ignore_all_whitespace"}}
</a>
<a class="item" href="?style={{if .IsSplitStyle}}split{{else}}unified{{end}}&whitespace=ignore-change">
<i class="circle {{ if eq .WhitespaceBehavior "ignore-change" }}dot{{else}}outline{{end}} icon"></i>
{{.i18n.Tr "repo.diff.whitespace_ignore_amount_changes"}}
</a>
<a class="item" href="?style={{if .IsSplitStyle}}split{{else}}unified{{end}}&whitespace=ignore-eol">
<i class="circle {{ if eq .WhitespaceBehavior "ignore-eol" }}dot{{else}}outline{{end}} icon"></i>
{{.i18n.Tr "repo.diff.whitespace_ignore_at_eol"}}
</a>
</div>
</div>
<a class="ui tiny basic toggle button" href="?style={{if .IsSplitStyle}}unified{{else}}split{{end}}&whitespace={{$.WhitespaceBehavior}}">{{ if .IsSplitStyle }}{{.i18n.Tr "repo.diff.show_unified_view"}}{{else}}{{.i18n.Tr "repo.diff.show_split_view"}}{{end}}</a>