Skip to content

Commit a17d5f9

Browse files
committed
Merge remote-tracking branch 'giteaofficial/main'
* giteaofficial/main: [skip ci] Updated translations via Crowdin Add option to disable ambiguous unicode characters detection (go-gitea#28454) Adjust object format interface (go-gitea#28469) Remove duplicate option in admin screen and now-unused translation keys (go-gitea#28492) [skip ci] Updated translations via Crowdin Initalize stroage for orphaned repository doctor (go-gitea#28487)
2 parents af8dff4 + 69f2b69 commit a17d5f9

Some content is hidden

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

74 files changed

+331
-360
lines changed

custom/conf/app.example.ini

+3
Original file line numberDiff line numberDiff line change
@@ -1212,6 +1212,9 @@ LEVEL = Info
12121212
;; Max size of files to be displayed (default is 8MiB)
12131213
;MAX_DISPLAY_FILE_SIZE = 8388608
12141214
;;
1215+
;; Detect ambiguous unicode characters in file contents and show warnings on the UI
1216+
;AMBIGUOUS_UNICODE_DETECTION = true
1217+
;;
12151218
;; Whether the email of the user should be shown in the Explore Users page
12161219
;SHOW_USER_EMAIL = true
12171220
;;

docs/content/administration/config-cheat-sheet.en-us.md

+1
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,7 @@ The following configuration set `Content-Type: application/vnd.android.package-a
220220
- `THEMES`: **gitea-auto,gitea-light,gitea-dark**: All available themes. Allow users select personalized themes.
221221
regardless of the value of `DEFAULT_THEME`.
222222
- `MAX_DISPLAY_FILE_SIZE`: **8388608**: Max size of files to be displayed (default is 8MiB)
223+
- `AMBIGUOUS_UNICODE_DETECTION`: **true**: Detect ambiguous unicode characters in file contents and show warnings on the UI
223224
- `REACTIONS`: All available reactions users can choose on issues/prs and comments
224225
Values can be emoji alias (:smile:) or a unicode emoji.
225226
For custom reactions, add a tightly cropped square image to public/assets/img/emoji/reaction_name.png

models/git/branch_test.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
func TestAddDeletedBranch(t *testing.T) {
2121
assert.NoError(t, unittest.PrepareTestDatabase())
2222
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
23+
assert.EqualValues(t, git.Sha1ObjectFormat.Name(), repo.ObjectFormatName)
2324
firstBranch := unittest.AssertExistsAndLoadBean(t, &git_model.Branch{ID: 1})
2425

2526
assert.True(t, firstBranch.IsDeleted)
@@ -29,8 +30,9 @@ func TestAddDeletedBranch(t *testing.T) {
2930
secondBranch := unittest.AssertExistsAndLoadBean(t, &git_model.Branch{RepoID: repo.ID, Name: "branch2"})
3031
assert.True(t, secondBranch.IsDeleted)
3132

33+
objectFormat := git.ObjectFormatFromName(repo.ObjectFormatName)
3234
commit := &git.Commit{
33-
ID: repo.ObjectFormat.MustIDFromString(secondBranch.CommitID),
35+
ID: objectFormat.MustIDFromString(secondBranch.CommitID),
3436
CommitMessage: secondBranch.CommitMessage,
3537
Committer: &git.Signature{
3638
When: secondBranch.CommitTime.AsLocalTime(),

models/repo/repo.go

+4-2
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ type Repository struct {
180180
IsFsckEnabled bool `xorm:"NOT NULL DEFAULT true"`
181181
CloseIssuesViaCommitInAnyBranch bool `xorm:"NOT NULL DEFAULT false"`
182182
Topics []string `xorm:"TEXT JSON"`
183-
ObjectFormat git.ObjectFormat `xorm:"-"`
183+
ObjectFormatName string `xorm:"-"`
184184

185185
TrustModel TrustModelType
186186

@@ -277,7 +277,9 @@ func (repo *Repository) AfterLoad() {
277277
repo.NumOpenProjects = repo.NumProjects - repo.NumClosedProjects
278278
repo.NumOpenActionRuns = repo.NumActionRuns - repo.NumClosedActionRuns
279279

280-
repo.ObjectFormat = git.ObjectFormatFromID(git.Sha1)
280+
// this is a temporary behaviour to support old repos, next step is to store the object format in the database
281+
// and read from database so this line could be removed. To not depend on git module, we use a constant variable here
282+
repo.ObjectFormatName = "sha1"
281283
}
282284

283285
// LoadAttributes loads attributes of the repository.

modules/charset/escape.go

+10-49
Original file line numberDiff line numberDiff line change
@@ -8,32 +8,31 @@
88
package charset
99

1010
import (
11-
"bufio"
11+
"html/template"
1212
"io"
1313
"strings"
1414

1515
"code.gitea.io/gitea/modules/log"
16+
"code.gitea.io/gitea/modules/setting"
1617
"code.gitea.io/gitea/modules/translation"
1718
)
1819

1920
// RuneNBSP is the codepoint for NBSP
2021
const RuneNBSP = 0xa0
2122

2223
// EscapeControlHTML escapes the unicode control sequences in a provided html document
23-
func EscapeControlHTML(text string, locale translation.Locale, allowed ...rune) (escaped *EscapeStatus, output string) {
24+
func EscapeControlHTML(html template.HTML, locale translation.Locale, allowed ...rune) (escaped *EscapeStatus, output template.HTML) {
2425
sb := &strings.Builder{}
25-
outputStream := &HTMLStreamerWriter{Writer: sb}
26-
streamer := NewEscapeStreamer(locale, outputStream, allowed...).(*escapeStreamer)
27-
28-
if err := StreamHTML(strings.NewReader(text), streamer); err != nil {
29-
streamer.escaped.HasError = true
30-
log.Error("Error whilst escaping: %v", err)
31-
}
32-
return streamer.escaped, sb.String()
26+
escaped, _ = EscapeControlReader(strings.NewReader(string(html)), sb, locale, allowed...) // err has been handled in EscapeControlReader
27+
return escaped, template.HTML(sb.String())
3328
}
3429

35-
// EscapeControlReaders escapes the unicode control sequences in a provided reader of HTML content and writer in a locale and returns the findings as an EscapeStatus and the escaped []byte
30+
// EscapeControlReader escapes the unicode control sequences in a provided reader of HTML content and writer in a locale and returns the findings as an EscapeStatus
3631
func EscapeControlReader(reader io.Reader, writer io.Writer, locale translation.Locale, allowed ...rune) (escaped *EscapeStatus, err error) {
32+
if !setting.UI.AmbiguousUnicodeDetection {
33+
_, err = io.Copy(writer, reader)
34+
return &EscapeStatus{}, err
35+
}
3736
outputStream := &HTMLStreamerWriter{Writer: writer}
3837
streamer := NewEscapeStreamer(locale, outputStream, allowed...).(*escapeStreamer)
3938

@@ -43,41 +42,3 @@ func EscapeControlReader(reader io.Reader, writer io.Writer, locale translation.
4342
}
4443
return streamer.escaped, err
4544
}
46-
47-
// EscapeControlStringReader escapes the unicode control sequences in a provided reader of string content and writer in a locale and returns the findings as an EscapeStatus and the escaped []byte. HTML line breaks are not inserted after every newline by this method.
48-
func EscapeControlStringReader(reader io.Reader, writer io.Writer, locale translation.Locale, allowed ...rune) (escaped *EscapeStatus, err error) {
49-
bufRd := bufio.NewReader(reader)
50-
outputStream := &HTMLStreamerWriter{Writer: writer}
51-
streamer := NewEscapeStreamer(locale, outputStream, allowed...).(*escapeStreamer)
52-
53-
for {
54-
line, rdErr := bufRd.ReadString('\n')
55-
if len(line) > 0 {
56-
if err := streamer.Text(line); err != nil {
57-
streamer.escaped.HasError = true
58-
log.Error("Error whilst escaping: %v", err)
59-
return streamer.escaped, err
60-
}
61-
}
62-
if rdErr != nil {
63-
if rdErr != io.EOF {
64-
err = rdErr
65-
}
66-
break
67-
}
68-
}
69-
return streamer.escaped, err
70-
}
71-
72-
// EscapeControlString escapes the unicode control sequences in a provided string and returns the findings as an EscapeStatus and the escaped string
73-
func EscapeControlString(text string, locale translation.Locale, allowed ...rune) (escaped *EscapeStatus, output string) {
74-
sb := &strings.Builder{}
75-
outputStream := &HTMLStreamerWriter{Writer: sb}
76-
streamer := NewEscapeStreamer(locale, outputStream, allowed...).(*escapeStreamer)
77-
78-
if err := streamer.Text(text); err != nil {
79-
streamer.escaped.HasError = true
80-
log.Error("Error whilst escaping: %v", err)
81-
}
82-
return streamer.escaped, sb.String()
83-
}

modules/charset/escape_stream.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ func (e *escapeStreamer) Text(data string) error {
6464
until, next = nextIdxs[0]+pos, nextIdxs[1]+pos
6565
}
6666

67-
// from pos until until we know that the runes are not \r\t\n or even ' '
67+
// from pos until we know that the runes are not \r\t\n or even ' '
6868
runes := make([]rune, 0, next-until)
6969
positions := make([]int, 0, next-until+1)
7070

modules/charset/escape_test.go

+16-36
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,14 @@
44
package charset
55

66
import (
7-
"reflect"
87
"strings"
98
"testing"
109

10+
"code.gitea.io/gitea/modules/setting"
11+
"code.gitea.io/gitea/modules/test"
1112
"code.gitea.io/gitea/modules/translation"
13+
14+
"github.com/stretchr/testify/assert"
1215
)
1316

1417
type escapeControlTest struct {
@@ -132,22 +135,8 @@ then resh (ר), and finally heh (ה) (which should appear leftmost).`,
132135
},
133136
}
134137

