Skip to content

Commit 910d4df

Browse files
authored
Merge branch 'main' into improve-push-memory
2 parents 0845aea + 1dbc58f commit 910d4df

File tree

97 files changed

+1756
-690
lines changed

Some content is hidden

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

97 files changed

+1756
-690
lines changed

.air.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ bin = "gitea"
77
include_ext = ["go", "tmpl"]
88
exclude_dir = ["modules/git/tests", "services/gitdiff/testdata", "modules/avatar/testdata"]
99
include_dir = ["cmd", "models", "modules", "options", "routers", "services", "templates"]
10+
exclude_regex = ["_test.go$"]

.eslintrc

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ plugins:
1313
- eslint-plugin-import
1414
- eslint-plugin-vue
1515
- eslint-plugin-html
16+
- eslint-plugin-github
1617

1718
extends:
1819
- plugin:vue/recommended
@@ -96,6 +97,23 @@ rules:
9697
function-paren-newline: [0]
9798
generator-star-spacing: [0]
9899
getter-return: [2]
100+
github/array-foreach: [2]
101+
github/async-currenttarget: [2]
102+
github/async-preventdefault: [2]
103+
github/authenticity-token: [0]
104+
github/get-attribute: [2]
105+
github/js-class-name: [0]
106+
github/no-blur: [0]
107+
github/no-d-none: [0]
108+
github/no-dataset: [2]
109+
github/no-implicit-buggy-globals: [0]
110+
github/no-inner-html: [0]
111+
github/no-innerText: [2]
112+
github/no-then: [2]
113+
github/no-useless-passive: [2]
114+
github/prefer-observers: [0]
115+
github/require-passive-events: [2]
116+
github/unescaped-html-literal: [0]
99117
grouped-accessor-pairs: [2]
100118
guard-for-in: [0]
101119
id-blacklist: [0]

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,7 @@ lint: lint-frontend lint-backend
328328

329329
.PHONY: lint-frontend
330330
lint-frontend: node_modules
331-
npx eslint --color --max-warnings=0 web_src/js build templates *.config.js
331+
npx eslint --color --max-warnings=0 web_src/js build templates *.config.js docs/assets/js
332332
npx stylelint --color --max-warnings=0 web_src/less
333333
npx editorconfig-checker templates
334334

build/generate-images.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,5 +80,5 @@ async function main() {
8080
]);
8181
}
8282

83-
main().then(exit).catch(exit);
83+
main().then(exit).catch(exit); // eslint-disable-line github/no-then
8484

build/generate-svg.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,5 +54,5 @@ async function main() {
5454
]);
5555
}
5656

57-
main().then(exit).catch(exit);
57+
main().then(exit).catch(exit); // eslint-disable-line github/no-then
5858

cmd/admin.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,7 @@ func runChangePassword(c *cli.Context) error {
366366
return err
367367
}
368368

369-
if err = models.UpdateUserCols(user, "passwd", "passwd_hash_algo", "salt"); err != nil {
369+
if err = models.UpdateUserCols(db.DefaultContext, user, "passwd", "passwd_hash_algo", "salt"); err != nil {
370370
return err
371371
}
372372

cmd/web_https.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313
"code.gitea.io/gitea/modules/graceful"
1414
"code.gitea.io/gitea/modules/log"
1515
"code.gitea.io/gitea/modules/setting"
16+
1617
"github.com/klauspost/cpuid/v2"
1718
)
1819

docs/assets/js/search.js

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ const fuseOptions = {
1515
shouldSort: true,
1616
includeMatches: true,
1717
matchAllTokens: true,
18-
threshold: 0.0, // for parsing diacritics
18+
threshold: 0, // for parsing diacritics
1919
tokenize: true,
2020
location: 0,
2121
distance: 100,
@@ -52,25 +52,25 @@ function doSearch() {
5252
executeSearch(searchQuery);
5353
} else {
5454
const para = document.createElement('P');
55-
para.innerText = 'Please enter a word or phrase above';
55+
para.textContent = 'Please enter a word or phrase above';
5656
document.getElementById('search-results').appendChild(para);
5757
}
5858
}
5959

