loading up the forgejo repo on tangled to test page performance
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

[GITEA] Configurable clone methods

Adds `[repository].DOWNLOAD_OR_CLONE_METHODS` (defaulting to
"download-zip,download-targz,download-bundle,vscode-clone"), which lets
an instance administrator override the additional clone methods
displayed on the repository home view.

This is purely display-only, the clone methods not listed here are still
available, unless disabled elsewhere. They're just not displayed.

Fixes #710.

Signed-off-by: Gergely Nagy <forgejo@gergo.csillger.hu>
(cherry picked from commit 2aadcf4946e48ee43800568fe705d00a062c42bf)
(cherry picked from commit 42ac34fbf9105eed27ee687b305a85515270f0cc)
(cherry picked from commit bd231b02450212aca6be775663c3d24ddf19f990)
(cherry picked from commit 3d3366dbbee37621fc665e557a4a87bf08104375)
(cherry picked from commit 0157fb9b88fd50832c07b06c11c8dba6e059a465)
(cherry picked from commit bee88f6a8309c6f9aeba1522383d77f08e5a4d2d)

authored by

Gergely Nagy and committed by
Earl Warren
1d8bca07 1bae2430

+117 -7
+11
modules/setting/repository.go
··· 7 7 "os/exec" 8 8 "path" 9 9 "path/filepath" 10 + "slices" 10 11 "strings" 11 12 12 13 "code.gitea.io/gitea/modules/log" ··· 18 19 RepoCreatingPrivate = "private" 19 20 RepoCreatingPublic = "public" 20 21 ) 22 + 23 + var RecognisedRepositoryDownloadOrCloneMethods = []string{"download-zip", "download-targz", "download-bundle", "vscode-clone", "vscodium-clone", "cite"} 21 24 22 25 // ItemsPerPage maximum items per page in forks, watchers and stars of a repo 23 26 const ItemsPerPage = 40 ··· 43 46 DisabledRepoUnits []string 44 47 DefaultRepoUnits []string 45 48 DefaultForkRepoUnits []string 49 + DownloadOrCloneMethods []string 46 50 PrefixArchiveFiles bool 47 51 DisableMigrations bool 48 52 DisableStars bool `ini:"DISABLE_STARS"` ··· 161 165 DisabledRepoUnits: []string{}, 162 166 DefaultRepoUnits: []string{}, 163 167 DefaultForkRepoUnits: []string{}, 168 + DownloadOrCloneMethods: []string{"download-zip", "download-targz", "download-bundle", "vscode-clone"}, 164 169 PrefixArchiveFiles: true, 165 170 DisableMigrations: false, 166 171 DisableStars: false, ··· 360 365 361 366 if err := loadRepoArchiveFrom(rootCfg); err != nil { 362 367 log.Fatal("loadRepoArchiveFrom: %v", err) 368 + } 369 + 370 + for _, method := range Repository.DownloadOrCloneMethods { 371 + if !slices.Contains(RecognisedRepositoryDownloadOrCloneMethods, method) { 372 + log.Error("Unrecognised repository download or clone method: %s", method) 373 + } 363 374 } 364 375 }
+1
modules/web/middleware/data.go
··· 53 53 "ShowMilestonesDashboardPage": setting.Service.ShowMilestonesDashboardPage, 54 54 "ShowFooterVersion": setting.Other.ShowFooterVersion, 55 55 "DisableDownloadSourceArchives": setting.Repository.DisableDownloadSourceArchives, 56 + "DownloadOrCloneMethods": setting.Repository.DownloadOrCloneMethods, 56 57 57 58 "EnableSwagger": setting.API.EnableSwagger, 58 59 "EnableOpenIDSignIn": setting.Service.EnableOpenIDSignIn,
+3
templates/repo/clone_script.tmpl
··· 38 38 for (const el of document.getElementsByClassName('js-clone-url-vsc')) { 39 39 el['href'] = 'vscode://vscode.git/clone?url=' + encodeURIComponent(link); 40 40 } 41 + for (const el of document.getElementsByClassName('js-clone-url-vscodium')) { 42 + el['href'] = 'vscodium://vscode.git/clone?url=' + encodeURIComponent(link); 43 + } 41 44 })(); 42 45 </script>
+24 -7
templates/repo/home.tmpl
··· 131 131 <button id="more-btn" class="ui basic small compact jump dropdown icon button" data-tooltip-content="{{ctx.Locale.Tr "repo.more_operations"}}"> 132 132 {{svg "octicon-kebab-horizontal"}} 133 133 <div class="menu"> 134 - {{if not $.DisableDownloadSourceArchives}} 135 - <a class="item archive-link" href="{{$.RepoLink}}/archive/{{PathEscapeSegments $.RefName}}.zip" rel="nofollow">{{svg "octicon-file-zip" 16 "gt-mr-3"}}{{ctx.Locale.Tr "repo.download_zip"}}</a> 136 - <a class="item archive-link" href="{{$.RepoLink}}/archive/{{PathEscapeSegments $.RefName}}.tar.gz" rel="nofollow">{{svg "octicon-file-zip" 16 "gt-mr-3"}}{{ctx.Locale.Tr "repo.download_tar"}}</a> 137 - <a class="item archive-link" href="{{$.RepoLink}}/archive/{{PathEscapeSegments $.RefName}}.bundle" rel="nofollow">{{svg "octicon-package" 16 "gt-mr-3"}}{{ctx.Locale.Tr "repo.download_bundle"}}</a> 138 - {{if .CitiationExist}} 139 - <a class="item" id="cite-repo-button">{{svg "octicon-cross-reference" 16 "gt-mr-3"}}{{ctx.Locale.Tr "repo.cite_this_repo"}}</a> 134 + {{$citation := .CitationExist}} 135 + {{$originLink := .CloneButtonOriginLink}} 136 + {{range $.DownloadOrCloneMethods}} 137 + {{if not $.DisableDownloadSourceArchives}} 138 + {{if eq . "download-zip"}} 139 + <a class="item archive-link" href="{{$.RepoLink}}/archive/{{PathEscapeSegments $.RefName}}.zip" rel="nofollow">{{svg "octicon-file-zip" 16 "gt-mr-3"}}{{ctx.Locale.Tr "repo.download_zip"}}</a> 140 + {{end}} 141 + {{if eq . "download-targz"}} 142 + <a class="item archive-link" href="{{$.RepoLink}}/archive/{{PathEscapeSegments $.RefName}}.tar.gz" rel="nofollow">{{svg "octicon-file-zip" 16 "gt-mr-3"}}{{ctx.Locale.Tr "repo.download_tar"}}</a> 143 + {{end}} 144 + {{if eq . "download-bundle"}} 145 + <a class="item archive-link" href="{{$.RepoLink}}/archive/{{PathEscapeSegments $.RefName}}.bundle" rel="nofollow">{{svg "octicon-package" 16 "gt-mr-3"}}{{ctx.Locale.Tr "repo.download_bundle"}}</a> 146 + {{end}} 147 + {{if $citation}} 148 + {{if eq . "cite"}} 149 + <a class="item" id="cite-repo-button">{{svg "octicon-cross-reference" 16 "gt-mr-3"}}{{ctx.Locale.Tr "repo.cite_this_repo"}}</a> 150 + {{end}} 151 + {{end}} 152 + {{end}} 153 + {{if eq . "vscode-clone"}} 154 + <a class="item js-clone-url-vsc" href="vscode://vscode.git/clone?url={{$originLink.HTTPS}}">{{svg "gitea-vscode" 16 "gt-mr-3"}}{{ctx.Locale.Tr "repo.clone_in_vsc"}}</a> 155 + {{end}} 156 + {{if eq . "vscodium-clone"}} 157 + <a class="item js-clone-url-vscodium" href="vscodium://vscode.git/clone?url={{$originLink.HTTPS}}">{{svg "gitea-vscode" 16 "gt-mr-3"}}{{ctx.Locale.Tr "repo.clone_in_vscodium"}}</a> 140 158 {{end}} 141 159 {{end}} 142 - <a class="item js-clone-url-vsc" href="vscode://vscode.git/clone?url={{.CloneButtonOriginLink.HTTPS}}">{{svg "gitea-vscode" 16 "gt-mr-3"}}{{ctx.Locale.Tr "repo.clone_in_vsc"}}</a> 143 160 </div> 144 161 </button> 145 162 {{template "repo/clone_script" .}}{{/* the script will update `.js-clone-url` and related elements */}}
+78
tests/integration/repo_test.go
··· 43 43 session.MakeRequest(t, req, http.StatusNotFound) 44 44 } 45 45 46 + func TestViewRepoCloneMethods(t *testing.T) { 47 + defer tests.PrepareTestEnv(t)() 48 + 49 + getCloneMethods := func() []string { 50 + req := NewRequest(t, "GET", "/user2/repo1") 51 + resp := MakeRequest(t, req, http.StatusOK) 52 + 53 + htmlDoc := NewHTMLParser(t, resp.Body) 54 + cloneMoreMethodsHTML := htmlDoc.doc.Find("#more-btn div a") 55 + 56 + var methods []string 57 + cloneMoreMethodsHTML.Each(func(i int, s *goquery.Selection) { 58 + a, _ := s.Attr("href") 59 + methods = append(methods, a) 60 + }) 61 + 62 + return methods 63 + } 64 + 65 + testCloneMethods := func(expected []string) { 66 + methods := getCloneMethods() 67 + 68 + assert.Len(t, methods, len(expected)) 69 + for i, expectedMethod := range expected { 70 + assert.Contains(t, methods[i], expectedMethod) 71 + } 72 + } 73 + 74 + t.Run("Defaults", func(t *testing.T) { 75 + defer tests.PrintCurrentTest(t)() 76 + 77 + testCloneMethods([]string{"/master.zip", "/master.tar.gz", "/master.bundle", "vscode://"}) 78 + }) 79 + 80 + t.Run("Customized methods", func(t *testing.T) { 81 + defer tests.PrintCurrentTest(t)() 82 + defer test.MockVariableValue(&setting.Repository.DownloadOrCloneMethods, []string{"vscodium-clone", "download-targz"})() 83 + 84 + testCloneMethods([]string{"vscodium://", "/master.tar.gz"}) 85 + }) 86 + 87 + t.Run("Individual methods", func(t *testing.T) { 88 + defer tests.PrintCurrentTest(t)() 89 + 90 + singleMethodTest := func(method, expectedURLPart string) { 91 + t.Run(method, func(t *testing.T) { 92 + defer tests.PrintCurrentTest(t)() 93 + defer test.MockVariableValue(&setting.Repository.DownloadOrCloneMethods, []string{method})() 94 + 95 + testCloneMethods([]string{expectedURLPart}) 96 + }) 97 + } 98 + 99 + cases := map[string]string{ 100 + "download-zip": "/master.zip", 101 + "download-targz": "/master.tar.gz", 102 + "download-bundle": "/master.bundle", 103 + "vscode-clone": "vscode://", 104 + "vscodium-clone": "vscodium://", 105 + } 106 + for method, expectedURLPart := range cases { 107 + singleMethodTest(method, expectedURLPart) 108 + } 109 + }) 110 + 111 + t.Run("All methods", func(t *testing.T) { 112 + defer tests.PrintCurrentTest(t)() 113 + defer test.MockVariableValue(&setting.Repository.DownloadOrCloneMethods, setting.RecognisedRepositoryDownloadOrCloneMethods)() 114 + 115 + methods := getCloneMethods() 116 + // We compare against 117 + // len(setting.RecognisedRepositoryDownloadOrCloneMethods) - 1, because 118 + // the test environment does not currently set things up for the cite 119 + // method to display. 120 + assert.GreaterOrEqual(t, len(methods), len(setting.RecognisedRepositoryDownloadOrCloneMethods)-1) 121 + }) 122 + } 123 + 46 124 func testViewRepo(t *testing.T) { 47 125 defer tests.PrepareTestEnv(t)() 48 126