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.

feat(ui): show link to download directory (#4736)

This adds links to download a directory as archive. This can be useful if you e.g. just want to download a assets directory instead of the full source tree. The logic already exists in the backend, so only the frontend had been changed.

![grafik](https://codeberg.org/attachments/bee69268-ed03-4a05-8505-3d11e977a82c)

Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/4736
Reviewed-by: 0ko <0ko@noreply.codeberg.org>
Co-authored-by: JakobDev <jakobdev@gmx.de>
Co-committed-by: JakobDev <jakobdev@gmx.de>

authored by

JakobDev
JakobDev
and committed by
0ko
3c68399e ec35eb25

+62
+11
templates/repo/home.tmpl
··· 144 144 <a class="ui button" href="{{.RepoLink}}/commits/{{.BranchNameSubURL}}/{{.TreePath | PathEscapeSegments}}"> 145 145 {{svg "octicon-history" 16 "tw-mr-2"}}{{ctx.Locale.Tr "repo.file_history"}} 146 146 </a> 147 + {{if not $.DisableDownloadSourceArchives}} 148 + <div class="clone-panel ui action tiny input"> 149 + <button class="ui small jump dropdown icon button" data-tooltip-content="{{ctx.Locale.Tr "repo.more_operations"}}"> 150 + {{svg "octicon-kebab-horizontal"}} 151 + <div class="menu"> 152 + <a class="item archive-link" href="{{$.RepoLink}}/archive/{{PathEscapeSegments (printf "%s:%s" $.RefName .TreePath)}}.zip" rel="nofollow">{{svg "octicon-file-zip" 16 "tw-mr-2"}}{{ctx.Locale.Tr "repo.download_zip"}}</a> 153 + <a class="item archive-link" href="{{$.RepoLink}}/archive/{{PathEscapeSegments (printf "%s:%s" $.RefName .TreePath)}}.tar.gz" rel="nofollow">{{svg "octicon-file-zip" 16 "tw-mr-2"}}{{ctx.Locale.Tr "repo.download_tar"}}</a> 154 + </div> 155 + </button> 156 + </div> 157 + {{end}} 147 158 {{end}} 148 159 </div> 149 160 </div>
+51
tests/integration/repo_archive_test.go
··· 4 4 package integration 5 5 6 6 import ( 7 + "archive/tar" 8 + "compress/gzip" 9 + "fmt" 7 10 "io" 8 11 "net/http" 12 + "net/url" 9 13 "testing" 10 14 15 + repo_model "code.gitea.io/gitea/models/repo" 16 + "code.gitea.io/gitea/models/unittest" 17 + user_model "code.gitea.io/gitea/models/user" 11 18 "code.gitea.io/gitea/modules/setting" 12 19 "code.gitea.io/gitea/modules/test" 13 20 "code.gitea.io/gitea/routers" ··· 32 39 assert.Empty(t, resp.Header().Get("Content-Encoding")) 33 40 assert.Len(t, bs, 320) 34 41 } 42 + 43 + func TestRepoDownloadArchiveSubdir(t *testing.T) { 44 + onGiteaRun(t, func(*testing.T, *url.URL) { 45 + defer test.MockVariableValue(&setting.EnableGzip, true)() 46 + defer test.MockVariableValue(&web.GzipMinSize, 10)() 47 + defer test.MockVariableValue(&testWebRoutes, routers.NormalRoutes())() 48 + 49 + repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) 50 + user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID}) 51 + 52 + // Create a subdirectory 53 + err := createOrReplaceFileInBranch(user, repo, "subdir/test.txt", "master", "Test") 54 + require.NoError(t, err) 55 + 56 + t.Run("Frontend", func(t *testing.T) { 57 + resp := MakeRequest(t, NewRequestf(t, "GET", "/%s/src/branch/master/subdir", repo.FullName()), http.StatusOK) 58 + 59 + assert.Contains(t, resp.Body.String(), fmt.Sprintf("/%s/archive/master:subdir.zip", repo.FullName())) 60 + assert.Contains(t, resp.Body.String(), fmt.Sprintf("/%s/archive/master:subdir.tar.gz", repo.FullName())) 61 + }) 62 + 63 + t.Run("Backend", func(t *testing.T) { 64 + resp := MakeRequest(t, NewRequestf(t, "GET", "/%s/archive/master:subdir.tar.gz", repo.FullName()), http.StatusOK) 65 + 66 + uncompressedStream, err := gzip.NewReader(resp.Body) 67 + require.NoError(t, err) 68 + 69 + tarReader := tar.NewReader(uncompressedStream) 70 + 71 + header, err := tarReader.Next() 72 + require.NoError(t, err) 73 + assert.Equal(t, tar.TypeDir, int32(header.Typeflag)) 74 + assert.Equal(t, fmt.Sprintf("%s/", repo.Name), header.Name) 75 + 76 + header, err = tarReader.Next() 77 + require.NoError(t, err) 78 + assert.Equal(t, tar.TypeReg, int32(header.Typeflag)) 79 + assert.Equal(t, fmt.Sprintf("%s/test.txt", repo.Name), header.Name) 80 + 81 + _, err = tarReader.Next() 82 + assert.Equal(t, io.EOF, err) 83 + }) 84 + }) 85 + }