Skip to content

Commit 8874bf5

Browse files
authored
Merge branch 'main' into sync-issue-pr-and-more
2 parents a0303a2 + 599ae09 commit 8874bf5

File tree

20 files changed

+145
-35
lines changed

20 files changed

+145
-35
lines changed

.eslintrc.yaml

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ plugins:
1212
- eslint-plugin-unicorn
1313
- eslint-plugin-import
1414
- eslint-plugin-jquery
15+
- eslint-plugin-sonarjs
1516

1617
env:
1718
es2022: true
@@ -369,6 +370,38 @@ rules:
369370
semi-spacing: [2, {before: false, after: true}]
370371
semi-style: [2, last]
371372
semi: [2, always, {omitLastInOneLineBlock: true}]
373+
sonarjs/cognitive-complexity: [0]
374+
sonarjs/elseif-without-else: [0]
375+
sonarjs/max-switch-cases: [0]
376+
sonarjs/no-all-duplicated-branches: [2]
377+
sonarjs/no-collapsible-if: [0]
378+
sonarjs/no-collection-size-mischeck: [2]
379+
sonarjs/no-duplicate-string: [0]
380+
sonarjs/no-duplicated-branches: [0]
381+
sonarjs/no-element-overwrite: [2]
382+
sonarjs/no-empty-collection: [2]
383+
sonarjs/no-extra-arguments: [0]
384+
sonarjs/no-gratuitous-expressions: [2]
385+
sonarjs/no-identical-conditions: [2]
386+
sonarjs/no-identical-expressions: [0]
387+
sonarjs/no-identical-functions: [0]
388+
sonarjs/no-ignored-return: [2]
389+
sonarjs/no-inverted-boolean-check: [2]
390+
sonarjs/no-nested-switch: [0]
391+
sonarjs/no-nested-template-literals: [0]
392+
sonarjs/no-one-iteration-loop: [2]
393+
sonarjs/no-redundant-boolean: [2]
394+
sonarjs/no-redundant-jump: [0]
395+
sonarjs/no-same-line-conditional: [2]
396+
sonarjs/no-small-switch: [0]
397+
sonarjs/no-unused-collection: [2]
398+
sonarjs/no-use-of-empty-return-value: [2]
399+
sonarjs/no-useless-catch: [0]
400+
sonarjs/non-existent-operator: [2]
401+
sonarjs/prefer-immediate-return: [0]
402+
sonarjs/prefer-object-literal: [0]
403+
sonarjs/prefer-single-boolean-return: [0]
404+
sonarjs/prefer-while: [2]
372405
sort-imports: [0]
373406
sort-keys: [0]
374407
sort-vars: [0]

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ AIR_PACKAGE ?= github.com/cosmtrek/[email protected]
2929
EDITORCONFIG_CHECKER_PACKAGE ?= github.com/editorconfig-checker/editorconfig-checker/cmd/[email protected]
3030
ERRCHECK_PACKAGE ?= github.com/kisielk/[email protected]
3131
GOFUMPT_PACKAGE ?= mvdan.cc/[email protected]
32-
GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/cmd/[email protected].1
32+
GOLANGCI_LINT_PACKAGE ?= github.com/golangci/golangci-lint/cmd/[email protected].0
3333
GXZ_PAGAGE ?= github.com/ulikunitz/xz/cmd/[email protected]
3434
MISSPELL_PACKAGE ?= github.com/client9/misspell/cmd/[email protected]
3535
SWAGGER_PACKAGE ?= github.com/go-swagger/go-swagger/cmd/[email protected]