135-
func TestEscapeControlString(t *testing.T) {
136-
for _, tt := range escapeControlTests {
137-
t.Run(tt.name, func(t *testing.T) {
138-
status, result := EscapeControlString(tt.text, &translation.MockLocale{})
139-
if !reflect.DeepEqual(*status, tt.status) {
140-
t.Errorf("EscapeControlString() status = %v, wanted= %v", status, tt.status)
141-
}
142-
if result != tt.result {
143-
t.Errorf("EscapeControlString()\nresult= %v,\nwanted= %v", result, tt.result)
144-
}
145-
})
146-
}
147-
}
148-
149138
func TestEscapeControlReader(t *testing.T) {
150-
// lets add some control characters to the tests
139+
// add some control characters to the tests
151140
tests := make([]escapeControlTest, 0, len(escapeControlTests)*3)
152141
copy(tests, escapeControlTests)
153142

@@ -169,29 +158,20 @@ func TestEscapeControlReader(t *testing.T) {
169158

170159
for _, tt := range tests {
171160
t.Run(tt.name, func(t *testing.T) {
172-
input := strings.NewReader(tt.text)
173161
output := &strings.Builder{}
174-
status, err := EscapeControlReader(input, output, &translation.MockLocale{})
175-
result := output.String()
176-
if err != nil {
177-
t.Errorf("EscapeControlReader(): err = %v", err)
178-
}
179-
180-
if !reflect.DeepEqual(*status, tt.status) {
181-
t.Errorf("EscapeControlReader() status = %v, wanted= %v", status, tt.status)
182-
}
183-
if result != tt.result {
184-
t.Errorf("EscapeControlReader()\nresult= %v,\nwanted= %v", result, tt.result)
185-
}
162+
status, err := EscapeControlReader(strings.NewReader(tt.text), output, &translation.MockLocale{})
163+
assert.NoError(t, err)
164+
assert.Equal(t, tt.status, *status)
165+
assert.Equal(t, tt.result, output.String())
186166
})
187167
}
188168
}
189169

190-
func TestEscapeControlReader_panic(t *testing.T) {
191-
bs := make([]byte, 0, 20479)
192-
bs = append(bs, 'A')
193-
for i := 0; i < 6826; i++ {
194-
bs = append(bs, []byte("—")...)
195-
}
196-
_, _ = EscapeControlString(string(bs), &translation.MockLocale{})
170+
func TestSettingAmbiguousUnicodeDetection(t *testing.T) {
171+
defer test.MockVariableValue(&setting.UI.AmbiguousUnicodeDetection, true)()
172+
_, out := EscapeControlHTML("a test", &translation.MockLocale{})
173+
assert.EqualValues(t, `a<span class="escaped-code-point" data-escaped="[U+00A0]"><span class="char"> </span></span>test`, out)
174+
setting.UI.AmbiguousUnicodeDetection = false
175+
_, out = EscapeControlHTML("a test", &translation.MockLocale{})
176+
assert.EqualValues(t, `a test`, out)
197177
}

modules/doctor/repository.go

+5
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"code.gitea.io/gitea/models/db"
1010
user_model "code.gitea.io/gitea/models/user"
1111
"code.gitea.io/gitea/modules/log"
12+
"code.gitea.io/gitea/modules/storage"
1213
repo_service "code.gitea.io/gitea/services/repository"
1314

1415
"xorm.io/builder"
@@ -31,6 +32,10 @@ func countOrphanedRepos(ctx context.Context) (int64, error) {
3132

3233
// deleteOrphanedRepos delete repository where user of owner_id do not exist
3334
func deleteOrphanedRepos(ctx context.Context) (int64, error) {
35+
if err := storage.Init(); err != nil {
36+
return 0, err
37+
}
38+
3439
batchSize := db.MaxBatchInsertSize("repository")
3540
e := db.GetEngine(ctx)
3641
var deleted int64

modules/git/blame_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ func TestReadingBlameOutput(t *testing.T) {
3939
}
4040

4141
for _, bypass := range []bool{false, true} {
42-
blameReader, err := CreateBlameReader(ctx, &Sha1ObjectFormat{}, "./tests/repos/repo5_pulls", commit, "README.md", bypass)
42+
blameReader, err := CreateBlameReader(ctx, Sha1ObjectFormat, "./tests/repos/repo5_pulls", commit, "README.md", bypass)
4343
assert.NoError(t, err)
4444
assert.NotNil(t, blameReader)
4545
defer blameReader.Close()

modules/git/command.go

+3-8
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ import (
1414
"os/exec"
1515
"strings"
1616
"time"
17-
"unsafe"
1817

1918
"code.gitea.io/gitea/modules/git/internal" //nolint:depguard // only this file can use the internal type CmdArg, other files and packages should use AddXxx functions
2019
"code.gitea.io/gitea/modules/log"
@@ -389,15 +388,11 @@ func (r *runStdError) IsExitCode(code int) bool {
389388
return false
390389
}
391390

392-
func bytesToString(b []byte) string {
393-
return *(*string)(unsafe.Pointer(&b)) // that's what Golang's strings.Builder.String() does (go/src/strings/builder.go)
394-
}
395-
396391
// RunStdString runs the command with options and returns stdout/stderr as string. and store stderr to returned error (err combined with stderr).
397392
func (c *Command) RunStdString(opts *RunOpts) (stdout, stderr string, runErr RunStdError) {
398393
stdoutBytes, stderrBytes, err := c.RunStdBytes(opts)
399-
stdout = bytesToString(stdoutBytes)
400-
stderr = bytesToString(stderrBytes)
394+
stdout = util.UnsafeBytesToString(stdoutBytes)
395+
stderr = util.UnsafeBytesToString(stderrBytes)
401396
if err != nil {
402397
return stdout, stderr, &runStdError{err: err, stderr: stderr}
403398
}
@@ -432,7 +427,7 @@ func (c *Command) RunStdBytes(opts *RunOpts) (stdout, stderr []byte, runErr RunS
432427
err := c.Run(newOpts)
433428
stderr = stderrBuf.Bytes()
434429
if err != nil {
435-
return nil, stderr, &runStdError{err: err, stderr: bytesToString(stderr)}
430+
return nil, stderr, &runStdError{err: err, stderr: util.UnsafeBytesToString(stderr)}
436431
}
437432
// even if there is no err, there could still be some stderr output
438433
return stdoutBuf.Bytes(), stderr, nil

modules/git/commit.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ func (c *Commit) IsForcePush(oldCommitID string) (bool, error) {
236236
if err != nil {
237237
return false, err
238238
}
239-
if oldCommitID == objectFormat.Empty().String() {
239+
if oldCommitID == objectFormat.EmptyObjectID().String() {
240240
return false, nil
241241
}
242242

0 commit comments

Comments
 (0)