Skip to content

Commit 21d8318

Browse files
committed
refactor repo home handler and add "sync fork"
1 parent faf5705 commit 21d8318

File tree

10 files changed

+313
-136
lines changed

10 files changed

+313
-136
lines changed

modules/git/repo.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ func Push(ctx context.Context, repoPath string, opts PushOptions) error {
223223
if err != nil {
224224
if strings.Contains(stderr, "non-fast-forward") {
225225
return &ErrPushOutOfDate{StdOut: stdout, StdErr: stderr, Err: err}
226-
} else if strings.Contains(stderr, "! [remote rejected]") {
226+
} else if strings.Contains(stderr, "! [remote rejected]") || strings.Contains(stderr, "! [rejected]") {
227227
err := &ErrPushRejected{StdOut: stdout, StdErr: stderr, Err: err}
228228
err.GenerateMessage()
229229
return err

options/locale/locale_en-US.ini

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1946,6 +1946,9 @@ pulls.delete.title = Delete this pull request?
19461946
pulls.delete.text = Do you really want to delete this pull request? (This will permanently remove all content. Consider closing it instead, if you intend to keep it archived)
19471947

19481948
pulls.recently_pushed_new_branches = You pushed on branch <strong>%[1]s</strong> %[2]s
1949+
pulls.upstream_diverging_prompt_behind_1 = This branch is %d commit behind %s
1950+
pulls.upstream_diverging_prompt_behind_n = This branch is %d commits behind %s
1951+
pulls.upstream_diverging_merge = Sync fork
19491952

19501953
pull.deleted_branch = (deleted):%s
19511954
pull.agit_documentation = Review documentation about AGit

routers/web/repo/branch.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,3 +259,20 @@ func CreateBranch(ctx *context.Context) {
259259
ctx.Flash.Success(ctx.Tr("repo.branch.create_success", form.NewBranchName))
260260
ctx.Redirect(ctx.Repo.RepoLink + "/src/branch/" + util.PathEscapeSegments(form.NewBranchName) + "/" + util.PathEscapeSegments(form.CurrentPath))
261261
}
262+
263+
func MergeUpstream(ctx *context.Context) {
264+
branchName := ctx.FormString("branch")
265+
_, err := repo_service.MergeUpstream(ctx, ctx.Doer, ctx.Repo.Repository, branchName)
266+
if err != nil {
267+
if errors.Is(err, util.ErrNotExist) {
268+
ctx.JSONError(ctx.Tr("error.not_found"))
269+
return
270+
} else if models.IsErrMergeConflicts(err) {
271+
ctx.JSONError(ctx.Tr("repo.pulls.merge_conflict"))
272+
return
273+
}
274+
ctx.ServerError("MergeUpstream", err)
275+
return
276+
}
277+
ctx.JSONRedirect("")
278+
}

routers/web/repo/view_file.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ import (
3131
"github.com/nektos/act/pkg/model"
3232
)
3333

34-
func renderFile(ctx *context.Context, entry *git.TreeEntry) {
34+
func prepareToRenderFile(ctx *context.Context, entry *git.TreeEntry) {
3535
ctx.Data["IsViewFile"] = true
3636
ctx.Data["HideRepoInfo"] = true
3737
blob := entry.Blob()

routers/web/repo/view_home.go

Lines changed: 160 additions & 133 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
package repo
55

66
import (
7+
"errors"
78
"fmt"
89
"html/template"
910
"net/http"
@@ -86,29 +87,31 @@ func prepareOpenWithEditorApps(ctx *context.Context) {
8687
ctx.Data["OpenWithEditorApps"] = tmplApps
8788
}
8889

89-
func prepareHomeSidebarCitationFile(ctx *context.Context, entry *git.TreeEntry) {
90-
if entry.Name() != "" {
91-
return
92-
}
93-
tree, err := ctx.Repo.Commit.SubTree(ctx.Repo.TreePath)
94-
if err != nil {
95-
HandleGitError(ctx, "Repo.Commit.SubTree", err)
96-
return
97-
}
98-
allEntries, err := tree.ListEntries()
99-
if err != nil {
100-
ctx.ServerError("ListEntries", err)
101-
return
102-
}
103-
for _, entry := range allEntries {
104-
if entry.Name() == "CITATION.cff" || entry.Name() == "CITATION.bib" {
105-
// Read Citation file contents
106-
if content, err := entry.Blob().GetBlobContent(setting.UI.MaxDisplayFileSize); err != nil {
107-
log.Error("checkCitationFile: GetBlobContent: %v", err)
108-
} else {
109-
ctx.Data["CitiationExist"] = true
110-
ctx.PageData["citationFileContent"] = content
111-
break
90+
func prepareHomeSidebarCitationFile(entry *git.TreeEntry) func(ctx *context.Context) {
91+
return func(ctx *context.Context) {
92+
if entry.Name() != "" {
93+
return
94+
}
95+
tree, err := ctx.Repo.Commit.SubTree(ctx.Repo.TreePath)
96+
if err != nil {
97+
HandleGitError(ctx, "Repo.Commit.SubTree", err)
98+
return
99+
}
100+
allEntries, err := tree.ListEntries()
101+
if err != nil {
102+
ctx.ServerError("ListEntries", err)
103+
return
104+
}
105+
for _, entry := range allEntries {
106+
if entry.Name() == "CITATION.cff" || entry.Name() == "CITATION.bib" {
107+
// Read Citation file contents
108+
if content, err := entry.Blob().GetBlobContent(setting.UI.MaxDisplayFileSize); err != nil {
109+
log.Error("checkCitationFile: GetBlobContent: %v", err)
110+
} else {
111+
ctx.Data["CitiationExist"] = true
112+
ctx.PageData["citationFileContent"] = content
113+
break
114+
}
112115
}
113116
}
114117
}
@@ -174,83 +177,21 @@ func prepareHomeSidebarLatestRelease(ctx *context.Context) {
174177
}
175178
}
176179

177-
func renderHomeCode(ctx *context.Context) {
178-
ctx.Data["PageIsViewCode"] = true
179-
ctx.Data["RepositoryUploadEnabled"] = setting.Repository.Upload.Enabled
180-
prepareOpenWithEditorApps(ctx)
181-
182-
if ctx.Repo.Commit == nil || ctx.Repo.Repository.IsEmpty || ctx.Repo.Repository.IsBroken() {
183-
showEmpty := true
184-
var err error
185-
if ctx.Repo.GitRepo != nil {
186-
showEmpty, err = ctx.Repo.GitRepo.IsEmpty()
187-
if err != nil {
188-
log.Error("GitRepo.IsEmpty: %v", err)
189-
ctx.Repo.Repository.Status = repo_model.RepositoryBroken
190-
showEmpty = true
191-
ctx.Flash.Error(ctx.Tr("error.occurred"), true)
192-
}
193-
}
194-
if showEmpty {
195-
ctx.HTML(http.StatusOK, tplRepoEMPTY)
196-
return
197-
}
198-
199-
// the repo is not really empty, so we should update the modal in database
200-
// such problem may be caused by:
201-
// 1) an error occurs during pushing/receiving. 2) the user replaces an empty git repo manually
202-
// and even more: the IsEmpty flag is deeply broken and should be removed with the UI changed to manage to cope with empty repos.
203-
// it's possible for a repository to be non-empty by that flag but still 500
204-
// because there are no branches - only tags -or the default branch is non-extant as it has been 0-pushed.
205-
ctx.Repo.Repository.IsEmpty = false
206-
if err = repo_model.UpdateRepositoryCols(ctx, ctx.Repo.Repository, "is_empty"); err != nil {
207-
ctx.ServerError("UpdateRepositoryCols", err)
208-
return
209-
}
210-
if err = repo_module.UpdateRepoSize(ctx, ctx.Repo.Repository); err != nil {
211-
ctx.ServerError("UpdateRepoSize", err)
212-
return
213-
}
214-
215-
// the repo's IsEmpty has been updated, redirect to this page to make sure middlewares can get the correct values
216-
link := ctx.Link
217-
if ctx.Req.URL.RawQuery != "" {
218-
link += "?" + ctx.Req.URL.RawQuery
219-
}
220-
ctx.Redirect(link)
221-
return
222-
}
223-
224-
title := ctx.Repo.Repository.Owner.Name + "/" + ctx.Repo.Repository.Name
225-
if len(ctx.Repo.Repository.Description) > 0 {
226-
title += ": " + ctx.Repo.Repository.Description
227-
}
228-
ctx.Data["Title"] = title
229-
230-
// Get Topics of this repo
231-
prepareHomeSidebarRepoTopics(ctx)
232-
if ctx.Written() {
180+
func prepareUpstreamDivergingInfo(ctx *context.Context) {
181+
if !ctx.Repo.Repository.IsFork || !ctx.Repo.IsViewBranch || ctx.Repo.TreePath != "" {
233182
return
234183
}
235-
236-
// Get current entry user currently looking at.
237-
entry, err := ctx.Repo.Commit.GetTreeEntryByPath(ctx.Repo.TreePath)
184+
upstreamDivergingInfo, err := repo_service.GetUpstreamDivergingInfo(ctx, ctx.Repo.Repository, ctx.Repo.BranchName)
238185
if err != nil {
239-
HandleGitError(ctx, "Repo.Commit.GetTreeEntryByPath", err)
240-
return
241-
}
242-
243-
checkOutdatedBranch(ctx)
244-
245-
if entry.IsDir() {
246-
prepareToRenderDirectory(ctx)
247-
} else {
248-
renderFile(ctx, entry)
249-
}
250-
if ctx.Written() {
186+
if !errors.Is(err, util.ErrNotExist) && !errors.Is(err, util.ErrInvalidArgument) {
187+
log.Error("GetUpstreamDivergingInfo: %v", err)
188+
}
251189
return
252190
}
191+
ctx.Data["UpstreamDivergingInfo"] = upstreamDivergingInfo
192+
}
253193

194+
func prepareRecentlyPushedNewBranches(ctx *context.Context) {
254195
if ctx.Doer != nil {
255196
if err := ctx.Repo.Repository.GetBaseRepo(ctx); err != nil {
256197
ctx.ServerError("GetBaseRepo", err)
@@ -280,53 +221,60 @@ func renderHomeCode(ctx *context.Context) {
280221
}
281222
}
282223
}
224+
}
283225

284-
var treeNames, paths []string
285-
branchLink := ctx.Repo.RepoLink + "/src/" + ctx.Repo.BranchNameSubURL()
286-
treeLink := branchLink
287-
if ctx.Repo.TreePath != "" {
288-
treeLink += "/" + util.PathEscapeSegments(ctx.Repo.TreePath)
289-
treeNames = strings.Split(ctx.Repo.TreePath, "/")
290-
for i := range treeNames {
291-
paths = append(paths, strings.Join(treeNames[:i+1], "/"))
292-
}
293-
ctx.Data["HasParentPath"] = true
294-
if len(paths)-2 >= 0 {
295-
ctx.Data["ParentPath"] = "/" + paths[len(paths)-2]
226+
func handleRepoEmptyOrBroken(ctx *context.Context) {
227+
showEmpty := true
228+
var err error
229+
if ctx.Repo.GitRepo != nil {
230+
showEmpty, err = ctx.Repo.GitRepo.IsEmpty()
231+
if err != nil {
232+
log.Error("GitRepo.IsEmpty: %v", err)
233+
ctx.Repo.Repository.Status = repo_model.RepositoryBroken
234+
showEmpty = true
235+
ctx.Flash.Error(ctx.Tr("error.occurred"), true)
296236
}
297237
}
238+
if showEmpty {
239+
ctx.HTML(http.StatusOK, tplRepoEMPTY)
240+
return
241+
}
298242

299-
isTreePathRoot := ctx.Repo.TreePath == ""
300-
if isTreePathRoot {
301-
prepareHomeSidebarLicenses(ctx)
302-
if ctx.Written() {
303-
return
304-
}
305-
prepareHomeSidebarCitationFile(ctx, entry)
306-
if ctx.Written() {
307-
return
308-
}
243+
// the repo is not really empty, so we should update the modal in database
244+
// such problem may be caused by:
245+
// 1) an error occurs during pushing/receiving. 2) the user replaces an empty git repo manually
246+
// and even more: the IsEmpty flag is deeply broken and should be removed with the UI changed to manage to cope with empty repos.
247+
// it's possible for a repository to be non-empty by that flag but still 500
248+
// because there are no branches - only tags -or the default branch is non-extant as it has been 0-pushed.
249+
ctx.Repo.Repository.IsEmpty = false
250+
if err = repo_model.UpdateRepositoryCols(ctx, ctx.Repo.Repository, "is_empty"); err != nil {
251+
ctx.ServerError("UpdateRepositoryCols", err)
252+
return
253+
}
254+
if err = repo_module.UpdateRepoSize(ctx, ctx.Repo.Repository); err != nil {
255+
ctx.ServerError("UpdateRepoSize", err)
256+
return
257+
}
309258

310-
prepareHomeSidebarLanguageStats(ctx)
311-
if ctx.Written() {
312-
return
313-
}
259+
// the repo's IsEmpty has been updated, redirect to this page to make sure middlewares can get the correct values
260+
link := ctx.Link
261+
if ctx.Req.URL.RawQuery != "" {
262+
link += "?" + ctx.Req.URL.RawQuery
263+
}
264+
ctx.Redirect(link)
265+
}
314266

315-
prepareHomeSidebarLatestRelease(ctx)
316-
if ctx.Written() {
317-
return
267+
func prepareToRenderDirOrFile(entry *git.TreeEntry) func(ctx *context.Context) {
268+
return func(ctx *context.Context) {
269+
if entry.IsDir() {
270+
prepareToRenderDirectory(ctx)
271+
} else {
272+
prepareToRenderFile(ctx, entry)
318273
}
319274
}
320-
321-
ctx.Data["Paths"] = paths
322-
ctx.Data["TreeLink"] = treeLink
323-
ctx.Data["TreeNames"] = treeNames
324-
ctx.Data["BranchLink"] = branchLink
325-
ctx.HTML(http.StatusOK, tplRepoHome)
326275
}
327276

328-
// Home render repository home page
329-
func Home(ctx *context.Context) {
277+
func handleRepoHomeFeed(ctx *context.Context) bool {
330278
if setting.Other.EnableFeed {
331279
isFeed, _, showFeedType := feed.GetFeedType(ctx.PathParam(":reponame"), ctx.Req)
332280
if isFeed {
@@ -338,14 +286,93 @@ func Home(ctx *context.Context) {
338286
case ctx.Repo.TreePath != "":
339287
feed.ShowFileFeed(ctx, ctx.Repo.Repository, showFeedType)
340288
}
341-
return
289+
return true
342290
}
343291
}
292+
return false
293+
}
294+
295+
// Home render repository home page
296+
func Home(ctx *context.Context) {
297+
if handleRepoHomeFeed(ctx) {
298+
return
299+
}
344300

301+
// Check whether the repo is viewable: not in migration, and the code unit should be enabled
302+
// Ideally the "feed" logic should be after this, but old code did so, so keep it as-is.
345303
checkHomeCodeViewable(ctx)
346304
if ctx.Written() {
347305
return
348306
}
349307

350-
renderHomeCode(ctx)
308+
title := ctx.Repo.Repository.Owner.Name + "/" + ctx.Repo.Repository.Name
309+
if len(ctx.Repo.Repository.Description) > 0 {
310+
title += ": " + ctx.Repo.Repository.Description
311+
}
312+
ctx.Data["Title"] = title
313+
ctx.Data["PageIsViewCode"] = true
314+
ctx.Data["RepositoryUploadEnabled"] = setting.Repository.Upload.Enabled // show New File / Upload File buttons
315+
316+
if ctx.Repo.Commit == nil || ctx.Repo.Repository.IsEmpty || ctx.Repo.Repository.IsBroken() {
317+
// emtpy or broken repositories need to be handled differently
318+
handleRepoEmptyOrBroken(ctx)
319+
return
320+
}
321+
322+
// get the current git entry which doer user is currently looking at.
323+
entry, err := ctx.Repo.Commit.GetTreeEntryByPath(ctx.Repo.TreePath)
324+
if err != nil {
325+
HandleGitError(ctx, "Repo.Commit.GetTreeEntryByPath", err)
326+
return
327+
}
328+
329+
// prepare the tree path
330+
var treeNames, paths []string
331+
branchLink := ctx.Repo.RepoLink + "/src/" + ctx.Repo.BranchNameSubURL()
332+
treeLink := branchLink
333+
if ctx.Repo.TreePath != "" {
334+
treeLink += "/" + util.PathEscapeSegments(ctx.Repo.TreePath)
335+
treeNames = strings.Split(ctx.Repo.TreePath, "/")
336+
for i := range treeNames {
337+
paths = append(paths, strings.Join(treeNames[:i+1], "/"))
338+
}
339+
ctx.Data["HasParentPath"] = true
340+
if len(paths)-2 >= 0 {
341+
ctx.Data["ParentPath"] = "/" + paths[len(paths)-2]
342+
}
343+
}
344+
ctx.Data["Paths"] = paths
345+
ctx.Data["TreeLink"] = treeLink
346+
ctx.Data["TreeNames"] = treeNames
347+
ctx.Data["BranchLink"] = branchLink
348+
349+
// some UI components are only shown when the tree path is root
350+
isTreePathRoot := ctx.Repo.TreePath == ""
351+
352+
prepareFuncs := []func(*context.Context){
353+
prepareOpenWithEditorApps,
354+
prepareHomeSidebarRepoTopics,
355+
checkOutdatedBranch,
356+
prepareToRenderDirOrFile(entry),
357+
prepareRecentlyPushedNewBranches,
358+
}
359+
360+
if isTreePathRoot {
361+
prepareFuncs = append(prepareFuncs,
362+
prepareUpstreamDivergingInfo,
363+
prepareHomeSidebarLicenses,
364+
prepareHomeSidebarCitationFile(entry),
365+
prepareHomeSidebarLanguageStats,
366+
prepareHomeSidebarLatestRelease,
367+
)
368+
}
369+
370+
for _, prepare := range prepareFuncs {
371+
prepare(ctx)
372+
if ctx.Written() {
373+
return
374+
}
375+
}
376+
377+
ctx.HTML(http.StatusOK, tplRepoHome)
351378
}

0 commit comments

Comments
 (0)