Skip to content

Commit f3a702b

Browse files
committed
fix
1 parent c706b3e commit f3a702b

File tree

5 files changed

+85
-1
lines changed

5 files changed

+85
-1
lines changed

models/git/branch.go

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,12 @@ import (
1313
user_model "code.gitea.io/gitea/models/user"
1414
"code.gitea.io/gitea/modules/git"
1515
"code.gitea.io/gitea/modules/log"
16+
"code.gitea.io/gitea/modules/setting"
1617
"code.gitea.io/gitea/modules/timeutil"
1718
"code.gitea.io/gitea/modules/util"
1819

1920
"xorm.io/builder"
21+
"xorm.io/xorm/schemas"
2022
)
2123

2224
// ErrBranchNotExist represents an error that branch with such name does not exist.
@@ -103,7 +105,7 @@ func (err ErrBranchesEqual) Unwrap() error {
103105
type Branch struct {
104106
ID int64
105107
RepoID int64 `xorm:"UNIQUE(s)"`
106-
Name string `xorm:"UNIQUE(s) NOT NULL"` // git's ref-name is case-sensitive internally, however, in some databases (mssql, mysql, by default), it's case-insensitive at the moment
108+
Name string `xorm:"UNIQUE(s) NOT NULL"`
107109
CommitID string
108110
CommitMessage string `xorm:"TEXT"` // it only stores the message summary (the first line)
109111
PusherID int64
@@ -117,6 +119,20 @@ type Branch struct {
117119
UpdatedUnix timeutil.TimeStamp `xorm:"updated"`
118120
}
119121

122+
// TableCollations is to make the "name" column case-sensitve for MySQL/MSSQL
123+
func (b *Branch) TableCollations() []*schemas.Collation {
124+
if setting.Database.Type.IsMySQL() {
125+
return []*schemas.Collation{
126+
{Column: "name", Name: "utf8mb4_bin"},
127+
}
128+
} else if setting.Database.Type.IsMSSQL() {
129+
return []*schemas.Collation{
130+
{Column: "name", Name: "Latin1_General_CS_AS"},
131+
}
132+
}
133+
return nil
134+
}
135+
120136
func (b *Branch) LoadDeletedBy(ctx context.Context) (err error) {
121137
if b.DeletedBy == nil {
122138
b.DeletedBy, err = user_model.GetUserByID(ctx, b.DeletedByID)

models/migrations/migrations.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -552,6 +552,8 @@ var migrations = []Migration{
552552
NewMigration("Add Index to pull_auto_merge.doer_id", v1_22.AddIndexToPullAutoMergeDoerID),
553553
// v283 -> v284
554554
NewMigration("Add combined Index to issue_user.uid and issue_id", v1_22.AddCombinedIndexToIssueUser),
555+
// v284 -> v285
556+
NewMigration("Alter branch name collation to be case-sensitvie", v1_22.AlterBranchNameCollation),
555557
}
556558

557559
// GetCurrentDBVersion returns the current db version

models/migrations/v1_22/v284.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
// Copyright 2023 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
package v1_22 //nolint
5+
6+
import (
7+
"code.gitea.io/gitea/modules/log"
8+
"code.gitea.io/gitea/modules/setting"
9+
10+
"xorm.io/xorm"
11+
)
12+
13+
func AlterBranchNameCollation(x *xorm.Engine) error {
14+
if setting.Database.Type.IsMySQL() {
15+
_, err := x.Exec("ALTER TABLE branch MODIFY COLUMN `name` VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin NOT NULL")
16+
return err
17+
} else if setting.Database.Type.IsMSSQL() {
18+
if _, err := x.Exec("DROP INDEX UQE_branch_s ON branch"); err != nil {
19+
log.Error("Failed to drop index UQE_branch_s on branch: %v", err) // ignore this error, in case the index has been dropped in previous migration
20+
}
21+
if _, err := x.Exec("ALTER TABLE branch ALTER COLUMN [name] nvarchar(255) COLLATE Latin1_General_CS_AS NOT NULL"); err != nil {
22+
return err
23+
}
24+
if _, err := x.Exec("CREATE UNIQUE NONCLUSTERED INDEX UQE_branch_s ON branch (repo_id ASC, [name] ASC)"); err != nil {
25+
return err
26+
}
27+
}
28+
return nil
29+
}

models/migrations/v1_22/v284_test.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// Copyright 2023 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
package v1_22 //nolint
5+
6+
import (
7+
"testing"
8+
9+
"code.gitea.io/gitea/models/migrations/base"
10+
11+
"github.com/stretchr/testify/assert"
12+
)
13+
14+
func TestAlterBranchNameCollation(t *testing.T) {
15+
type Branch struct {
16+
ID int64
17+
RepoID int64 `xorm:"UNIQUE(s)"`
18+
Name string `xorm:"UNIQUE(s) NOT NULL"`
19+
}
20+
21+
x, deferable := base.PrepareTestEnv(t, 0, new(Branch))
22+
defer deferable()
23+
24+
assert.NoError(t, AlterBranchNameCollation(x))
25+
}

tests/integration/api_branch_test.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,18 @@ func testAPICreateBranches(t *testing.T, giteaURL *url.URL) {
142142
NewBranch: "branch_2",
143143
ExpectedHTTPStatus: http.StatusCreated,
144144
},
145+
// Trying to create a case-sensive branch name
146+
{
147+
OldBranch: "new_branch_from_master_1",
148+
NewBranch: "Branch_2",
149+
ExpectedHTTPStatus: http.StatusCreated,
150+
},
151+
// Trying to create a branch with UTF8
152+
{
153+
OldBranch: "master",
154+
NewBranch: "test-👀",
155+
ExpectedHTTPStatus: http.StatusCreated,
156+
},
145157
// Trying to create from a branch which does not exist
146158
{
147159
OldBranch: "does_not_exist",

0 commit comments

Comments
 (0)