···7575 return nil, err
7676 }
77777878- additionalUserIDs := make([]int64, 0, 10)
7979- if err = e.Table("team_user").
8080- Join("INNER", "team_repo", "`team_repo`.team_id = `team_user`.team_id").
8181- Join("INNER", "team_unit", "`team_unit`.team_id = `team_user`.team_id").
8282- Where("`team_repo`.repo_id = ? AND (`team_unit`.access_mode >= ? OR (`team_unit`.access_mode = ? AND `team_unit`.`type` = ?))",
8383- repo.ID, perm.AccessModeWrite, perm.AccessModeRead, unit.TypePullRequests).
8484- Distinct("`team_user`.uid").
8585- Select("`team_user`.uid").
8686- Find(&additionalUserIDs); err != nil {
8787- return nil, err
8888- }
8989-9078 uniqueUserIDs := make(container.Set[int64])
9179 uniqueUserIDs.AddMultiple(userIDs...)
9292- uniqueUserIDs.AddMultiple(additionalUserIDs...)
8080+8181+ if repo.Owner.IsOrganization() {
8282+ additionalUserIDs := make([]int64, 0, 10)
8383+ if err = e.Table("team_user").
8484+ Join("INNER", "team_repo", "`team_repo`.team_id = `team_user`.team_id").
8585+ Join("INNER", "team_unit", "`team_unit`.team_id = `team_user`.team_id").
8686+ Where("`team_repo`.repo_id = ? AND (`team_unit`.access_mode >= ? OR (`team_unit`.access_mode = ? AND `team_unit`.`type` = ?))",
8787+ repo.ID, perm.AccessModeWrite, perm.AccessModeRead, unit.TypePullRequests).
8888+ Distinct("`team_user`.uid").
8989+ Select("`team_user`.uid").
9090+ Find(&additionalUserIDs); err != nil {
9191+ return nil, err
9292+ }
9393+ uniqueUserIDs.AddMultiple(additionalUserIDs...)
9494+ }
93959496 // Leave a seat for owner itself to append later, but if owner is an organization
9597 // and just waste 1 unit is cheaper than re-allocate memory once.
9698 users := make([]*user_model.User, 0, len(uniqueUserIDs)+1)
9797- if len(userIDs) > 0 {
9999+ if len(uniqueUserIDs) > 0 {
98100 if err = e.In("id", uniqueUserIDs.Values()).
99101 Where(builder.Eq{"`user`.is_active": true}).
100102 OrderBy(user_model.GetOrderByName()).
+1
release-notes/5988.md
···11+fix: [commit](https://codeberg.org/forgejo/forgejo/commit/fc26becba4b08877a726f2e7e453992310245fe5) when a tag was removed and a release existed for that tag, it would be broken. The release is no longer broken the tag can be added again.
···55package integration
6677import (
88+ "fmt"
89 "net/http"
910 "net/url"
1011 "strings"
1112 "testing"
12131314 "code.gitea.io/gitea/models"
1515+ auth_model "code.gitea.io/gitea/models/auth"
1416 repo_model "code.gitea.io/gitea/models/repo"
1517 "code.gitea.io/gitea/models/unittest"
1618 user_model "code.gitea.io/gitea/models/user"
1719 "code.gitea.io/gitea/modules/git"
1820 repo_module "code.gitea.io/gitea/modules/repository"
2121+ api "code.gitea.io/gitea/modules/structs"
1922 "code.gitea.io/gitea/services/release"
2023 "code.gitea.io/gitea/tests"
2124···159162 })
160163 })
161164}
165165+166166+func TestRepushTag(t *testing.T) {
167167+ onGiteaRun(t, func(t *testing.T, u *url.URL) {
168168+ repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
169169+ owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID})
170170+ session := loginUser(t, owner.LowerName)
171171+ token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository)
172172+173173+ httpContext := NewAPITestContext(t, owner.Name, repo.Name)
174174+175175+ dstPath := t.TempDir()
176176+177177+ u.Path = httpContext.GitPath()
178178+ u.User = url.UserPassword(owner.Name, userPassword)
179179+180180+ doGitClone(dstPath, u)(t)
181181+182182+ // create and push a tag
183183+ _, _, err := git.NewCommand(git.DefaultContext, "tag", "v2.0").RunStdString(&git.RunOpts{Dir: dstPath})
184184+ require.NoError(t, err)
185185+ _, _, err = git.NewCommand(git.DefaultContext, "push", "origin", "--tags", "v2.0").RunStdString(&git.RunOpts{Dir: dstPath})
186186+ require.NoError(t, err)
187187+ // create a release for the tag
188188+ createdRelease := createNewReleaseUsingAPI(t, token, owner, repo, "v2.0", "", "Release of v2.0", "desc")
189189+ assert.False(t, createdRelease.IsDraft)
190190+ // delete the tag
191191+ _, _, err = git.NewCommand(git.DefaultContext, "push", "origin", "--delete", "v2.0").RunStdString(&git.RunOpts{Dir: dstPath})
192192+ require.NoError(t, err)
193193+ // query the release by API and it should be a draft
194194+ req := NewRequest(t, "GET", fmt.Sprintf("/api/v1/repos/%s/%s/releases/tags/%s", owner.Name, repo.Name, "v2.0"))
195195+ resp := MakeRequest(t, req, http.StatusOK)
196196+ var respRelease *api.Release
197197+ DecodeJSON(t, resp, &respRelease)
198198+ assert.True(t, respRelease.IsDraft)
199199+ // re-push the tag
200200+ _, _, err = git.NewCommand(git.DefaultContext, "push", "origin", "--tags", "v2.0").RunStdString(&git.RunOpts{Dir: dstPath})
201201+ require.NoError(t, err)
202202+ // query the release by API and it should not be a draft
203203+ req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/repos/%s/%s/releases/tags/%s", owner.Name, repo.Name, "v2.0"))
204204+ resp = MakeRequest(t, req, http.StatusOK)
205205+ DecodeJSON(t, resp, &respRelease)
206206+ assert.False(t, respRelease.IsDraft)
207207+ })
208208+}
+12-1
web_src/js/markup/mermaid.js
···5656 btn.setAttribute('data-clipboard-text', source);
5757 mermaidBlock.append(btn);
58585959+ const updateIframeHeight = () => {
6060+ iframe.style.height = `${iframe.contentWindow.document.body.clientHeight}px`;
6161+ };
6262+6363+ // update height when element's visibility state changes, for example when the diagram is inside
6464+ // a <details> + <summary> block and the <details> block becomes visible upon user interaction, it
6565+ // would initially set a incorrect height and the correct height is set during this callback.
6666+ (new IntersectionObserver(() => {
6767+ updateIframeHeight();
6868+ }, {root: document.documentElement})).observe(iframe);
6969+5970 iframe.addEventListener('load', () => {
6071 pre.replaceWith(mermaidBlock);
6172 mermaidBlock.classList.remove('tw-hidden');
6262- iframe.style.height = `${iframe.contentWindow.document.body.clientHeight}px`;
7373+ updateIframeHeight();
6374 setTimeout(() => { // avoid flash of iframe background
6475 mermaidBlock.classList.remove('is-loading');
6576 iframe.classList.remove('tw-invisible');