[FEAT]Add Option to hide Release Archive links (#3139)
This adds a new options to releases to hide the links to the automatically generated archives. This is useful, when the automatically generated Archives are broken e.g. because of Submodules. ![grafik](/attachments/5686edf6-f318-4175-8459-89c33973b181) ![grafik](/attachments/74a8bf92-2abb-47a0-876d-d41024770d0b) Note: This juts hides the Archives from the UI. Users can still download 5the Archive if they know t correct URL. Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/3139 Reviewed-by: Otto <otto@codeberg.org> Reviewed-by: 0ko <0ko@noreply.codeberg.org> Co-authored-by: JakobDev <jakobdev@gmx.de> Co-committed-by: JakobDev <jakobdev@gmx.de>
This commit is contained in:
parent
6bcaf4f875
commit
1bce2dc5c5
14 changed files with 220 additions and 106 deletions
|
@ -62,6 +62,8 @@ var migrations = []*Migration{
|
|||
NewMigration("Add the `created` column to the `issue` table", forgejo_v1_22.AddCreatedToIssue),
|
||||
// v12 -> v13
|
||||
NewMigration("Add repo_archive_download_count table", forgejo_v1_22.AddRepoArchiveDownloadCount),
|
||||
// v13 -> v14
|
||||
NewMigration("Add `hide_archive_links` column to `release` table", AddHideArchiveLinksToRelease),
|
||||
}
|
||||
|
||||
// GetCurrentDBVersion returns the current Forgejo database version.
|
||||
|
|
15
models/forgejo_migrations/v13.go
Normal file
15
models/forgejo_migrations/v13.go
Normal file
|
@ -0,0 +1,15 @@
|
|||
// Copyright 2024 The Forgejo Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package forgejo_migrations //nolint:revive
|
||||
|
||||
import "xorm.io/xorm"
|
||||
|
||||
func AddHideArchiveLinksToRelease(x *xorm.Engine) error {
|
||||
type Release struct {
|
||||
ID int64 `xorm:"pk autoincr"`
|
||||
HideArchiveLinks bool `xorm:"NOT NULL DEFAULT false"`
|
||||
}
|
||||
|
||||
return x.Sync(&Release{})
|
||||
}
|
|
@ -78,6 +78,7 @@ type Release struct {
|
|||
TargetBehind string `xorm:"-"` // to handle non-existing or empty target
|
||||
Title string
|
||||
Sha1 string `xorm:"VARCHAR(64)"`
|
||||
HideArchiveLinks bool `xorm:"NOT NULL DEFAULT false"`
|
||||
NumCommits int64
|
||||
NumCommitsBehind int64 `xorm:"-"`
|
||||
Note string `xorm:"TEXT"`
|
||||
|
|
|
@ -18,6 +18,7 @@ type Release struct {
|
|||
HTMLURL string `json:"html_url"`
|
||||
TarURL string `json:"tarball_url"`
|
||||
ZipURL string `json:"zipball_url"`
|
||||
HideArchiveLinks bool `json:"hide_archive_links"`
|
||||
UploadURL string `json:"upload_url"`
|
||||
IsDraft bool `json:"draft"`
|
||||
IsPrerelease bool `json:"prerelease"`
|
||||
|
@ -39,6 +40,7 @@ type CreateReleaseOption struct {
|
|||
Note string `json:"body"`
|
||||
IsDraft bool `json:"draft"`
|
||||
IsPrerelease bool `json:"prerelease"`
|
||||
HideArchiveLinks bool `json:"hide_archive_links"`
|
||||
}
|
||||
|
||||
// EditReleaseOption options when editing a release
|
||||
|
@ -49,4 +51,5 @@ type EditReleaseOption struct {
|
|||
Note string `json:"body"`
|
||||
IsDraft *bool `json:"draft"`
|
||||
IsPrerelease *bool `json:"prerelease"`
|
||||
HideArchiveLinks *bool `json:"hide_archive_links"`
|
||||
}
|
||||
|
|
|
@ -2662,6 +2662,8 @@ release.downloads = Downloads
|
|||
release.download_count_one = %s download
|
||||
release.download_count_few = %s downloads
|
||||
release.add_tag_msg = Use the title and content of release as tag message.
|
||||
release.hide_archive_links = Hide automatically generated archives
|
||||
release.hide_archive_links_helper = Hide automatically generated source code archives for this release. For example, if you are uploading your own.
|
||||
release.add_tag = Create Tag Only
|
||||
release.releases_for = Releases for %s
|
||||
release.tags_for = Tags for %s
|
||||
|
|
|
@ -240,6 +240,7 @@ func CreateRelease(ctx *context.APIContext) {
|
|||
Note: form.Note,
|
||||
IsDraft: form.IsDraft,
|
||||
IsPrerelease: form.IsPrerelease,
|
||||
HideArchiveLinks: form.HideArchiveLinks,
|
||||
IsTag: false,
|
||||
Repo: ctx.Repo.Repository,
|
||||
}
|
||||
|
@ -261,6 +262,7 @@ func CreateRelease(ctx *context.APIContext) {
|
|||
rel.Note = form.Note
|
||||
rel.IsDraft = form.IsDraft
|
||||
rel.IsPrerelease = form.IsPrerelease
|
||||
rel.HideArchiveLinks = form.HideArchiveLinks
|
||||
rel.PublisherID = ctx.Doer.ID
|
||||
rel.IsTag = false
|
||||
rel.Repo = ctx.Repo.Repository
|
||||
|
@ -341,6 +343,9 @@ func EditRelease(ctx *context.APIContext) {
|
|||
if form.IsPrerelease != nil {
|
||||
rel.IsPrerelease = *form.IsPrerelease
|
||||
}
|
||||
if form.HideArchiveLinks != nil {
|
||||
rel.HideArchiveLinks = *form.HideArchiveLinks
|
||||
}
|
||||
if err := release_service.UpdateRelease(ctx, ctx.Doer, ctx.Repo.GitRepo, rel, nil, nil, nil, false); err != nil {
|
||||
ctx.Error(http.StatusInternalServerError, "UpdateRelease", err)
|
||||
return
|
||||
|
|
|
@ -441,6 +441,20 @@ func NewRelease(ctx *context.Context) {
|
|||
}
|
||||
ctx.Data["Tags"] = tags
|
||||
|
||||
// We set the value of the hide_archive_link textbox depending on the latest release
|
||||
latestRelease, err := repo_model.GetLatestReleaseByRepoID(ctx, ctx.Repo.Repository.ID)
|
||||
if err != nil {
|
||||
if repo_model.IsErrReleaseNotExist(err) {
|
||||
ctx.Data["hide_archive_links"] = false
|
||||
} else {
|
||||
ctx.ServerError("GetLatestReleaseByRepoID", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
if latestRelease != nil {
|
||||
ctx.Data["hide_archive_links"] = latestRelease.HideArchiveLinks
|
||||
}
|
||||
|
||||
ctx.HTML(http.StatusOK, tplReleaseNew)
|
||||
}
|
||||
|
||||
|
@ -535,6 +549,7 @@ func NewReleasePost(ctx *context.Context) {
|
|||
Note: form.Content,
|
||||
IsDraft: len(form.Draft) > 0,
|
||||
IsPrerelease: form.Prerelease,
|
||||
HideArchiveLinks: form.HideArchiveLinks,
|
||||
IsTag: false,
|
||||
}
|
||||
|
||||
|
@ -565,6 +580,7 @@ func NewReleasePost(ctx *context.Context) {
|
|||
rel.IsDraft = len(form.Draft) > 0
|
||||
rel.IsPrerelease = form.Prerelease
|
||||
rel.PublisherID = ctx.Doer.ID
|
||||
rel.HideArchiveLinks = form.HideArchiveLinks
|
||||
rel.IsTag = false
|
||||
|
||||
if err = releaseservice.UpdateRelease(ctx, ctx.Doer, ctx.Repo.GitRepo, rel, attachmentUUIDs, nil, nil, true); err != nil {
|
||||
|
@ -602,6 +618,7 @@ func EditRelease(ctx *context.Context) {
|
|||
ctx.Data["title"] = rel.Title
|
||||
ctx.Data["content"] = rel.Note
|
||||
ctx.Data["prerelease"] = rel.IsPrerelease
|
||||
ctx.Data["hide_archive_links"] = rel.HideArchiveLinks
|
||||
ctx.Data["IsDraft"] = rel.IsDraft
|
||||
|
||||
rel.Repo = ctx.Repo.Repository
|
||||
|
@ -648,6 +665,7 @@ func EditReleasePost(ctx *context.Context) {
|
|||
ctx.Data["title"] = rel.Title
|
||||
ctx.Data["content"] = rel.Note
|
||||
ctx.Data["prerelease"] = rel.IsPrerelease
|
||||
ctx.Data["hide_archive_links"] = rel.HideArchiveLinks
|
||||
|
||||
if ctx.HasError() {
|
||||
ctx.HTML(http.StatusOK, tplReleaseNew)
|
||||
|
@ -673,6 +691,7 @@ func EditReleasePost(ctx *context.Context) {
|
|||
rel.Note = form.Content
|
||||
rel.IsDraft = len(form.Draft) > 0
|
||||
rel.IsPrerelease = form.Prerelease
|
||||
rel.HideArchiveLinks = form.HideArchiveLinks
|
||||
if err = releaseservice.UpdateRelease(ctx, ctx.Doer, ctx.Repo.GitRepo,
|
||||
rel, addAttachmentUUIDs, delAttachmentUUIDs, editAttachments, false); err != nil {
|
||||
ctx.ServerError("UpdateRelease", err)
|
||||
|
|
|
@ -22,6 +22,7 @@ func ToAPIRelease(ctx context.Context, repo *repo_model.Repository, r *repo_mode
|
|||
HTMLURL: r.HTMLURL(),
|
||||
TarURL: r.TarURL(),
|
||||
ZipURL: r.ZipURL(),
|
||||
HideArchiveLinks: r.HideArchiveLinks,
|
||||
UploadURL: r.APIUploadURL(),
|
||||
IsDraft: r.IsDraft,
|
||||
IsPrerelease: r.IsPrerelease,
|
||||
|
|
|
@ -567,6 +567,7 @@ type NewReleaseForm struct {
|
|||
TagOnly string
|
||||
Prerelease bool
|
||||
AddTagMsg bool
|
||||
HideArchiveLinks bool
|
||||
Files []string
|
||||
}
|
||||
|
||||
|
@ -582,6 +583,7 @@ type EditReleaseForm struct {
|
|||
Content string `form:"content"`
|
||||
Draft string `form:"draft"`
|
||||
Prerelease bool `form:"prerelease"`
|
||||
HideArchiveLinks bool
|
||||
Files []string
|
||||
}
|
||||
|
||||
|
|
|
@ -61,14 +61,16 @@
|
|||
<div class="markup desc">
|
||||
{{$release.RenderedNote}}
|
||||
</div>
|
||||
{{$hasReleaseAttachment := gt (len $release.Attachments) 0}}
|
||||
{{$hasArchiveLinks := and (not $.DisableDownloadSourceArchives) (not $release.IsDraft) (not $release.HideArchiveLinks) ($.Permission.CanRead $.UnitTypeCode)}}
|
||||
{{if or $hasArchiveLinks $hasReleaseAttachment}}
|
||||
<div class="divider"></div>
|
||||
<details class="download" {{if eq $idx 0}}open{{end}}>
|
||||
<summary class="tw-my-4">
|
||||
{{ctx.Locale.Tr "repo.release.downloads"}}
|
||||
</summary>
|
||||
<ul class="list">
|
||||
{{$hasReleaseAttachment := gt (len $release.Attachments) 0}}
|
||||
{{if and (not $.DisableDownloadSourceArchives) (not $release.IsDraft) ($.Permission.CanRead $.UnitTypeCode)}}
|
||||
{{if $hasArchiveLinks}}
|
||||
<li>
|
||||
<a class="archive-link tw-flex-1" href="{{$.RepoLink}}/archive/{{$release.TagName | PathEscapeSegments}}.zip" rel="nofollow"><strong>{{svg "octicon-file-zip" 16 "tw-mr-1"}}{{ctx.Locale.Tr "repo.release.source_code"}} (ZIP)</strong></a>
|
||||
<div class="tw-mr-1">
|
||||
|
@ -101,6 +103,7 @@
|
|||
{{end}}
|
||||
</ul>
|
||||
</details>
|
||||
{{end}}
|
||||
<div class="dot"></div>
|
||||
</div>
|
||||
</li>
|
||||
|
|
|
@ -98,6 +98,15 @@
|
|||
</div>
|
||||
</div>
|
||||
<span class="help">{{ctx.Locale.Tr "repo.release.prerelease_helper"}}</span>
|
||||
{{if not .DisableDownloadSourceArchives}}
|
||||
<div class="field">
|
||||
<div class="ui checkbox">
|
||||
<input type="checkbox" name="hide_archive_links" {{if .hide_archive_links}}checked{{end}}>
|
||||
<label><strong>{{ctx.Locale.Tr "repo.release.hide_archive_links"}}</strong></label>
|
||||
</div>
|
||||
</div>
|
||||
<span class="help">{{ctx.Locale.Tr "repo.release.hide_archive_links_helper"}}</span>
|
||||
{{end}}
|
||||
<div class="divider tw-mt-0"></div>
|
||||
<div class="tw-flex tw-justify-end">
|
||||
{{if .PageIsEditRelease}}
|
||||
|
|
12
templates/swagger/v1_json.tmpl
generated
12
templates/swagger/v1_json.tmpl
generated
|
@ -19890,6 +19890,10 @@
|
|||
"type": "boolean",
|
||||
"x-go-name": "IsDraft"
|
||||
},
|
||||
"hide_archive_links": {
|
||||
"type": "boolean",
|
||||
"x-go-name": "HideArchiveLinks"
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"x-go-name": "Title"
|
||||
|
@ -20795,6 +20799,10 @@
|
|||
"type": "boolean",
|
||||
"x-go-name": "IsDraft"
|
||||
},
|
||||
"hide_archive_links": {
|
||||
"type": "boolean",
|
||||
"x-go-name": "HideArchiveLinks"
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"x-go-name": "Title"
|
||||
|
@ -23562,6 +23570,10 @@
|
|||
"type": "boolean",
|
||||
"x-go-name": "IsDraft"
|
||||
},
|
||||
"hide_archive_links": {
|
||||
"type": "boolean",
|
||||
"x-go-name": "HideArchiveLinks"
|
||||
},
|
||||
"html_url": {
|
||||
"type": "string",
|
||||
"x-go-name": "HTMLURL"
|
||||
|
|
|
@ -133,6 +133,9 @@ func TestAPICreateAndUpdateRelease(t *testing.T) {
|
|||
assert.Equal(t, newRelease.TagName, release.TagName)
|
||||
assert.Equal(t, newRelease.Title, release.Title)
|
||||
assert.Equal(t, newRelease.Note, release.Note)
|
||||
assert.False(t, newRelease.HideArchiveLinks)
|
||||
|
||||
hideArchiveLinks := true
|
||||
|
||||
req = NewRequestWithJSON(t, "PATCH", urlStr, &api.EditReleaseOption{
|
||||
TagName: release.TagName,
|
||||
|
@ -141,6 +144,7 @@ func TestAPICreateAndUpdateRelease(t *testing.T) {
|
|||
IsDraft: &release.IsDraft,
|
||||
IsPrerelease: &release.IsPrerelease,
|
||||
Target: release.Target,
|
||||
HideArchiveLinks: &hideArchiveLinks,
|
||||
}).AddTokenAuth(token)
|
||||
resp = MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
|
@ -152,6 +156,7 @@ func TestAPICreateAndUpdateRelease(t *testing.T) {
|
|||
}
|
||||
unittest.AssertExistsAndLoadBean(t, rel)
|
||||
assert.EqualValues(t, rel.Note, newRelease.Note)
|
||||
assert.True(t, newRelease.HideArchiveLinks)
|
||||
}
|
||||
|
||||
func TestAPICreateReleaseToDefaultBranch(t *testing.T) {
|
||||
|
|
|
@ -9,15 +9,19 @@ import (
|
|||
"testing"
|
||||
"time"
|
||||
|
||||
auth_model "code.gitea.io/gitea/models/auth"
|
||||
"code.gitea.io/gitea/models/db"
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
"code.gitea.io/gitea/models/unittest"
|
||||
"code.gitea.io/gitea/modules/setting"
|
||||
api "code.gitea.io/gitea/modules/structs"
|
||||
"code.gitea.io/gitea/modules/test"
|
||||
"code.gitea.io/gitea/modules/translation"
|
||||
"code.gitea.io/gitea/tests"
|
||||
|
||||
"github.com/PuerkitoBio/goquery"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func createNewRelease(t *testing.T, session *TestSession, repoURL, tag, title string, preRelease, draft bool) {
|
||||
|
@ -307,3 +311,34 @@ func TestDownloadReleaseAttachment(t *testing.T) {
|
|||
session := loginUser(t, "user2")
|
||||
session.MakeRequest(t, req, http.StatusOK)
|
||||
}
|
||||
|
||||
func TestReleaseHideArchiveLinksUI(t *testing.T) {
|
||||
defer tests.PrepareTestEnv(t)()
|
||||
|
||||
release := unittest.AssertExistsAndLoadBean(t, &repo_model.Release{TagName: "v2.0"})
|
||||
|
||||
require.NoError(t, release.LoadAttributes(db.DefaultContext))
|
||||
|
||||
session := loginUser(t, release.Repo.OwnerName)
|
||||
token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
|
||||
|
||||
zipURL := fmt.Sprintf("%s/archive/%s.zip", release.Repo.Link(), release.TagName)
|
||||
tarGzURL := fmt.Sprintf("%s/archive/%s.tar.gz", release.Repo.Link(), release.TagName)
|
||||
|
||||
resp := session.MakeRequest(t, NewRequest(t, "GET", release.HTMLURL()), http.StatusOK)
|
||||
body := resp.Body.String()
|
||||
assert.Contains(t, body, zipURL)
|
||||
assert.Contains(t, body, tarGzURL)
|
||||
|
||||
hideArchiveLinks := true
|
||||
|
||||
req := NewRequestWithJSON(t, "PATCH", release.APIURL(), &api.EditReleaseOption{
|
||||
HideArchiveLinks: &hideArchiveLinks,
|
||||
}).AddTokenAuth(token)
|
||||
MakeRequest(t, req, http.StatusOK)
|
||||
|
||||
resp = session.MakeRequest(t, NewRequest(t, "GET", release.HTMLURL()), http.StatusOK)
|
||||
body = resp.Body.String()
|
||||
assert.NotContains(t, body, zipURL)
|
||||
assert.NotContains(t, body, tarGzURL)
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue