Skip to content

Commit 538790a

Browse files
lunnywxiaoguangsilverwind
authored
Put an edit file button on pull request files to allow a quick operation (#29697)
Resolve #23848 This PR put an edit file button on pull request files to allow a quick edit for a file. After the edit finished, it will return back to the viewed file position on pull request files tab. It also use a branch view file link instead of commit link when it's a non-commit pull request files view. <img width="1532" alt="image" src="https://github.com/go-gitea/gitea/assets/81045/3637ca4c-89d5-4621-847b-79702a44f617"> --------- Co-authored-by: wxiaoguang <[email protected]> Co-authored-by: silverwind <[email protected]>
1 parent f47e00d commit 538790a

File tree

8 files changed

+91
-24
lines changed

8 files changed

+91
-24
lines changed

routers/private/hook_post_receive.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"code.gitea.io/gitea/modules/util"
2121
"code.gitea.io/gitea/modules/web"
2222
gitea_context "code.gitea.io/gitea/services/context"
23+
pull_service "code.gitea.io/gitea/services/pull"
2324
repo_service "code.gitea.io/gitea/services/repository"
2425
)
2526

@@ -109,6 +110,9 @@ func HookPostReceive(ctx *gitea_context.PrivateContext) {
109110
}
110111
} else {
111112
branchesToSync = append(branchesToSync, update)
113+
114+
// TODO: should we return the error and return the error when pushing? Currently it will log the error and not prevent the pushing
115+
pull_service.UpdatePullsRefs(ctx, repo, update)
112116
}
113117
}
114118
if len(branchesToSync) > 0 {

routers/web/repo/editor.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,12 @@ func redirectForCommitChoice(ctx *context.Context, commitChoice, newBranchName,
8080
}
8181
}
8282

83-
// Redirect to viewing file or folder
84-
ctx.Redirect(ctx.Repo.RepoLink + "/src/branch/" + util.PathEscapeSegments(newBranchName) + "/" + util.PathEscapeSegments(treePath))
83+
returnURI := ctx.FormString("return_uri")
84+
85+
ctx.RedirectToCurrentSite(
86+
returnURI,
87+
ctx.Repo.RepoLink+"/src/branch/"+util.PathEscapeSegments(newBranchName)+"/"+util.PathEscapeSegments(treePath),
88+
)
8589
}
8690

8791
// getParentTreeFields returns list of parent tree names and corresponding tree paths
@@ -100,6 +104,7 @@ func getParentTreeFields(treePath string) (treeNames, treePaths []string) {
100104
}
101105

