Skip to content

Commit fad4ae7

Browse files
authored
Merge branch 'main' into issue-commet-render-23671
2 parents 8f471ea + f384b13 commit fad4ae7

File tree

31 files changed

+1751
-73
lines changed

31 files changed

+1751
-73
lines changed

MAINTAINERS

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ Jimmy Praet <[email protected]> (@jpraet)
4444
Leon Hofmeister <[email protected]> (@delvh)
4545
Wim <[email protected]> (@42wim)
4646
Jason Song <[email protected]> (@wolfogre)
47-
Yarden Shoham <hrsi88@gmail.com> (@yardenshoham)
47+
Yarden Shoham <git@yardenshoham.com> (@yardenshoham)
4848
Yu Tian <[email protected]> (@Zettat123)
4949
Eddie Yang <[email protected]> (@yp05327)
5050
Dong Ge <[email protected]> (@sillyguodong)

cmd/migrate_storage.go

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -72,12 +72,21 @@ var CmdMigrateStorage = cli.Command{
7272
cli.StringFlag{
7373
Name: "minio-base-path",
7474
Value: "",
75-
Usage: "Minio storage basepath on the bucket",
75+
Usage: "Minio storage base path on the bucket",
7676
},
7777
cli.BoolFlag{
7878
Name: "minio-use-ssl",
7979
Usage: "Enable SSL for minio",
8080
},
81+
cli.BoolFlag{
82+
Name: "minio-insecure-skip-verify",
83+
Usage: "Skip SSL verification",
84+
},
85+
cli.StringFlag{
86+
Name: "minio-checksum-algorithm",
87+
Value: "",
88+
Usage: "Minio checksum algorithm (default/md5)",
89+
},
8190
},
8291
}
8392

