Skip to content

Commit 8e00dc0

Browse files
committed
Merge remote-tracking branch 'giteaofficial/main'
* giteaofficial/main: Fix bug of branch/tag selector in the issue sidebar (go-gitea#32744) Fix lfs migration (go-gitea#32812) Avoid MacOS keychain dialog in integration tests (go-gitea#32813) Update actionlint.yaml Detect whether action view branch was deleted (go-gitea#32764) Add "n commits" link to contributors in contributors graph page (go-gitea#32799) Fix "unicode escape" JS error (go-gitea#32806) use dedicated runners for release artifacts (go-gitea#32811) Make API "compare" accept commit IDs (go-gitea#32801) Implement update branch API (go-gitea#32433) Fix JS error when dropping a file to a editor without dropzone (go-gitea#32804) chore: use errors.New to replace fmt.Errorf with no parameters (go-gitea#32800)
2 parents 1b31a2f + 30008fc commit 8e00dc0

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

43 files changed

+499
-169
lines changed

.github/actionlint.yaml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,5 @@ self-hosted-runner:
33
- actuated-4cpu-8gb
44
- actuated-4cpu-16gb
55
- nscloud
6+
- namespace-profile-gitea-release-docker
7+
- namespace-profile-gitea-release-binary

.github/workflows/release-nightly.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ concurrency:
1010

1111
jobs:
1212
nightly-binary:
13-
runs-on: nscloud
13+
runs-on: namespace-profile-gitea-release-binary
1414
steps:
1515
- uses: actions/checkout@v4
1616
# fetch all commits instead of only the last as some branches are long lived and could have many between versions
@@ -58,7 +58,7 @@ jobs:
5858
run: |
5959
aws s3 sync dist/release s3://${{ secrets.AWS_S3_BUCKET }}/gitea/${{ steps.clean_name.outputs.branch }} --no-progress
6060
nightly-docker-rootful:
61-
runs-on: ubuntu-latest
61+
runs-on: namespace-profile-gitea-release-docker
6262
steps:
6363
- uses: actions/checkout@v4
6464
# fetch all commits instead of only the last as some branches are long lived and could have many between versions
@@ -95,7 +95,7 @@ jobs:
9595
push: true
9696
tags: gitea/gitea:${{ steps.clean_name.outputs.branch }}
9797
nightly-docker-rootless:
98-
runs-on: ubuntu-latest
98+
runs-on: namespace-profile-gitea-release-docker
9999
steps:
100100
- uses: actions/checkout@v4
101101
# fetch all commits instead of only the last as some branches are long lived and could have many between versions

.github/workflows/release-tag-rc.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ concurrency:
1111

1212
jobs:
1313
binary:
14-
runs-on: nscloud
14+
runs-on: namespace-profile-gitea-release-binary
1515
steps:
1616
- uses: actions/checkout@v4
1717
# fetch all commits instead of only the last as some branches are long lived and could have many between versions
@@ -68,7 +68,7 @@ jobs:
6868
env:
6969
GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }}
7070
docker-rootful:
71-
runs-on: ubuntu-latest
71+
runs-on: namespace-profile-gitea-release-docker
7272
steps:
7373
- uses: actions/checkout@v4
7474
# fetch all commits instead of only the last as some branches are long lived and could have many between versions
@@ -99,7 +99,7 @@ jobs:
9999
tags: ${{ steps.meta.outputs.tags }}
100100
labels: ${{ steps.meta.outputs.labels }}
101101
docker-rootless:
102-
runs-on: ubuntu-latest
102+
runs-on: namespace-profile-gitea-release-docker
103103
steps:
104104
- uses: actions/checkout@v4
105105
# fetch all commits instead of only the last as some branches are long lived and could have many between versions

.github/workflows/release-tag-version.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ concurrency:
1313