102106
func editFile(ctx *context.Context, isNewFile bool) {
107+
ctx.Data["PageIsViewCode"] = true
103108
ctx.Data["PageIsEdit"] = true
104109
ctx.Data["IsNewFile"] = isNewFile
105110
canCommit := renderCommitRights(ctx)
@@ -190,6 +195,9 @@ func editFile(ctx *context.Context, isNewFile bool) {
190195
ctx.Data["LineWrapExtensions"] = strings.Join(setting.Repository.Editor.LineWrapExtensions, ",")
191196
ctx.Data["EditorconfigJson"] = GetEditorConfig(ctx, treePath)
192197

198+
ctx.Data["IsEditingFileOnly"] = ctx.FormString("return_uri") != ""
199+
ctx.Data["ReturnURI"] = ctx.FormString("return_uri")
200+
193201
ctx.HTML(http.StatusOK, tplEditFile)
194202
}
195203

routers/web/repo/pull.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -857,6 +857,32 @@ func viewPullFiles(ctx *context.Context, specifiedStartCommit, specifiedEndCommi
857857
ctx.Data["CanBlockUser"] = func(blocker, blockee *user_model.User) bool {
858858
return user_service.CanBlockUser(ctx, ctx.Doer, blocker, blockee)
859859
}
860+
if !willShowSpecifiedCommit && !willShowSpecifiedCommitRange && pull.Flow == issues_model.PullRequestFlowGithub {
861+
if err := pull.LoadHeadRepo(ctx); err != nil {
862+
ctx.ServerError("LoadHeadRepo", err)
863+
return
864+
}
865+
866+
if pull.HeadRepo != nil {
867+
ctx.Data["SourcePath"] = pull.HeadRepo.Link() + "/src/branch/" + util.PathEscapeSegments(pull.HeadBranch)
868+
}
869+
870+
if !pull.HasMerged && ctx.Doer != nil {
871+
perm, err := access_model.GetUserRepoPermission(ctx, pull.HeadRepo, ctx.Doer)
872+
if err != nil {
873+
ctx.ServerError("GetUserRepoPermission", err)
874+
return
875+
}
876+
877+
if perm.CanWrite(unit.TypeCode) || issues_model.CanMaintainerWriteToBranch(ctx, perm, pull.HeadBranch, ctx.Doer) {
878+
ctx.Data["CanEditFile"] = true
879+
ctx.Data["EditFileTooltip"] = ctx.Tr("repo.editor.edit_this_file")
880+
ctx.Data["HeadRepoLink"] = pull.HeadRepo.Link()
881+
ctx.Data["HeadBranchName"] = pull.HeadBranch
882+
ctx.Data["BackToLink"] = setting.AppSubURL + ctx.Req.URL.RequestURI()
883+
}
884+
}
885+
}
860886

861887
ctx.HTML(http.StatusOK, tplPullFiles)
862888
}

services/pull/pull.go

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -526,6 +526,25 @@ func pushToBaseRepoHelper(ctx context.Context, pr *issues_model.PullRequest, pre
526526
return nil
527527
}
528528

529+
// UpdatePullsRefs update all the PRs head file pointers like /refs/pull/1/head so that it will be dependent by other operations
530+
func UpdatePullsRefs(ctx context.Context, repo *repo_model.Repository, update *repo_module.PushUpdateOptions) {
531+
branch := update.RefFullName.BranchName()
532+
// GetUnmergedPullRequestsByHeadInfo() only return open and unmerged PR.
533+
prs, err := issues_model.GetUnmergedPullRequestsByHeadInfo(ctx, repo.ID, branch)
534+
if err != nil {
535+
log.Error("Find pull requests [head_repo_id: %d, head_branch: %s]: %v", repo.ID, branch, err)
536+
} else {
537+
for _, pr := range prs {
538+
log.Trace("Updating PR[%d]: composing new test task", pr.ID)
539+
if pr.Flow == issues_model.PullRequestFlowGithub {
540+
if err := PushToBaseRepo(ctx, pr); err != nil {
541+
log.Error("PushToBaseRepo: %v", err)
542+
}
543+
}
544+
}
545+
}
546+
}
547+
529548
// UpdateRef update refs/pull/id/head directly for agit flow pull request
530549
func UpdateRef(ctx context.Context, pr *issues_model.PullRequest) (err error) {
531550
log.Trace("UpdateRef[%d]: upgate pull request ref in base repo '%s'", pr.ID, pr.GetGitRefName())

templates/repo/diff/box.tmpl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,9 @@
166166
<a class="ui basic tiny button" rel="nofollow" href="{{$.BeforeSourcePath}}/{{PathEscapeSegments .Name}}">{{ctx.Locale.Tr "repo.diff.view_file"}}</a>
167167
{{else}}
168168
<a class="ui basic tiny button" rel="nofollow" href="{{$.SourcePath}}/{{PathEscapeSegments .Name}}">{{ctx.Locale.Tr "repo.diff.view_file"}}</a>
169+
{{if and $.Repository.CanEnableEditor $.CanEditFile (not $file.IsLFSFile) (not $file.IsBin)}}
170+
<a class="ui basic tiny button" rel="nofollow" href="{{$.HeadRepoLink}}/_edit/{{PathEscapeSegments $.HeadBranchName}}/{{PathEscapeSegments $file.Name}}?return_uri={{print $.BackToLink "#diff-" $file.NameHash | QueryEscape}}">{{ctx.Locale.Tr "repo.editor.edit_this_file"}}</a>
171+
{{end}}
169172
{{end}}
170173
{{end}}
171174
{{if $isReviewFile}}

templates/repo/editor/commit_form.tmpl

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -39,36 +39,36 @@
3939
</label>
4040
</div>
4141
</div>
42-
{{if not .Repository.IsEmpty}}
43-
<div class="field">
44-
<div class="ui radio checkbox">
45-
{{if .CanCreatePullRequest}}
46-
<input type="radio" class="js-quick-pull-choice-option" name="commit_choice" value="commit-to-new-branch" button_text="{{ctx.Locale.Tr "repo.editor.propose_file_change"}}" {{if eq .commit_choice "commit-to-new-branch"}}checked{{end}}>
47-
{{else}}
48-
<input type="radio" class="js-quick-pull-choice-option" name="commit_choice" value="commit-to-new-branch" button_text="{{ctx.Locale.Tr "repo.editor.commit_changes"}}" {{if eq .commit_choice "commit-to-new-branch"}}checked{{end}}>
49-
{{end}}
50-
<label>
51-
{{svg "octicon-git-pull-request"}}
42+
{{if and (not .Repository.IsEmpty) (not .IsEditingFileOnly)}}
43+
<div class="field">
44+
<div class="ui radio checkbox">
5245
{{if .CanCreatePullRequest}}
53-
{{ctx.Locale.Tr "repo.editor.create_new_branch"}}
46+
<input type="radio" class="js-quick-pull-choice-option" name="commit_choice" value="commit-to-new-branch" button_text="{{ctx.Locale.Tr "repo.editor.propose_file_change"}}" {{if eq .commit_choice "commit-to-new-branch"}}checked{{end}}>
5447
{{else}}
55-
{{ctx.Locale.Tr "repo.editor.create_new_branch_np"}}
48+
<input type="radio" class="js-quick-pull-choice-option" name="commit_choice" value="commit-to-new-branch" button_text="{{ctx.Locale.Tr "repo.editor.commit_changes"}}" {{if eq .commit_choice "commit-to-new-branch"}}checked{{end}}>
5649
{{end}}
57-
</label>
50+
<label>
51+
{{svg "octicon-git-pull-request"}}
52+
{{if .CanCreatePullRequest}}
53+
{{ctx.Locale.Tr "repo.editor.create_new_branch"}}
54+
{{else}}
55+
{{ctx.Locale.Tr "repo.editor.create_new_branch_np"}}
56+
{{end}}
57+
</label>
58+
</div>
5859
</div>
59-
</div>
60-
<div class="quick-pull-branch-name {{if not (eq .commit_choice "commit-to-new-branch")}}tw-hidden{{end}}">
61-
<div class="new-branch-name-input field {{if .Err_NewBranchName}}error{{end}}">
62-
{{svg "octicon-git-branch"}}
63-
<input type="text" name="new_branch_name" maxlength="100" value="{{.new_branch_name}}" class="input-contrast tw-mr-1 js-quick-pull-new-branch-name" placeholder="{{ctx.Locale.Tr "repo.editor.new_branch_name_desc"}}" {{if eq .commit_choice "commit-to-new-branch"}}required{{end}} title="{{ctx.Locale.Tr "repo.editor.new_branch_name"}}">
64-
<span class="text-muted js-quick-pull-normalization-info"></span>
60+
<div class="quick-pull-branch-name {{if not (eq .commit_choice "commit-to-new-branch")}}tw-hidden{{end}}">
61+
<div class="new-branch-name-input field {{if .Err_NewBranchName}}error{{end}}">
62+
{{svg "octicon-git-branch"}}
63+
<input type="text" name="new_branch_name" maxlength="100" value="{{.new_branch_name}}" class="input-contrast tw-mr-1 js-quick-pull-new-branch-name" placeholder="{{ctx.Locale.Tr "repo.editor.new_branch_name_desc"}}" {{if eq .commit_choice "commit-to-new-branch"}}required{{end}} title="{{ctx.Locale.Tr "repo.editor.new_branch_name"}}">
64+
<span class="text-muted js-quick-pull-normalization-info"></span>
65+
</div>
6566
</div>
66-
</div>
6767
{{end}}
6868
</div>
6969
</div>
7070
<button id="commit-button" type="submit" class="ui primary button">
7171
{{if eq .commit_choice "commit-to-new-branch"}}{{ctx.Locale.Tr "repo.editor.propose_file_change"}}{{else}}{{ctx.Locale.Tr "repo.editor.commit_changes"}}{{end}}
7272
</button>
73-
<a class="ui button red" href="{{$.BranchLink}}/{{PathEscapeSegments .TreePath}}">{{ctx.Locale.Tr "repo.editor.cancel"}}</a>
73+
<a class="ui button red" href="{{if .ReturnURI}}{{.ReturnURI}}{{else}}{{$.BranchLink}}/{{PathEscapeSegments .TreePath}}{{end}}">{{ctx.Locale.Tr "repo.editor.cancel"}}</a>
7474
</div>

templates/repo/editor/edit.tmpl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
<span class="section"><a href="{{$.BranchLink}}/{{index $.TreePaths $i | PathEscapeSegments}}">{{$v}}</a></span>
2222
{{end}}
2323
{{end}}
24-
<span>{{ctx.Locale.Tr "repo.editor.or"}} <a href="{{$.BranchLink}}{{if not .IsNewFile}}/{{PathEscapeSegments .TreePath}}{{end}}">{{ctx.Locale.Tr "repo.editor.cancel_lower"}}</a></span>
24+
<span>{{ctx.Locale.Tr "repo.editor.or"}} <a href="{{if .ReturnURI}}{{.ReturnURI}}{{else}}{{$.BranchLink}}{{if not .IsNewFile}}/{{PathEscapeSegments .TreePath}}{{end}}{{end}}">{{ctx.Locale.Tr "repo.editor.cancel_lower"}}</a></span>
2525
<input type="hidden" id="tree_path" name="tree_path" value="{{.TreePath}}" required>
2626
</div>
2727
</div>

tests/integration/pull_compare_test.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,4 +25,11 @@ func TestPullCompare(t *testing.T) {
2525
req = NewRequest(t, "GET", link)
2626
resp = session.MakeRequest(t, req, http.StatusOK)
2727
assert.EqualValues(t, http.StatusOK, resp.Code)
28+
29+
// test the edit button in the PR diff view
30+
req = NewRequest(t, "GET", "/user2/repo1/pulls/3/files")
31+
resp = session.MakeRequest(t, req, http.StatusOK)
32+
doc := NewHTMLParser(t, resp.Body)
33+
editButtonCount := doc.doc.Find(".diff-file-header-actions a[href*='/_edit/']").Length()
34+
assert.Greater(t, editButtonCount, 0, "Expected to find a button to edit a file in the PR diff view but there were none")
2835
}

0 commit comments

Comments
 (0)