docs/content/doc/help/faq.en-us.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -403,3 +403,9 @@ gitea doctor recreate-table
403403
```
404404

405405
It is highly recommended to back-up your database before running these commands.
406+
407+
408+
## Why are tabs/indents wrong when viewing files
409+
410+
If you are using Cloudflare, turn off the auto-minify option in the dashboard.
411+
`Speed` -> `Optimization` -> Uncheck `HTML` within the `Auto-Minify` settings.

docs/content/doc/installation/from-package.en-us.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,9 +47,9 @@ pacman -S gitea
4747

4848
There is a [Gitea Snap](https://snapcraft.io/gitea) package which follows the latest stable version.
4949

50-
``sh
50+
```sh
5151
snap install gitea
52-
``
52+
```
5353

5454
## SUSE and openSUSE
5555

integrations/api_repo_raw_test.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import (
1010

1111
"code.gitea.io/gitea/models/unittest"
1212
user_model "code.gitea.io/gitea/models/user"
13+
14+
"github.com/stretchr/testify/assert"
1315
)
1416

1517
func TestAPIReposRaw(t *testing.T) {
@@ -25,9 +27,11 @@ func TestAPIReposRaw(t *testing.T) {
2527
"65f1bf27bc3bf70f64657658635e66094edbcb4d", // Commit
2628
} {
2729
req := NewRequestf(t, "GET", "/api/v1/repos/%s/repo1/raw/%s/README.md?token="+token, user.Name, ref)
28-
session.MakeRequest(t, req, http.StatusOK)
30+
resp := session.MakeRequest(t, req, http.StatusOK)
31+
assert.EqualValues(t, "file", resp.Header().Get("x-gitea-object-type"))
2932
}
3033
// Test default branch
3134
req := NewRequestf(t, "GET", "/api/v1/repos/%s/repo1/raw/README.md?token="+token, user.Name)
32-
session.MakeRequest(t, req, http.StatusOK)
35+
resp := session.MakeRequest(t, req, http.StatusOK)
36+
assert.EqualValues(t, "file", resp.Header().Get("x-gitea-object-type"))
3337
}

models/repo/repo_list.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package repo
66

77
import (
88
"context"
9+
"errors"
910
"fmt"
1011
"strings"
1112

@@ -695,6 +696,9 @@ func GetUserRepositories(opts *SearchRepoOptions) (RepositoryList, int64, error)
695696
}
696697

697698
cond := builder.NewCond()
699+
if opts.Actor == nil {
700+
return nil, 0, errors.New("GetUserRepositories: Actor is needed but not given")
701+
}
698702
cond = cond.And(builder.Eq{"owner_id": opts.Actor.ID})
699703
if !opts.Private {
700704
cond = cond.And(builder.Eq{"is_private": false})

models/user/search.go

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -59,25 +59,18 @@ func (opts *SearchUserOptions) toSearchQueryBase() *xorm.Session {
5959
}
6060

6161
if opts.Actor != nil {
62-
exprCond := builder.Expr("org_user.org_id = `user`.id")
63-
6462
// If Admin - they see all users!
6563
if !opts.Actor.IsAdmin {
66-
// Force visibility for privacy
67-
var accessCond builder.Cond
64+
// Users can see an organization they are a member of
65+
accessCond := builder.In("id", builder.Select("org_id").From("org_user").Where(builder.Eq{"uid": opts.Actor.ID}))
6866
if !opts.Actor.IsRestricted {
69-
accessCond = builder.Or(
70-
builder.In("id", builder.Select("org_id").From("org_user").LeftJoin("`user`", exprCond).Where(builder.And(builder.Eq{"uid": opts.Actor.ID}, builder.Eq{"visibility": structs.VisibleTypePrivate}))),
71-
builder.In("visibility", structs.VisibleTypePublic, structs.VisibleTypeLimited))
72-
} else {
73-
// restricted users only see orgs they are a member of
74-
accessCond = builder.In("id", builder.Select("org_id").From("org_user").LeftJoin("`user`", exprCond).Where(builder.And(builder.Eq{"uid": opts.Actor.ID})))
67+
// Not-Restricted users can see public and limited users/organizations
68+
accessCond = accessCond.Or(builder.In("visibility", structs.VisibleTypePublic, structs.VisibleTypeLimited))
7569
}
7670
// Don't forget about self
7771
accessCond = accessCond.Or(builder.Eq{"id": opts.Actor.ID})
7872
cond = cond.And(accessCond)
7973
}
80-
8174
} else {
8275
// Force visibility for privacy
8376
// Not logged in - only public users

modules/markup/html.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1176,7 +1176,7 @@ func genDefaultLinkProcessor(defaultLink string) processor {
11761176
node.DataAtom = atom.A
11771177
node.Attr = []html.Attribute{
11781178
{Key: "href", Val: defaultLink},
1179-
{Key: "class", Val: "default-link"},
1179+
{Key: "class", Val: "default-link muted"},
11801180
}
11811181
node.FirstChild, node.LastChild = ch, ch
11821182
}

package-lock.json

Lines changed: 20 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
"eslint": "8.20.0",
5151
"eslint-plugin-import": "2.26.0",
5252
"eslint-plugin-jquery": "1.5.1",
53+
"eslint-plugin-sonarjs": "0.13.0",
5354
"eslint-plugin-unicorn": "43.0.2",
5455
"eslint-plugin-vue": "9.2.0",
5556
"jest": "28.1.3",

routers/api/v1/repo/file.go

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,8 @@ import (
3333
files_service "code.gitea.io/gitea/services/repository/files"
3434
)
3535

36+
const giteaObjectTypeHeader = "X-Gitea-Object-Type"
37+
3638
// GetRawFile get a file by path on a repository
3739
func GetRawFile(ctx *context.APIContext) {
3840
// swagger:operation GET /repos/{owner}/{repo}/raw/{filepath} repository repoGetRawFile
@@ -72,11 +74,13 @@ func GetRawFile(ctx *context.APIContext) {
7274
return
7375
}
7476

75-
blob, lastModified := getBlobForEntry(ctx)
77+
blob, entry, lastModified := getBlobForEntry(ctx)
7678
if ctx.Written() {
7779
return
7880
}
7981

82+
ctx.RespHeader().Set(giteaObjectTypeHeader, string(files_service.GetObjectTypeFromTreeEntry(entry)))
83+
8084
if err := common.ServeBlob(ctx.Context, blob, lastModified); err != nil {
8185
ctx.Error(http.StatusInternalServerError, "ServeBlob", err)
8286
}
@@ -119,11 +123,13 @@ func GetRawFileOrLFS(ctx *context.APIContext) {
119123
return
120124
}
121125

122-
blob, lastModified := getBlobForEntry(ctx)
126+
blob, entry, lastModified := getBlobForEntry(ctx)
123127
if ctx.Written() {
124128
return
125129
}
126130

131+
ctx.RespHeader().Set(giteaObjectTypeHeader, string(files_service.GetObjectTypeFromTreeEntry(entry)))
132+
127133
// LFS Pointer files are at most 1024 bytes - so any blob greater than 1024 bytes cannot be an LFS file
128134
if blob.Size() > 1024 {
129135
// First handle caching for the blob
@@ -218,7 +224,7 @@ func GetRawFileOrLFS(ctx *context.APIContext) {
218224
}
219225
}
220226

221-
func getBlobForEntry(ctx *context.APIContext) (blob *git.Blob, lastModified time.Time) {
227+
func getBlobForEntry(ctx *context.APIContext) (blob *git.Blob, entry *git.TreeEntry, lastModified time.Time) {
222228
entry, err := ctx.Repo.Commit.GetTreeEntryByPath(ctx.Repo.TreePath)
223229
if err != nil {
224230
if git.IsErrNotExist(err) {
@@ -251,7 +257,7 @@ func getBlobForEntry(ctx *context.APIContext) (blob *git.Blob, lastModified time
251257
}
252258
blob = entry.Blob()
253259

254-
return blob, lastModified
260+
return blob, entry, lastModified
255261
}
256262

257263
// GetArchive get archive of a repository

services/repository/files/content.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,22 @@ func GetContentsOrList(ctx context.Context, repo *repo_model.Repository, treePat
101101
return fileList, nil
102102
}
103103

104+
// GetObjectTypeFromTreeEntry check what content is behind it
105+
func GetObjectTypeFromTreeEntry(entry *git.TreeEntry) ContentType {
106+
switch {
107+
case entry.IsDir():
108+
return ContentTypeDir
109+
case entry.IsSubModule():
110+
return ContentTypeSubmodule
111+
case entry.IsExecutable(), entry.IsRegular():
112+
return ContentTypeRegular
113+
case entry.IsLink():
114+
return ContentTypeLink
115+
default:
116+
return ""
117+
}
118+
}
119+
104120
// GetContents gets the meta data on a file's contents. Ref can be a branch, commit or tag
105121
func GetContents(ctx context.Context, repo *repo_model.Repository, treePath, ref string, forList bool) (*api.ContentsResponse, error) {
106122
if ref == "" {

services/user/user.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ func DeleteUser(ctx context.Context, u *user_model.User, purge bool) error {
7575
},
7676
Private: true,
7777
OwnerID: u.ID,
78+
Actor: u,
7879
})
7980
if err != nil {
8081
return fmt.Errorf("SearchRepositoryByName: %v", err)

services/user/user_test.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,26 @@ func TestDeleteUser(t *testing.T) {
6060
assert.Error(t, DeleteUser(db.DefaultContext, org, false))
6161
}
6262

63+
func TestPurgeUser(t *testing.T) {
64+
test := func(userID int64) {
65+
assert.NoError(t, unittest.PrepareTestDatabase())
66+
user := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: userID}).(*user_model.User)
67+
68+
err := DeleteUser(db.DefaultContext, user, true)
69+
assert.NoError(t, err)
70+
71+
unittest.AssertNotExistsBean(t, &user_model.User{ID: userID})
72+
unittest.CheckConsistencyFor(t, &user_model.User{}, &repo_model.Repository{})
73+
}
74+
test(2)
75+
test(4)
76+
test(8)
77+
test(11)
78+
79+
org := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 3}).(*user_model.User)
80+
assert.Error(t, DeleteUser(db.DefaultContext, org, false))
81+
}
82+
6383
func TestCreateUser(t *testing.T) {
6484
user := &user_model.User{
6585
Name: "GiteaBot",

templates/repo/view_list.tmpl

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@
88
{{if .LatestCommitUser}}
99
{{avatar .LatestCommitUser 24}}
1010
{{if .LatestCommitUser.FullName}}
11-
<a href="{{.LatestCommitUser.HomeLink}}"><strong>{{.LatestCommitUser.FullName}}</strong></a>
11+
<a class="muted" href="{{.LatestCommitUser.HomeLink}}"><strong>{{.LatestCommitUser.FullName}}</strong></a>
1212
{{else}}
13-
<a href="{{.LatestCommitUser.HomeLink}}"><strong>{{if .LatestCommit.Author}}{{.LatestCommit.Author.Name}}{{else}}{{.LatestCommitUser.Name}}{{end}}</strong></a>
13+
<a class="muted" href="{{.LatestCommitUser.HomeLink}}"><strong>{{if .LatestCommit.Author}}{{.LatestCommit.Author.Name}}{{else}}{{.LatestCommitUser.Name}}{{end}}</strong></a>
1414
{{end}}
1515
{{else}}
1616
{{if .LatestCommit.Author}}
@@ -54,7 +54,7 @@
5454
{{svg "octicon-file-submodule"}}
5555
{{$refURL := $subModuleFile.RefURL AppUrl $.Repository.FullName $.SSHDomain}}
5656
{{if $refURL}}
57-
<a href="{{$refURL}}">{{$entry.Name}}</a><span class="at">@</span><a href="{{$refURL}}/commit/{{PathEscape $subModuleFile.RefID}}">{{ShortSha $subModuleFile.RefID}}</a>
57+
<a class="muted" href="{{$refURL}}">{{$entry.Name}}</a><span class="at">@</span><a href="{{$refURL}}/commit/{{PathEscape $subModuleFile.RefID}}">{{ShortSha $subModuleFile.RefID}}</a>
5858
{{else}}
5959
{{$entry.Name}}<span class="at">@</span>{{ShortSha $subModuleFile.RefID}}
6060
{{end}}
@@ -63,16 +63,16 @@
6363
{{$subJumpablePathName := $entry.GetSubJumpablePathName}}
6464
{{$subJumpablePath := SubJumpablePath $subJumpablePathName}}
6565
{{svg "octicon-file-directory-fill"}}
66-
<a href="{{$.TreeLink}}/{{PathEscapeSegments $subJumpablePathName}}" title="{{$subJumpablePathName}}">
66+
<a class="muted" href="{{$.TreeLink}}/{{PathEscapeSegments $subJumpablePathName}}" title="{{$subJumpablePathName}}">
6767
{{if eq (len $subJumpablePath) 2}}
68-
<span class="jumpable-path">{{index $subJumpablePath 0}}</span>{{index $subJumpablePath 1}}
68+
<span class="color-text-light-2">{{index $subJumpablePath 0}}</span>{{index $subJumpablePath 1}}
6969
{{else}}
7070
{{index $subJumpablePath 0}}
7171
{{end}}
7272
</a>
7373
{{else}}
7474
{{svg (printf "octicon-%s" (EntryIcon $entry))}}
75-
<a href="{{$.TreeLink}}/{{PathEscapeSegments $entry.Name}}" title="{{$entry.Name}}">{{$entry.Name}}</a>
75+
<a class="muted" href="{{$.TreeLink}}/{{PathEscapeSegments $entry.Name}}" title="{{$entry.Name}}">{{$entry.Name}}</a>
7676
{{end}}
7777
{{end}}
7878
</span>

web_src/js/features/stopwatch.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ function updateStopwatchData(data) {
140140
$('.stopwatch-cancel').attr('action', `${issueUrl}/times/stopwatch/cancel`);
141141
$('.stopwatch-issue').text(`${repo_owner_name}/${repo_name}#${issue_index}`);
142142
$('.stopwatch-time').text(prettyMilliseconds(seconds * 1000));
143-
updateStopwatchTime(seconds);
143+
updateTimeInterval = updateStopwatchTime(seconds);
144144
btnEl.removeClass('hidden');
145145
}
146146

@@ -149,10 +149,10 @@ function updateStopwatchData(data) {
149149

150150
function updateStopwatchTime(seconds) {
151151
const secs = parseInt(seconds);
152-
if (!Number.isFinite(secs)) return;
152+
if (!Number.isFinite(secs)) return null;
153153

154154
const start = Date.now();
155-
updateTimeInterval = setInterval(() => {
155+
return setInterval(() => {
156156
const delta = Date.now() - start;
157157
const dur = prettyMilliseconds(secs * 1000 + delta, {compact: true});
158158
$('.stopwatch-time').text(dur);

web_src/js/utils.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ export function parseIssueHref(href) {
6464
export function strSubMatch(full, sub) {
6565
const res = [''];
6666
let i = 0, j = 0;
67-
for (; i < sub.length && j < full.length;) {
67+
while (i < sub.length && j < full.length) {
6868
while (j < full.length) {
6969
if (sub[i] === full[j]) {
7070
if (res.length % 2 !== 0) res.push('');

0 commit comments

Comments
 (0)