6060
function getJSON(url, fn) {
6161
const request = new XMLHttpRequest();
6262
request.open('GET', url, true);
63-
request.onload = function () {
63+
request.addEventListener('load', () => {
6464
if (request.status >= 200 && request.status < 400) {
6565
const data = JSON.parse(request.responseText);
6666
fn(data);
6767
} else {
6868
console.error(`Target reached on ${url} with error ${request.status}`);
6969
}
70-
};
71-
request.onerror = function () {
70+
});
71+
request.addEventListener('error', () => {
7272
console.error(`Connection error ${request.status}`);
73-
};
73+
});
7474
request.send();
7575
}
7676

@@ -84,20 +84,20 @@ function executeSearch(searchQuery) {
8484
populateResults(result);
8585
} else {
8686
const para = document.createElement('P');
87-
para.innerText = 'No matches found';
87+
para.textContent = 'No matches found';
8888
document.getElementById('search-results').appendChild(para);
8989
}
9090
});
9191
}
9292

9393
function populateResults(result) {
94-
result.forEach((value, key) => {
94+
for (const [key, value] of result.entries()) {
9595
const content = value.item.contents;
9696
let snippet = '';
9797
const snippetHighlights = [];
9898
if (fuseOptions.tokenize) {
9999
snippetHighlights.push(searchQuery);
100-
value.matches.forEach((mvalue) => {
100+
for (const mvalue of value.matches) {
101101
if (mvalue.key === 'tags' || mvalue.key === 'categories') {
102102
snippetHighlights.push(mvalue.value);
103103
} else if (mvalue.key === 'contents') {
@@ -111,7 +111,7 @@ function populateResults(result) {
111111
snippetHighlights.push(mvalue.value.substring(mvalue.indices[0][0], mvalue.indices[0][1] - mvalue.indices[0][0] + 1));
112112
}
113113
}
114-
});
114+
}
115115
}
116116

117117
if (snippet.length < 1) {
@@ -130,10 +130,10 @@ function populateResults(result) {
130130
});
131131
document.getElementById('search-results').appendChild(htmlToElement(output));
132132

133-
snippetHighlights.forEach((snipvalue) => {
133+
for (const snipvalue of snippetHighlights) {
134134
new Mark(document.getElementById(`summary-${key}`)).mark(snipvalue);
135-
});
136-
});
135+
}
136+
}
137137
}
138138

