Skip to content

Commit 632e5e1

Browse files
authored
Merge branch 'main' into improve-action-fe
2 parents 15297ad + 8cadd51 commit 632e5e1

File tree

78 files changed

+666
-223
lines changed

Some content is hidden

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

78 files changed

+666
-223
lines changed

CODE_OF_CONDUCT.md

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
# Gitea Community Code of Conduct
2+
3+
## About
4+
5+
Online communities include people from many different backgrounds. The Gitea contributors are committed to providing a friendly, safe and welcoming environment for all, regardless of gender identity and expression, sexual orientation, disabilities, neurodiversity, physical appearance, body size, ethnicity, nationality, race, age, religion, or similar personal characteristics.
6+
7+
The first goal of the Code of Conduct is to specify a baseline standard of behavior so that people with different social values and communication styles can talk about Gitea effectively, productively, and respectfully.
8+
9+
The second goal is to provide a mechanism for resolving conflicts in the community when they arise.
10+
11+
The third goal of the Code of Conduct is to make our community welcoming to people from different backgrounds. Diversity is critical to the project; for Gitea to be successful, it needs contributors and users from all backgrounds.
12+
13+
We believe that healthy debate and disagreement are essential to a healthy project and community. However, it is never ok to be disrespectful. We value diverse opinions, but we value respectful behavior more.
14+
15+
## Community values
16+
17+
These are the values to which people in the Gitea community should aspire.
18+
19+
- **Be friendly and welcoming.**
20+
- **Be patient.**
21+
- Remember that people have varying communication styles and that not everyone is using their native language. (Meaning and tone can be lost in translation.)
22+
- **Be thoughtful.**
23+
- Productive communication requires effort. Think about how your words will be interpreted.
24+
- Remember that sometimes it is best to refrain entirely from commenting.
25+
- **Be respectful.**
26+
- In particular, respect differences of opinion.
27+
- **Be charitable.**
28+
- Interpret the arguments of others in good faith, do not seek to disagree.
29+
- When we do disagree, try to understand why.
30+
- **Be constructive.**
31+
- Avoid derailing: stay on topic; if you want to talk about something else, start a new conversation.
32+
- Avoid unconstructive criticism: don't merely decry the current state of affairs; offer—or at least solicit—suggestions as to how things may be improved.
33+
- Avoid snarking (pithy, unproductive, sniping comments)
34+
- Avoid discussing potentially offensive or sensitive issues; this all too often leads to unnecessary conflict.
35+
- Avoid microaggressions (brief and commonplace verbal, behavioral and environmental indignities that communicate hostile, derogatory or negative slights and insults to a person or group).
36+
- **Be responsible.**
37+
- What you say and do matters. Take responsibility for your words and actions, including their consequences, whether intended or otherwise.
38+
39+
People are complicated. You should expect to be misunderstood and to misunderstand others; when this inevitably occurs, resist the urge to be defensive or assign blame. Try not to take offense where no offense was intended. Give people the benefit of the doubt. Even if the intent was to provoke, do not rise to it. It is the responsibility of all parties to de-escalate conflict when it arises.
40+
41+
## Code of Conduct
42+
43+
### Our Pledge
44+
45+
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation.
46+
47+
### Our Standards
48+
49+
Examples of behavior that contributes to creating a positive environment include:
50+
51+
- Using welcoming and inclusive language
52+
- Being respectful of differing viewpoints and experiences
53+
- Gracefully accepting constructive criticism
54+
- Focusing on what is best for the community
55+
- Showing empathy towards other community members
56+
57+
Examples of unacceptable behavior by participants include:
58+
59+
- The use of sexualized language or imagery and unwelcome sexual attention or advances
60+
- Trolling, insulting/derogatory comments, and personal or political attacks
61+
- Public or private harassment
62+
- Publishing others’ private information, such as a physical or electronic address, without explicit permission
63+
- Other conduct which could reasonably be considered inappropriate in a professional setting
64+
65+
### Our Responsibilities
66+
67+
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
68+
69+
Project maintainers have the right and responsibility to remove, edit, or reject: comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, as well as to ban (temporarily or permanently) any contributor for behaviors that they deem inappropriate, threatening, offensive, or harmful.
70+
71+
### Scope
72+
73+
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
74+
75+
This Code of Conduct also applies outside the project spaces when the Project Stewards have a reasonable belief that an individual’s behavior may have a negative impact on the project or its community.
76+
77+
### Conflict Resolution
78+
79+
We do not believe that all conflict is bad; healthy debate and disagreement often yield positive results. However, it is never okay to be disrespectful or to engage in behavior that violates the project’s code of conduct.
80+
81+
If you see someone violating the code of conduct, you are encouraged to address the behavior directly with those involved. Many issues can be resolved quickly and easily, and this gives people more control over the outcome of their dispute. If you are unable to resolve the matter for any reason, or if the behavior is threatening or harassing, report it. We are dedicated to providing an environment where participants feel welcome and safe.
82+
83+
Reports should be directed to the Gitea Project Stewards at [email protected]. It is the Project Stewards’ duty to receive and address reported violations of the code of conduct. They will then work with a committee consisting of representatives from the technical-oversight-committee.
84+
85+
We will investigate every complaint, but you may not receive a direct response. We will use our discretion in determining when and how to follow up on reported incidents, which may range from not taking action to permanent expulsion from the project and project-sponsored spaces. Under normal circumstances, we will notify the accused of the report and provide them an opportunity to discuss it before any action is taken. If there is a consensus between maintainers that such an endeavor would be useless (i.e. in case of an obvious spammer), we reserve the right to take action without notifying the accused first. The identity of the reporter will be omitted from the details of the report supplied to the accused. In potentially harmful situations, such as ongoing harassment or threats to anyone’s safety, we may take action without notice.
86+
87+
### Attribution
88+
89+
This Code of Conduct is adapted from the Contributor Covenant, version 1.4, available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
90+
91+
## Summary
92+
93+
- Treat everyone with respect and kindness.
94+
- Be thoughtful in how you communicate.
95+
- Don’t be destructive or inflammatory.
96+
- If you encounter an issue, please mail [email protected].