1414
jobs:
1515
binary:
16-
runs-on: nscloud
16+
runs-on: namespace-profile-gitea-release-binary
1717
steps:
1818
- uses: actions/checkout@v4
1919
# fetch all commits instead of only the last as some branches are long lived and could have many between versions
@@ -70,7 +70,7 @@ jobs:
7070
env:
7171
GITHUB_TOKEN: ${{ secrets.RELEASE_TOKEN }}
7272
docker-rootful:
73-
runs-on: ubuntu-latest
73+
runs-on: namespace-profile-gitea-release-docker
7474
steps:
7575
- uses: actions/checkout@v4
7676
# fetch all commits instead of only the last as some branches are long lived and could have many between versions
@@ -105,7 +105,7 @@ jobs:
105105
tags: ${{ steps.meta.outputs.tags }}
106106
labels: ${{ steps.meta.outputs.labels }}
107107
docker-rootless:
108-
runs-on: ubuntu-latest
108+
runs-on: namespace-profile-gitea-release-docker
109109
steps:
110110
- uses: actions/checkout@v4
111111
# fetch all commits instead of only the last as some branches are long lived and could have many between versions

models/actions/run.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ type ActionRun struct {
3737
TriggerUser *user_model.User `xorm:"-"`
3838
ScheduleID int64
3939
Ref string `xorm:"index"` // the commit/tag/… that caused the run
40+
IsRefDeleted bool `xorm:"-"`
4041
CommitSHA string
4142
IsForkPullRequest bool // If this is triggered by a PR from a forked repository or an untrusted user, we need to check if it is approved and limit permissions when running the workflow.
4243
NeedApproval bool // may need approval if it's a fork pull request

models/db/context_committer_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
package db // it's not db_test, because this file is for testing the private type halfCommitter
55

66
import (
7-
"fmt"
7+
"errors"
88
"testing"
99

1010
"github.com/stretchr/testify/assert"
@@ -80,7 +80,7 @@ func Test_halfCommitter(t *testing.T) {
8080
testWithCommitter(mockCommitter, func(committer Committer) error {
8181
defer committer.Close()
8282
if true {
83-
return fmt.Errorf("error")
83+
return errors.New("error")
8484
}
8585
return committer.Commit()
8686
})
@@ -94,7 +94,7 @@ func Test_halfCommitter(t *testing.T) {
9494
testWithCommitter(mockCommitter, func(committer Committer) error {
9595
committer.Close()
9696
committer.Commit()
97-
return fmt.Errorf("error")
97+
return errors.New("error")
9898
})
9999

100100
mockCommitter.Assert(t)

models/git/branch.go

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
repo_model "code.gitea.io/gitea/models/repo"
1313
"code.gitea.io/gitea/models/unit"
1414
user_model "code.gitea.io/gitea/models/user"
15+
"code.gitea.io/gitea/modules/container"
1516
"code.gitea.io/gitea/modules/git"
1617
"code.gitea.io/gitea/modules/log"
1718
"code.gitea.io/gitea/modules/optional"
@@ -169,9 +170,22 @@ func GetBranch(ctx context.Context, repoID int64, branchName string) (*Branch, e
169170
return &branch, nil
170171
}
171172

172-
func GetBranches(ctx context.Context, repoID int64, branchNames []string) ([]*Branch, error) {
173+
func GetBranches(ctx context.Context, repoID int64, branchNames []string, includeDeleted bool) ([]*Branch, error) {
173174
branches := make([]*Branch, 0, len(branchNames))
174-
return branches, db.GetEngine(ctx).Where("repo_id=?", repoID).In("name", branchNames).Find(&branches)
175+
176+
sess := db.GetEngine(ctx).Where("repo_id=?", repoID).In("name", branchNames)
177+
if !includeDeleted {
178+
sess.And("is_deleted=?", false)
179+
}
180+
return branches, sess.Find(&branches)
181+
}
182+
183+
func BranchesToNamesSet(branches []*Branch) container.Set[string] {
184+
names := make(container.Set[string], len(branches))
185+
for _, branch := range branches {
186+
names.Add(branch.Name)
187+
}
188+
return names
175189
}
176190

177191
func AddBranches(ctx context.Context, branches []*Branch) error {

models/issues/issue.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,8 +125,11 @@ type Issue struct {
125125
IsPull bool `xorm:"INDEX"` // Indicates whether is a pull request or not.
126126
PullRequest *PullRequest `xorm:"-"`
127127
NumComments int
128-
Ref string
129-
PinOrder int `xorm:"DEFAULT 0"`
128+
129+
// TODO: RemoveIssueRef: see "repo/issue/branch_selector_field.tmpl"
130+
Ref string
131+
132+
PinOrder int `xorm:"DEFAULT 0"`
130133

131134
DeadlineUnix timeutil.TimeStamp `xorm:"INDEX"`
132135

modules/git/commit.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -474,3 +474,17 @@ func (c *Commit) GetRepositoryDefaultPublicGPGKey(forceUpdate bool) (*GPGSetting
474474
}
475475
return c.repo.GetDefaultPublicGPGKey(forceUpdate)
476476
}
477+
478+
func IsStringLikelyCommitID(objFmt ObjectFormat, s string, minLength ...int) bool {
479+
minLen := util.OptionalArg(minLength, objFmt.FullLength())
480+
if len(s) < minLen || len(s) > objFmt.FullLength() {
481+
return false
482+
}
483+
for _, c := range s {
484+
isHex := (c >= '0' && c <= '9') || (c >= 'a' && c <= 'f')
485+
if !isHex {
486+
return false
487+
}
488+
}
489+
return true
490+
}

modules/git/ref.go

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,6 @@ func (ref RefName) RemoteName() string {
142142

143143
// ShortName returns the short name of the reference name
144144
func (ref RefName) ShortName() string {
145-
refName := string(ref)
146145
if ref.IsBranch() {
147146
return ref.BranchName()
148147
}
@@ -158,8 +157,7 @@ func (ref RefName) ShortName() string {
158157
if ref.IsFor() {
159158
return ref.ForBranchName()
160159
}
161-
162-
return refName
160+
return string(ref) // usually it is a commit ID
163161
}
164162

165163
// RefGroup returns the group type of the reference

modules/git/repo_ref.go

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,3 +61,31 @@ func parseTags(refs []string) []string {
6161
}
6262
return results
6363
}
64+
65+
// UnstableGuessRefByShortName does the best guess to see whether a "short name" provided by user is a branch, tag or commit.
66+
// It could guess wrongly if the input is already ambiguous. For example:
67+
// * "refs/heads/the-name" vs "refs/heads/refs/heads/the-name"
68+
// * "refs/tags/1234567890" vs commit "1234567890"
69+
// In most cases, it SHOULD AVOID using this function, unless there is an irresistible reason (eg: make API friendly to end users)
70+
// If the function is used, the caller SHOULD CHECK the ref type carefully.
71+
func (repo *Repository) UnstableGuessRefByShortName(shortName string) RefName {
72+
if repo.IsBranchExist(shortName) {
73+
return RefNameFromBranch(shortName)
74+
}
75+
if repo.IsTagExist(shortName) {
76+
return RefNameFromTag(shortName)
77+
}
78+
if strings.HasPrefix(shortName, "refs/") {
79+
if repo.IsReferenceExist(shortName) {
80+
return RefName(shortName)
81+
}
82+
}
83+
commit, err := repo.GetCommit(shortName)
84+
if err == nil {
85+
commitIDString := commit.ID.String()
86+
if strings.HasPrefix(commitIDString, shortName) {
87+
return RefName(commitIDString)
88+
}
89+
}
90+
return ""
91+
}

modules/globallock/globallock_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ func TestLockAndDo(t *testing.T) {
6464
}
6565

6666
func testLockAndDo(t *testing.T) {
67-
const concurrency = 1000
67+
const concurrency = 50
6868

6969
ctx := context.Background()
7070
count := 0

modules/lfs/http_client.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,7 @@ func createRequest(ctx context.Context, method, url string, headers map[string]s
236236
req.Header.Set(key, value)
237237
}
238238
req.Header.Set("Accept", AcceptHeader)
239+
req.Header.Set("User-Agent", UserAgentHeader)
239240

240241
return req, nil
241242
}

modules/lfs/shared.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ const (
1515
// MediaType contains the media type for LFS server requests
1616
MediaType = "application/vnd.git-lfs+json"
1717
// Some LFS servers offer content with other types, so fallback to '*/*' if application/vnd.git-lfs+json cannot be served
18-
AcceptHeader = "application/vnd.git-lfs+json;q=0.9, */*;q=0.8"
18+
AcceptHeader = "application/vnd.git-lfs+json;q=0.9, */*;q=0.8"
19+
UserAgentHeader = "git-lfs"
1920
)
2021

2122
// BatchRequest contains multiple requests processed in one batch operation.

modules/structs/repo.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -278,6 +278,16 @@ type CreateBranchRepoOption struct {
278278
OldRefName string `json:"old_ref_name" binding:"GitRefName;MaxSize(100)"`
279279
}
280280

281+
// UpdateBranchRepoOption options when updating a branch in a repository
282+
// swagger:model
283+
type UpdateBranchRepoOption struct {
284+
// New branch name
285+
//
286+
// required: true
287+
// unique: true
288+
Name string `json:"name" binding:"Required;GitRefName;MaxSize(100)"`
289+
}
290+
281291
// TransferRepoOption options when transfer a repository's ownership
282292
// swagger:model
283293
type TransferRepoOption struct {

routers/api/v1/api.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1195,6 +1195,7 @@ func Routes() *web.Router {
11951195
m.Get("/*", repo.GetBranch)
11961196
m.Delete("/*", reqToken(), reqRepoWriter(unit.TypeCode), mustNotBeArchived, repo.DeleteBranch)
11971197
m.Post("", reqToken(), reqRepoWriter(unit.TypeCode), mustNotBeArchived, bind(api.CreateBranchRepoOption{}), repo.CreateBranch)
1198+
m.Patch("/*", reqToken(), reqRepoWriter(unit.TypeCode), mustNotBeArchived, bind(api.UpdateBranchRepoOption{}), repo.UpdateBranch)
11981199
}, context.ReferencesGitRepo(), reqRepoReader(unit.TypeCode))
11991200
m.Group("/branch_protections", func() {
12001201
m.Get("", repo.ListBranchProtections)

routers/api/v1/repo/branch.go

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,77 @@ func ListBranches(ctx *context.APIContext) {
386386
ctx.JSON(http.StatusOK, apiBranches)
387387
}
388388

389+
// UpdateBranch updates a repository's branch.
390+
func UpdateBranch(ctx *context.APIContext) {
391+
// swagger:operation PATCH /repos/{owner}/{repo}/branches/{branch} repository repoUpdateBranch
392+
// ---
393+
// summary: Update a branch
394+
// consumes:
395+
// - application/json
396+
// produces:
397+
// - application/json
398+
// parameters:
399+
// - name: owner
400+
// in: path
401+
// description: owner of the repo
402+
// type: string
403+
// required: true
404+
// - name: repo
405+
// in: path
406+
// description: name of the repo
407+
// type: string
408+
// required: true
409+
// - name: branch
410+
// in: path
411+
// description: name of the branch
412+
// type: string
413+
// required: true
414+
// - name: body
415+
// in: body
416+
// schema:
417+
// "$ref": "#/definitions/UpdateBranchRepoOption"
418+
// responses:
419+
// "204":
420+
// "$ref": "#/responses/empty"
421+
// "403":
422+
// "$ref": "#/responses/forbidden"
423+
// "404":
424+
// "$ref": "#/responses/notFound"
425+
// "422":
426+
// "$ref": "#/responses/validationError"
427+
428+
opt := web.GetForm(ctx).(*api.UpdateBranchRepoOption)
429+
430+
oldName := ctx.PathParam("*")
431+
repo := ctx.Repo.Repository
432+
433+
if repo.IsEmpty {
434+
ctx.Error(http.StatusNotFound, "", "Git Repository is empty.")
435+
return
436+
}
437+
438+
if repo.IsMirror {
439+
ctx.Error(http.StatusForbidden, "", "Git Repository is a mirror.")
440+
return
441+
}
442+
443+
msg, err := repo_service.RenameBranch(ctx, repo, ctx.Doer, ctx.Repo.GitRepo, oldName, opt.Name)
444+
if err != nil {
445+
ctx.Error(http.StatusInternalServerError, "RenameBranch", err)
446+
return
447+
}
448+
if msg == "target_exist" {
449+
ctx.Error(http.StatusUnprocessableEntity, "", "Cannot rename a branch using the same name or rename to a branch that already exists.")
450+
return
451+
}
452+
if msg == "from_not_exist" {
453+
ctx.Error(http.StatusNotFound, "", "Branch doesn't exist.")
454+
return
455+
}
456+
457+
ctx.Status(http.StatusNoContent)
458+
}
459+
389460
// GetBranchProtection gets a branch protection
390461
func GetBranchProtection(ctx *context.APIContext) {
391462
// swagger:operation GET /repos/{owner}/{repo}/branch_protections/{name} repository repoGetBranchProtection

0 commit comments

Comments
 (0)