139139
function render(templateString, data) {

docs/content/doc/developers/guidelines-frontend.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,19 @@ We recommend [Google HTML/CSS Style Guide](https://google.github.io/styleguide/h
4040
7. Simple pages and SEO-related pages use Go HTML Template render to generate static Fomantic-UI HTML output. Complex pages can use Vue2 (or Vue3 in future).
4141

4242

43+
### Framework Usage
44+
45+
Mixing different frameworks together is highly discouraged. A JavaScript module should follow one major framework and follow the framework's best practice.
46+
47+
Recommended implementations:
48+
* Vue + Native
49+
* Fomantic-UI (jQuery)
50+
* Native only
51+
52+
Discouraged implementations:
53+
* Vue + jQuery
54+
* jQuery + Native
55+
4356
### `async` Functions
4457

4558
Only mark a function as `async` if and only if there are `await` calls
@@ -98,6 +111,19 @@ $('#el').on('click', async (e) => { // not recommended but acceptable
98111
});
99112
```
100113

114+
### HTML Attributes and `dataset`
115+
116+
We forbid `dataset` usage, its camel-casing behaviour makes it hard to grep for attributes. However there are still some special cases, so the current guideline is:
117+
118+
* For legacy code:
119+
* `$.data()` should be refactored to `$.attr()`.
120+
* `$.data()` can be used to bind some non-string data to elements in rare cases, but it is highly discouraged.
121+
122+
* For new code:
123+
* `node.dataset` should not be used, use `node.getAttribute` instead.
124+
* never bind any user data to a DOM node, use a suitable design pattern to describe the relation between node and data.
125+
126+
101127
### Vue2/Vue3 and JSX
102128

103129
Gitea is using Vue2 now, we plan to upgrade to Vue3. We decided not to introduce JSX to keep the HTML and the JavaScript code separated.

integrations/api_repo_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,7 @@ func TestAPIRepoMigrate(t *testing.T) {
334334
case "You can not import from disallowed hosts.":
335335
assert.EqualValues(t, "private-ip", testCase.repoName)
336336
default:
337-
assert.Fail(t, "unexpected error '%v' on url '%s'", respJSON["message"], testCase.cloneURL)
337+
assert.Failf(t, "unexpected error '%v' on url '%s'", respJSON["message"], testCase.cloneURL)
338338
}
339339
} else {
340340
assert.EqualValues(t, testCase.expectedStatus, resp.Code)

integrations/org_count_test.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,10 @@ func doCheckOrgCounts(username string, orgCounts map[string]int, strict bool, ca
116116
Name: username,
117117
}).(*models.User)
118118

119-
orgs, err := models.GetOrgsByUserID(user.ID, true)
119+
orgs, err := models.FindOrgs(models.FindOrgOptions{
120+
UserID: user.ID,
121+
IncludePrivate: true,
122+
})
120123
assert.NoError(t, err)
121124

122125
calcOrgCounts := map[string]int{}

models/access.go

Lines changed: 0 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -105,66 +105,6 @@ func accessLevel(e db.Engine, user *User, repo *Repository) (AccessMode, error)
105105
return a.Mode, nil
106106
}
107107

108-
type repoAccess struct {
109-
Access `xorm:"extends"`
110-
Repository `xorm:"extends"`
111-
}
112-
113-
func (repoAccess) TableName() string {
114-
return "access"
115-
}
116-
117-
// GetRepositoryAccesses finds all repositories with their access mode where a user has access but does not own.
118-
func (user *User) GetRepositoryAccesses() (map[*Repository]AccessMode, error) {
119-
rows, err := db.GetEngine(db.DefaultContext).
120-
Join("INNER", "repository", "repository.id = access.repo_id").
121-
Where("access.user_id = ?", user.ID).
122-
And("repository.owner_id <> ?", user.ID).
123-
Rows(new(repoAccess))
124-
if err != nil {
125-
return nil, err
126-
}
127-
defer rows.Close()
128-
129-
repos := make(map[*Repository]AccessMode, 10)
130-
ownerCache := make(map[int64]*User, 10)
131-
for rows.Next() {
132-
var repo repoAccess
133-
err = rows.Scan(&repo)
134-
if err != nil {
135-
return nil, err
136-
}
137-
138-
var ok bool
139-
if repo.Owner, ok = ownerCache[repo.OwnerID]; !ok {
140-
if err = repo.GetOwner(); err != nil {
141-
return nil, err
142-
}
143-
ownerCache[repo.OwnerID] = repo.Owner
144-
}
145-
146-
repos[&repo.Repository] = repo.Access.Mode
147-
}
148-
return repos, nil
149-
}
150-
151-
// GetAccessibleRepositories finds repositories which the user has access but does not own.
152-
// If limit is smaller than 1 means returns all found results.
153-
func (user *User) GetAccessibleRepositories(limit int) (repos []*Repository, _ error) {
154-
sess := db.GetEngine(db.DefaultContext).
155-
Where("owner_id !=? ", user.ID).
156-
Desc("updated_unix")
157-
if limit > 0 {
158-
sess.Limit(limit)
159-
repos = make([]*Repository, 0, limit)
160-
} else {
161-
repos = make([]*Repository, 0, 10)
162-
}
163-
return repos, sess.
164-
Join("INNER", "access", "access.user_id = ? AND access.repo_id = repository.id", user.ID).
165-
Find(&repos)
166-
}
167-
168108
func maxAccessMode(modes ...AccessMode) AccessMode {
169109
max := AccessModeNone
170110
for _, mode := range modes {

models/access_test.go

Lines changed: 0 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -90,39 +90,6 @@ func TestHasAccess(t *testing.T) {
9090
assert.NoError(t, err)
9191
}
9292

93-
func TestUser_GetRepositoryAccesses(t *testing.T) {
94-
assert.NoError(t, unittest.PrepareTestDatabase())
95-
96-
user1 := unittest.AssertExistsAndLoadBean(t, &User{ID: 1}).(*User)
97-
accesses, err := user1.GetRepositoryAccesses()
98-
assert.NoError(t, err)
99-
assert.Len(t, accesses, 0)
100-
101-
user29 := unittest.AssertExistsAndLoadBean(t, &User{ID: 29}).(*User)
102-
accesses, err = user29.GetRepositoryAccesses()
103-
assert.NoError(t, err)
104-
assert.Len(t, accesses, 2)
105-
}
106-
107-
func TestUser_GetAccessibleRepositories(t *testing.T) {
108-
assert.NoError(t, unittest.PrepareTestDatabase())
109-
110-
user1 := unittest.AssertExistsAndLoadBean(t, &User{ID: 1}).(*User)
111-
repos, err := user1.GetAccessibleRepositories(0)
112-
assert.NoError(t, err)
113-
assert.Len(t, repos, 0)
114-
115-
user2 := unittest.AssertExistsAndLoadBean(t, &User{ID: 2}).(*User)
116-
repos, err = user2.GetAccessibleRepositories(0)
117-
assert.NoError(t, err)
118-
assert.Len(t, repos, 4)
119-
120-
user29 := unittest.AssertExistsAndLoadBean(t, &User{ID: 29}).(*User)
121-
repos, err = user29.GetAccessibleRepositories(0)
122-
assert.NoError(t, err)
123-
assert.Len(t, repos, 2)
124-
}
125-
12693
func TestRepository_RecalculateAccesses(t *testing.T) {
12794
// test with organization repo
12895
assert.NoError(t, unittest.PrepareTestDatabase())

models/issue.go

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -824,14 +824,25 @@ func (issue *Issue) UpdateAttachments(uuids []string) (err error) {
824824

825825
// ChangeContent changes issue content, as the given user.
826826
func (issue *Issue) ChangeContent(doer *User, content string) (err error) {
827-
issue.Content = content
828-
829827
ctx, committer, err := db.TxContext()
830828
if err != nil {
831829
return err
832830
}
833831
defer committer.Close()
834832

833+
hasContentHistory, err := issues.HasIssueContentHistory(ctx, issue.ID, 0)
834+
if err != nil {
835+
return fmt.Errorf("HasIssueContentHistory: %v", err)
836+
}
837+
if !hasContentHistory {
838+
if err = issues.SaveIssueContentHistory(db.GetEngine(ctx), issue.PosterID, issue.ID, 0,
839+
issue.CreatedUnix, issue.Content, true); err != nil {
840+
return fmt.Errorf("SaveIssueContentHistory: %v", err)
841+
}
842+
}
843+
844+
issue.Content = content
845+
835846
if err = updateIssueCols(db.GetEngine(ctx), issue, "content"); err != nil {
836847
return fmt.Errorf("UpdateIssueCols: %v", err)
837848
}
@@ -1012,11 +1023,6 @@ func newIssue(ctx context.Context, doer *User, opts NewIssueOptions) (err error)
10121023
return err
10131024
}
10141025

1015-
if err = issues.SaveIssueContentHistory(e, doer.ID, opts.Issue.ID, 0,
1016-
timeutil.TimeStampNow(), opts.Issue.Content, true); err != nil {
1017-
return err
1018-
}
1019-
10201026
return opts.Issue.addCrossReferences(ctx, doer, false)
10211027
}
10221028

0 commit comments

Comments
 (0)