Skip to content

Commit d21ce9f

Browse files
authored
Improve the performance when detecting the file editable (#34653)
Noticed the SQL will be executed 4 times when visit the file render view page. For a repository which have many pull requests, it maybe slow. ```SQL 2025/06/08 15:24:44 models/issues/pull_list.go:69:GetUnmergedPullRequestsByHeadInfo() [I] [SQL] SELECT * FROM `pull_request` INNER JOIN `issue` ON issue.id = pull_request.issue_id WHERE (head_repo_id = ? AND head_branch = ? AND has_merged = ? AND issue.is_closed = ? AND flow = ?) [393 main false false 0] - 2.004167ms 2025/06/08 15:24:44 models/issues/pull_list.go:69:GetUnmergedPullRequestsByHeadInfo() [I] [SQL] SELECT * FROM `pull_request` INNER JOIN `issue` ON issue.id = pull_request.issue_id WHERE (head_repo_id = ? AND head_branch = ? AND has_merged = ? AND issue.is_closed = ? AND flow = ?) [393 main false false 0] - 1.03975ms 2025/06/08 15:24:44 models/issues/pull_list.go:69:GetUnmergedPullRequestsByHeadInfo() [I] [SQL] SELECT * FROM `pull_request` INNER JOIN `issue` ON issue.id = pull_request.issue_id WHERE (head_repo_id = ? AND head_branch = ? AND has_merged = ? AND issue.is_closed = ? AND flow = ?) [393 main false false 0] - 881.583µs 2025/06/08 15:24:44 models/issues/pull_list.go:69:GetUnmergedPullRequestsByHeadInfo() [I] [SQL] SELECT * FROM `pull_request` INNER JOIN `issue` ON issue.id = pull_request.issue_id WHERE (head_repo_id = ? AND head_branch = ? AND has_merged = ? AND issue.is_closed = ? AND flow = ?) [393 main false false 0] - 935.084µs ``` This PR did a refactor to query it once only.
1 parent 8fed27b commit d21ce9f

File tree

2 files changed

+45
-34
lines changed

2 files changed

+45
-34
lines changed

routers/web/repo/view_file.go

Lines changed: 42 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -140,13 +140,6 @@ func prepareToRenderFile(ctx *context.Context, entry *git.TreeEntry) {
140140
ctx.Data["LFSLockHint"] = ctx.Tr("repo.editor.this_file_locked")
141141
}
142142

143-
// Assume file is not editable first.
144-
if fInfo.isLFSFile {
145-
ctx.Data["EditFileTooltip"] = ctx.Tr("repo.editor.cannot_edit_lfs_files")
146-
} else if !isRepresentableAsText {
147-
ctx.Data["EditFileTooltip"] = ctx.Tr("repo.editor.cannot_edit_non_text_files")
148-
}
149-
150143
// read all needed attributes which will be used later
151144
// there should be no performance different between reading 2 or 4 here
152145
attrsMap, err := attribute.CheckAttributes(ctx, ctx.Repo.GitRepo, ctx.Repo.CommitID, attribute.CheckAttributeOpts{
@@ -243,21 +236,6 @@ func prepareToRenderFile(ctx *context.Context, entry *git.TreeEntry) {
243236
ctx.Data["FileContent"] = fileContent
244237
ctx.Data["LineEscapeStatus"] = statuses
245238
}
246-
if !fInfo.isLFSFile {
247-
if ctx.Repo.CanEnableEditor(ctx, ctx.Doer) {
248-
if lfsLock != nil && lfsLock.OwnerID != ctx.Doer.ID {
249-
ctx.Data["CanEditFile"] = false
250-
ctx.Data["EditFileTooltip"] = ctx.Tr("repo.editor.this_file_locked")
251-
} else {
252-
ctx.Data["CanEditFile"] = true
253-
ctx.Data["EditFileTooltip"] = ctx.Tr("repo.editor.edit_this_file")
254-
}
255-
} else if !ctx.Repo.RefFullName.IsBranch() {
256-
ctx.Data["EditFileTooltip"] = ctx.Tr("repo.editor.must_be_on_a_branch")
257-
} else if !ctx.Repo.CanWriteToBranch(ctx, ctx.Doer, ctx.Repo.BranchName) {
258-
ctx.Data["EditFileTooltip"] = ctx.Tr("repo.editor.fork_before_edit")
259-
}
260-
}
261239

262240
case fInfo.st.IsPDF():
263241
ctx.Data["IsPDFFile"] = true
@@ -307,17 +285,49 @@ func prepareToRenderFile(ctx *context.Context, entry *git.TreeEntry) {
307285
}
308286
}
309287

310-
if ctx.Repo.CanEnableEditor(ctx, ctx.Doer) {
311-
if lfsLock != nil && lfsLock.OwnerID != ctx.Doer.ID {
312-
ctx.Data["CanDeleteFile"] = false
313-
ctx.Data["DeleteFileTooltip"] = ctx.Tr("repo.editor.this_file_locked")
314-
} else {
315-
ctx.Data["CanDeleteFile"] = true
316-
ctx.Data["DeleteFileTooltip"] = ctx.Tr("repo.editor.delete_this_file")
317-
}
318-
} else if !ctx.Repo.RefFullName.IsBranch() {
288+
prepareToRenderButtons(ctx, fInfo.isLFSFile, isRepresentableAsText, lfsLock)
289+
}
290+
291+
func prepareToRenderButtons(ctx *context.Context, isLFSFile, isRepresentableAsText bool, lfsLock *git_model.LFSLock) {
292+
// archived or mirror repository, the buttons should not be shown
293+
if ctx.Repo.Repository.IsArchived || !ctx.Repo.Repository.CanEnableEditor() {
294+
return
295+
}
296+
297+
// The buttons should not be shown if it's not a branch
298+
if !ctx.Repo.RefFullName.IsBranch() {
299+
ctx.Data["EditFileTooltip"] = ctx.Tr("repo.editor.must_be_on_a_branch")
319300
ctx.Data["DeleteFileTooltip"] = ctx.Tr("repo.editor.must_be_on_a_branch")
320-
} else if !ctx.Repo.CanWriteToBranch(ctx, ctx.Doer, ctx.Repo.BranchName) {
301+
return
302+
}
303+
304+
if isLFSFile {
305+
ctx.Data["EditFileTooltip"] = ctx.Tr("repo.editor.cannot_edit_lfs_files")
306+
} else if !isRepresentableAsText {
307+
ctx.Data["EditFileTooltip"] = ctx.Tr("repo.editor.cannot_edit_non_text_files")
308+
}
309+
310+
if !ctx.Repo.CanWriteToBranch(ctx, ctx.Doer, ctx.Repo.BranchName) {
311+
if !isLFSFile { // lfs file cannot be edited after fork
312+
ctx.Data["EditFileTooltip"] = ctx.Tr("repo.editor.fork_before_edit")
313+
}
321314
ctx.Data["DeleteFileTooltip"] = ctx.Tr("repo.editor.must_have_write_access")
315+
return
316+
}
317+
318+
// it's a lfs file and the user is not the owner of the lock
319+
if lfsLock != nil && lfsLock.OwnerID != ctx.Doer.ID {
320+
ctx.Data["CanEditFile"] = false
321+
ctx.Data["EditFileTooltip"] = ctx.Tr("repo.editor.this_file_locked")
322+
ctx.Data["CanDeleteFile"] = false
323+
ctx.Data["DeleteFileTooltip"] = ctx.Tr("repo.editor.this_file_locked")
324+
return
325+
}
326+
327+
if !isLFSFile { // lfs file cannot be edited
328+
ctx.Data["CanEditFile"] = true
329+
ctx.Data["EditFileTooltip"] = ctx.Tr("repo.editor.edit_this_file")
322330
}
331+
ctx.Data["CanDeleteFile"] = true
332+
ctx.Data["DeleteFileTooltip"] = ctx.Tr("repo.editor.delete_this_file")
323333
}

services/context/repo.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,8 @@ func (r *Repository) CanCommitToBranch(ctx context.Context, doer *user_model.Use
123123

124124
sign, keyID, _, err := asymkey_service.SignCRUDAction(ctx, r.Repository.RepoPath(), doer, r.Repository.RepoPath(), git.BranchPrefix+r.BranchName)
125125

126-
canCommit := r.CanEnableEditor(ctx, doer) && userCanPush
126+
canEnableEditor := r.CanEnableEditor(ctx, doer)
127+
canCommit := canEnableEditor && userCanPush
127128
if requireSigned {
128129
canCommit = canCommit && sign
129130
}
@@ -139,7 +140,7 @@ func (r *Repository) CanCommitToBranch(ctx context.Context, doer *user_model.Use
139140

140141
return CanCommitToBranchResults{
141142
CanCommitToBranch: canCommit,
142-
EditorEnabled: r.CanEnableEditor(ctx, doer),
143+
EditorEnabled: canEnableEditor,
143144
UserCanPush: userCanPush,
144145
RequireSigned: requireSigned,
145146
WillSign: sign,

0 commit comments

Comments
 (0)