@@ -168,13 +177,15 @@ func runMigrateStorage(ctx *cli.Context) error {
168177
dstStorage, err = storage.NewMinioStorage(
169178
stdCtx,
170179
storage.MinioStorageConfig{
171-
Endpoint: ctx.String("minio-endpoint"),
172-
AccessKeyID: ctx.String("minio-access-key-id"),
173-
SecretAccessKey: ctx.String("minio-secret-access-key"),
174-
Bucket: ctx.String("minio-bucket"),
175-
Location: ctx.String("minio-location"),
176-
BasePath: ctx.String("minio-base-path"),
177-
UseSSL: ctx.Bool("minio-use-ssl"),
180+
Endpoint: ctx.String("minio-endpoint"),
181+
AccessKeyID: ctx.String("minio-access-key-id"),
182+
SecretAccessKey: ctx.String("minio-secret-access-key"),
183+
Bucket: ctx.String("minio-bucket"),
184+
Location: ctx.String("minio-location"),
185+
BasePath: ctx.String("minio-base-path"),
186+
UseSSL: ctx.Bool("minio-use-ssl"),
187+
InsecureSkipVerify: ctx.Bool("minio-insecure-skip-verify"),
188+
ChecksumAlgorithm: ctx.String("minio-checksum-algorithm"),
178189
})
179190
default:
180191
return fmt.Errorf("unsupported storage type: %s", ctx.String("storage"))

custom/conf/app.example.ini

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -583,15 +583,15 @@ ROUTER = console
583583
;; * In request Header: X-Request-ID: test-id-123
584584
;; * Configuration in app.ini: REQUEST_ID_HEADERS = X-Request-ID
585585
;; * Print in log: 127.0.0.1:58384 - - [14/Feb/2023:16:33:51 +0800] "test-id-123"
586-
;;
587-
;; If you configure more than one in the .ini file, it will match in the order of configuration,
586+
;;
587+
;; If you configure more than one in the .ini file, it will match in the order of configuration,
588588
;; and the first match will be finally printed in the log.
589589
;; * E.g:
590590
;; * In reuqest Header: X-Trace-ID: trace-id-1q2w3e4r
591591
;; * Configuration in app.ini: REQUEST_ID_HEADERS = X-Request-ID, X-Trace-ID, X-Req-ID
592592
;; * Print in log: 127.0.0.1:58384 - - [14/Feb/2023:16:33:51 +0800] "trace-id-1q2w3e4r"
593593
;;
594-
;; REQUEST_ID_HEADERS =
594+
;; REQUEST_ID_HEADERS =
595595

596596
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
597597
;;
@@ -1886,6 +1886,9 @@ ROUTER = console
18861886
;;
18871887
;; Minio skip SSL verification available when STORAGE_TYPE is `minio`
18881888
;MINIO_INSECURE_SKIP_VERIFY = false
1889+
;;
1890+
;; Minio checksum algorithm: default (for MinIO or AWS S3) or md5 (for Cloudflare or Backblaze)
1891+
;MINIO_CHECKSUM_ALGORITHM = default
18891892

18901893
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
18911894
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -855,6 +855,7 @@ Default templates for project boards:
855855
- `MINIO_BASE_PATH`: **attachments/**: Minio base path on the bucket only available when STORAGE_TYPE is `minio`
856856
- `MINIO_USE_SSL`: **false**: Minio enabled ssl only available when STORAGE_TYPE is `minio`
857857
- `MINIO_INSECURE_SKIP_VERIFY`: **false**: Minio skip SSL verification available when STORAGE_TYPE is `minio`
858+
- `MINIO_CHECKSUM_ALGORITHM`: **default**: Minio checksum algorithm: `default` (for MinIO or AWS S3) or `md5` (for Cloudflare or Backblaze)
858859

859860
## Log (`log`)
860861

docs/content/doc/usage/issue-pull-request-templates.en-us.md

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,17 @@ Possible file names for issue templates:
5050
- `.github/issue_template.yaml`
5151
- `.github/issue_template.yml`
5252

53+
Possible file names for issue config:
54+
55+
- `.gitea/ISSUE_TEMPLATE/config.yaml`
56+
- `.gitea/ISSUE_TEMPLATE/config.yml`
57+
- `.gitea/issue_template/config.yaml`
58+
- `.gitea/issue_template/config.yml`
59+
- `.github/ISSUE_TEMPLATE/config.yaml`
60+
- `.github/ISSUE_TEMPLATE/config.yml`
61+
- `.github/issue_template/config.yaml`
62+
- `.github/issue_template/config.yml`
63+
5364
Possible file names for PR templates:
5465

5566
- `PULL_REQUEST_TEMPLATE.md`
@@ -267,3 +278,30 @@ For each value in the options array, you can set the following keys.
267278
|----------|------------------------------------------------------------------------------------------------------------------------------------------|----------|---------|---------|---------|
268279
| label | The identifier for the option, which is displayed in the form. Markdown is supported for bold or italic text formatting, and hyperlinks. | Required | String | - | - |
269280
| required | Prevents form submission until element is completed. | Optional | Boolean | false | - |
281+
282+
## Syntax for issue config
283+
284+
This is a example for a issue config file
285+
286+
```yaml
287+
blank_issues_enabled: true
288+
contact_links:
289+
- name: Gitea
290+
url: https://gitea.io
291+
about: Visit the Gitea Website
292+
```
293+
294+
### Possible Options
295+
296+
| Key | Description | Type | Default |
297+
|----------------------|-------------------------------------------------------------------------------------------------------|--------------------|----------------|
298+
| blank_issues_enabled | If set to false, the User is forced to use a Template | Boolean | true |
299+
| contact_links | Custom Links to show in the Choose Box | Contact Link Array | Empty Array |
300+
301+
### Contact Link
302+
303+
| Key | Description | Type | Required |
304+
|----------------------|-------------------------------------------------------------------------------------------------------|---------|----------|
305+
| name | the name of your link | String | true |
306+
| url | The URL of your Link | String | true |
307+
| about | A short description of your Link | String | true |

models/issues/dependency.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ func CreateIssueDependency(user *user_model.User, issue, dep *Issue) error {
134134
}
135135
defer committer.Close()
136136

137-
// Check if it aleready exists
137+
// Check if it already exists
138138
exists, err := issueDepExists(ctx, issue.ID, dep.ID)
139139
if err != nil {
140140
return err

models/issues/issue.go

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ func (issue *Issue) IsOverdue() bool {
189189

190190
// LoadRepo loads issue's repository
191191
func (issue *Issue) LoadRepo(ctx context.Context) (err error) {
192-
if issue.Repo == nil {
192+
if issue.Repo == nil && issue.RepoID != 0 {
193193
issue.Repo, err = repo_model.GetRepositoryByID(ctx, issue.RepoID)
194194
if err != nil {
195195
return fmt.Errorf("getRepositoryByID [%d]: %w", issue.RepoID, err)
@@ -223,7 +223,7 @@ func (issue *Issue) GetPullRequest() (pr *PullRequest, err error) {
223223

224224
// LoadLabels loads labels
225225
func (issue *Issue) LoadLabels(ctx context.Context) (err error) {
226-
if issue.Labels == nil {
226+
if issue.Labels == nil && issue.ID != 0 {
227227
issue.Labels, err = GetLabelsByIssueID(ctx, issue.ID)
228228
if err != nil {
229229
return fmt.Errorf("getLabelsByIssueID [%d]: %w", issue.ID, err)
@@ -234,7 +234,7 @@ func (issue *Issue) LoadLabels(ctx context.Context) (err error) {
234234

235235
// LoadPoster loads poster
236236
func (issue *Issue) LoadPoster(ctx context.Context) (err error) {
237-
if issue.Poster == nil {
237+
if issue.Poster == nil && issue.PosterID != 0 {
238238
issue.Poster, err = user_model.GetPossibleUserByID(ctx, issue.PosterID)
239239
if err != nil {
240240
issue.PosterID = -1
@@ -252,7 +252,7 @@ func (issue *Issue) LoadPoster(ctx context.Context) (err error) {
252252
// LoadPullRequest loads pull request info
253253
func (issue *Issue) LoadPullRequest(ctx context.Context) (err error) {
254254
if issue.IsPull {
255-
if issue.PullRequest == nil {
255+
if issue.PullRequest == nil && issue.ID != 0 {
256256
issue.PullRequest, err = GetPullRequestByIssueID(ctx, issue.ID)
257257
if err != nil {
258258
if IsErrPullRequestNotExist(err) {
@@ -261,7 +261,9 @@ func (issue *Issue) LoadPullRequest(ctx context.Context) (err error) {
261261
return fmt.Errorf("getPullRequestByIssueID [%d]: %w", issue.ID, err)
262262
}
263263
}
264-
issue.PullRequest.Issue = issue
264+
if issue.PullRequest != nil {
265+
issue.PullRequest.Issue = issue
266+
}
265267
}
266268
return nil
267269
}
@@ -2128,15 +2130,18 @@ func (issue *Issue) GetParticipantIDsByIssue(ctx context.Context) ([]int64, erro
21282130
}
21292131

21302132
// BlockedByDependencies finds all Dependencies an issue is blocked by
2131-
func (issue *Issue) BlockedByDependencies(ctx context.Context) (issueDeps []*DependencyInfo, err error) {
2132-
err = db.GetEngine(ctx).
2133+
func (issue *Issue) BlockedByDependencies(ctx context.Context, opts db.ListOptions) (issueDeps []*DependencyInfo, err error) {
2134+
sess := db.GetEngine(ctx).
21332135
Table("issue").
21342136
Join("INNER", "repository", "repository.id = issue.repo_id").
21352137
Join("INNER", "issue_dependency", "issue_dependency.dependency_id = issue.id").
21362138
Where("issue_id = ?", issue.ID).
21372139
// sort by repo id then created date, with the issues of the same repo at the beginning of the list
2138-
OrderBy("CASE WHEN issue.repo_id = ? THEN 0 ELSE issue.repo_id END, issue.created_unix DESC", issue.RepoID).
2139-
Find(&issueDeps)
2140+
OrderBy("CASE WHEN issue.repo_id = ? THEN 0 ELSE issue.repo_id END, issue.created_unix DESC", issue.RepoID)
2141+
if opts.Page != 0 {
2142+
sess = db.SetSessionPagination(sess, &opts)
2143+
}
2144+
err = sess.Find(&issueDeps)
21402145

21412146
for _, depInfo := range issueDeps {
21422147
depInfo.Issue.Repo = &depInfo.Repository

models/repo/repo.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -658,6 +658,49 @@ func GetRepositoryByName(ownerID int64, name string) (*Repository, error) {
658658
return repo, err
659659
}
660660

661+
// getRepositoryURLPathSegments returns segments (owner, reponame) extracted from a url
662+
func getRepositoryURLPathSegments(repoURL string) []string {
663+
if strings.HasPrefix(repoURL, setting.AppURL) {
664+
return strings.Split(strings.TrimPrefix(repoURL, setting.AppURL), "/")
665+
}
666+
667+
sshURLVariants := [4]string{
668+
setting.SSH.Domain + ":",
669+
setting.SSH.User + "@" + setting.SSH.Domain + ":",
670+
"git+ssh://" + setting.SSH.Domain + "/",
671+
"git+ssh://" + setting.SSH.User + "@" + setting.SSH.Domain + "/",
672+
}
673+
674+
for _, sshURL := range sshURLVariants {
675+
if strings.HasPrefix(repoURL, sshURL) {
676+
return strings.Split(strings.TrimPrefix(repoURL, sshURL), "/")
677+
}
678+
}
679+
680+
return nil
681+
}
682+
683+
// GetRepositoryByURL returns the repository by given url
684+
func GetRepositoryByURL(ctx context.Context, repoURL string) (*Repository, error) {
685+
// possible urls for git:
686+
// https://my.domain/sub-path/<owner>/<repo>.git
687+
// https://my.domain/sub-path/<owner>/<repo>
688+
// git+ssh://[email protected]/<owner>/<repo>.git
689+
// git+ssh://[email protected]/<owner>/<repo>
690+
// [email protected]:<owner>/<repo>.git
691+
// [email protected]:<owner>/<repo>
692+
693+
pathSegments := getRepositoryURLPathSegments(repoURL)
694+
695+
if len(pathSegments) != 2 {
696+
return nil, fmt.Errorf("unknown or malformed repository URL")
697+
}
698+
699+
ownerName := pathSegments[0]
700+
repoName := strings.TrimSuffix(pathSegments[1], ".git")
701+
return GetRepositoryByOwnerAndName(ctx, ownerName, repoName)
702+
}
703+
661704
// GetRepositoryByID returns the repository by given id if exists.
662705
func GetRepositoryByID(ctx context.Context, id int64) (*Repository, error) {
663706
repo := new(Repository)

models/repo/repo_test.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -124,3 +124,65 @@ func TestMetas(t *testing.T) {
124124
assert.Equal(t, "user3", metas["org"])
125125
assert.Equal(t, ",owners,team1,", metas["teams"])
126126
}
127+
128+
func TestGetRepositoryByURL(t *testing.T) {
129+
assert.NoError(t, unittest.PrepareTestDatabase())
130+
131+
t.Run("InvalidPath", func(t *testing.T) {
132+
repo, err := repo_model.GetRepositoryByURL(db.DefaultContext, "something")
133+
134+
assert.Nil(t, repo)
135+
assert.Error(t, err)
136+
})
137+
138+
t.Run("ValidHttpURL", func(t *testing.T) {
139+
test := func(t *testing.T, url string) {
140+
repo, err := repo_model.GetRepositoryByURL(db.DefaultContext, url)
141+
142+
assert.NotNil(t, repo)
143+
assert.NoError(t, err)
144+
145+
assert.Equal(t, repo.ID, int64(2))
146+
assert.Equal(t, repo.OwnerID, int64(2))
147+
}
148+
149+
test(t, "https://try.gitea.io/user2/repo2")
150+
test(t, "https://try.gitea.io/user2/repo2.git")
151+
})
152+
153+
t.Run("ValidGitSshURL", func(t *testing.T) {
154+
test := func(t *testing.T, url string) {
155+
repo, err := repo_model.GetRepositoryByURL(db.DefaultContext, url)
156+
157+
assert.NotNil(t, repo)
158+
assert.NoError(t, err)
159+
160+
assert.Equal(t, repo.ID, int64(2))
161+
assert.Equal(t, repo.OwnerID, int64(2))
162+
}
163+
164+
test(t, "git+ssh://[email protected]/user2/repo2")
165+
test(t, "git+ssh://[email protected]/user2/repo2.git")
166+
167+
test(t, "git+ssh://try.gitea.io/user2/repo2")
168+
test(t, "git+ssh://try.gitea.io/user2/repo2.git")
169+
})
170+
171+
t.Run("ValidImplicitSshURL", func(t *testing.T) {
172+
test := func(t *testing.T, url string) {
173+
repo, err := repo_model.GetRepositoryByURL(db.DefaultContext, url)
174+
175+
assert.NotNil(t, repo)
176+
assert.NoError(t, err)
177+
178+
assert.Equal(t, repo.ID, int64(2))
179+
assert.Equal(t, repo.OwnerID, int64(2))
180+
}
181+
182+
test(t, "[email protected]:user2/repo2")
183+
test(t, "[email protected]:user2/repo2.git")
184+
185+
test(t, "try.gitea.io:user2/repo2")
186+
test(t, "try.gitea.io:user2/repo2.git")
187+
})
188+
}

0 commit comments

Comments
 (0)