Merge pull request '[TESTS] fail when log.Error is called' (#2657) from oliverpool/forgejo:fail_test_on_log_error into forgejo
Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/2657
This commit is contained in:
commit
5a18b74632
46 changed files with 732 additions and 105 deletions
|
@ -271,13 +271,19 @@ package "code.gitea.io/gitea/modules/sync"
|
||||||
|
|
||||||
package "code.gitea.io/gitea/modules/testlogger"
|
package "code.gitea.io/gitea/modules/testlogger"
|
||||||
func (*testLoggerWriterCloser).pushT
|
func (*testLoggerWriterCloser).pushT
|
||||||
func (*testLoggerWriterCloser).Write
|
func (*testLoggerWriterCloser).Log
|
||||||
|
func (*testLoggerWriterCloser).recordError
|
||||||
|
func (*testLoggerWriterCloser).printMsg
|
||||||
func (*testLoggerWriterCloser).popT
|
func (*testLoggerWriterCloser).popT
|
||||||
func (*testLoggerWriterCloser).Close
|
|
||||||
func (*testLoggerWriterCloser).Reset
|
func (*testLoggerWriterCloser).Reset
|
||||||
func PrintCurrentTest
|
func PrintCurrentTest
|
||||||
func Printf
|
func Printf
|
||||||
func NewTestLoggerWriter
|
func NewTestLoggerWriter
|
||||||
|
func (*TestLogEventWriter).Base
|
||||||
|
func (*TestLogEventWriter).GetLevel
|
||||||
|
func (*TestLogEventWriter).GetWriterName
|
||||||
|
func (*TestLogEventWriter).GetWriterType
|
||||||
|
func (*TestLogEventWriter).Run
|
||||||
|
|
||||||
package "code.gitea.io/gitea/modules/timeutil"
|
package "code.gitea.io/gitea/modules/timeutil"
|
||||||
func GetExecutableModTime
|
func GetExecutableModTime
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
repo_id: 2 # private
|
repo_id: 2 # private
|
||||||
is_private: true
|
is_private: true
|
||||||
created_unix: 1603228283
|
created_unix: 1603228283
|
||||||
|
content: '1|' # issueId 4
|
||||||
|
|
||||||
-
|
-
|
||||||
id: 2
|
id: 2
|
||||||
|
|
|
@ -17,6 +17,195 @@
|
||||||
updated: 1683636626
|
updated: 1683636626
|
||||||
need_approval: 0
|
need_approval: 0
|
||||||
approved_by: 0
|
approved_by: 0
|
||||||
|
event_payload: |
|
||||||
|
{
|
||||||
|
"after": "7a3858dc7f059543a8807a8b551304b7e362a7ef",
|
||||||
|
"before": "0000000000000000000000000000000000000000",
|
||||||
|
"commits": [
|
||||||
|
{
|
||||||
|
"added": [
|
||||||
|
".forgejo/workflows/test.yml"
|
||||||
|
],
|
||||||
|
"author": {
|
||||||
|
"email": "root@example.com",
|
||||||
|
"name": "username",
|
||||||
|
"username": "root"
|
||||||
|
},
|
||||||
|
"committer": {
|
||||||
|
"email": "root@example.com",
|
||||||
|
"name": "username",
|
||||||
|
"username": "root"
|
||||||
|
},
|
||||||
|
"id": "7a3858dc7f059543a8807a8b551304b7e362a7ef",
|
||||||
|
"message": "initial commit\n",
|
||||||
|
"modified": [],
|
||||||
|
"removed": [],
|
||||||
|
"timestamp": "2024-01-24T18:59:25Z",
|
||||||
|
"url": "http://10.201.14.40:3000/root/example-push/commit/7a3858dc7f059543a8807a8b551304b7e362a7ef",
|
||||||
|
"verification": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"compare_url": "http://10.201.14.40:3000/",
|
||||||
|
"head_commit": {
|
||||||
|
"added": [
|
||||||
|
".forgejo/workflows/test.yml"
|
||||||
|
],
|
||||||
|
"author": {
|
||||||
|
"email": "root@example.com",
|
||||||
|
"name": "username",
|
||||||
|
"username": "root"
|
||||||
|
},
|
||||||
|
"committer": {
|
||||||
|
"email": "root@example.com",
|
||||||
|
"name": "username",
|
||||||
|
"username": "root"
|
||||||
|
},
|
||||||
|
"id": "7a3858dc7f059543a8807a8b551304b7e362a7ef",
|
||||||
|
"message": "initial commit\n",
|
||||||
|
"modified": [],
|
||||||
|
"removed": [],
|
||||||
|
"timestamp": "2024-01-24T18:59:25Z",
|
||||||
|
"url": "http://10.201.14.40:3000/root/example-push/commit/7a3858dc7f059543a8807a8b551304b7e362a7ef",
|
||||||
|
"verification": null
|
||||||
|
},
|
||||||
|
"pusher": {
|
||||||
|
"active": false,
|
||||||
|
"avatar_url": "http://10.201.14.40:3000/avatars/04edfc0ef6c6cf6d6b88fbc69f9f9071",
|
||||||
|
"created": "2024-01-24T18:57:32Z",
|
||||||
|
"description": "",
|
||||||
|
"email": "root@noreply.10.201.14.40",
|
||||||
|
"followers_count": 0,
|
||||||
|
"following_count": 0,
|
||||||
|
"full_name": "",
|
||||||
|
"id": 1,
|
||||||
|
"is_admin": false,
|
||||||
|
"language": "",
|
||||||
|
"last_login": "0001-01-01T00:00:00Z",
|
||||||
|
"location": "",
|
||||||
|
"login": "root",
|
||||||
|
"login_name": "",
|
||||||
|
"prohibit_login": false,
|
||||||
|
"restricted": false,
|
||||||
|
"starred_repos_count": 0,
|
||||||
|
"username": "root",
|
||||||
|
"visibility": "public",
|
||||||
|
"website": ""
|
||||||
|
},
|
||||||
|
"ref": "refs/heads/main",
|
||||||
|
"repository": {
|
||||||
|
"allow_merge_commits": true,
|
||||||
|
"allow_rebase": true,
|
||||||
|
"allow_rebase_explicit": true,
|
||||||
|
"allow_rebase_update": true,
|
||||||
|
"allow_squash_merge": true,
|
||||||
|
"archived": false,
|
||||||
|
"archived_at": "1970-01-01T00:00:00Z",
|
||||||
|
"avatar_url": "",
|
||||||
|
"clone_url": "http://10.201.14.40:3000/root/example-push.git",
|
||||||
|
"created_at": "2024-01-24T18:59:25Z",
|
||||||
|
"default_allow_maintainer_edit": false,
|
||||||
|
"default_branch": "main",
|
||||||
|
"default_delete_branch_after_merge": false,
|
||||||
|
"default_merge_style": "merge",
|
||||||
|
"description": "",
|
||||||
|
"empty": false,
|
||||||
|
"fork": false,
|
||||||
|
"forks_count": 0,
|
||||||
|
"full_name": "root/example-push",
|
||||||
|
"has_actions": true,
|
||||||
|
"has_issues": true,
|
||||||
|
"has_packages": true,
|
||||||
|
"has_projects": true,
|
||||||
|
"has_pull_requests": true,
|
||||||
|
"has_releases": true,
|
||||||
|
"has_wiki": true,
|
||||||
|
"html_url": "http://10.201.14.40:3000/root/example-push",
|
||||||
|
"id": 2,
|
||||||
|
"ignore_whitespace_conflicts": false,
|
||||||
|
"internal": false,
|
||||||
|
"internal_tracker": {
|
||||||
|
"allow_only_contributors_to_track_time": true,
|
||||||
|
"enable_issue_dependencies": true,
|
||||||
|
"enable_time_tracker": true
|
||||||
|
},
|
||||||
|
"language": "",
|
||||||
|
"languages_url": "http://10.201.14.40:3000/api/v1/repos/root/example-push/languages",
|
||||||
|
"link": "",
|
||||||
|
"mirror": false,
|
||||||
|
"mirror_interval": "",
|
||||||
|
"mirror_updated": "0001-01-01T00:00:00Z",
|
||||||
|
"name": "example-push",
|
||||||
|
"object_format_name": "",
|
||||||
|
"open_issues_count": 0,
|
||||||
|
"open_pr_counter": 0,
|
||||||
|
"original_url": "",
|
||||||
|
"owner": {
|
||||||
|
"active": false,
|
||||||
|
"avatar_url": "http://10.201.14.40:3000/avatars/04edfc0ef6c6cf6d6b88fbc69f9f9071",
|
||||||
|
"created": "2024-01-24T18:57:32Z",
|
||||||
|
"description": "",
|
||||||
|
"email": "root@example.com",
|
||||||
|
"followers_count": 0,
|
||||||
|
"following_count": 0,
|
||||||
|
"full_name": "",
|
||||||
|
"id": 1,
|
||||||
|
"is_admin": false,
|
||||||
|
"language": "",
|
||||||
|
"last_login": "0001-01-01T00:00:00Z",
|
||||||
|
"location": "",
|
||||||
|
"login": "root",
|
||||||
|
"login_name": "",
|
||||||
|
"prohibit_login": false,
|
||||||
|
"restricted": false,
|
||||||
|
"starred_repos_count": 0,
|
||||||
|
"username": "root",
|
||||||
|
"visibility": "public",
|
||||||
|
"website": ""
|
||||||
|
},
|
||||||
|
"parent": null,
|
||||||
|
"permissions": {
|
||||||
|
"admin": true,
|
||||||
|
"pull": true,
|
||||||
|
"push": true
|
||||||
|
},
|
||||||
|
"private": false,
|
||||||
|
"release_counter": 0,
|
||||||
|
"repo_transfer": null,
|
||||||
|
"size": 25,
|
||||||
|
"ssh_url": "forgejo@10.201.14.40:root/example-push.git",
|
||||||
|
"stars_count": 0,
|
||||||
|
"template": false,
|
||||||
|
"updated_at": "2024-01-24T18:59:25Z",
|
||||||
|
"url": "http://10.201.14.40:3000/api/v1/repos/root/example-push",
|
||||||
|
"watchers_count": 1,
|
||||||
|
"website": ""
|
||||||
|
},
|
||||||
|
"sender": {
|
||||||
|
"active": false,
|
||||||
|
"avatar_url": "http://10.201.14.40:3000/avatars/04edfc0ef6c6cf6d6b88fbc69f9f9071",
|
||||||
|
"created": "2024-01-24T18:57:32Z",
|
||||||
|
"description": "",
|
||||||
|
"email": "root@noreply.10.201.14.40",
|
||||||
|
"followers_count": 0,
|
||||||
|
"following_count": 0,
|
||||||
|
"full_name": "",
|
||||||
|
"id": 1,
|
||||||
|
"is_admin": false,
|
||||||
|
"language": "",
|
||||||
|
"last_login": "0001-01-01T00:00:00Z",
|
||||||
|
"location": "",
|
||||||
|
"login": "root",
|
||||||
|
"login_name": "",
|
||||||
|
"prohibit_login": false,
|
||||||
|
"restricted": false,
|
||||||
|
"starred_repos_count": 0,
|
||||||
|
"username": "root",
|
||||||
|
"visibility": "public",
|
||||||
|
"website": ""
|
||||||
|
},
|
||||||
|
"total_commits": 0
|
||||||
|
}
|
||||||
|
|
||||||
-
|
-
|
||||||
id: 792
|
id: 792
|
||||||
title: "update actions"
|
title: "update actions"
|
||||||
|
@ -36,3 +225,191 @@
|
||||||
updated: 1683636626
|
updated: 1683636626
|
||||||
need_approval: 0
|
need_approval: 0
|
||||||
approved_by: 0
|
approved_by: 0
|
||||||
|
event_payload: |
|
||||||
|
{
|
||||||
|
"after": "7a3858dc7f059543a8807a8b551304b7e362a7ef",
|
||||||
|
"before": "0000000000000000000000000000000000000000",
|
||||||
|
"commits": [
|
||||||
|
{
|
||||||
|
"added": [
|
||||||
|
".forgejo/workflows/test.yml"
|
||||||
|
],
|
||||||
|
"author": {
|
||||||
|
"email": "root@example.com",
|
||||||
|
"name": "username",
|
||||||
|
"username": "root"
|
||||||
|
},
|
||||||
|
"committer": {
|
||||||
|
"email": "root@example.com",
|
||||||
|
"name": "username",
|
||||||
|
"username": "root"
|
||||||
|
},
|
||||||
|
"id": "7a3858dc7f059543a8807a8b551304b7e362a7ef",
|
||||||
|
"message": "initial commit\n",
|
||||||
|
"modified": [],
|
||||||
|
"removed": [],
|
||||||
|
"timestamp": "2024-01-24T18:59:25Z",
|
||||||
|
"url": "http://10.201.14.40:3000/root/example-push/commit/7a3858dc7f059543a8807a8b551304b7e362a7ef",
|
||||||
|
"verification": null
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"compare_url": "http://10.201.14.40:3000/",
|
||||||
|
"head_commit": {
|
||||||
|
"added": [
|
||||||
|
".forgejo/workflows/test.yml"
|
||||||
|
],
|
||||||
|
"author": {
|
||||||
|
"email": "root@example.com",
|
||||||
|
"name": "username",
|
||||||
|
"username": "root"
|
||||||
|
},
|
||||||
|
"committer": {
|
||||||
|
"email": "root@example.com",
|
||||||
|
"name": "username",
|
||||||
|
"username": "root"
|
||||||
|
},
|
||||||
|
"id": "7a3858dc7f059543a8807a8b551304b7e362a7ef",
|
||||||
|
"message": "initial commit\n",
|
||||||
|
"modified": [],
|
||||||
|
"removed": [],
|
||||||
|
"timestamp": "2024-01-24T18:59:25Z",
|
||||||
|
"url": "http://10.201.14.40:3000/root/example-push/commit/7a3858dc7f059543a8807a8b551304b7e362a7ef",
|
||||||
|
"verification": null
|
||||||
|
},
|
||||||
|
"pusher": {
|
||||||
|
"active": false,
|
||||||
|
"avatar_url": "http://10.201.14.40:3000/avatars/04edfc0ef6c6cf6d6b88fbc69f9f9071",
|
||||||
|
"created": "2024-01-24T18:57:32Z",
|
||||||
|
"description": "",
|
||||||
|
"email": "root@noreply.10.201.14.40",
|
||||||
|
"followers_count": 0,
|
||||||
|
"following_count": 0,
|
||||||
|
"full_name": "",
|
||||||
|
"id": 1,
|
||||||
|
"is_admin": false,
|
||||||
|
"language": "",
|
||||||
|
"last_login": "0001-01-01T00:00:00Z",
|
||||||
|
"location": "",
|
||||||
|
"login": "root",
|
||||||
|
"login_name": "",
|
||||||
|
"prohibit_login": false,
|
||||||
|
"restricted": false,
|
||||||
|
"starred_repos_count": 0,
|
||||||
|
"username": "root",
|
||||||
|
"visibility": "public",
|
||||||
|
"website": ""
|
||||||
|
},
|
||||||
|
"ref": "refs/heads/main",
|
||||||
|
"repository": {
|
||||||
|
"allow_merge_commits": true,
|
||||||
|
"allow_rebase": true,
|
||||||
|
"allow_rebase_explicit": true,
|
||||||
|
"allow_rebase_update": true,
|
||||||
|
"allow_squash_merge": true,
|
||||||
|
"archived": false,
|
||||||
|
"archived_at": "1970-01-01T00:00:00Z",
|
||||||
|
"avatar_url": "",
|
||||||
|
"clone_url": "http://10.201.14.40:3000/root/example-push.git",
|
||||||
|
"created_at": "2024-01-24T18:59:25Z",
|
||||||
|
"default_allow_maintainer_edit": false,
|
||||||
|
"default_branch": "main",
|
||||||
|
"default_delete_branch_after_merge": false,
|
||||||
|
"default_merge_style": "merge",
|
||||||
|
"description": "",
|
||||||
|
"empty": false,
|
||||||
|
"fork": false,
|
||||||
|
"forks_count": 0,
|
||||||
|
"full_name": "root/example-push",
|
||||||
|
"has_actions": true,
|
||||||
|
"has_issues": true,
|
||||||
|
"has_packages": true,
|
||||||
|
"has_projects": true,
|
||||||
|
"has_pull_requests": true,
|
||||||
|
"has_releases": true,
|
||||||
|
"has_wiki": true,
|
||||||
|
"html_url": "http://10.201.14.40:3000/root/example-push",
|
||||||
|
"id": 2,
|
||||||
|
"ignore_whitespace_conflicts": false,
|
||||||
|
"internal": false,
|
||||||
|
"internal_tracker": {
|
||||||
|
"allow_only_contributors_to_track_time": true,
|
||||||
|
"enable_issue_dependencies": true,
|
||||||
|
"enable_time_tracker": true
|
||||||
|
},
|
||||||
|
"language": "",
|
||||||
|
"languages_url": "http://10.201.14.40:3000/api/v1/repos/root/example-push/languages",
|
||||||
|
"link": "",
|
||||||
|
"mirror": false,
|
||||||
|
"mirror_interval": "",
|
||||||
|
"mirror_updated": "0001-01-01T00:00:00Z",
|
||||||
|
"name": "example-push",
|
||||||
|
"object_format_name": "",
|
||||||
|
"open_issues_count": 0,
|
||||||
|
"open_pr_counter": 0,
|
||||||
|
"original_url": "",
|
||||||
|
"owner": {
|
||||||
|
"active": false,
|
||||||
|
"avatar_url": "http://10.201.14.40:3000/avatars/04edfc0ef6c6cf6d6b88fbc69f9f9071",
|
||||||
|
"created": "2024-01-24T18:57:32Z",
|
||||||
|
"description": "",
|
||||||
|
"email": "root@example.com",
|
||||||
|
"followers_count": 0,
|
||||||
|
"following_count": 0,
|
||||||
|
"full_name": "",
|
||||||
|
"id": 1,
|
||||||
|
"is_admin": false,
|
||||||
|
"language": "",
|
||||||
|
"last_login": "0001-01-01T00:00:00Z",
|
||||||
|
"location": "",
|
||||||
|
"login": "root",
|
||||||
|
"login_name": "",
|
||||||
|
"prohibit_login": false,
|
||||||
|
"restricted": false,
|
||||||
|
"starred_repos_count": 0,
|
||||||
|
"username": "root",
|
||||||
|
"visibility": "public",
|
||||||
|
"website": ""
|
||||||
|
},
|
||||||
|
"parent": null,
|
||||||
|
"permissions": {
|
||||||
|
"admin": true,
|
||||||
|
"pull": true,
|
||||||
|
"push": true
|
||||||
|
},
|
||||||
|
"private": false,
|
||||||
|
"release_counter": 0,
|
||||||
|
"repo_transfer": null,
|
||||||
|
"size": 25,
|
||||||
|
"ssh_url": "forgejo@10.201.14.40:root/example-push.git",
|
||||||
|
"stars_count": 0,
|
||||||
|
"template": false,
|
||||||
|
"updated_at": "2024-01-24T18:59:25Z",
|
||||||
|
"url": "http://10.201.14.40:3000/api/v1/repos/root/example-push",
|
||||||
|
"watchers_count": 1,
|
||||||
|
"website": ""
|
||||||
|
},
|
||||||
|
"sender": {
|
||||||
|
"active": false,
|
||||||
|
"avatar_url": "http://10.201.14.40:3000/avatars/04edfc0ef6c6cf6d6b88fbc69f9f9071",
|
||||||
|
"created": "2024-01-24T18:57:32Z",
|
||||||
|
"description": "",
|
||||||
|
"email": "root@noreply.10.201.14.40",
|
||||||
|
"followers_count": 0,
|
||||||
|
"following_count": 0,
|
||||||
|
"full_name": "",
|
||||||
|
"id": 1,
|
||||||
|
"is_admin": false,
|
||||||
|
"language": "",
|
||||||
|
"last_login": "0001-01-01T00:00:00Z",
|
||||||
|
"location": "",
|
||||||
|
"login": "root",
|
||||||
|
"login_name": "",
|
||||||
|
"prohibit_login": false,
|
||||||
|
"restricted": false,
|
||||||
|
"starred_repos_count": 0,
|
||||||
|
"username": "root",
|
||||||
|
"visibility": "public",
|
||||||
|
"website": ""
|
||||||
|
},
|
||||||
|
"total_commits": 0
|
||||||
|
}
|
||||||
|
|
|
@ -1,15 +1,17 @@
|
||||||
-
|
-
|
||||||
id: 1
|
id: 1
|
||||||
repo_id: 1
|
repo_id: 1
|
||||||
url: www.example.com/url1
|
url: http://www.example.com/url1
|
||||||
|
http_method: POST
|
||||||
content_type: 1 # json
|
content_type: 1 # json
|
||||||
events: '{"push_only":true,"send_everything":false,"choose_events":false,"events":{"create":false,"push":true,"pull_request":false}}'
|
events: '{"push_only":true,"send_everything":false,"choose_events":false,"events":{"create":false,"push":true,"pull_request":false}}'
|
||||||
is_active: true
|
is_active: false # disable to prevent sending hook task during unrelated tests
|
||||||
|
|
||||||
-
|
-
|
||||||
id: 2
|
id: 2
|
||||||
repo_id: 1
|
repo_id: 1
|
||||||
url: www.example.com/url2
|
url: http://www.example.com/url2
|
||||||
|
http_method: POST
|
||||||
content_type: 1 # json
|
content_type: 1 # json
|
||||||
events: '{"push_only":false,"send_everything":false,"choose_events":false,"events":{"create":false,"push":true,"pull_request":true}}'
|
events: '{"push_only":false,"send_everything":false,"choose_events":false,"events":{"create":false,"push":true,"pull_request":true}}'
|
||||||
is_active: false
|
is_active: false
|
||||||
|
@ -18,14 +20,16 @@
|
||||||
id: 3
|
id: 3
|
||||||
owner_id: 3
|
owner_id: 3
|
||||||
repo_id: 3
|
repo_id: 3
|
||||||
url: www.example.com/url3
|
url: http://www.example.com/url3
|
||||||
|
http_method: POST
|
||||||
content_type: 1 # json
|
content_type: 1 # json
|
||||||
events: '{"push_only":false,"send_everything":false,"choose_events":false,"events":{"create":false,"push":true,"pull_request":true}}'
|
events: '{"push_only":false,"send_everything":false,"choose_events":false,"events":{"create":false,"push":true,"pull_request":true}}'
|
||||||
is_active: true
|
is_active: false
|
||||||
-
|
-
|
||||||
id: 4
|
id: 4
|
||||||
repo_id: 2
|
repo_id: 2
|
||||||
url: www.example.com/url4
|
url: http://www.example.com/url4
|
||||||
|
http_method: POST
|
||||||
content_type: 1 # json
|
content_type: 1 # json
|
||||||
events: '{"push_only":true,"branch_filter":"{master,feature*}"}'
|
events: '{"push_only":true,"branch_filter":"{master,feature*}"}'
|
||||||
is_active: true
|
is_active: false
|
||||||
|
|
|
@ -199,22 +199,17 @@ func (status *CommitStatus) LocaleString(lang translation.Locale) string {
|
||||||
|
|
||||||
// CalcCommitStatus returns commit status state via some status, the commit statues should order by id desc
|
// CalcCommitStatus returns commit status state via some status, the commit statues should order by id desc
|
||||||
func CalcCommitStatus(statuses []*CommitStatus) *CommitStatus {
|
func CalcCommitStatus(statuses []*CommitStatus) *CommitStatus {
|
||||||
var lastStatus *CommitStatus
|
if len(statuses) == 0 {
|
||||||
state := api.CommitStatusSuccess
|
return nil
|
||||||
for _, status := range statuses {
|
}
|
||||||
if status.State.NoBetterThan(state) {
|
|
||||||
state = status.State
|
latestWorstStatus := statuses[0]
|
||||||
lastStatus = status
|
for _, status := range statuses[1:] {
|
||||||
|
if status.State.NoBetterThan(latestWorstStatus.State) {
|
||||||
|
latestWorstStatus = status
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if lastStatus == nil {
|
return latestWorstStatus
|
||||||
if len(statuses) > 0 {
|
|
||||||
lastStatus = statuses[0]
|
|
||||||
} else {
|
|
||||||
lastStatus = &CommitStatus{}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return lastStatus
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// CommitStatusOptions holds the options for query commit statuses
|
// CommitStatusOptions holds the options for query commit statuses
|
||||||
|
|
|
@ -141,16 +141,20 @@ func Test_CalcCommitStatus(t *testing.T) {
|
||||||
statuses: []*git_model.CommitStatus{
|
statuses: []*git_model.CommitStatus{
|
||||||
{
|
{
|
||||||
State: structs.CommitStatusSuccess,
|
State: structs.CommitStatusSuccess,
|
||||||
|
ID: 1,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
State: structs.CommitStatusSuccess,
|
State: structs.CommitStatusSuccess,
|
||||||
|
ID: 2,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
State: structs.CommitStatusSuccess,
|
State: structs.CommitStatusSuccess,
|
||||||
|
ID: 3,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
expected: &git_model.CommitStatus{
|
expected: &git_model.CommitStatus{
|
||||||
State: structs.CommitStatusSuccess,
|
State: structs.CommitStatusSuccess,
|
||||||
|
ID: 3,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -169,6 +173,10 @@ func Test_CalcCommitStatus(t *testing.T) {
|
||||||
State: structs.CommitStatusError,
|
State: structs.CommitStatusError,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
statuses: []*git_model.CommitStatus{},
|
||||||
|
expected: nil,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, kase := range kases {
|
for _, kase := range kases {
|
||||||
|
|
|
@ -500,7 +500,7 @@ func (issue *Issue) GetLastEventLabelFake() string {
|
||||||
// GetIssueByIndex returns raw issue without loading attributes by index in a repository.
|
// GetIssueByIndex returns raw issue without loading attributes by index in a repository.
|
||||||
func GetIssueByIndex(ctx context.Context, repoID, index int64) (*Issue, error) {
|
func GetIssueByIndex(ctx context.Context, repoID, index int64) (*Issue, error) {
|
||||||
if index < 1 {
|
if index < 1 {
|
||||||
return nil, ErrIssueNotExist{}
|
return nil, ErrIssueNotExist{0, repoID, index}
|
||||||
}
|
}
|
||||||
issue := &Issue{
|
issue := &Issue{
|
||||||
RepoID: repoID,
|
RepoID: repoID,
|
||||||
|
|
|
@ -160,6 +160,10 @@ func MainTest(m *testing.M) {
|
||||||
|
|
||||||
exitStatus := m.Run()
|
exitStatus := m.Run()
|
||||||
|
|
||||||
|
if err := testlogger.WriterCloser.Reset(); err != nil && exitStatus == 0 {
|
||||||
|
fmt.Printf("testlogger.WriterCloser.Reset: %v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
if err := removeAllWithRetry(setting.RepoRootPath); err != nil {
|
if err := removeAllWithRetry(setting.RepoRootPath); err != nil {
|
||||||
fmt.Fprintf(os.Stderr, "os.RemoveAll: %v\n", err)
|
fmt.Fprintf(os.Stderr, "os.RemoveAll: %v\n", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,8 +24,8 @@ func AddBranchProtectionCanPushAndEnableWhitelist(x *xorm.Engine) error {
|
||||||
|
|
||||||
// Permissions
|
// Permissions
|
||||||
IsAdmin bool
|
IsAdmin bool
|
||||||
IsRestricted bool `xorm:"NOT NULL DEFAULT false"`
|
// IsRestricted bool `xorm:"NOT NULL DEFAULT false"` glitch: this column was added in v1_12/v121.go
|
||||||
Visibility int `xorm:"NOT NULL DEFAULT 0"`
|
// Visibility int `xorm:"NOT NULL DEFAULT 0"` glitch: this column was added in v1_12/v124.go
|
||||||
}
|
}
|
||||||
|
|
||||||
type Review struct {
|
type Review struct {
|
||||||
|
@ -51,9 +51,9 @@ func AddBranchProtectionCanPushAndEnableWhitelist(x *xorm.Engine) error {
|
||||||
ReviewTypeReject int = 3
|
ReviewTypeReject int = 3
|
||||||
|
|
||||||
// VisibleTypePublic Visible for everyone
|
// VisibleTypePublic Visible for everyone
|
||||||
VisibleTypePublic int = 0
|
// VisibleTypePublic int = 0
|
||||||
// VisibleTypePrivate Visible only for organization's members
|
// VisibleTypePrivate Visible only for organization's members
|
||||||
VisibleTypePrivate int = 2
|
// VisibleTypePrivate int = 2
|
||||||
|
|
||||||
// unit.UnitTypeCode is unit type code
|
// unit.UnitTypeCode is unit type code
|
||||||
UnitTypeCode int = 1
|
UnitTypeCode int = 1
|
||||||
|
@ -145,9 +145,9 @@ func AddBranchProtectionCanPushAndEnableWhitelist(x *xorm.Engine) error {
|
||||||
hasOrgVisible := true
|
hasOrgVisible := true
|
||||||
// Not SignedUser
|
// Not SignedUser
|
||||||
if user == nil {
|
if user == nil {
|
||||||
hasOrgVisible = repoOwner.Visibility == VisibleTypePublic
|
// hasOrgVisible = repoOwner.Visibility == VisibleTypePublic // VisibleTypePublic is the default
|
||||||
} else if !user.IsAdmin {
|
} else if !user.IsAdmin {
|
||||||
hasMemberWithUserID, err := sess.
|
_, err := sess.
|
||||||
Where("uid=?", user.ID).
|
Where("uid=?", user.ID).
|
||||||
And("org_id=?", repoOwner.ID).
|
And("org_id=?", repoOwner.ID).
|
||||||
Table("org_user").
|
Table("org_user").
|
||||||
|
@ -155,9 +155,10 @@ func AddBranchProtectionCanPushAndEnableWhitelist(x *xorm.Engine) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
hasOrgVisible = false
|
hasOrgVisible = false
|
||||||
}
|
}
|
||||||
if (repoOwner.Visibility == VisibleTypePrivate || user.IsRestricted) && !hasMemberWithUserID {
|
// VisibleTypePublic is the default so the condition below is always false
|
||||||
hasOrgVisible = false
|
// if (repoOwner.Visibility == VisibleTypePrivate) && !hasMemberWithUserID {
|
||||||
}
|
// hasOrgVisible = false
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
isCollaborator, err := sess.Get(&Collaboration{RepoID: repo.ID, UserID: user.ID})
|
isCollaborator, err := sess.Get(&Collaboration{RepoID: repo.ID, UserID: user.ID})
|
||||||
|
@ -195,7 +196,7 @@ func AddBranchProtectionCanPushAndEnableWhitelist(x *xorm.Engine) error {
|
||||||
|
|
||||||
if user != nil {
|
if user != nil {
|
||||||
userID = user.ID
|
userID = user.ID
|
||||||
restricted = user.IsRestricted
|
restricted = false
|
||||||
}
|
}
|
||||||
|
|
||||||
if !restricted && !repo.IsPrivate {
|
if !restricted && !repo.IsPrivate {
|
||||||
|
@ -284,7 +285,7 @@ func AddBranchProtectionCanPushAndEnableWhitelist(x *xorm.Engine) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
// for a public repo on an organization, a non-restricted user has read permission on non-team defined units.
|
// for a public repo on an organization, a non-restricted user has read permission on non-team defined units.
|
||||||
if !found && !repo.IsPrivate && !user.IsRestricted {
|
if !found && !repo.IsPrivate {
|
||||||
if _, ok := perm.UnitsMode[u.Type]; !ok {
|
if _, ok := perm.UnitsMode[u.Type]; !ok {
|
||||||
perm.UnitsMode[u.Type] = AccessModeRead
|
perm.UnitsMode[u.Type] = AccessModeRead
|
||||||
}
|
}
|
||||||
|
|
|
@ -94,7 +94,7 @@ func FixMergeBase(x *xorm.Engine) error {
|
||||||
} else {
|
} else {
|
||||||
parentsString, _, err := git.NewCommand(git.DefaultContext, "rev-list", "--parents", "-n", "1").AddDynamicArguments(pr.MergedCommitID).RunStdString(&git.RunOpts{Dir: repoPath})
|
parentsString, _, err := git.NewCommand(git.DefaultContext, "rev-list", "--parents", "-n", "1").AddDynamicArguments(pr.MergedCommitID).RunStdString(&git.RunOpts{Dir: repoPath})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Unable to get parents for merged PR ID %d, Index %d in %s/%s. Error: %v", pr.ID, pr.Index, baseRepo.OwnerName, baseRepo.Name, err)
|
log.Warn("Unable to get parents for merged PR ID %d, Index %d in %s/%s. Error: %v", pr.ID, pr.Index, baseRepo.OwnerName, baseRepo.Name, err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
parents := strings.Split(strings.TrimSpace(parentsString), " ")
|
parents := strings.Split(strings.TrimSpace(parentsString), " ")
|
||||||
|
|
|
@ -81,7 +81,7 @@ func RefixMergeBase(x *xorm.Engine) error {
|
||||||
|
|
||||||
parentsString, _, err := git.NewCommand(git.DefaultContext, "rev-list", "--parents", "-n", "1").AddDynamicArguments(pr.MergedCommitID).RunStdString(&git.RunOpts{Dir: repoPath})
|
parentsString, _, err := git.NewCommand(git.DefaultContext, "rev-list", "--parents", "-n", "1").AddDynamicArguments(pr.MergedCommitID).RunStdString(&git.RunOpts{Dir: repoPath})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Unable to get parents for merged PR ID %d, Index %d in %s/%s. Error: %v", pr.ID, pr.Index, baseRepo.OwnerName, baseRepo.Name, err)
|
log.Warn("Unable to get parents for merged PR ID %d, Index %d in %s/%s. Error: %v", pr.ID, pr.Index, baseRepo.OwnerName, baseRepo.Name, err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
parents := strings.Split(strings.TrimSpace(parentsString), " ")
|
parents := strings.Split(strings.TrimSpace(parentsString), " ")
|
||||||
|
|
|
@ -124,6 +124,9 @@ func TestGetWebhookByOwnerID(t *testing.T) {
|
||||||
|
|
||||||
func TestGetActiveWebhooksByRepoID(t *testing.T) {
|
func TestGetActiveWebhooksByRepoID(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
|
activateWebhook(t, 1)
|
||||||
|
|
||||||
hooks, err := db.Find[Webhook](db.DefaultContext, ListWebhookOptions{RepoID: 1, IsActive: optional.Some(true)})
|
hooks, err := db.Find[Webhook](db.DefaultContext, ListWebhookOptions{RepoID: 1, IsActive: optional.Some(true)})
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
if assert.Len(t, hooks, 1) {
|
if assert.Len(t, hooks, 1) {
|
||||||
|
@ -144,6 +147,9 @@ func TestGetWebhooksByRepoID(t *testing.T) {
|
||||||
|
|
||||||
func TestGetActiveWebhooksByOwnerID(t *testing.T) {
|
func TestGetActiveWebhooksByOwnerID(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
|
activateWebhook(t, 3)
|
||||||
|
|
||||||
hooks, err := db.Find[Webhook](db.DefaultContext, ListWebhookOptions{OwnerID: 3, IsActive: optional.Some(true)})
|
hooks, err := db.Find[Webhook](db.DefaultContext, ListWebhookOptions{OwnerID: 3, IsActive: optional.Some(true)})
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
if assert.Len(t, hooks, 1) {
|
if assert.Len(t, hooks, 1) {
|
||||||
|
@ -152,8 +158,18 @@ func TestGetActiveWebhooksByOwnerID(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func activateWebhook(t *testing.T, hookID int64) {
|
||||||
|
t.Helper()
|
||||||
|
updated, err := db.GetEngine(db.DefaultContext).ID(hookID).Cols("is_active").Update(Webhook{IsActive: true})
|
||||||
|
assert.Equal(t, int64(1), updated)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
func TestGetWebhooksByOwnerID(t *testing.T) {
|
func TestGetWebhooksByOwnerID(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
|
activateWebhook(t, 3)
|
||||||
|
|
||||||
hooks, err := db.Find[Webhook](db.DefaultContext, ListWebhookOptions{OwnerID: 3})
|
hooks, err := db.Find[Webhook](db.DefaultContext, ListWebhookOptions{OwnerID: 3})
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
if assert.Len(t, hooks, 1) {
|
if assert.Len(t, hooks, 1) {
|
||||||
|
|
|
@ -334,7 +334,10 @@ func (q *WorkerPoolQueue[T]) doRun() {
|
||||||
// since we are already in a "flush" operation, so the dispatching function shouldn't read the flush chan.
|
// since we are already in a "flush" operation, so the dispatching function shouldn't read the flush chan.
|
||||||
q.doDispatchBatchToWorker(wg, skipFlushChan)
|
q.doDispatchBatchToWorker(wg, skipFlushChan)
|
||||||
q.doFlush(wg, flush)
|
q.doFlush(wg, flush)
|
||||||
case err := <-wg.popItemErr:
|
case err, errOk := <-wg.popItemErr:
|
||||||
|
if !errOk {
|
||||||
|
return
|
||||||
|
}
|
||||||
if !q.isCtxRunCanceled() {
|
if !q.isCtxRunCanceled() {
|
||||||
log.Error("Failed to pop item from queue %q (doRun): %v", q.GetName(), err)
|
log.Error("Failed to pop item from queue %q (doRun): %v", q.GetName(), err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,8 +4,11 @@
|
||||||
package testlogger
|
package testlogger
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -28,52 +31,145 @@ var WriterCloser = &testLoggerWriterCloser{}
|
||||||
type testLoggerWriterCloser struct {
|
type testLoggerWriterCloser struct {
|
||||||
sync.RWMutex
|
sync.RWMutex
|
||||||
t []testing.TB
|
t []testing.TB
|
||||||
|
errs []error // stack of error, parallel to the stack of testing.TB
|
||||||
|
err error // fallback if the stack is empty
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *testLoggerWriterCloser) pushT(t testing.TB) {
|
func (w *testLoggerWriterCloser) pushT(t testing.TB) {
|
||||||
w.Lock()
|
w.Lock()
|
||||||
w.t = append(w.t, t)
|
w.t = append(w.t, t)
|
||||||
|
w.errs = append(w.errs, nil)
|
||||||
w.Unlock()
|
w.Unlock()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *testLoggerWriterCloser) Write(p []byte) (int, error) {
|
func (w *testLoggerWriterCloser) Log(level log.Level, msg string) {
|
||||||
|
if len(msg) > 0 && msg[len(msg)-1] == '\n' {
|
||||||
|
msg = msg[:len(msg)-1]
|
||||||
|
}
|
||||||
|
|
||||||
|
w.printMsg(msg)
|
||||||
|
if level >= log.ERROR {
|
||||||
|
w.recordError(msg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// list of error message which will not fail the test
|
||||||
|
// ideally this list should be empty, however ensuring that it does not grow
|
||||||
|
// is already a good first step.
|
||||||
|
var ignoredErrorMessageSuffixes = []string{
|
||||||
|
// only seen on mysql tests https://codeberg.org/forgejo/forgejo/pulls/2657#issuecomment-1693055
|
||||||
|
`table columns using inconsistent collation, they should use "utf8mb4_0900_ai_ci". Please go to admin panel Self Check page`,
|
||||||
|
|
||||||
|
// TestAPIDeleteReleaseByTagName
|
||||||
|
// action notification were a commit cannot be computed (because the commit got deleted)
|
||||||
|
`Notify() [E] an error occurred while executing the DeleteRelease actions method: gitRepo.GetCommit: object does not exist [id: refs/tags/release-tag, rel_path: ]`,
|
||||||
|
`Notify() [E] an error occurred while executing the PushCommits actions method: gitRepo.GetCommit: object does not exist [id: refs/tags/release-tag, rel_path: ]`,
|
||||||
|
|
||||||
|
// TestAPIRepoTags
|
||||||
|
`Notify() [E] an error occurred while executing the DeleteRelease actions method: gitRepo.GetCommit: object does not exist [id: refs/tags/gitea/22, rel_path: ]`,
|
||||||
|
`Notify() [E] an error occurred while executing the PushCommits actions method: gitRepo.GetCommit: object does not exist [id: refs/tags/gitea/22, rel_path: ]`,
|
||||||
|
|
||||||
|
// TestAPIDeleteTagByName
|
||||||
|
`Notify() [E] an error occurred while executing the DeleteRelease actions method: gitRepo.GetCommit: object does not exist [id: refs/tags/delete-tag, rel_path: ]`,
|
||||||
|
`Notify() [E] an error occurred while executing the PushCommits actions method: gitRepo.GetCommit: object does not exist [id: refs/tags/delete-tag, rel_path: ]`,
|
||||||
|
|
||||||
|
// TestAPIGenerateRepo
|
||||||
|
`Notify() [E] an error occurred while executing the CreateRepository actions method: gitRepo.GetCommit: object does not exist [id: , rel_path: ]`,
|
||||||
|
|
||||||
|
// TestAPIPullReview
|
||||||
|
`PullRequestReview() [E] Unsupported review webhook type`,
|
||||||
|
|
||||||
|
// TestAPIPullReviewRequest
|
||||||
|
`ToAPIPullRequest() [E] unable to resolve PR head ref`,
|
||||||
|
|
||||||
|
// TestAPILFSUpload
|
||||||
|
`Put() [E] Whilst putting LFS OID[ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb]: Failed to copy to tmpPath: ca/97/8112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb Error: content size does not match`,
|
||||||
|
`[E] Error putting LFS MetaObject [ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb] into content store. Error: content size does not match`,
|
||||||
|
`UploadHandler() [E] Upload does not match LFS MetaObject [ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb]. Error: content size does not match`,
|
||||||
|
`Put() [E] Whilst putting LFS OID[2581dd7bbc1fe44726de4b7dd806a087a978b9c5aec0a60481259e34be09b06a]: Failed to copy to tmpPath: 25/81/dd7bbc1fe44726de4b7dd806a087a978b9c5aec0a60481259e34be09b06a Error: content hash does not match OID`,
|
||||||
|
`[E] Error putting LFS MetaObject [2581dd7bbc1fe44726de4b7dd806a087a978b9c5aec0a60481259e34be09b06a] into content store. Error: content hash does not match OID`,
|
||||||
|
`UploadHandler() [E] Upload does not match LFS MetaObject [2581dd7bbc1fe44726de4b7dd806a087a978b9c5aec0a60481259e34be09b06a]. Error: content hash does not match OID`,
|
||||||
|
`UploadHandler() [E] Upload does not match LFS MetaObject [83de2e488b89a0aa1c97496b888120a28b0c1e15463a4adb8405578c540f36d4]. Error: content size does not match`,
|
||||||
|
|
||||||
|
// TestAPILFSVerify
|
||||||
|
`getAuthenticatedMeta() [E] Unable to get LFS OID[fb8f7d8435968c4f82a726a92395be4d16f2f63116caf36c8ad35c60831ab042] Error: LFS Meta object does not exist`,
|
||||||
|
|
||||||
|
// TestAPIUpdateOrgAvatar
|
||||||
|
`UpdateAvatar() [E] UploadAvatar: image.DecodeConfig: image: unknown format`,
|
||||||
|
|
||||||
|
// TestGetAttachment
|
||||||
|
`/data/attachments/a/0/a0eebc99-9c0b-4ef8-bb6d-6bb9bd380a18: no such file or directory`,
|
||||||
|
|
||||||
|
// TestBlockUser
|
||||||
|
`BlockedUsersUnblock() [E] IsOrganization: org3 is an organization not a user`,
|
||||||
|
`BlockedUsersBlock() [E] IsOrganization: org3 is an organization not a user`,
|
||||||
|
`Action() [E] Cannot perform this action on an organization "unblock"`,
|
||||||
|
`Action() [E] Cannot perform this action on an organization "block"`,
|
||||||
|
|
||||||
|
// TestBlockActions
|
||||||
|
`/gitea-repositories/user10/repo7.git Error: no such file or directory`,
|
||||||
|
|
||||||
|
// TestE2e/explore.test.e2e
|
||||||
|
`TrString() [E] Missing translation "more_items"`,
|
||||||
|
|
||||||
|
// TestRebuildCargo
|
||||||
|
`RebuildCargoIndex() [E] RebuildIndex failed: GetRepositoryByOwnerAndName: repository does not exist [id: 0, uid: 0, owner_name: user2, name: _cargo-index]`,
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *testLoggerWriterCloser) recordError(msg string) {
|
||||||
|
for _, s := range ignoredErrorMessageSuffixes {
|
||||||
|
if strings.HasSuffix(msg, s) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
w.Lock()
|
||||||
|
defer w.Unlock()
|
||||||
|
|
||||||
|
err := w.err
|
||||||
|
if len(w.errs) > 0 {
|
||||||
|
err = w.errs[len(w.errs)-1]
|
||||||
|
}
|
||||||
|
|
||||||
|
err = errors.Join(err, errors.New(msg))
|
||||||
|
|
||||||
|
if len(w.errs) > 0 {
|
||||||
|
w.errs[len(w.errs)-1] = err
|
||||||
|
} else {
|
||||||
|
w.err = err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (w *testLoggerWriterCloser) printMsg(msg string) {
|
||||||
// There was a data race problem: the logger system could still try to output logs after the runner is finished.
|
// There was a data race problem: the logger system could still try to output logs after the runner is finished.
|
||||||
// So we must ensure that the "t" in stack is still valid.
|
// So we must ensure that the "t" in stack is still valid.
|
||||||
w.RLock()
|
w.RLock()
|
||||||
defer w.RUnlock()
|
defer w.RUnlock()
|
||||||
|
|
||||||
var t testing.TB
|
|
||||||
if len(w.t) > 0 {
|
if len(w.t) > 0 {
|
||||||
t = w.t[len(w.t)-1]
|
t := w.t[len(w.t)-1]
|
||||||
}
|
t.Log(msg)
|
||||||
|
} else {
|
||||||
if len(p) > 0 && p[len(p)-1] == '\n' {
|
|
||||||
p = p[:len(p)-1]
|
|
||||||
}
|
|
||||||
|
|
||||||
if t == nil {
|
|
||||||
// if there is no running test, the log message should be outputted to console, to avoid losing important information.
|
// if there is no running test, the log message should be outputted to console, to avoid losing important information.
|
||||||
// the "???" prefix is used to match the "===" and "+++" in PrintCurrentTest
|
// the "???" prefix is used to match the "===" and "+++" in PrintCurrentTest
|
||||||
return fmt.Fprintf(os.Stdout, "??? [TestLogger] %s\n", p)
|
fmt.Fprintln(os.Stdout, "??? [TestLogger]", msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
t.Log(string(p))
|
|
||||||
return len(p), nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *testLoggerWriterCloser) popT() {
|
func (w *testLoggerWriterCloser) popT() error {
|
||||||
w.Lock()
|
w.Lock()
|
||||||
|
defer w.Unlock()
|
||||||
|
|
||||||
if len(w.t) > 0 {
|
if len(w.t) > 0 {
|
||||||
w.t = w.t[:len(w.t)-1]
|
w.t = w.t[:len(w.t)-1]
|
||||||
|
err := w.errs[len(w.errs)-1]
|
||||||
|
w.errs = w.errs[:len(w.errs)-1]
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
w.Unlock()
|
return w.err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (w *testLoggerWriterCloser) Close() error {
|
func (w *testLoggerWriterCloser) Reset() error {
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *testLoggerWriterCloser) Reset() {
|
|
||||||
w.Lock()
|
w.Lock()
|
||||||
if len(w.t) > 0 {
|
if len(w.t) > 0 {
|
||||||
for _, t := range w.t {
|
for _, t := range w.t {
|
||||||
|
@ -84,8 +180,12 @@ func (w *testLoggerWriterCloser) Reset() {
|
||||||
t.Errorf("Unclosed logger writer in test: %s", t.Name())
|
t.Errorf("Unclosed logger writer in test: %s", t.Name())
|
||||||
}
|
}
|
||||||
w.t = nil
|
w.t = nil
|
||||||
|
w.errs = nil
|
||||||
}
|
}
|
||||||
|
err := w.err
|
||||||
|
w.err = nil
|
||||||
w.Unlock()
|
w.Unlock()
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// PrintCurrentTest prints the current test to os.Stdout
|
// PrintCurrentTest prints the current test to os.Stdout
|
||||||
|
@ -132,7 +232,10 @@ func PrintCurrentTest(t testing.TB, skip ...int) func() {
|
||||||
_, _ = fmt.Fprintf(os.Stdout, "+++ %s had a slow clean-up flush (took %v)\n", t.Name(), flushTook)
|
_, _ = fmt.Fprintf(os.Stdout, "+++ %s had a slow clean-up flush (took %v)\n", t.Name(), flushTook)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
WriterCloser.popT()
|
|
||||||
|
if err := WriterCloser.popT(); err != nil {
|
||||||
|
t.Errorf("testlogger.go:recordError() FATAL ERROR: log.Error has been called: %v", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,19 +249,72 @@ func Printf(format string, args ...any) {
|
||||||
_, _ = fmt.Fprintf(os.Stdout, "\t"+format, args...)
|
_, _ = fmt.Fprintf(os.Stdout, "\t"+format, args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TestLogEventWriter is a logger which will write to the testing log
|
|
||||||
type TestLogEventWriter struct {
|
|
||||||
*log.EventWriterBaseImpl
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewTestLoggerWriter creates a TestLogEventWriter as a log.LoggerProvider
|
// NewTestLoggerWriter creates a TestLogEventWriter as a log.LoggerProvider
|
||||||
func NewTestLoggerWriter(name string, mode log.WriterMode) log.EventWriter {
|
func NewTestLoggerWriter(name string, mode log.WriterMode) log.EventWriter {
|
||||||
w := &TestLogEventWriter{}
|
w := &TestLogEventWriter{}
|
||||||
w.EventWriterBaseImpl = log.NewEventWriterBase(name, "test-log-writer", mode)
|
w.base = log.NewEventWriterBase(name, "test-log-writer", mode)
|
||||||
w.OutputWriteCloser = WriterCloser
|
w.writer = WriterCloser
|
||||||
return w
|
return w
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TestLogEventWriter is a logger which will write to the testing log
|
||||||
|
type TestLogEventWriter struct {
|
||||||
|
base *log.EventWriterBaseImpl
|
||||||
|
writer *testLoggerWriterCloser
|
||||||
|
}
|
||||||
|
|
||||||
|
// Base implements log.EventWriter.
|
||||||
|
func (t *TestLogEventWriter) Base() *log.EventWriterBaseImpl {
|
||||||
|
return t.base
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetLevel implements log.EventWriter.
|
||||||
|
func (t *TestLogEventWriter) GetLevel() log.Level {
|
||||||
|
return t.base.GetLevel()
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetWriterName implements log.EventWriter.
|
||||||
|
func (t *TestLogEventWriter) GetWriterName() string {
|
||||||
|
return t.base.GetWriterName()
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetWriterType implements log.EventWriter.
|
||||||
|
func (t *TestLogEventWriter) GetWriterType() string {
|
||||||
|
return t.base.GetWriterType()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run implements log.EventWriter.
|
||||||
|
func (t *TestLogEventWriter) Run(ctx context.Context) {
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-ctx.Done():
|
||||||
|
return
|
||||||
|
case event, ok := <-t.base.Queue:
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var errorMsg string
|
||||||
|
|
||||||
|
switch msg := event.Msg.(type) {
|
||||||
|
case string:
|
||||||
|
errorMsg = msg
|
||||||
|
case []byte:
|
||||||
|
errorMsg = string(msg)
|
||||||
|
case io.WriterTo:
|
||||||
|
var buf bytes.Buffer
|
||||||
|
if _, err := msg.WriteTo(&buf); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
errorMsg = buf.String()
|
||||||
|
default:
|
||||||
|
errorMsg = fmt.Sprint(msg)
|
||||||
|
}
|
||||||
|
t.writer.Log(event.Origin.Level, errorMsg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
const relFilePath = "modules/testlogger/testlogger.go"
|
const relFilePath = "modules/testlogger/testlogger.go"
|
||||||
_, filename, _, _ := runtime.Caller(0)
|
_, filename, _, _ := runtime.Caller(0)
|
||||||
|
|
|
@ -114,16 +114,22 @@ func (l *locale) TrString(trKey string, trArgs ...any) string {
|
||||||
format := trKey
|
format := trKey
|
||||||
|
|
||||||
idx, ok := l.store.trKeyToIdxMap[trKey]
|
idx, ok := l.store.trKeyToIdxMap[trKey]
|
||||||
|
found := false
|
||||||
if ok {
|
if ok {
|
||||||
if msg, ok := l.idxToMsgMap[idx]; ok {
|
if msg, ok := l.idxToMsgMap[idx]; ok {
|
||||||
format = msg // use the found translation
|
format = msg // use the found translation
|
||||||
|
found = true
|
||||||
} else if def, ok := l.store.localeMap[l.store.defaultLang]; ok {
|
} else if def, ok := l.store.localeMap[l.store.defaultLang]; ok {
|
||||||
// try to use default locale's translation
|
// try to use default locale's translation
|
||||||
if msg, ok := def.idxToMsgMap[idx]; ok {
|
if msg, ok := def.idxToMsgMap[idx]; ok {
|
||||||
format = msg
|
format = msg
|
||||||
|
found = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if !found {
|
||||||
|
log.Error("Missing translation %q", trKey)
|
||||||
|
}
|
||||||
|
|
||||||
msg, err := Format(format, trArgs...)
|
msg, err := Format(format, trArgs...)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -1655,6 +1655,7 @@ config.default_keep_email_private = أخفِ عناوين البريد الإل
|
||||||
config.default_allow_create_organization = اسمح بإنشاء المنظمات مبدئيا
|
config.default_allow_create_organization = اسمح بإنشاء المنظمات مبدئيا
|
||||||
config.enable_timetracking = فعّل تتبع الوقت
|
config.enable_timetracking = فعّل تتبع الوقت
|
||||||
config.default_enable_timetracking = فعّل تتبع الوقت مبدئيا
|
config.default_enable_timetracking = فعّل تتبع الوقت مبدئيا
|
||||||
|
config.allow_dots_in_usernames = السماح للمستخدمين بوضع نقاط في أسمائهم. لا يؤثر على الحسابات الموجودة.
|
||||||
config.default_allow_only_contributors_to_track_time = اسمح للمشتركين في المستودع موحدهم بتتبع الوقت
|
config.default_allow_only_contributors_to_track_time = اسمح للمشتركين في المستودع موحدهم بتتبع الوقت
|
||||||
|
|
||||||
[form]
|
[form]
|
||||||
|
|
|
@ -3224,6 +3224,7 @@ config.default_keep_email_private=Ve výchozím nastavení skrýt e-mailové adr
|
||||||
config.default_allow_create_organization=Povolit ve výchozím nastavení vytvářet organizace
|
config.default_allow_create_organization=Povolit ve výchozím nastavení vytvářet organizace
|
||||||
config.enable_timetracking=Povolit sledování času
|
config.enable_timetracking=Povolit sledování času
|
||||||
config.default_enable_timetracking=Povolit ve výchozím nastavení sledování času
|
config.default_enable_timetracking=Povolit ve výchozím nastavení sledování času
|
||||||
|
config.allow_dots_in_usernames = Povolit uživatelům používat tečky ve svých uživatelských jménech. Neovlivní stávající účty.
|
||||||
config.default_allow_only_contributors_to_track_time=Povolit sledování času pouze přispěvatelům
|
config.default_allow_only_contributors_to_track_time=Povolit sledování času pouze přispěvatelům
|
||||||
config.no_reply_address=Skrytá e-mailová doména
|
config.no_reply_address=Skrytá e-mailová doména
|
||||||
config.default_visibility_organization=Výchozí viditelnost nových organizací
|
config.default_visibility_organization=Výchozí viditelnost nových organizací
|
||||||
|
|
|
@ -3204,6 +3204,7 @@ config.default_keep_email_private=E-Mail-Adressen standardmäßig verbergen
|
||||||
config.default_allow_create_organization=Erstellen von Organisationen standardmäßig erlauben
|
config.default_allow_create_organization=Erstellen von Organisationen standardmäßig erlauben
|
||||||
config.enable_timetracking=Zeiterfassung aktivieren
|
config.enable_timetracking=Zeiterfassung aktivieren
|
||||||
config.default_enable_timetracking=Zeiterfassung standardmäßig aktivieren
|
config.default_enable_timetracking=Zeiterfassung standardmäßig aktivieren
|
||||||
|
config.allow_dots_in_usernames = Erlaubt Benutzern die Verwendung von Punkten in ihren Benutzernamen. Hat keine Auswirkungen auf bestehende Konten.
|
||||||
config.default_allow_only_contributors_to_track_time=Nur Mitarbeitern erlauben, die Zeiterfassung zu nutzen
|
config.default_allow_only_contributors_to_track_time=Nur Mitarbeitern erlauben, die Zeiterfassung zu nutzen
|
||||||
config.no_reply_address=Versteckte E-Mail-Domain
|
config.no_reply_address=Versteckte E-Mail-Domain
|
||||||
config.default_visibility_organization=Standard-Sichtbarkeit für neue Organisationen
|
config.default_visibility_organization=Standard-Sichtbarkeit für neue Organisationen
|
||||||
|
|
|
@ -3192,6 +3192,7 @@ config.default_keep_email_private=Να αποκρύπτονται οι διευ
|
||||||
config.default_allow_create_organization=Να επιτρέπεται η δημιουργία οργανισμών από προεπιλογή
|
config.default_allow_create_organization=Να επιτρέπεται η δημιουργία οργανισμών από προεπιλογή
|
||||||
config.enable_timetracking=Ενεργοποίηση καταγραφής χρόνου
|
config.enable_timetracking=Ενεργοποίηση καταγραφής χρόνου
|
||||||
config.default_enable_timetracking=Ενεργοποίηση καταγραφής χρόνου από προεπιλογή
|
config.default_enable_timetracking=Ενεργοποίηση καταγραφής χρόνου από προεπιλογή
|
||||||
|
config.allow_dots_in_usernames = Επιτρέπει την χρήση τελείων σε ονόματα χρηστών. Δεν θα επηρεαστούν λογαριασμοί που ήδη υπάρχουν.
|
||||||
config.default_allow_only_contributors_to_track_time=Να επιτρέπεται η καταγραφή χρόνου μόνο από συνεισφέροντες
|
config.default_allow_only_contributors_to_track_time=Να επιτρέπεται η καταγραφή χρόνου μόνο από συνεισφέροντες
|
||||||
config.no_reply_address=Κρυφό email domain
|
config.no_reply_address=Κρυφό email domain
|
||||||
config.default_visibility_organization=Προεπιλεγμένη ορατότητα νέων οργανισμών
|
config.default_visibility_organization=Προεπιλεγμένη ορατότητα νέων οργανισμών
|
||||||
|
|
|
@ -3215,6 +3215,7 @@ config.default_keep_email_private = Hide email addresses by default
|
||||||
config.default_allow_create_organization = Allow creation of organizations by default
|
config.default_allow_create_organization = Allow creation of organizations by default
|
||||||
config.enable_timetracking = Enable time tracking
|
config.enable_timetracking = Enable time tracking
|
||||||
config.default_enable_timetracking = Enable time tracking by default
|
config.default_enable_timetracking = Enable time tracking by default
|
||||||
|
config.allow_dots_in_usernames = Allow users to use dots in their usernames. Doesn't affect existing accounts.
|
||||||
config.default_allow_only_contributors_to_track_time = Let only contributors track time
|
config.default_allow_only_contributors_to_track_time = Let only contributors track time
|
||||||
config.no_reply_address = Hidden email domain
|
config.no_reply_address = Hidden email domain
|
||||||
config.default_visibility_organization = Default visibility of new organizations
|
config.default_visibility_organization = Default visibility of new organizations
|
||||||
|
|
|
@ -303,6 +303,7 @@ smtp_from_invalid = La «Sendu retleterojn kiel» adreso malvalidas
|
||||||
|
|
||||||
[admin]
|
[admin]
|
||||||
config.app_data_path = Programdatuja doseiervojo
|
config.app_data_path = Programdatuja doseiervojo
|
||||||
|
config.allow_dots_in_usernames = Permesi ĉeeston de punktoj en uzantonomoj. Ne efikas je jamaj kontoj.
|
||||||
|
|
||||||
[home]
|
[home]
|
||||||
filter = Aliaj filtriloj
|
filter = Aliaj filtriloj
|
||||||
|
|
|
@ -3107,6 +3107,7 @@ config.default_keep_email_private=Ocultar direcciones de correo electrónico por
|
||||||
config.default_allow_create_organization=Permitir la creación de organizaciones por defecto
|
config.default_allow_create_organization=Permitir la creación de organizaciones por defecto
|
||||||
config.enable_timetracking=Habilitar seguimiento de tiempo
|
config.enable_timetracking=Habilitar seguimiento de tiempo
|
||||||
config.default_enable_timetracking=Habilitar seguimiento de tiempo por defecto
|
config.default_enable_timetracking=Habilitar seguimiento de tiempo por defecto
|
||||||
|
config.allow_dots_in_usernames = Permite utilizar puntos en los nombres de usuario. No tiene efecto sobre cuentas existentes.
|
||||||
config.default_allow_only_contributors_to_track_time=Deje que solo los colaboradores hagan un seguimiento del tiempo
|
config.default_allow_only_contributors_to_track_time=Deje que solo los colaboradores hagan un seguimiento del tiempo
|
||||||
config.no_reply_address=Dominio de correos electrónicos ocultos
|
config.no_reply_address=Dominio de correos electrónicos ocultos
|
||||||
config.default_visibility_organization=Visibilidad por defecto para nuevas organizaciones
|
config.default_visibility_organization=Visibilidad por defecto para nuevas organizaciones
|
||||||
|
|
|
@ -3229,6 +3229,7 @@ config.default_keep_email_private=Masquer les adresses courriel par défaut
|
||||||
config.default_allow_create_organization=Autoriser la création d'organisations par défaut
|
config.default_allow_create_organization=Autoriser la création d'organisations par défaut
|
||||||
config.enable_timetracking=Activer le suivi du temps
|
config.enable_timetracking=Activer le suivi du temps
|
||||||
config.default_enable_timetracking=Activer le suivi de temps par défaut
|
config.default_enable_timetracking=Activer le suivi de temps par défaut
|
||||||
|
config.allow_dots_in_usernames = Les points sont autorisés dans les noms d'utilisateurs. Sans effet sur les comptes existants.
|
||||||
config.default_allow_only_contributors_to_track_time=Restreindre le suivi de temps aux contributeurs
|
config.default_allow_only_contributors_to_track_time=Restreindre le suivi de temps aux contributeurs
|
||||||
config.no_reply_address=Domaine pour les courriels cachés
|
config.no_reply_address=Domaine pour les courriels cachés
|
||||||
config.default_visibility_organization=Visibilité par défaut des nouvelles organisations
|
config.default_visibility_organization=Visibilité par défaut des nouvelles organisations
|
||||||
|
|
|
@ -3145,6 +3145,7 @@ config.default_keep_email_private=Nascondi indirizzo email in modo predefinito
|
||||||
config.default_allow_create_organization=Consenti la creazione di organizzazioni in modo predefinito
|
config.default_allow_create_organization=Consenti la creazione di organizzazioni in modo predefinito
|
||||||
config.enable_timetracking=Abilita il cronografo
|
config.enable_timetracking=Abilita il cronografo
|
||||||
config.default_enable_timetracking=Attiva il cronografo di default
|
config.default_enable_timetracking=Attiva il cronografo di default
|
||||||
|
config.allow_dots_in_usernames = Consenti l'uso del punto nel nome utente. Non impatta gli account già esistenti.
|
||||||
config.default_allow_only_contributors_to_track_time=Consenti soltanto ai contributori di utilizzare il cronografo
|
config.default_allow_only_contributors_to_track_time=Consenti soltanto ai contributori di utilizzare il cronografo
|
||||||
config.no_reply_address=Dominio email nascosto
|
config.no_reply_address=Dominio email nascosto
|
||||||
config.default_visibility_organization=Visibilità predefinita per le nuove organizzazioni
|
config.default_visibility_organization=Visibilità predefinita per le nuove organizzazioni
|
||||||
|
|
|
@ -3184,6 +3184,7 @@ config.default_keep_email_private=デフォルトでメールアドレスを隠
|
||||||
config.default_allow_create_organization=デフォルトで組織の作成を許可
|
config.default_allow_create_organization=デフォルトで組織の作成を許可
|
||||||
config.enable_timetracking=タイムトラッキング有効
|
config.enable_timetracking=タイムトラッキング有効
|
||||||
config.default_enable_timetracking=デフォルトでタイムトラッキング有効
|
config.default_enable_timetracking=デフォルトでタイムトラッキング有効
|
||||||
|
config.allow_dots_in_usernames = ユーザー名にドットを使用できるようにします。既存のアカウントには影響しません。
|
||||||
config.default_allow_only_contributors_to_track_time=コントリビューターだけタイムトラッキングする
|
config.default_allow_only_contributors_to_track_time=コントリビューターだけタイムトラッキングする
|
||||||
config.no_reply_address=メールを隠すときのドメイン
|
config.no_reply_address=メールを隠すときのドメイン
|
||||||
config.default_visibility_organization=新しい組織のデフォルトの表示設定
|
config.default_visibility_organization=新しい組織のデフォルトの表示設定
|
||||||
|
|
|
@ -3096,6 +3096,7 @@ config.default_keep_email_private=Verberg standaard alle e-mailadressen
|
||||||
config.default_allow_create_organization=Standaard toestaan om organisaties aan te maken
|
config.default_allow_create_organization=Standaard toestaan om organisaties aan te maken
|
||||||
config.enable_timetracking=Tijdregistratie inschakelen
|
config.enable_timetracking=Tijdregistratie inschakelen
|
||||||
config.default_enable_timetracking=Tijdregistratie standaard inschakelen
|
config.default_enable_timetracking=Tijdregistratie standaard inschakelen
|
||||||
|
config.allow_dots_in_usernames = Sta gebruikers toe om punten te gebruiken in hun gebruikersnaam. Heeft geen invloed op bestaande accounts.
|
||||||
config.default_allow_only_contributors_to_track_time=Sta alleen bijdragers toe tijdregistratie te gebruiken
|
config.default_allow_only_contributors_to_track_time=Sta alleen bijdragers toe tijdregistratie te gebruiken
|
||||||
config.no_reply_address=Verborgen e-maildomein
|
config.no_reply_address=Verborgen e-maildomein
|
||||||
config.default_visibility_organization=Standaard zichtbaarheid voor nieuwe organisaties
|
config.default_visibility_organization=Standaard zichtbaarheid voor nieuwe organisaties
|
||||||
|
|
|
@ -3096,6 +3096,7 @@ config.default_keep_email_private=Ocultar endereços de e-mail por padrão
|
||||||
config.default_allow_create_organization=Permitir a criação de organizações por padrão
|
config.default_allow_create_organization=Permitir a criação de organizações por padrão
|
||||||
config.enable_timetracking=Habilitar Cronômetro
|
config.enable_timetracking=Habilitar Cronômetro
|
||||||
config.default_enable_timetracking=Habilitar o Cronômetro por Padrão
|
config.default_enable_timetracking=Habilitar o Cronômetro por Padrão
|
||||||
|
config.allow_dots_in_usernames = Permitir pontos em nomes de usuário. Esta opção não afeta contas já existentes.
|
||||||
config.default_allow_only_contributors_to_track_time=Permitir que apenas os colaboradores acompanhem o contador de tempo
|
config.default_allow_only_contributors_to_track_time=Permitir que apenas os colaboradores acompanhem o contador de tempo
|
||||||
config.no_reply_address=Ocultar domínio de e-mail
|
config.no_reply_address=Ocultar domínio de e-mail
|
||||||
config.default_visibility_organization=Visibilidade padrão para novas organizações
|
config.default_visibility_organization=Visibilidade padrão para novas organizações
|
||||||
|
|
|
@ -3189,6 +3189,7 @@ config.default_keep_email_private=Скрывать адреса эл. почты
|
||||||
config.default_allow_create_organization=Разрешить создание организаций по умолчанию
|
config.default_allow_create_organization=Разрешить создание организаций по умолчанию
|
||||||
config.enable_timetracking=Отслеживание времени
|
config.enable_timetracking=Отслеживание времени
|
||||||
config.default_enable_timetracking=Включить отслеживание времени по умолчанию
|
config.default_enable_timetracking=Включить отслеживание времени по умолчанию
|
||||||
|
config.allow_dots_in_usernames = Разрешить точки в логинах пользователей. Это не повлияет на уже созданные учётные записи.
|
||||||
config.default_allow_only_contributors_to_track_time=Подсчитывать время могут только соавторы
|
config.default_allow_only_contributors_to_track_time=Подсчитывать время могут только соавторы
|
||||||
config.no_reply_address=Домен скрытых адресов почты
|
config.no_reply_address=Домен скрытых адресов почты
|
||||||
config.default_visibility_organization=Видимость новых организаций по умолчанию
|
config.default_visibility_organization=Видимость новых организаций по умолчанию
|
||||||
|
|
|
@ -267,6 +267,7 @@ config.git_config = Konfiguracija Git
|
||||||
config.git_max_diff_line_characters = Največ različnih znakov na vrstico
|
config.git_max_diff_line_characters = Največ različnih znakov na vrstico
|
||||||
notices.view_detail_header = Podrobnosti obvestila
|
notices.view_detail_header = Podrobnosti obvestila
|
||||||
config.log_config = Konfiguracija dnevnika
|
config.log_config = Konfiguracija dnevnika
|
||||||
|
config.allow_dots_in_usernames = Uporabnikom dovolite uporabo pik v uporabniških imenih. Ne vpliva na obstoječe račune.
|
||||||
|
|
||||||
[repo]
|
[repo]
|
||||||
migrate.github_token_desc = Tu lahko vstavite enega ali več žetonov, ločenih z vejico, da bo selitev hitrejša zaradi omejitve hitrosti GitHub API. OPOZORILO: Zloraba te funkcije lahko krši pravila ponudnika storitev in povzroči blokado računa.
|
migrate.github_token_desc = Tu lahko vstavite enega ali več žetonov, ločenih z vejico, da bo selitev hitrejša zaradi omejitve hitrosti GitHub API. OPOZORILO: Zloraba te funkcije lahko krši pravila ponudnika storitev in povzroči blokado računa.
|
||||||
|
|
|
@ -3224,6 +3224,7 @@ config.default_keep_email_private=默认情况下隐藏电子邮件地址
|
||||||
config.default_allow_create_organization=默认情况下允许创建组织
|
config.default_allow_create_organization=默认情况下允许创建组织
|
||||||
config.enable_timetracking=启用时间跟踪
|
config.enable_timetracking=启用时间跟踪
|
||||||
config.default_enable_timetracking=默认情况下启用时间跟踪
|
config.default_enable_timetracking=默认情况下启用时间跟踪
|
||||||
|
config.allow_dots_in_usernames = 允许用户在用户名中使用英文句号。不影响已有的帐户。
|
||||||
config.default_allow_only_contributors_to_track_time=仅允许成员跟踪时间
|
config.default_allow_only_contributors_to_track_time=仅允许成员跟踪时间
|
||||||
config.no_reply_address=隐藏电子邮件域
|
config.no_reply_address=隐藏电子邮件域
|
||||||
config.default_visibility_organization=新组织的默认可见性
|
config.default_visibility_organization=新组织的默认可见性
|
||||||
|
|
|
@ -311,7 +311,7 @@ func (ar artifactRoutes) comfirmUploadArtifact(ctx *ArtifactContext) {
|
||||||
}
|
}
|
||||||
artifactName := ctx.Req.URL.Query().Get("artifactName")
|
artifactName := ctx.Req.URL.Query().Get("artifactName")
|
||||||
if artifactName == "" {
|
if artifactName == "" {
|
||||||
log.Error("Error artifact name is empty")
|
log.Warn("Error artifact name is empty")
|
||||||
ctx.Error(http.StatusBadRequest, "Error artifact name is empty")
|
ctx.Error(http.StatusBadRequest, "Error artifact name is empty")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,7 +61,7 @@ func validateArtifactHash(ctx *ArtifactContext, artifactName string) bool {
|
||||||
if paramHash == artifactHash {
|
if paramHash == artifactHash {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
log.Error("Invalid artifact hash: %s", paramHash)
|
log.Warn("Invalid artifact hash: %s", paramHash)
|
||||||
ctx.Error(http.StatusBadRequest, "Invalid artifact hash")
|
ctx.Error(http.StatusBadRequest, "Invalid artifact hash")
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
|
@ -359,7 +359,7 @@ func (r *artifactV4Routes) finalizeArtifact(ctx *ArtifactContext) {
|
||||||
checksum = req.Hash.Value
|
checksum = req.Hash.Value
|
||||||
}
|
}
|
||||||
if err := mergeChunksForArtifact(ctx, chunks, r.fs, artifact, checksum); err != nil {
|
if err := mergeChunksForArtifact(ctx, chunks, r.fs, artifact, checksum); err != nil {
|
||||||
log.Error("Error merge chunks: %v", err)
|
log.Warn("Error merge chunks: %v", err)
|
||||||
ctx.Error(http.StatusInternalServerError, "Error merge chunks")
|
ctx.Error(http.StatusInternalServerError, "Error merge chunks")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,7 +49,10 @@ var (
|
||||||
func apiError(ctx *context.Context, status int, obj any) {
|
func apiError(ctx *context.Context, status int, obj any) {
|
||||||
helper.LogAndProcessError(ctx, status, obj, func(message string) {
|
helper.LogAndProcessError(ctx, status, obj, func(message string) {
|
||||||
// The maven client does not present the error message to the user. Log it for users with access to server logs.
|
// The maven client does not present the error message to the user. Log it for users with access to server logs.
|
||||||
if status == http.StatusBadRequest || status == http.StatusInternalServerError {
|
switch status {
|
||||||
|
case http.StatusBadRequest:
|
||||||
|
log.Warn(message)
|
||||||
|
case http.StatusInternalServerError:
|
||||||
log.Error(message)
|
log.Error(message)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,7 @@ import (
|
||||||
|
|
||||||
"code.gitea.io/gitea/modules/activitypub"
|
"code.gitea.io/gitea/modules/activitypub"
|
||||||
"code.gitea.io/gitea/modules/httplib"
|
"code.gitea.io/gitea/modules/httplib"
|
||||||
|
"code.gitea.io/gitea/modules/log"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
gitea_context "code.gitea.io/gitea/services/context"
|
gitea_context "code.gitea.io/gitea/services/context"
|
||||||
|
|
||||||
|
@ -89,7 +90,8 @@ func verifyHTTPSignatures(ctx *gitea_context.APIContext) (authenticated bool, er
|
||||||
func ReqHTTPSignature() func(ctx *gitea_context.APIContext) {
|
func ReqHTTPSignature() func(ctx *gitea_context.APIContext) {
|
||||||
return func(ctx *gitea_context.APIContext) {
|
return func(ctx *gitea_context.APIContext) {
|
||||||
if authenticated, err := verifyHTTPSignatures(ctx); err != nil {
|
if authenticated, err := verifyHTTPSignatures(ctx); err != nil {
|
||||||
ctx.ServerError("verifyHttpSignatures", err)
|
log.Warn("verifyHttpSignatures failed: %v", err)
|
||||||
|
ctx.Error(http.StatusBadRequest, "reqSignature", "request signature verification failed")
|
||||||
} else if !authenticated {
|
} else if !authenticated {
|
||||||
ctx.Error(http.StatusForbidden, "reqSignature", "request signature verification failed")
|
ctx.Error(http.StatusForbidden, "reqSignature", "request signature verification failed")
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,6 @@ import (
|
||||||
|
|
||||||
activities_model "code.gitea.io/gitea/models/activities"
|
activities_model "code.gitea.io/gitea/models/activities"
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
"code.gitea.io/gitea/modules/log"
|
|
||||||
"code.gitea.io/gitea/modules/structs"
|
"code.gitea.io/gitea/modules/structs"
|
||||||
"code.gitea.io/gitea/services/context"
|
"code.gitea.io/gitea/services/context"
|
||||||
"code.gitea.io/gitea/services/convert"
|
"code.gitea.io/gitea/services/convert"
|
||||||
|
@ -201,7 +200,6 @@ func ReadRepoNotifications(ctx *context.APIContext) {
|
||||||
if !ctx.FormBool("all") {
|
if !ctx.FormBool("all") {
|
||||||
statuses := ctx.FormStrings("status-types")
|
statuses := ctx.FormStrings("status-types")
|
||||||
opts.Status = statusStringsToNotificationStatuses(statuses, []string{"unread"})
|
opts.Status = statusStringsToNotificationStatuses(statuses, []string{"unread"})
|
||||||
log.Error("%v", opts.Status)
|
|
||||||
}
|
}
|
||||||
nl, err := db.Find[activities_model.Notification](ctx, opts)
|
nl, err := db.Find[activities_model.Notification](ctx, opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -6,6 +6,7 @@ package actions
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"slices"
|
"slices"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -25,6 +26,7 @@ import (
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
api "code.gitea.io/gitea/modules/structs"
|
api "code.gitea.io/gitea/modules/structs"
|
||||||
|
"code.gitea.io/gitea/modules/util"
|
||||||
webhook_module "code.gitea.io/gitea/modules/webhook"
|
webhook_module "code.gitea.io/gitea/modules/webhook"
|
||||||
"code.gitea.io/gitea/services/convert"
|
"code.gitea.io/gitea/services/convert"
|
||||||
|
|
||||||
|
@ -190,6 +192,12 @@ func notify(ctx context.Context, input *notifyInput) error {
|
||||||
baseRef := git.BranchPrefix + input.PullRequest.BaseBranch
|
baseRef := git.BranchPrefix + input.PullRequest.BaseBranch
|
||||||
baseCommit, err := gitRepo.GetCommit(baseRef)
|
baseCommit, err := gitRepo.GetCommit(baseRef)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
if prp, ok := input.Payload.(*api.PullRequestPayload); ok && errors.Is(err, util.ErrNotExist) {
|
||||||
|
// the baseBranch was deleted and the PR closed: the action can be skipped
|
||||||
|
if prp.Action == api.HookIssueClosed {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
return fmt.Errorf("gitRepo.GetCommit: %w", err)
|
return fmt.Errorf("gitRepo.GetCommit: %w", err)
|
||||||
}
|
}
|
||||||
baseWorkflows, _, err := actions_module.DetectWorkflows(gitRepo, baseCommit, input.Event, input.Payload)
|
baseWorkflows, _, err := actions_module.DetectWorkflows(gitRepo, baseCommit, input.Event, input.Payload)
|
||||||
|
|
|
@ -165,11 +165,15 @@ func createPackageAndVersion(ctx context.Context, pvci *PackageCreationInfo, all
|
||||||
if pv, err = packages_model.GetOrInsertVersion(ctx, pv); err != nil {
|
if pv, err = packages_model.GetOrInsertVersion(ctx, pv); err != nil {
|
||||||
if err == packages_model.ErrDuplicatePackageVersion {
|
if err == packages_model.ErrDuplicatePackageVersion {
|
||||||
versionCreated = false
|
versionCreated = false
|
||||||
}
|
} else {
|
||||||
if err != packages_model.ErrDuplicatePackageVersion || !allowDuplicate {
|
|
||||||
log.Error("Error inserting package: %v", err)
|
log.Error("Error inserting package: %v", err)
|
||||||
return nil, false, err
|
return nil, false, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !allowDuplicate {
|
||||||
|
// no need to log an error
|
||||||
|
return nil, false, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if versionCreated {
|
if versionCreated {
|
||||||
|
|
|
@ -65,7 +65,7 @@ func MergeRequiredContextsCommitStatus(commitStatuses []*git_model.CommitStatus,
|
||||||
if status != nil {
|
if status != nil {
|
||||||
return status.State
|
return status.State
|
||||||
}
|
}
|
||||||
return structs.CommitStatusSuccess
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
return returnedStatus
|
return returnedStatus
|
||||||
|
|
|
@ -123,7 +123,7 @@ func FindReposLastestCommitStatuses(ctx context.Context, repos []*repo_model.Rep
|
||||||
for i, repo := range repos {
|
for i, repo := range repos {
|
||||||
if results[i] == nil {
|
if results[i] == nil {
|
||||||
results[i] = git_model.CalcCommitStatus(repoToItsLatestCommitStatuses[repo.ID])
|
results[i] = git_model.CalcCommitStatus(repoToItsLatestCommitStatuses[repo.ID])
|
||||||
if results[i].State != "" {
|
if results[i] != nil {
|
||||||
if err := updateCommitStatusCache(ctx, repo.ID, repo.DefaultBranch, results[i].State); err != nil {
|
if err := updateCommitStatusCache(ctx, repo.ID, repo.DefaultBranch, results[i].State); err != nil {
|
||||||
log.Error("updateCommitStatusCache[%d:%s] failed: %v", repo.ID, repo.DefaultBranch, err)
|
log.Error("updateCommitStatusCache[%d:%s] failed: %v", repo.ID, repo.DefaultBranch, err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,10 +28,19 @@ func TestWebhook_GetSlackHook(t *testing.T) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func activateWebhook(t *testing.T, hookID int64) {
|
||||||
|
t.Helper()
|
||||||
|
updated, err := db.GetEngine(db.DefaultContext).ID(hookID).Cols("is_active").Update(webhook_model.Webhook{IsActive: true})
|
||||||
|
assert.Equal(t, int64(1), updated)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
func TestPrepareWebhooks(t *testing.T) {
|
func TestPrepareWebhooks(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
|
||||||
|
activateWebhook(t, 1)
|
||||||
|
|
||||||
hookTasks := []*webhook_model.HookTask{
|
hookTasks := []*webhook_model.HookTask{
|
||||||
{HookID: 1, EventType: webhook_module.HookEventPush},
|
{HookID: 1, EventType: webhook_module.HookEventPush},
|
||||||
}
|
}
|
||||||
|
@ -48,6 +57,8 @@ func TestPrepareWebhooksBranchFilterMatch(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2})
|
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 2})
|
||||||
|
activateWebhook(t, 4)
|
||||||
|
|
||||||
hookTasks := []*webhook_model.HookTask{
|
hookTasks := []*webhook_model.HookTask{
|
||||||
{HookID: 4, EventType: webhook_module.HookEventPush},
|
{HookID: 4, EventType: webhook_module.HookEventPush},
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,8 +59,10 @@ func TestMain(m *testing.M) {
|
||||||
|
|
||||||
exitVal := m.Run()
|
exitVal := m.Run()
|
||||||
|
|
||||||
testlogger.WriterCloser.Reset()
|
if err := testlogger.WriterCloser.Reset(); err != nil {
|
||||||
|
fmt.Printf("testlogger.WriterCloser.Reset: %v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
if err = util.RemoveAll(setting.Indexer.IssuePath); err != nil {
|
if err = util.RemoveAll(setting.Indexer.IssuePath); err != nil {
|
||||||
fmt.Printf("util.RemoveAll: %v\n", err)
|
fmt.Printf("util.RemoveAll: %v\n", err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
|
|
|
@ -108,6 +108,6 @@ func TestActivityPubPersonInbox(t *testing.T) {
|
||||||
|
|
||||||
// Unsigned request fails
|
// Unsigned request fails
|
||||||
req := NewRequest(t, "POST", user2inboxurl)
|
req := NewRequest(t, "POST", user2inboxurl)
|
||||||
MakeRequest(t, req, http.StatusInternalServerError)
|
MakeRequest(t, req, http.StatusBadRequest)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -145,7 +145,10 @@ func TestMain(m *testing.M) {
|
||||||
// Instead, "No tests were found", last nonsense log is "According to the configuration, subsequent logs will not be printed to the console"
|
// Instead, "No tests were found", last nonsense log is "According to the configuration, subsequent logs will not be printed to the console"
|
||||||
exitCode := m.Run()
|
exitCode := m.Run()
|
||||||
|
|
||||||
testlogger.WriterCloser.Reset()
|
if err := testlogger.WriterCloser.Reset(); err != nil {
|
||||||
|
fmt.Printf("testlogger.WriterCloser.Reset: %v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
if err = util.RemoveAll(setting.Indexer.IssuePath); err != nil {
|
if err = util.RemoveAll(setting.Indexer.IssuePath); err != nil {
|
||||||
fmt.Printf("util.RemoveAll: %v\n", err)
|
fmt.Printf("util.RemoveAll: %v\n", err)
|
||||||
|
|
|
@ -80,10 +80,22 @@ func testPullCleanUp(t *testing.T, session *TestSession, user, repo, pullnum str
|
||||||
return resp
|
return resp
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func retrieveHookTasks(t *testing.T, hookID int64, activateWebhook bool) []*webhook.HookTask {
|
||||||
|
t.Helper()
|
||||||
|
if activateWebhook {
|
||||||
|
updated, err := db.GetEngine(db.DefaultContext).ID(hookID).Cols("is_active").Update(webhook.Webhook{IsActive: true})
|
||||||
|
assert.Equal(t, int64(1), updated)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
hookTasks, err := webhook.HookTasks(db.DefaultContext, hookID, 1)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
return hookTasks
|
||||||
|
}
|
||||||
|
|
||||||
func TestPullMerge(t *testing.T) {
|
func TestPullMerge(t *testing.T) {
|
||||||
onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
|
onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
|
||||||
hookTasks, err := webhook.HookTasks(db.DefaultContext, 1, 1) // Retrieve previous hook number
|
hookTasks := retrieveHookTasks(t, 1, true)
|
||||||
assert.NoError(t, err)
|
|
||||||
hookTasksLenBefore := len(hookTasks)
|
hookTasksLenBefore := len(hookTasks)
|
||||||
|
|
||||||
session := loginUser(t, "user1")
|
session := loginUser(t, "user1")
|
||||||
|
@ -96,16 +108,14 @@ func TestPullMerge(t *testing.T) {
|
||||||
assert.EqualValues(t, "pulls", elem[3])
|
assert.EqualValues(t, "pulls", elem[3])
|
||||||
testPullMerge(t, session, elem[1], elem[2], elem[4], repo_model.MergeStyleMerge, false)
|
testPullMerge(t, session, elem[1], elem[2], elem[4], repo_model.MergeStyleMerge, false)
|
||||||
|
|
||||||
hookTasks, err = webhook.HookTasks(db.DefaultContext, 1, 1)
|
hookTasks = retrieveHookTasks(t, 1, false)
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.Len(t, hookTasks, hookTasksLenBefore+1)
|
assert.Len(t, hookTasks, hookTasksLenBefore+1)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPullRebase(t *testing.T) {
|
func TestPullRebase(t *testing.T) {
|
||||||
onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
|
onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
|
||||||
hookTasks, err := webhook.HookTasks(db.DefaultContext, 1, 1) // Retrieve previous hook number
|
hookTasks := retrieveHookTasks(t, 1, true)
|
||||||
assert.NoError(t, err)
|
|
||||||
hookTasksLenBefore := len(hookTasks)
|
hookTasksLenBefore := len(hookTasks)
|
||||||
|
|
||||||
session := loginUser(t, "user1")
|
session := loginUser(t, "user1")
|
||||||
|
@ -118,16 +128,14 @@ func TestPullRebase(t *testing.T) {
|
||||||
assert.EqualValues(t, "pulls", elem[3])
|
assert.EqualValues(t, "pulls", elem[3])
|
||||||
testPullMerge(t, session, elem[1], elem[2], elem[4], repo_model.MergeStyleRebase, false)
|
testPullMerge(t, session, elem[1], elem[2], elem[4], repo_model.MergeStyleRebase, false)
|
||||||
|
|
||||||
hookTasks, err = webhook.HookTasks(db.DefaultContext, 1, 1)
|
hookTasks = retrieveHookTasks(t, 1, false)
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.Len(t, hookTasks, hookTasksLenBefore+1)
|
assert.Len(t, hookTasks, hookTasksLenBefore+1)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPullRebaseMerge(t *testing.T) {
|
func TestPullRebaseMerge(t *testing.T) {
|
||||||
onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
|
onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
|
||||||
hookTasks, err := webhook.HookTasks(db.DefaultContext, 1, 1) // Retrieve previous hook number
|
hookTasks := retrieveHookTasks(t, 1, true)
|
||||||
assert.NoError(t, err)
|
|
||||||
hookTasksLenBefore := len(hookTasks)
|
hookTasksLenBefore := len(hookTasks)
|
||||||
|
|
||||||
session := loginUser(t, "user1")
|
session := loginUser(t, "user1")
|
||||||
|
@ -140,16 +148,14 @@ func TestPullRebaseMerge(t *testing.T) {
|
||||||
assert.EqualValues(t, "pulls", elem[3])
|
assert.EqualValues(t, "pulls", elem[3])
|
||||||
testPullMerge(t, session, elem[1], elem[2], elem[4], repo_model.MergeStyleRebaseMerge, false)
|
testPullMerge(t, session, elem[1], elem[2], elem[4], repo_model.MergeStyleRebaseMerge, false)
|
||||||
|
|
||||||
hookTasks, err = webhook.HookTasks(db.DefaultContext, 1, 1)
|
hookTasks = retrieveHookTasks(t, 1, false)
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.Len(t, hookTasks, hookTasksLenBefore+1)
|
assert.Len(t, hookTasks, hookTasksLenBefore+1)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPullSquash(t *testing.T) {
|
func TestPullSquash(t *testing.T) {
|
||||||
onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
|
onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) {
|
||||||
hookTasks, err := webhook.HookTasks(db.DefaultContext, 1, 1) // Retrieve previous hook number
|
hookTasks := retrieveHookTasks(t, 1, true)
|
||||||
assert.NoError(t, err)
|
|
||||||
hookTasksLenBefore := len(hookTasks)
|
hookTasksLenBefore := len(hookTasks)
|
||||||
|
|
||||||
session := loginUser(t, "user1")
|
session := loginUser(t, "user1")
|
||||||
|
@ -163,8 +169,7 @@ func TestPullSquash(t *testing.T) {
|
||||||
assert.EqualValues(t, "pulls", elem[3])
|
assert.EqualValues(t, "pulls", elem[3])
|
||||||
testPullMerge(t, session, elem[1], elem[2], elem[4], repo_model.MergeStyleSquash, false)
|
testPullMerge(t, session, elem[1], elem[2], elem[4], repo_model.MergeStyleSquash, false)
|
||||||
|
|
||||||
hookTasks, err = webhook.HookTasks(db.DefaultContext, 1, 1)
|
hookTasks = retrieveHookTasks(t, 1, false)
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.Len(t, hookTasks, hookTasksLenBefore+1)
|
assert.Len(t, hookTasks, hookTasksLenBefore+1)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -251,9 +251,8 @@ const sfc = {
|
||||||
this.repos = json.data.map((webSearchRepo) => {
|
this.repos = json.data.map((webSearchRepo) => {
|
||||||
return {
|
return {
|
||||||
...webSearchRepo.repository,
|
...webSearchRepo.repository,
|
||||||
latest_commit_status_state: webSearchRepo.latest_commit_status.State,
|
latest_commit_status: webSearchRepo.latest_commit_status,
|
||||||
locale_latest_commit_status_state: webSearchRepo.locale_latest_commit_status,
|
locale_latest_commit_status_state: webSearchRepo.locale_latest_commit_status
|
||||||
latest_commit_status_state_link: webSearchRepo.latest_commit_status.TargetURL
|
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
const count = response.headers.get('X-Total-Count');
|
const count = response.headers.get('X-Total-Count');
|
||||||
|
@ -416,9 +415,9 @@ export default sfc; // activate the IDE's Vue plugin
|
||||||
<svg-icon name="octicon-archive" :size="16"/>
|
<svg-icon name="octicon-archive" :size="16"/>
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
<a class="gt-df gt-ac" v-if="repo.latest_commit_status_state" :href="repo.latest_commit_status_state_link" :data-tooltip-content="repo.locale_latest_commit_status_state">
|
<a class="gt-df gt-ac" v-if="repo.latest_commit_status" :href="repo.latest_commit_status.TargetLink" :data-tooltip-content="repo.locale_latest_commit_status.State">
|
||||||
<!-- the commit status icon logic is taken from templates/repo/commit_status.tmpl -->
|
<!-- the commit status icon logic is taken from templates/repo/commit_status.tmpl -->
|
||||||
<svg-icon :name="statusIcon(repo.latest_commit_status_state)" :class-name="'gt-ml-3 commit-status icon text ' + statusColor(repo.latest_commit_status_state)" :size="16"/>
|
<svg-icon :name="statusIcon(repo.latest_commit_status.State)" :class-name="'gt-ml-3 commit-status icon text ' + statusColor(repo.latest_commit_status.State)" :size="16"/>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
Loading…
Reference in a new issue