summaryrefslogtreecommitdiffstats
path: root/routers/web
diff options
context:
space:
mode:
authorzeripath <art27@cantab.net>2021-10-08 14:08:22 +0100
committerGitHub <noreply@github.com>2021-10-08 15:08:22 +0200
commit001dbf100de40f19c7ade5b8f013fbcccbe09ec3 (patch)
tree0b1a57f8efbb2e941fe4c344005a70ec76ad57d1 /routers/web
parent88fa9f3fb168bc6c9c2bdc6341b83bc048b38846 (diff)
downloadgitea-001dbf100de40f19c7ade5b8f013fbcccbe09ec3.tar.gz
gitea-001dbf100de40f19c7ade5b8f013fbcccbe09ec3.zip
Defer Last Commit Info (#16467)
One of the biggest reasons for slow repository browsing is that we wait until last commit information has been generated for all files in the repository. This PR proposes deferring this generation to a new POST endpoint that does the look up outside of the main page request. Signed-off-by: Andrew Thornton <art27@cantab.net>
Diffstat (limited to 'routers/web')
-rw-r--r--routers/web/repo/view.go205
-rw-r--r--routers/web/web.go3
2 files changed, 156 insertions, 52 deletions
diff --git a/routers/web/repo/view.go b/routers/web/repo/view.go
index c0a35bcb4f..0777a10e7b 100644
--- a/routers/web/repo/view.go
+++ b/routers/web/repo/view.go
@@ -7,6 +7,7 @@ package repo
import (
"bytes"
+ gocontext "context"
"encoding/base64"
"fmt"
gotemplate "html/template"
@@ -16,6 +17,7 @@ import (
"path"
"strconv"
"strings"
+ "time"
"code.gitea.io/gitea/models"
"code.gitea.io/gitea/models/db"
@@ -34,11 +36,12 @@ import (
)
const (
- tplRepoEMPTY base.TplName = "repo/empty"
- tplRepoHome base.TplName = "repo/home"
- tplWatchers base.TplName = "repo/watchers"
- tplForks base.TplName = "repo/forks"
- tplMigrating base.TplName = "repo/migrate/migrating"
+ tplRepoEMPTY base.TplName = "repo/empty"
+ tplRepoHome base.TplName = "repo/home"
+ tplRepoViewList base.TplName = "repo/view_list"
+ tplWatchers base.TplName = "repo/watchers"
+ tplForks base.TplName = "repo/forks"
+ tplMigrating base.TplName = "repo/migrate/migrating"
)
type namedBlob struct {
@@ -128,28 +131,8 @@ func getReadmeFileFromPath(commit *git.Commit, treePath string) (*namedBlob, err
}
func renderDirectory(ctx *context.Context, treeLink string) {
- tree, err := ctx.Repo.Commit.SubTree(ctx.Repo.TreePath)
- if err != nil {
- ctx.NotFoundOrServerError("Repo.Commit.SubTree", git.IsErrNotExist, err)
- return
- }
-
- entries, err := tree.ListEntries()
- if err != nil {
- ctx.ServerError("ListEntries", err)
- return
- }
- entries.CustomSort(base.NaturalSortLess)
-
- var c *git.LastCommitCache
- if setting.CacheService.LastCommit.Enabled && ctx.Repo.CommitsCount >= setting.CacheService.LastCommit.CommitsCount {
- c = git.NewLastCommitCache(ctx.Repo.Repository.FullName(), ctx.Repo.GitRepo, setting.LastCommitCacheTTLSeconds, cache.GetCache())
- }
-
- var latestCommit *git.Commit
- ctx.Data["Files"], latestCommit, err = entries.GetCommitsInfo(ctx, ctx.Repo.Commit, ctx.Repo.TreePath, c)
- if err != nil {
- ctx.ServerError("GetCommitsInfo", err)
+ entries := renderDirectoryFiles(ctx, 1*time.Second)
+ if ctx.Written() {
return
}
@@ -186,6 +169,7 @@ func renderDirectory(ctx *context.Context, treeLink string) {
isSymlink := entry.IsLink()
target := entry
if isSymlink {
+ var err error
target, err = entry.FollowLinks()
if err != nil && !git.IsErrBadLink(err) {
ctx.ServerError("FollowLinks", err)
@@ -207,6 +191,7 @@ func renderDirectory(ctx *context.Context, treeLink string) {
name := entry.Name()
isSymlink := entry.IsLink()
if isSymlink {
+ var err error
entry, err = entry.FollowLinks()
if err != nil && !git.IsErrBadLink(err) {
ctx.ServerError("FollowLinks", err)
@@ -237,6 +222,7 @@ func renderDirectory(ctx *context.Context, treeLink string) {
if entry == nil {
continue
}
+ var err error
readmeFile, err = getReadmeFileFromPath(ctx.Repo.Commit, entry.GetSubJumpablePathName())
if err != nil {
ctx.ServerError("getReadmeFileFromPath", err)
@@ -365,34 +351,12 @@ func renderDirectory(ctx *context.Context, treeLink string) {
}
}
- // Show latest commit info of repository in table header,
- // or of directory if not in root directory.
- ctx.Data["LatestCommit"] = latestCommit
- verification := models.ParseCommitWithSignature(latestCommit)
-
- if err := models.CalculateTrustStatus(verification, ctx.Repo.Repository, nil); err != nil {
- ctx.ServerError("CalculateTrustStatus", err)
- return
- }
- ctx.Data["LatestCommitVerification"] = verification
-
- ctx.Data["LatestCommitUser"] = models.ValidateCommitWithEmail(latestCommit)
-
- statuses, err := models.GetLatestCommitStatus(ctx.Repo.Repository.ID, ctx.Repo.Commit.ID.String(), db.ListOptions{})
- if err != nil {
- log.Error("GetLatestCommitStatus: %v", err)
- }
-
- ctx.Data["LatestCommitStatus"] = models.CalcCommitStatus(statuses)
- ctx.Data["LatestCommitStatuses"] = statuses
-
// Check permission to add or upload new file.
if ctx.Repo.CanWrite(models.UnitTypeCode) && ctx.Repo.IsViewBranch {
ctx.Data["CanAddFile"] = !ctx.Repo.Repository.IsArchived
ctx.Data["CanUploadFile"] = setting.Repository.Upload.Enabled && !ctx.Repo.Repository.IsArchived
}
- ctx.Data["SSHDomain"] = setting.SSH.Domain
}
func renderFile(ctx *context.Context, entry *git.TreeEntry, treeLink, rawLink string) {
@@ -614,8 +578,7 @@ func safeURL(address string) string {
return u.String()
}
-// Home render repository home page
-func Home(ctx *context.Context) {
+func checkHomeCodeViewable(ctx *context.Context) {
if len(ctx.Repo.Units) > 0 {
if ctx.Repo.Repository.IsBeingCreated() {
task, err := models.GetMigratingTask(ctx.Repo.Repository.ID)
@@ -648,7 +611,6 @@ func Home(ctx *context.Context) {
var firstUnit *models.Unit
for _, repoUnit := range ctx.Repo.Units {
if repoUnit.Type == models.UnitTypeCode {
- renderCode(ctx)
return
}
@@ -667,6 +629,145 @@ func Home(ctx *context.Context) {
ctx.NotFound("Home", fmt.Errorf(ctx.Tr("units.error.no_unit_allowed_repo")))
}
+// Home render repository home page
+func Home(ctx *context.Context) {
+ checkHomeCodeViewable(ctx)
+ if ctx.Written() {
+ return
+ }
+
+ renderCode(ctx)
+}
+
+// LastCommit returns lastCommit data for the provided branch/tag/commit and directory (in url) and filenames in body
+func LastCommit(ctx *context.Context) {
+ checkHomeCodeViewable(ctx)
+ if ctx.Written() {
+ return
+ }
+
+ renderDirectoryFiles(ctx, 0)
+ if ctx.Written() {
+ return
+ }
+
+ var treeNames []string
+ paths := make([]string, 0, 5)
+ if len(ctx.Repo.TreePath) > 0 {
+ treeNames = strings.Split(ctx.Repo.TreePath, "/")
+ for i := range treeNames {
+ paths = append(paths, strings.Join(treeNames[:i+1], "/"))
+ }
+
+ ctx.Data["HasParentPath"] = true
+ if len(paths)-2 >= 0 {
+ ctx.Data["ParentPath"] = "/" + paths[len(paths)-2]
+ }
+ }
+ branchLink := ctx.Repo.RepoLink + "/src/" + ctx.Repo.BranchNameSubURL()
+ ctx.Data["BranchLink"] = branchLink
+
+ ctx.HTML(http.StatusOK, tplRepoViewList)
+}
+
+func renderDirectoryFiles(ctx *context.Context, timeout time.Duration) git.Entries {
+ tree, err := ctx.Repo.Commit.SubTree(ctx.Repo.TreePath)
+ if err != nil {
+ ctx.NotFoundOrServerError("Repo.Commit.SubTree", git.IsErrNotExist, err)
+ return nil
+ }
+
+ ctx.Data["LastCommitLoaderURL"] = ctx.Repo.RepoLink + "/lastcommit/" + ctx.Repo.CommitID + "/" + ctx.Repo.TreePath
+
+ // Get current entry user currently looking at.
+ entry, err := ctx.Repo.Commit.GetTreeEntryByPath(ctx.Repo.TreePath)
+ if err != nil {
+ ctx.NotFoundOrServerError("Repo.Commit.GetTreeEntryByPath", git.IsErrNotExist, err)
+ return nil
+ }
+
+ if !entry.IsDir() {
+ ctx.NotFoundOrServerError("Repo.Commit.GetTreeEntryByPath", git.IsErrNotExist, err)
+ return nil
+ }
+
+ allEntries, err := tree.ListEntries()
+ if err != nil {
+ ctx.ServerError("ListEntries", err)
+ return nil
+ }
+ allEntries.CustomSort(base.NaturalSortLess)
+
+ commitInfoCtx := gocontext.Context(ctx)
+ if timeout > 0 {
+ var cancel gocontext.CancelFunc
+ commitInfoCtx, cancel = gocontext.WithTimeout(ctx, timeout)
+ defer cancel()
+ }
+
+ var c *git.LastCommitCache
+ if setting.CacheService.LastCommit.Enabled && ctx.Repo.CommitsCount >= setting.CacheService.LastCommit.CommitsCount {
+ c = git.NewLastCommitCache(ctx.Repo.Repository.FullName(), ctx.Repo.GitRepo, setting.LastCommitCacheTTLSeconds, cache.GetCache())
+ }
+
+ selected := map[string]bool{}
+ for _, pth := range ctx.FormStrings("f[]") {
+ selected[pth] = true
+ }
+
+ entries := allEntries
+ if len(selected) > 0 {
+ entries = make(git.Entries, 0, len(selected))
+ for _, entry := range allEntries {
+ if selected[entry.Name()] {
+ entries = append(entries, entry)
+ }
+ }
+ }
+
+ var latestCommit *git.Commit
+ ctx.Data["Files"], latestCommit, err = entries.GetCommitsInfo(commitInfoCtx, ctx.Repo.Commit, ctx.Repo.TreePath, c)
+ if err != nil {
+ ctx.ServerError("GetCommitsInfo", err)
+ return nil
+ }
+
+ // Show latest commit info of repository in table header,
+ // or of directory if not in root directory.
+ ctx.Data["LatestCommit"] = latestCommit
+ if latestCommit != nil {
+
+ verification := models.ParseCommitWithSignature(latestCommit)
+
+ if err := models.CalculateTrustStatus(verification, ctx.Repo.Repository, nil); err != nil {
+ ctx.ServerError("CalculateTrustStatus", err)
+ return nil
+ }
+ ctx.Data["LatestCommitVerification"] = verification
+ ctx.Data["LatestCommitUser"] = models.ValidateCommitWithEmail(latestCommit)
+ }
+
+ statuses, err := models.GetLatestCommitStatus(ctx.Repo.Repository.ID, ctx.Repo.Commit.ID.String(), db.ListOptions{})
+ if err != nil {
+ log.Error("GetLatestCommitStatus: %v", err)
+ }
+
+ ctx.Data["LatestCommitStatus"] = models.CalcCommitStatus(statuses)
+ ctx.Data["LatestCommitStatuses"] = statuses
+
+ branchLink := ctx.Repo.RepoLink + "/src/" + ctx.Repo.BranchNameSubURL()
+ treeLink := branchLink
+
+ if len(ctx.Repo.TreePath) > 0 {
+ treeLink += "/" + ctx.Repo.TreePath
+ }
+
+ ctx.Data["TreeLink"] = treeLink
+ ctx.Data["SSHDomain"] = setting.SSH.Domain
+
+ return allEntries
+}
+
func renderLanguageStats(ctx *context.Context) {
langs, err := ctx.Repo.Repository.GetTopLanguageStats(5)
if err != nil {
diff --git a/routers/web/web.go b/routers/web/web.go
index e12552f4d4..01d90d206f 100644
--- a/routers/web/web.go
+++ b/routers/web/web.go
@@ -995,6 +995,9 @@ func RegisterRoutes(m *web.Route) {
m.Get("/commit/{sha:([a-f0-9]{7,40})}.{ext:patch|diff}",
repo.MustBeNotEmpty, reqRepoCodeReader, repo.RawDiff)
}, ignSignIn, context.RepoAssignment, context.UnitTypes())
+
+ m.Post("/{username}/{reponame}/lastcommit/*", ignSignInAndCsrf, context.RepoAssignment, context.UnitTypes(), context.RepoRefByType(context.RepoRefCommit), reqRepoCodeReader, repo.LastCommit)
+
m.Group("/{username}/{reponame}", func() {
m.Get("/stars", repo.Stars)
m.Get("/watchers", repo.Watchers)