models/db/iterate_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ func TestIterate(t *testing.T) {
2525
return nil
2626
})
2727
assert.NoError(t, err)
28-
assert.EqualValues(t, 83, repoCnt)
28+
assert.EqualValues(t, 84, repoCnt)
2929

3030
err = db.Iterate(db.DefaultContext, nil, func(ctx context.Context, repoUnit *repo_model.RepoUnit) error {
3131
reopUnit2 := repo_model.RepoUnit{ID: repoUnit.ID}

models/db/list_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,11 @@ func TestFind(t *testing.T) {
3535
var repoUnits []repo_model.RepoUnit
3636
err := db.Find(db.DefaultContext, &opts, &repoUnits)
3737
assert.NoError(t, err)
38-
assert.EqualValues(t, 83, len(repoUnits))
38+
assert.EqualValues(t, 84, len(repoUnits))
3939

4040
cnt, err := db.Count(db.DefaultContext, &opts, new(repo_model.RepoUnit))
4141
assert.NoError(t, err)
42-
assert.EqualValues(t, 83, cnt)
42+
assert.EqualValues(t, 84, cnt)
4343

4444
repoUnits = make([]repo_model.RepoUnit, 0, 10)
4545
newCnt, err := db.FindAndCount(db.DefaultContext, &opts, &repoUnits)

models/fixtures/repo_unit.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -569,3 +569,9 @@
569569
type: 3
570570
config: "{\"IgnoreWhitespaceConflicts\":false,\"AllowMerge\":true,\"AllowRebase\":true,\"AllowRebaseMerge\":true,\"AllowSquash\":true}"
571571
created_unix: 946684810
572+
573+
-
574+
id: 84
575+
repo_id: 56
576+
type: 1
577+
created_unix: 946684810

models/fixtures/repository.yml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1634,3 +1634,16 @@
16341634
is_private: true
16351635
num_issues: 1
16361636
status: 0
1637+
1638+
-
1639+
id: 56
1640+
owner_id: 2
1641+
owner_name: user2
1642+
lower_name: readme-test
1643+
name: readme-test
1644+
default_branch: master
1645+
is_empty: false
1646+
is_archived: false
1647+
is_private: true
1648+
status: 0
1649+
num_issues: 0

models/fixtures/user.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@
6666
num_followers: 2
6767
num_following: 1
6868
num_stars: 2
69-
num_repos: 11
69+
num_repos: 12
7070
num_teams: 0
7171
num_members: 0
7272
visibility: 0

models/git/lfs_lock.go

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ package git
66
import (
77
"context"
88
"fmt"
9-
"path"
109
"strings"
1110
"time"
1211

@@ -17,6 +16,7 @@ import (
1716
"code.gitea.io/gitea/models/unit"
1817
user_model "code.gitea.io/gitea/models/user"
1918
"code.gitea.io/gitea/modules/setting"
19+
"code.gitea.io/gitea/modules/util"
2020
)
2121

2222
// LFSLock represents a git lfs lock of repository.
@@ -34,11 +34,7 @@ func init() {
3434

3535
// BeforeInsert is invoked from XORM before inserting an object of this type.
3636
func (l *LFSLock) BeforeInsert() {
37-
l.Path = cleanPath(l.Path)
38-
}
39-
40-
func cleanPath(p string) string {
41-
return path.Clean("/" + p)[1:]
37+
l.Path = util.CleanPath(l.Path)
4238
}
4339

4440
// CreateLFSLock creates a new lock.
@@ -53,7 +49,7 @@ func CreateLFSLock(ctx context.Context, repo *repo_model.Repository, lock *LFSLo
5349
return nil, err
5450
}
5551

56-
lock.Path = cleanPath(lock.Path)
52+
lock.Path = util.CleanPath(lock.Path)
5753
lock.RepoID = repo.ID
5854

5955
l, err := GetLFSLock(dbCtx, repo, lock.Path)
@@ -73,7 +69,7 @@ func CreateLFSLock(ctx context.Context, repo *repo_model.Repository, lock *LFSLo
7369

7470
// GetLFSLock returns release by given path.
7571
func GetLFSLock(ctx context.Context, repo *repo_model.Repository, path string) (*LFSLock, error) {
76-
path = cleanPath(path)
72+
path = util.CleanPath(path)
7773
rel := &LFSLock{RepoID: repo.ID}
7874
has, err := db.GetEngine(ctx).Where("lower(path) = ?", strings.ToLower(path)).Get(rel)
7975
if err != nil {

modules/cache/context.go

Lines changed: 103 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ package cache
66
import (
77
"context"
88
"sync"
9+
"time"
910

1011
"code.gitea.io/gitea/modules/log"
1112
)
@@ -14,65 +15,151 @@ import (
1415
// This is useful for caching data that is expensive to calculate and is likely to be
1516
// used multiple times in a request.
1617
type cacheContext struct {
17-
ctx context.Context
18-
data map[any]map[any]any
19-
lock sync.RWMutex
18+
data map[any]map[any]any
19+
lock sync.RWMutex
20+
created time.Time
21+
discard bool
2022
}
2123

2224
func (cc *cacheContext) Get(tp, key any) any {
2325
cc.lock.RLock()
2426
defer cc.lock.RUnlock()
25-
if cc.data[tp] == nil {
26-
return nil
27-
}
2827
return cc.data[tp][key]
2928
}
3029

3130
func (cc *cacheContext) Put(tp, key, value any) {
3231
cc.lock.Lock()
3332
defer cc.lock.Unlock()
34-
if cc.data[tp] == nil {
35-
cc.data[tp] = make(map[any]any)
33+
34+
if cc.discard {
35+
return
36+
}
37+
38+
d := cc.data[tp]
39+
if d == nil {
40+
d = make(map[any]any)
41+
cc.data[tp] = d
3642
}
37-
cc.data[tp][key] = value
43+
d[key] = value
3844
}
3945

4046
func (cc *cacheContext) Delete(tp, key any) {
4147
cc.lock.Lock()
4248
defer cc.lock.Unlock()
43-
if cc.data[tp] == nil {
44-
return
45-
}
4649
delete(cc.data[tp], key)
4750
}
4851

52+
func (cc *cacheContext) Discard() {
53+
cc.lock.Lock()
54+
defer cc.lock.Unlock()
55+
cc.data = nil
56+
cc.discard = true
57+
}
58+
59+
func (cc *cacheContext) isDiscard() bool {
60+
cc.lock.RLock()
61+
defer cc.lock.RUnlock()
62+
return cc.discard
63+
}
64+
65+
// cacheContextLifetime is the max lifetime of cacheContext.
66+
// Since cacheContext is used to cache data in a request level context, 10s is enough.
67+
// If a cacheContext is used more than 10s, it's probably misuse.
68+
const cacheContextLifetime = 10 * time.Second
69+
70+
var timeNow = time.Now
71+
72+
func (cc *cacheContext) Expired() bool {
73+
return timeNow().Sub(cc.created) > cacheContextLifetime
74+
}
75+
4976
var cacheContextKey = struct{}{}
5077

78+
/*
79+
Since there are both WithCacheContext and WithNoCacheContext,
80+
it may be confusing when there is nesting.
81+
82+
Some cases to explain the design:
83+
84+
When:
85+
- A, B or C means a cache context.
86+
- A', B' or C' means a discard cache context.
87+
- ctx means context.Backgrand().
88+
- A(ctx) means a cache context with ctx as the parent context.
89+
- B(A(ctx)) means a cache context with A(ctx) as the parent context.
90+
- With is alias of WithCacheContext.
91+
- WithNo is alias of WithNoCacheContext.
92+
93+
So:
94+
- With(ctx) -> A(ctx)
95+
- With(With(ctx)) -> A(ctx), not B(A(ctx)), always reuse parent cache context if possible.
96+
- With(With(With(ctx))) -> A(ctx), not C(B(A(ctx))), ditto.
97+
- WithNo(ctx) -> ctx, not A'(ctx), don't create new cache context if we don't have to.
98+
- WithNo(With(ctx)) -> A'(ctx)
99+
- WithNo(WithNo(With(ctx))) -> A'(ctx), not B'(A'(ctx)), don't create new cache context if we don't have to.
100+
- With(WithNo(With(ctx))) -> B(A'(ctx)), not A(ctx), never reuse a discard cache context.
101+
- WithNo(With(WithNo(With(ctx)))) -> B'(A'(ctx))
102+
- With(WithNo(With(WithNo(With(ctx))))) -> C(B'(A'(ctx))), so there's always only one not-discard cache context.
103+
*/
104+
51105
func WithCacheContext(ctx context.Context) context.Context {
106+
if c, ok := ctx.Value(cacheContextKey).(*cacheContext); ok {
107+
if !c.isDiscard() {
108+
// reuse parent context
109+
return ctx
110+
}
111+
}
52112
return context.WithValue(ctx, cacheContextKey, &cacheContext{
53-
ctx: ctx,
54-
data: make(map[any]map[any]any),
113+
data: make(map[any]map[any]any),
114+
created: timeNow(),
55115
})
56116
}
57117

118+
func WithNoCacheContext(ctx context.Context) context.Context {
119+
if c, ok := ctx.Value(cacheContextKey).(*cacheContext); ok {
120+
// The caller want to run long-life tasks, but the parent context is a cache context.
121+
// So we should disable and clean the cache data, or it will be kept in memory for a long time.
122+
c.Discard()
123+
return ctx
124+
}
125+
126+
return ctx
127+
}
128+
58129
func GetContextData(ctx context.Context, tp, key any) any {
59130
if c, ok := ctx.Value(cacheContextKey).(*cacheContext); ok {
131+
if c.Expired() {
132+
// The warning means that the cache context is misused for long-life task,
133+
// it can be resolved with WithNoCacheContext(ctx).
134+
log.Warn("cache context is expired, may be misused for long-life tasks: %v", c)
135+
return nil
136+
}
60137
return c.Get(tp, key)
61138
}
62-
log.Warn("cannot get cache context when getting data: %v", ctx)
63139
return nil
64140
}
65141

66142
func SetContextData(ctx context.Context, tp, key, value any) {
67143
if c, ok := ctx.Value(cacheContextKey).(*cacheContext); ok {
144+
if c.Expired() {
145+
// The warning means that the cache context is misused for long-life task,
146+
// it can be resolved with WithNoCacheContext(ctx).
147+
log.Warn("cache context is expired, may be misused for long-life tasks: %v", c)
148+
return
149+
}
68150
c.Put(tp, key, value)
69151
return
70152
}
71-
log.Warn("cannot get cache context when setting data: %v", ctx)
72153
}
73154

74155
func RemoveContextData(ctx context.Context, tp, key any) {
75156
if c, ok := ctx.Value(cacheContextKey).(*cacheContext); ok {
157+
if c.Expired() {
158+
// The warning means that the cache context is misused for long-life task,
159+
// it can be resolved with WithNoCacheContext(ctx).
160+
log.Warn("cache context is expired, may be misused for long-life tasks: %v", c)
161+
return
162+
}
76163
c.Delete(tp, key)
77164
}
78165
}

0 commit comments

Comments
 (0)