mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-26 12:27:06 +00:00 
			
		
		
		
	Fix bug when review pull request commits (#35192)
The commit range in the UI follows a half-open, half-closed convention: (,]. When reviewing a range of commits, the beforeCommitID should be set to the commit immediately preceding the first selected commit. For single-commit reviews, we must identify and use the previous commit of that specific commit. The endpoint ViewPullFilesStartingFromCommit is currently unused and can be safely removed. Fix #35157 Replace #35184 Partially extract from #35077
This commit is contained in:
		| @@ -643,8 +643,17 @@ func ViewPullCommits(ctx *context.Context) { | |||||||
| 	ctx.HTML(http.StatusOK, tplPullCommits) | 	ctx.HTML(http.StatusOK, tplPullCommits) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func indexCommit(commits []*git.Commit, commitID string) *git.Commit { | ||||||
|  | 	for i := range commits { | ||||||
|  | 		if commits[i].ID.String() == commitID { | ||||||
|  | 			return commits[i] | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return nil | ||||||
|  | } | ||||||
|  |  | ||||||
| // ViewPullFiles render pull request changed files list page | // ViewPullFiles render pull request changed files list page | ||||||
| func viewPullFiles(ctx *context.Context, specifiedStartCommit, specifiedEndCommit string, willShowSpecifiedCommitRange, willShowSpecifiedCommit bool) { | func viewPullFiles(ctx *context.Context, beforeCommitID, afterCommitID string) { | ||||||
| 	ctx.Data["PageIsPullList"] = true | 	ctx.Data["PageIsPullList"] = true | ||||||
| 	ctx.Data["PageIsPullFiles"] = true | 	ctx.Data["PageIsPullFiles"] = true | ||||||
|  |  | ||||||
| @@ -654,11 +663,7 @@ func viewPullFiles(ctx *context.Context, specifiedStartCommit, specifiedEndCommi | |||||||
| 	} | 	} | ||||||
| 	pull := issue.PullRequest | 	pull := issue.PullRequest | ||||||
|  |  | ||||||
| 	var ( | 	gitRepo := ctx.Repo.GitRepo | ||||||
| 		startCommitID string |  | ||||||
| 		endCommitID   string |  | ||||||
| 		gitRepo       = ctx.Repo.GitRepo |  | ||||||
| 	) |  | ||||||
|  |  | ||||||
| 	prInfo := preparePullViewPullInfo(ctx, issue) | 	prInfo := preparePullViewPullInfo(ctx, issue) | ||||||
| 	if ctx.Written() { | 	if ctx.Written() { | ||||||
| @@ -668,77 +673,68 @@ func viewPullFiles(ctx *context.Context, specifiedStartCommit, specifiedEndCommi | |||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	// Validate the given commit sha to show (if any passed) |  | ||||||
| 	if willShowSpecifiedCommit || willShowSpecifiedCommitRange { |  | ||||||
| 		foundStartCommit := len(specifiedStartCommit) == 0 |  | ||||||
| 		foundEndCommit := len(specifiedEndCommit) == 0 |  | ||||||
|  |  | ||||||
| 		if !(foundStartCommit && foundEndCommit) { |  | ||||||
| 			for _, commit := range prInfo.Commits { |  | ||||||
| 				if commit.ID.String() == specifiedStartCommit { |  | ||||||
| 					foundStartCommit = true |  | ||||||
| 				} |  | ||||||
| 				if commit.ID.String() == specifiedEndCommit { |  | ||||||
| 					foundEndCommit = true |  | ||||||
| 				} |  | ||||||
|  |  | ||||||
| 				if foundStartCommit && foundEndCommit { |  | ||||||
| 					break |  | ||||||
| 				} |  | ||||||
| 			} |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		if !(foundStartCommit && foundEndCommit) { |  | ||||||
| 			ctx.NotFound(nil) |  | ||||||
| 			return |  | ||||||
| 		} |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	if ctx.Written() { |  | ||||||
| 		return |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	headCommitID, err := gitRepo.GetRefCommitID(pull.GetGitHeadRefName()) | 	headCommitID, err := gitRepo.GetRefCommitID(pull.GetGitHeadRefName()) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		ctx.ServerError("GetRefCommitID", err) | 		ctx.ServerError("GetRefCommitID", err) | ||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	ctx.Data["IsShowingOnlySingleCommit"] = willShowSpecifiedCommit | 	isSingleCommit := beforeCommitID == "" && afterCommitID != "" | ||||||
|  | 	ctx.Data["IsShowingOnlySingleCommit"] = isSingleCommit | ||||||
|  | 	isShowAllCommits := (beforeCommitID == "" || beforeCommitID == prInfo.MergeBase) && (afterCommitID == "" || afterCommitID == headCommitID) | ||||||
|  | 	ctx.Data["IsShowingAllCommits"] = isShowAllCommits | ||||||
|  |  | ||||||
| 	if willShowSpecifiedCommit || willShowSpecifiedCommitRange { | 	if afterCommitID == "" || afterCommitID == headCommitID { | ||||||
| 		if len(specifiedEndCommit) > 0 { | 		afterCommitID = headCommitID | ||||||
| 			endCommitID = specifiedEndCommit | 	} | ||||||
|  | 	afterCommit := indexCommit(prInfo.Commits, afterCommitID) | ||||||
|  | 	if afterCommit == nil { | ||||||
|  | 		ctx.HTTPError(http.StatusBadRequest, "after commit not found in PR commits") | ||||||
|  | 		return | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	var beforeCommit *git.Commit | ||||||
|  | 	if !isSingleCommit { | ||||||
|  | 		if beforeCommitID == "" || beforeCommitID == prInfo.MergeBase { | ||||||
|  | 			beforeCommitID = prInfo.MergeBase | ||||||
|  | 			// mergebase commit is not in the list of the pull request commits | ||||||
|  | 			beforeCommit, err = gitRepo.GetCommit(beforeCommitID) | ||||||
|  | 			if err != nil { | ||||||
|  | 				ctx.ServerError("GetCommit", err) | ||||||
|  | 				return | ||||||
|  | 			} | ||||||
| 		} else { | 		} else { | ||||||
| 			endCommitID = headCommitID | 			beforeCommit = indexCommit(prInfo.Commits, beforeCommitID) | ||||||
|  | 			if beforeCommit == nil { | ||||||
|  | 				ctx.HTTPError(http.StatusBadRequest, "before commit not found in PR commits") | ||||||
|  | 				return | ||||||
|  | 			} | ||||||
| 		} | 		} | ||||||
| 		if len(specifiedStartCommit) > 0 { |  | ||||||
| 			startCommitID = specifiedStartCommit |  | ||||||
| 		} else { |  | ||||||
| 			startCommitID = prInfo.MergeBase |  | ||||||
| 		} |  | ||||||
| 		ctx.Data["IsShowingAllCommits"] = false |  | ||||||
| 	} else { | 	} else { | ||||||
| 		endCommitID = headCommitID | 		beforeCommit, err = afterCommit.Parent(0) | ||||||
| 		startCommitID = prInfo.MergeBase | 		if err != nil { | ||||||
| 		ctx.Data["IsShowingAllCommits"] = true | 			ctx.ServerError("Parent", err) | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  | 		beforeCommitID = beforeCommit.ID.String() | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	ctx.Data["Username"] = ctx.Repo.Owner.Name | 	ctx.Data["Username"] = ctx.Repo.Owner.Name | ||||||
| 	ctx.Data["Reponame"] = ctx.Repo.Repository.Name | 	ctx.Data["Reponame"] = ctx.Repo.Repository.Name | ||||||
| 	ctx.Data["AfterCommitID"] = endCommitID | 	ctx.Data["MergeBase"] = prInfo.MergeBase | ||||||
| 	ctx.Data["BeforeCommitID"] = startCommitID | 	ctx.Data["AfterCommitID"] = afterCommitID | ||||||
|  | 	ctx.Data["BeforeCommitID"] = beforeCommitID | ||||||
| 	fileOnly := ctx.FormBool("file-only") |  | ||||||
|  |  | ||||||
| 	maxLines, maxFiles := setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffFiles | 	maxLines, maxFiles := setting.Git.MaxGitDiffLines, setting.Git.MaxGitDiffFiles | ||||||
| 	files := ctx.FormStrings("files") | 	files := ctx.FormStrings("files") | ||||||
|  | 	fileOnly := ctx.FormBool("file-only") | ||||||
| 	if fileOnly && (len(files) == 2 || len(files) == 1) { | 	if fileOnly && (len(files) == 2 || len(files) == 1) { | ||||||
| 		maxLines, maxFiles = -1, -1 | 		maxLines, maxFiles = -1, -1 | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	diffOptions := &gitdiff.DiffOptions{ | 	diffOptions := &gitdiff.DiffOptions{ | ||||||
| 		AfterCommitID:      endCommitID, | 		BeforeCommitID:     beforeCommitID, | ||||||
|  | 		AfterCommitID:      afterCommitID, | ||||||
| 		SkipTo:             ctx.FormString("skip-to"), | 		SkipTo:             ctx.FormString("skip-to"), | ||||||
| 		MaxLines:           maxLines, | 		MaxLines:           maxLines, | ||||||
| 		MaxLineCharacters:  setting.Git.MaxGitDiffLineCharacters, | 		MaxLineCharacters:  setting.Git.MaxGitDiffLineCharacters, | ||||||
| @@ -746,10 +742,6 @@ func viewPullFiles(ctx *context.Context, specifiedStartCommit, specifiedEndCommi | |||||||
| 		WhitespaceBehavior: gitdiff.GetWhitespaceFlag(ctx.Data["WhitespaceBehavior"].(string)), | 		WhitespaceBehavior: gitdiff.GetWhitespaceFlag(ctx.Data["WhitespaceBehavior"].(string)), | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if !willShowSpecifiedCommit { |  | ||||||
| 		diffOptions.BeforeCommitID = startCommitID |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	diff, err := gitdiff.GetDiffForRender(ctx, ctx.Repo.RepoLink, gitRepo, diffOptions, files...) | 	diff, err := gitdiff.GetDiffForRender(ctx, ctx.Repo.RepoLink, gitRepo, diffOptions, files...) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		ctx.ServerError("GetDiff", err) | 		ctx.ServerError("GetDiff", err) | ||||||
| @@ -761,7 +753,7 @@ func viewPullFiles(ctx *context.Context, specifiedStartCommit, specifiedEndCommi | |||||||
| 	// as the viewed information is designed to be loaded only on latest PR | 	// as the viewed information is designed to be loaded only on latest PR | ||||||
| 	// diff and if you're signed in. | 	// diff and if you're signed in. | ||||||
| 	var reviewState *pull_model.ReviewState | 	var reviewState *pull_model.ReviewState | ||||||
| 	if ctx.IsSigned && !willShowSpecifiedCommit && !willShowSpecifiedCommitRange { | 	if ctx.IsSigned && isShowAllCommits { | ||||||
| 		reviewState, err = gitdiff.SyncUserSpecificDiff(ctx, ctx.Doer.ID, pull, gitRepo, diff, diffOptions) | 		reviewState, err = gitdiff.SyncUserSpecificDiff(ctx, ctx.Doer.ID, pull, gitRepo, diff, diffOptions) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			ctx.ServerError("SyncUserSpecificDiff", err) | 			ctx.ServerError("SyncUserSpecificDiff", err) | ||||||
| @@ -769,7 +761,7 @@ func viewPullFiles(ctx *context.Context, specifiedStartCommit, specifiedEndCommi | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	diffShortStat, err := gitdiff.GetDiffShortStat(ctx.Repo.GitRepo, startCommitID, endCommitID) | 	diffShortStat, err := gitdiff.GetDiffShortStat(ctx.Repo.GitRepo, beforeCommitID, afterCommitID) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		ctx.ServerError("GetDiffShortStat", err) | 		ctx.ServerError("GetDiffShortStat", err) | ||||||
| 		return | 		return | ||||||
| @@ -816,7 +808,7 @@ func viewPullFiles(ctx *context.Context, specifiedStartCommit, specifiedEndCommi | |||||||
|  |  | ||||||
| 	if !fileOnly { | 	if !fileOnly { | ||||||
| 		// note: use mergeBase is set to false because we already have the merge base from the pull request info | 		// note: use mergeBase is set to false because we already have the merge base from the pull request info | ||||||
| 		diffTree, err := gitdiff.GetDiffTree(ctx, gitRepo, false, startCommitID, endCommitID) | 		diffTree, err := gitdiff.GetDiffTree(ctx, gitRepo, false, beforeCommitID, afterCommitID) | ||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			ctx.ServerError("GetDiffTree", err) | 			ctx.ServerError("GetDiffTree", err) | ||||||
| 			return | 			return | ||||||
| @@ -836,17 +828,6 @@ func viewPullFiles(ctx *context.Context, specifiedStartCommit, specifiedEndCommi | |||||||
| 	ctx.Data["Diff"] = diff | 	ctx.Data["Diff"] = diff | ||||||
| 	ctx.Data["DiffNotAvailable"] = diffShortStat.NumFiles == 0 | 	ctx.Data["DiffNotAvailable"] = diffShortStat.NumFiles == 0 | ||||||
|  |  | ||||||
| 	baseCommit, err := ctx.Repo.GitRepo.GetCommit(startCommitID) |  | ||||||
| 	if err != nil { |  | ||||||
| 		ctx.ServerError("GetCommit", err) |  | ||||||
| 		return |  | ||||||
| 	} |  | ||||||
| 	commit, err := gitRepo.GetCommit(endCommitID) |  | ||||||
| 	if err != nil { |  | ||||||
| 		ctx.ServerError("GetCommit", err) |  | ||||||
| 		return |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	if ctx.IsSigned && ctx.Doer != nil { | 	if ctx.IsSigned && ctx.Doer != nil { | ||||||
| 		if ctx.Data["CanMarkConversation"], err = issues_model.CanMarkConversation(ctx, issue, ctx.Doer); err != nil { | 		if ctx.Data["CanMarkConversation"], err = issues_model.CanMarkConversation(ctx, issue, ctx.Doer); err != nil { | ||||||
| 			ctx.ServerError("CanMarkConversation", err) | 			ctx.ServerError("CanMarkConversation", err) | ||||||
| @@ -854,7 +835,7 @@ func viewPullFiles(ctx *context.Context, specifiedStartCommit, specifiedEndCommi | |||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	setCompareContext(ctx, baseCommit, commit, ctx.Repo.Owner.Name, ctx.Repo.Repository.Name) | 	setCompareContext(ctx, beforeCommit, afterCommit, ctx.Repo.Owner.Name, ctx.Repo.Repository.Name) | ||||||
|  |  | ||||||
| 	assigneeUsers, err := repo_model.GetRepoAssignees(ctx, ctx.Repo.Repository) | 	assigneeUsers, err := repo_model.GetRepoAssignees(ctx, ctx.Repo.Repository) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| @@ -901,7 +882,7 @@ func viewPullFiles(ctx *context.Context, specifiedStartCommit, specifiedEndCommi | |||||||
| 	ctx.Data["CanBlockUser"] = func(blocker, blockee *user_model.User) bool { | 	ctx.Data["CanBlockUser"] = func(blocker, blockee *user_model.User) bool { | ||||||
| 		return user_service.CanBlockUser(ctx, ctx.Doer, blocker, blockee) | 		return user_service.CanBlockUser(ctx, ctx.Doer, blocker, blockee) | ||||||
| 	} | 	} | ||||||
| 	if !willShowSpecifiedCommit && !willShowSpecifiedCommitRange && pull.Flow == issues_model.PullRequestFlowGithub { | 	if isShowAllCommits && pull.Flow == issues_model.PullRequestFlowGithub { | ||||||
| 		if err := pull.LoadHeadRepo(ctx); err != nil { | 		if err := pull.LoadHeadRepo(ctx); err != nil { | ||||||
| 			ctx.ServerError("LoadHeadRepo", err) | 			ctx.ServerError("LoadHeadRepo", err) | ||||||
| 			return | 			return | ||||||
| @@ -930,19 +911,17 @@ func viewPullFiles(ctx *context.Context, specifiedStartCommit, specifiedEndCommi | |||||||
| } | } | ||||||
|  |  | ||||||
| func ViewPullFilesForSingleCommit(ctx *context.Context) { | func ViewPullFilesForSingleCommit(ctx *context.Context) { | ||||||
| 	viewPullFiles(ctx, "", ctx.PathParam("sha"), true, true) | 	// it doesn't support showing files from mergebase to the special commit | ||||||
|  | 	// otherwise it will be ambiguous | ||||||
|  | 	viewPullFiles(ctx, "", ctx.PathParam("sha")) | ||||||
| } | } | ||||||
|  |  | ||||||
| func ViewPullFilesForRange(ctx *context.Context) { | func ViewPullFilesForRange(ctx *context.Context) { | ||||||
| 	viewPullFiles(ctx, ctx.PathParam("shaFrom"), ctx.PathParam("shaTo"), true, false) | 	viewPullFiles(ctx, ctx.PathParam("shaFrom"), ctx.PathParam("shaTo")) | ||||||
| } |  | ||||||
|  |  | ||||||
| func ViewPullFilesStartingFromCommit(ctx *context.Context) { |  | ||||||
| 	viewPullFiles(ctx, "", ctx.PathParam("sha"), true, false) |  | ||||||
| } | } | ||||||
|  |  | ||||||
| func ViewPullFilesForAllCommitsOfPr(ctx *context.Context) { | func ViewPullFilesForAllCommitsOfPr(ctx *context.Context) { | ||||||
| 	viewPullFiles(ctx, "", "", false, false) | 	viewPullFiles(ctx, "", "") | ||||||
| } | } | ||||||
|  |  | ||||||
| // UpdatePullRequest merge PR's baseBranch into headBranch | // UpdatePullRequest merge PR's baseBranch into headBranch | ||||||
|   | |||||||
| @@ -1531,7 +1531,7 @@ func registerWebRoutes(m *web.Router) { | |||||||
| 			m.Group("/commits", func() { | 			m.Group("/commits", func() { | ||||||
| 				m.Get("", repo.SetWhitespaceBehavior, repo.GetPullDiffStats, repo.ViewPullCommits) | 				m.Get("", repo.SetWhitespaceBehavior, repo.GetPullDiffStats, repo.ViewPullCommits) | ||||||
| 				m.Get("/list", repo.GetPullCommits) | 				m.Get("/list", repo.GetPullCommits) | ||||||
| 				m.Get("/{sha:[a-f0-9]{7,40}}", repo.SetEditorconfigIfExists, repo.SetDiffViewStyle, repo.SetWhitespaceBehavior, repo.SetShowOutdatedComments, repo.ViewPullFilesForSingleCommit) | 				m.Get("/{sha:[a-f0-9]{7,64}}", repo.SetEditorconfigIfExists, repo.SetDiffViewStyle, repo.SetWhitespaceBehavior, repo.SetShowOutdatedComments, repo.ViewPullFilesForSingleCommit) | ||||||
| 			}) | 			}) | ||||||
| 			m.Post("/merge", context.RepoMustNotBeArchived(), web.Bind(forms.MergePullRequestForm{}), repo.MergePullRequest) | 			m.Post("/merge", context.RepoMustNotBeArchived(), web.Bind(forms.MergePullRequestForm{}), repo.MergePullRequest) | ||||||
| 			m.Post("/cancel_auto_merge", context.RepoMustNotBeArchived(), repo.CancelAutoMergePullRequest) | 			m.Post("/cancel_auto_merge", context.RepoMustNotBeArchived(), repo.CancelAutoMergePullRequest) | ||||||
| @@ -1540,8 +1540,7 @@ func registerWebRoutes(m *web.Router) { | |||||||
| 			m.Post("/cleanup", context.RepoMustNotBeArchived(), repo.CleanUpPullRequest) | 			m.Post("/cleanup", context.RepoMustNotBeArchived(), repo.CleanUpPullRequest) | ||||||
| 			m.Group("/files", func() { | 			m.Group("/files", func() { | ||||||
| 				m.Get("", repo.SetEditorconfigIfExists, repo.SetDiffViewStyle, repo.SetWhitespaceBehavior, repo.SetShowOutdatedComments, repo.ViewPullFilesForAllCommitsOfPr) | 				m.Get("", repo.SetEditorconfigIfExists, repo.SetDiffViewStyle, repo.SetWhitespaceBehavior, repo.SetShowOutdatedComments, repo.ViewPullFilesForAllCommitsOfPr) | ||||||
| 				m.Get("/{sha:[a-f0-9]{7,40}}", repo.SetEditorconfigIfExists, repo.SetDiffViewStyle, repo.SetWhitespaceBehavior, repo.SetShowOutdatedComments, repo.ViewPullFilesStartingFromCommit) | 				m.Get("/{shaFrom:[a-f0-9]{7,64}}..{shaTo:[a-f0-9]{7,64}}", repo.SetEditorconfigIfExists, repo.SetDiffViewStyle, repo.SetWhitespaceBehavior, repo.SetShowOutdatedComments, repo.ViewPullFilesForRange) | ||||||
| 				m.Get("/{shaFrom:[a-f0-9]{7,40}}..{shaTo:[a-f0-9]{7,40}}", repo.SetEditorconfigIfExists, repo.SetDiffViewStyle, repo.SetWhitespaceBehavior, repo.SetShowOutdatedComments, repo.ViewPullFilesForRange) |  | ||||||
| 				m.Group("/reviews", func() { | 				m.Group("/reviews", func() { | ||||||
| 					m.Get("/new_comment", repo.RenderNewCodeCommentForm) | 					m.Get("/new_comment", repo.RenderNewCodeCommentForm) | ||||||
| 					m.Post("/comments", web.Bind(forms.CodeCommentForm{}), repo.SetShowOutdatedComments, repo.CreateCodeComment) | 					m.Post("/comments", web.Bind(forms.CodeCommentForm{}), repo.SetShowOutdatedComments, repo.CreateCodeComment) | ||||||
|   | |||||||
| @@ -35,7 +35,7 @@ | |||||||
| 			{{template "repo/diff/whitespace_dropdown" .}} | 			{{template "repo/diff/whitespace_dropdown" .}} | ||||||
| 			{{template "repo/diff/options_dropdown" .}} | 			{{template "repo/diff/options_dropdown" .}} | ||||||
| 			{{if .PageIsPullFiles}} | 			{{if .PageIsPullFiles}} | ||||||
| 				<div id="diff-commit-select" data-issuelink="{{$.Issue.Link}}" data-queryparams="?style={{if $.IsSplitStyle}}split{{else}}unified{{end}}&whitespace={{$.WhitespaceBehavior}}&show-outdated={{$.ShowOutdatedComments}}" data-filter_changes_by_commit="{{ctx.Locale.Tr "repo.pulls.filter_changes_by_commit"}}"> | 				<div id="diff-commit-select" data-merge-base="{{.MergeBase}}" data-issuelink="{{$.Issue.Link}}" data-queryparams="?style={{if $.IsSplitStyle}}split{{else}}unified{{end}}&whitespace={{$.WhitespaceBehavior}}&show-outdated={{$.ShowOutdatedComments}}" data-filter_changes_by_commit="{{ctx.Locale.Tr "repo.pulls.filter_changes_by_commit"}}"> | ||||||
| 					{{/* the following will be replaced by vue component, but this avoids any loading artifacts till the vue component is initialized */}} | 					{{/* the following will be replaced by vue component, but this avoids any loading artifacts till the vue component is initialized */}} | ||||||
| 					<div class="ui jump dropdown tiny basic button custom"> | 					<div class="ui jump dropdown tiny basic button custom"> | ||||||
| 						{{svg "octicon-git-commit"}} | 						{{svg "octicon-git-commit"}} | ||||||
|   | |||||||
| @@ -25,10 +25,6 @@ func TestPullDiff_CommitRangePRDiff(t *testing.T) { | |||||||
| 	doTestPRDiff(t, "/user2/commitsonpr/pulls/1/files/4ca8bcaf27e28504df7bf996819665986b01c847..23576dd018294e476c06e569b6b0f170d0558705", true, []string{"test2.txt", "test3.txt", "test4.txt"}) | 	doTestPRDiff(t, "/user2/commitsonpr/pulls/1/files/4ca8bcaf27e28504df7bf996819665986b01c847..23576dd018294e476c06e569b6b0f170d0558705", true, []string{"test2.txt", "test3.txt", "test4.txt"}) | ||||||
| } | } | ||||||
|  |  | ||||||
| func TestPullDiff_StartingFromBaseToCommitPRDiff(t *testing.T) { |  | ||||||
| 	doTestPRDiff(t, "/user2/commitsonpr/pulls/1/files/c5626fc9eff57eb1bb7b796b01d4d0f2f3f792a2", true, []string{"test1.txt", "test2.txt", "test3.txt"}) |  | ||||||
| } |  | ||||||
|  |  | ||||||
| func doTestPRDiff(t *testing.T, prDiffURL string, reviewBtnDisabled bool, expectedFilenames []string) { | func doTestPRDiff(t *testing.T, prDiffURL string, reviewBtnDisabled bool, expectedFilenames []string) { | ||||||
| 	defer tests.PrepareTestEnv(t)() | 	defer tests.PrepareTestEnv(t)() | ||||||
|  |  | ||||||
|   | |||||||
| @@ -32,6 +32,7 @@ export default defineComponent({ | |||||||
|       locale: { |       locale: { | ||||||
|         filter_changes_by_commit: el.getAttribute('data-filter_changes_by_commit'), |         filter_changes_by_commit: el.getAttribute('data-filter_changes_by_commit'), | ||||||
|       } as Record<string, string>, |       } as Record<string, string>, | ||||||
|  |       mergeBase: el.getAttribute('data-merge-base'), | ||||||
|       commits: [] as Array<Commit>, |       commits: [] as Array<Commit>, | ||||||
|       hoverActivated: false, |       hoverActivated: false, | ||||||
|       lastReviewCommitSha: '', |       lastReviewCommitSha: '', | ||||||
| @@ -176,32 +177,38 @@ export default defineComponent({ | |||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|     /** |     /** | ||||||
|      * When a commit is clicked with shift this enables the range |      * When a commit is clicked while holding Shift, it enables range selection. | ||||||
|      * selection. Second click (with shift) defines the end of the |      * - The range selection is a half-open, half-closed range, meaning it excludes the start commit but includes the end commit. | ||||||
|      * range. This opens the diff of this range |      * - The start of the commit range is always the previous commit of the first clicked commit. | ||||||
|      * Exception: first commit is the first commit of this PR. Then |      * - If the first commit in the list is clicked, the mergeBase will be used as the start of the range instead. | ||||||
|      * the diff from beginning of PR up to the second clicked commit is |      * - The second Shift-click defines the end of the range. | ||||||
|      * opened |      * - Once both are selected, the diff view for the selected commit range will open. | ||||||
|      */ |      */ | ||||||
|     commitClickedShift(commit: Commit) { |     commitClickedShift(commit: Commit) { | ||||||
|       this.hoverActivated = !this.hoverActivated; |       this.hoverActivated = !this.hoverActivated; | ||||||
|       commit.selected = true; |       commit.selected = true; | ||||||
|       // Second click -> determine our range and open links accordingly |       // Second click -> determine our range and open links accordingly | ||||||
|       if (!this.hoverActivated) { |       if (!this.hoverActivated) { | ||||||
|  |         // since at least one commit is selected, we can determine the range | ||||||
|         // find all selected commits and generate a link |         // find all selected commits and generate a link | ||||||
|         if (this.commits[0].selected) { |         const firstSelected = this.commits.findIndex((x) => x.selected); | ||||||
|           // first commit is selected - generate a short url with only target sha |         const lastSelected = this.commits.findLastIndex((x) => x.selected); | ||||||
|           const lastCommitIdx = this.commits.findLastIndex((x) => x.selected); |         let beforeCommitID: string; | ||||||
|           if (lastCommitIdx === this.commits.length - 1) { |         if (firstSelected === 0) { | ||||||
|             // user selected all commits - just show the normal diff page |           beforeCommitID = this.mergeBase; | ||||||
|             window.location.assign(`${this.issueLink}/files${this.queryParams}`); |  | ||||||
|           } else { |  | ||||||
|             window.location.assign(`${this.issueLink}/files/${this.commits[lastCommitIdx].id}${this.queryParams}`); |  | ||||||
|           } |  | ||||||
|         } else { |         } else { | ||||||
|           const start = this.commits[this.commits.findIndex((x) => x.selected) - 1].id; |           beforeCommitID = this.commits[firstSelected - 1].id; | ||||||
|           const end = this.commits.findLast((x) => x.selected).id; |         } | ||||||
|           window.location.assign(`${this.issueLink}/files/${start}..${end}${this.queryParams}`); |         const afterCommitID = this.commits[lastSelected].id; | ||||||
|  |  | ||||||
|  |         if (firstSelected === lastSelected) { | ||||||
|  |           // if the start and end are the same, we show this single commit | ||||||
|  |           window.location.assign(`${this.issueLink}/commits/${afterCommitID}${this.queryParams}`); | ||||||
|  |         } else if (beforeCommitID === this.mergeBase && afterCommitID === this.commits.at(-1).id) { | ||||||
|  |           // if the first commit is selected and the last commit is selected, we show all commits | ||||||
|  |           window.location.assign(`${this.issueLink}/files${this.queryParams}`); | ||||||
|  |         } else { | ||||||
|  |           window.location.assign(`${this.issueLink}/files/${beforeCommitID}..${afterCommitID}${this.queryParams}`); | ||||||
|         } |         } | ||||||
|       } |       } | ||||||
|     }, |     }, | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Lunny Xiao
					Lunny Xiao