From 5b17c1d6ebc39ab20327a502bea5bbc39a456846 Mon Sep 17 00:00:00 2001 From: Dirk Date: Sun, 29 Sep 2024 00:29:01 +0200 Subject: [PATCH 01/37] make sqlite3 the default database --- custom/conf/app.example.ini | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/custom/conf/app.example.ini b/custom/conf/app.example.ini index 2eff51fe98..7eb4f1c655 100644 --- a/custom/conf/app.example.ini +++ b/custom/conf/app.example.ini @@ -349,16 +349,25 @@ RUN_USER = ; git ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; -;; Database to use. Either "mysql", "postgres", "mssql" or "sqlite3". +;; Database to use. Either "sqlite3", "mySQL", "postgres" or "mssql". +;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; +;; SQLite Configuration +;; +DB_TYPE = sqlite3 +;PATH= ; defaults to data/forgejo.db +;SQLITE_TIMEOUT = ; Query timeout defaults to: 500 +;SQLITE_JOURNAL_MODE = ; defaults to sqlite database default (often DELETE), can be used to enable WAL mode. https://www.sqlite.org/pragma.html#pragma_journal_mode ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;; MySQL Configuration ;; -DB_TYPE = mysql -HOST = 127.0.0.1:3306 ; can use socket e.g. /var/run/mysqld/mysqld.sock -NAME = gitea -USER = root +;DB_TYPE = mysql +;HOST = 127.0.0.1:3306 ; can use socket e.g. /var/run/mysqld/mysqld.sock +;NAME = gitea +;USER = root ;PASSWD = ;Use PASSWD = `your password` for quoting if you use special characters in the password. ;SSL_MODE = false ; either "false" (default), "true", or "skip-verify" ;CHARSET_COLLATION = ; Empty as default, Gitea will try to find a case-sensitive collation. Don't change it unless you clearly know what you need. @@ -377,15 +386,6 @@ USER = root ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; -;; SQLite Configuration -;; -;DB_TYPE = sqlite3 -;PATH= ; defaults to data/forgejo.db -;SQLITE_TIMEOUT = ; Query timeout defaults to: 500 -;SQLITE_JOURNAL_MODE = ; defaults to sqlite database default (often DELETE), can be used to enable WAL mode. https://www.sqlite.org/pragma.html#pragma_journal_mode -;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; MSSQL Configuration ;; ;DB_TYPE = mssql From ba891d50bffef71106984a422bd1ee59ef558412 Mon Sep 17 00:00:00 2001 From: Dirk Date: Thu, 3 Oct 2024 14:03:10 +0200 Subject: [PATCH 02/37] remove mssql as requested per review comment see https://codeberg.org/forgejo/forgejo/pulls/5415#issuecomment-2349746 --- custom/conf/app.example.ini | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/custom/conf/app.example.ini b/custom/conf/app.example.ini index 7eb4f1c655..87eb83c762 100644 --- a/custom/conf/app.example.ini +++ b/custom/conf/app.example.ini @@ -349,7 +349,7 @@ RUN_USER = ; git ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; -;; Database to use. Either "sqlite3", "mySQL", "postgres" or "mssql". +;; Database to use. Either "sqlite3", "mySQL" or "postgres". ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; @@ -386,17 +386,6 @@ DB_TYPE = sqlite3 ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; -;; MSSQL Configuration -;; -;DB_TYPE = mssql -;HOST = 172.17.0.2:1433 -;NAME = gitea -;USER = SA -;PASSWD = MwantsaSecurePassword1 -;CHARSET_COLLATION = ; Empty as default, Gitea will try to find a case-sensitive collation. Don't change it unless you clearly know what you need. -;; -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; -;; ;; Other settings ;; ;; For iterate buffer, default is 50 From 4f336e589d2f8185e8325728c3a35e071f6330a9 Mon Sep 17 00:00:00 2001 From: Michael Kriese Date: Fri, 8 Nov 2024 12:17:00 +0100 Subject: [PATCH 03/37] chore(renovate): group forgejo go-chi packages --- renovate.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/renovate.json b/renovate.json index 28cb82e2df..cd927797f5 100644 --- a/renovate.json +++ b/renovate.json @@ -83,6 +83,12 @@ "matchUpdateTypes": ["minor", "patch"], "groupName": "postcss" }, + { + "description": "Group Forgejo go-chi packages", + "matchUpdateTypes": ["minor", "patch", "digest"], + "matchPackageNames": ["code.forgejo.org/go-chi/**"], + "groupName": "forgejo go-chi packages" + }, { "description": "Split minor and patch updates", "matchPackageNames": [ From 669b4b46e6b620edf10b7330492898eb1277f0c8 Mon Sep 17 00:00:00 2001 From: Michael Kriese Date: Fri, 8 Nov 2024 12:18:29 +0100 Subject: [PATCH 04/37] chore(renovate): pin to single actions runner --- .forgejo/workflows/renovate.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.forgejo/workflows/renovate.yml b/.forgejo/workflows/renovate.yml index 1f29156069..0da82d9154 100644 --- a/.forgejo/workflows/renovate.yml +++ b/.forgejo/workflows/renovate.yml @@ -21,7 +21,7 @@ jobs: renovate: if: ${{ secrets.RENOVATE_TOKEN != '' }} - runs-on: docker + runs-on: docker-runner-one container: image: code.forgejo.org/forgejo-contrib/renovate:39.5.0 From 2eeb2fcd359cd9a210d95c647ec4bb2fed7f13e0 Mon Sep 17 00:00:00 2001 From: Michael Kriese Date: Fri, 8 Nov 2024 13:05:43 +0100 Subject: [PATCH 05/37] chore(renovate): only run if renovate workflow changed --- .forgejo/workflows/renovate.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.forgejo/workflows/renovate.yml b/.forgejo/workflows/renovate.yml index 0da82d9154..468d107325 100644 --- a/.forgejo/workflows/renovate.yml +++ b/.forgejo/workflows/renovate.yml @@ -8,7 +8,9 @@ name: renovate on: push: branches: - - 'renovate/**' # self-test updates + - renovate/** # self-test updates + paths: + - .forgejo/workflows/renovate.yml schedule: - cron: '0 0/2 * * *' workflow_dispatch: From d2a3eefcd0c1339de37bec275f8d8e0dd614036d Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Fri, 8 Nov 2024 17:43:48 +0000 Subject: [PATCH 06/37] Update module code.forgejo.org/go-chi/binding to v1 (forgejo) (#5862) Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/5862 Reviewed-by: Michael Kriese Co-authored-by: Renovate Bot Co-committed-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 513f119014..3171b0cfdc 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( code.forgejo.org/f3/gof3/v3 v3.7.0 code.forgejo.org/forgejo-contrib/go-libravatar v0.0.0-20191008002943-06d1c002b251 code.forgejo.org/forgejo/reply v1.0.2 - code.forgejo.org/go-chi/binding v0.0.0-20241105210225-1f8bf5136720 + code.forgejo.org/go-chi/binding v1.0.0 code.forgejo.org/go-chi/cache v0.0.0-20240912103640-dcb08fba860d code.forgejo.org/go-chi/captcha v0.0.0-20240905153133-df43b9250ed5 code.forgejo.org/go-chi/session v0.0.0-20241017103059-2a992261fc26 diff --git a/go.sum b/go.sum index c2af9b3c36..3e6bb14ae4 100644 --- a/go.sum +++ b/go.sum @@ -10,8 +10,8 @@ code.forgejo.org/forgejo/archiver/v3 v3.5.1 h1:UmmbA7D5550uf71SQjarmrn6yKwOGxtEj code.forgejo.org/forgejo/archiver/v3 v3.5.1/go.mod h1:e3dqJ7H78uzsRSEACH1joayhuSyhnonssnDhppzS1L4= code.forgejo.org/forgejo/reply v1.0.2 h1:dMhQCHV6/O3L5CLWNTol+dNzDAuyCK88z4J/lCdgFuQ= code.forgejo.org/forgejo/reply v1.0.2/go.mod h1:RyZUfzQLc+fuLIGjTSQWDAJWPiL4WtKXB/FifT5fM7U= -code.forgejo.org/go-chi/binding v0.0.0-20241105210225-1f8bf5136720 h1:DDdvrdov1a6HK0xiJIUTfGh1RpKP0prkHi2guxhDKIU= -code.forgejo.org/go-chi/binding v0.0.0-20241105210225-1f8bf5136720/go.mod h1:fWwqaHj0H1/KeCpBqdvKunflq8pYfciEHI5v3UUeE2E= +code.forgejo.org/go-chi/binding v1.0.0 h1:EIDJtk9brK7WsT7rvS/D4cxX8XlnhY3LMy8ex1jeHu0= +code.forgejo.org/go-chi/binding v1.0.0/go.mod h1:fWwqaHj0H1/KeCpBqdvKunflq8pYfciEHI5v3UUeE2E= code.forgejo.org/go-chi/cache v0.0.0-20240912103640-dcb08fba860d h1:nOu/2GX571t4intmtfvpctS148OqsBYrGUySVm93ifc= code.forgejo.org/go-chi/cache v0.0.0-20240912103640-dcb08fba860d/go.mod h1:OVlZ/TqDYJ+RUJ+R+J+OLxtlyjo3pbjBeK7LAWAB+Vk= code.forgejo.org/go-chi/captcha v0.0.0-20240905153133-df43b9250ed5 h1:A7P1liXCpJBHEJ5KIDsF0ujnQ8FQ/aX1UixTW0vGrDQ= From bf69683df6bb1eb894320f7250e3d3b6e664d168 Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Fri, 8 Nov 2024 21:12:20 +0000 Subject: [PATCH 07/37] Update module code.forgejo.org/go-chi/cache to v1 (forgejo) (#5863) Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/5863 Reviewed-by: Michael Kriese Co-authored-by: Renovate Bot Co-committed-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 3171b0cfdc..88d9caae90 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( code.forgejo.org/forgejo-contrib/go-libravatar v0.0.0-20191008002943-06d1c002b251 code.forgejo.org/forgejo/reply v1.0.2 code.forgejo.org/go-chi/binding v1.0.0 - code.forgejo.org/go-chi/cache v0.0.0-20240912103640-dcb08fba860d + code.forgejo.org/go-chi/cache v1.0.0 code.forgejo.org/go-chi/captcha v0.0.0-20240905153133-df43b9250ed5 code.forgejo.org/go-chi/session v0.0.0-20241017103059-2a992261fc26 code.gitea.io/actions-proto-go v0.4.0 diff --git a/go.sum b/go.sum index 3e6bb14ae4..d722e955ef 100644 --- a/go.sum +++ b/go.sum @@ -12,8 +12,8 @@ code.forgejo.org/forgejo/reply v1.0.2 h1:dMhQCHV6/O3L5CLWNTol+dNzDAuyCK88z4J/lCd code.forgejo.org/forgejo/reply v1.0.2/go.mod h1:RyZUfzQLc+fuLIGjTSQWDAJWPiL4WtKXB/FifT5fM7U= code.forgejo.org/go-chi/binding v1.0.0 h1:EIDJtk9brK7WsT7rvS/D4cxX8XlnhY3LMy8ex1jeHu0= code.forgejo.org/go-chi/binding v1.0.0/go.mod h1:fWwqaHj0H1/KeCpBqdvKunflq8pYfciEHI5v3UUeE2E= -code.forgejo.org/go-chi/cache v0.0.0-20240912103640-dcb08fba860d h1:nOu/2GX571t4intmtfvpctS148OqsBYrGUySVm93ifc= -code.forgejo.org/go-chi/cache v0.0.0-20240912103640-dcb08fba860d/go.mod h1:OVlZ/TqDYJ+RUJ+R+J+OLxtlyjo3pbjBeK7LAWAB+Vk= +code.forgejo.org/go-chi/cache v1.0.0 h1:akLfGxNlHcacmtutovNtYFSTMsbdcp5MGjAEsP4pxnE= +code.forgejo.org/go-chi/cache v1.0.0/go.mod h1:OVlZ/TqDYJ+RUJ+R+J+OLxtlyjo3pbjBeK7LAWAB+Vk= code.forgejo.org/go-chi/captcha v0.0.0-20240905153133-df43b9250ed5 h1:A7P1liXCpJBHEJ5KIDsF0ujnQ8FQ/aX1UixTW0vGrDQ= code.forgejo.org/go-chi/captcha v0.0.0-20240905153133-df43b9250ed5/go.mod h1:YLOsiln/arX3egGtxG4QNp49G2CIqP9pqD2VL56obLc= code.forgejo.org/go-chi/session v0.0.0-20241017103059-2a992261fc26 h1:6XCLWu8A0nPM862Uh68kQmxsBsaQNfPPFwYjzG8M8QE= From 2541a943ce01636203e8e456e0a2308b24c4ba4a Mon Sep 17 00:00:00 2001 From: Earl Warren Date: Sat, 9 Nov 2024 00:07:18 +0100 Subject: [PATCH 08/37] bug: require.Eventually must not test with assert Otherwise it fails the test instead of retrying if the condition fails at least once. --- tests/integration/actions_trigger_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/integration/actions_trigger_test.go b/tests/integration/actions_trigger_test.go index 25dcacde34..9cf2d4305f 100644 --- a/tests/integration/actions_trigger_test.go +++ b/tests/integration/actions_trigger_test.go @@ -321,7 +321,7 @@ jobs: require.Eventually(t, func() bool { actionRuns = make([]*actions_model.ActionRun, 0) require.NoError(t, db.GetEngine(db.DefaultContext).Where("repo_id=?", baseRepo.ID).Find(&actionRuns)) - return assert.Len(t, actionRuns, count) + return len(actionRuns) == count }, 30*time.Second, 1*time.Second) // verify the expected ActionRuns were created From 5ab832ba8779b8718cd9513cedc109fe5f2508a6 Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Fri, 8 Nov 2024 23:37:13 +0000 Subject: [PATCH 09/37] Update module code.forgejo.org/go-chi/session to v1 (forgejo) (#5865) Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/5865 Reviewed-by: Michael Kriese Co-authored-by: Renovate Bot Co-committed-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 88d9caae90..583892d428 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( code.forgejo.org/go-chi/binding v1.0.0 code.forgejo.org/go-chi/cache v1.0.0 code.forgejo.org/go-chi/captcha v0.0.0-20240905153133-df43b9250ed5 - code.forgejo.org/go-chi/session v0.0.0-20241017103059-2a992261fc26 + code.forgejo.org/go-chi/session v1.0.0 code.gitea.io/actions-proto-go v0.4.0 code.gitea.io/gitea-vet v0.2.3 code.gitea.io/sdk/gitea v0.17.1 diff --git a/go.sum b/go.sum index d722e955ef..f1e833caa4 100644 --- a/go.sum +++ b/go.sum @@ -16,8 +16,8 @@ code.forgejo.org/go-chi/cache v1.0.0 h1:akLfGxNlHcacmtutovNtYFSTMsbdcp5MGjAEsP4p code.forgejo.org/go-chi/cache v1.0.0/go.mod h1:OVlZ/TqDYJ+RUJ+R+J+OLxtlyjo3pbjBeK7LAWAB+Vk= code.forgejo.org/go-chi/captcha v0.0.0-20240905153133-df43b9250ed5 h1:A7P1liXCpJBHEJ5KIDsF0ujnQ8FQ/aX1UixTW0vGrDQ= code.forgejo.org/go-chi/captcha v0.0.0-20240905153133-df43b9250ed5/go.mod h1:YLOsiln/arX3egGtxG4QNp49G2CIqP9pqD2VL56obLc= -code.forgejo.org/go-chi/session v0.0.0-20241017103059-2a992261fc26 h1:6XCLWu8A0nPM862Uh68kQmxsBsaQNfPPFwYjzG8M8QE= -code.forgejo.org/go-chi/session v0.0.0-20241017103059-2a992261fc26/go.mod h1:lS76JFHZqGXYJTBHqwZ910UG046hIXAaYIN6J0Lf8sI= +code.forgejo.org/go-chi/session v1.0.0 h1:1hjLWHpXkb4vs/g9rk/unhRL4AoKEqVUPJ+opI8UO3Y= +code.forgejo.org/go-chi/session v1.0.0/go.mod h1:lS76JFHZqGXYJTBHqwZ910UG046hIXAaYIN6J0Lf8sI= code.gitea.io/actions-proto-go v0.4.0 h1:OsPBPhodXuQnsspG1sQ4eRE1PeoZyofd7+i73zCwnsU= code.gitea.io/actions-proto-go v0.4.0/go.mod h1:mn7Wkqz6JbnTOHQpot3yDeHx+O5C9EGhMEE+htvHBas= code.gitea.io/gitea-vet v0.2.3 h1:gdFmm6WOTM65rE8FUBTRzeQZYzXePKSSB1+r574hWwI= From 2efc1f56863b82ac805a549d1f81deb31a6356b0 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Mon, 15 Apr 2024 22:11:07 +0800 Subject: [PATCH 10/37] [PORT] Fix code owners will not be mentioned when a pull request comes from a forked repository (gitea#30476) Fix #30277 Caused by #29783 --- - Resolves #5842 - Regression from #2855 (cherry picked from commit c63060b130d34e3f03f28f4dccbf04d381a95c17) --- services/issue/pull.go | 8 ++++---- tests/integration/pull_review_test.go | 12 ++++++++++-- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/services/issue/pull.go b/services/issue/pull.go index c5a12ce7c4..896802108d 100644 --- a/services/issue/pull.go +++ b/services/issue/pull.go @@ -51,14 +51,14 @@ func PullRequestCodeOwnersReview(ctx context.Context, issue *issues_model.Issue, return nil, err } - if pr.HeadRepo.IsFork { - return nil, nil - } - if err := pr.LoadBaseRepo(ctx); err != nil { return nil, err } + if pr.BaseRepo.IsFork { + return nil, nil + } + repo, err := gitrepo.OpenRepository(ctx, pr.BaseRepo) if err != nil { return nil, err diff --git a/tests/integration/pull_review_test.go b/tests/integration/pull_review_test.go index d15a7bd130..fc3e9be4a0 100644 --- a/tests/integration/pull_review_test.go +++ b/tests/integration/pull_review_test.go @@ -397,10 +397,18 @@ func TestPullView_CodeOwner(t *testing.T) { require.NoError(t, err) session := loginUser(t, "user5") - testPullCreate(t, session, "user5", "test_codeowner_fork", false, forkedRepo.DefaultBranch, "codeowner-basebranch-forked", "Test Pull Request2") - pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{BaseRepoID: repo.ID, HeadBranch: "codeowner-basebranch-forked"}) + // create a pull request on the forked repository, code reviewers should not be mentioned + testPullCreateDirectly(t, session, "user5", "test_codeowner_fork", forkedRepo.DefaultBranch, "", "", "codeowner-basebranch-forked", "Test Pull Request on Forked Repository") + + pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{BaseRepoID: forkedRepo.ID, HeadBranch: "codeowner-basebranch-forked"}) unittest.AssertExistsIf(t, false, &issues_model.Review{IssueID: pr.IssueID, Type: issues_model.ReviewTypeRequest, ReviewerID: 8}) + + // create a pull request to base repository, code reviewers should be mentioned + testPullCreateDirectly(t, session, repo.OwnerName, repo.Name, repo.DefaultBranch, forkedRepo.OwnerName, forkedRepo.Name, "codeowner-basebranch-forked", "Test Pull Request3") + + pr = unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{BaseRepoID: repo.ID, HeadRepoID: forkedRepo.ID, HeadBranch: "codeowner-basebranch-forked"}) + unittest.AssertExistsIf(t, true, &issues_model.Review{IssueID: pr.IssueID, Type: issues_model.ReviewTypeRequest, ReviewerID: 8}) }) }) } From dffee135f829a19f456d1e7419dd38000610f5e3 Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Sat, 9 Nov 2024 07:28:23 +0000 Subject: [PATCH 11/37] Update module code.forgejo.org/go-chi/captcha to v1 (forgejo) (#5864) Reviewed-on: https://codeberg.org/forgejo/forgejo/pulls/5864 Reviewed-by: Michael Kriese Co-authored-by: Renovate Bot Co-committed-by: Renovate Bot --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 583892d428..edd8108f6f 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ require ( code.forgejo.org/forgejo/reply v1.0.2 code.forgejo.org/go-chi/binding v1.0.0 code.forgejo.org/go-chi/cache v1.0.0 - code.forgejo.org/go-chi/captcha v0.0.0-20240905153133-df43b9250ed5 + code.forgejo.org/go-chi/captcha v1.0.0 code.forgejo.org/go-chi/session v1.0.0 code.gitea.io/actions-proto-go v0.4.0 code.gitea.io/gitea-vet v0.2.3 diff --git a/go.sum b/go.sum index f1e833caa4..78a867b0cc 100644 --- a/go.sum +++ b/go.sum @@ -14,8 +14,8 @@ code.forgejo.org/go-chi/binding v1.0.0 h1:EIDJtk9brK7WsT7rvS/D4cxX8XlnhY3LMy8ex1 code.forgejo.org/go-chi/binding v1.0.0/go.mod h1:fWwqaHj0H1/KeCpBqdvKunflq8pYfciEHI5v3UUeE2E= code.forgejo.org/go-chi/cache v1.0.0 h1:akLfGxNlHcacmtutovNtYFSTMsbdcp5MGjAEsP4pxnE= code.forgejo.org/go-chi/cache v1.0.0/go.mod h1:OVlZ/TqDYJ+RUJ+R+J+OLxtlyjo3pbjBeK7LAWAB+Vk= -code.forgejo.org/go-chi/captcha v0.0.0-20240905153133-df43b9250ed5 h1:A7P1liXCpJBHEJ5KIDsF0ujnQ8FQ/aX1UixTW0vGrDQ= -code.forgejo.org/go-chi/captcha v0.0.0-20240905153133-df43b9250ed5/go.mod h1:YLOsiln/arX3egGtxG4QNp49G2CIqP9pqD2VL56obLc= +code.forgejo.org/go-chi/captcha v1.0.0 h1:ZKVznXrPfruc1RMavCFBEINGxB3RAYr4I+WQAK8+eP0= +code.forgejo.org/go-chi/captcha v1.0.0/go.mod h1:YLOsiln/arX3egGtxG4QNp49G2CIqP9pqD2VL56obLc= code.forgejo.org/go-chi/session v1.0.0 h1:1hjLWHpXkb4vs/g9rk/unhRL4AoKEqVUPJ+opI8UO3Y= code.forgejo.org/go-chi/session v1.0.0/go.mod h1:lS76JFHZqGXYJTBHqwZ910UG046hIXAaYIN6J0Lf8sI= code.gitea.io/actions-proto-go v0.4.0 h1:OsPBPhodXuQnsspG1sQ4eRE1PeoZyofd7+i73zCwnsU= From 39f4018d87bc37c70f4fcd295af3b12555341231 Mon Sep 17 00:00:00 2001 From: Earl Warren Date: Sat, 9 Nov 2024 18:16:38 +0100 Subject: [PATCH 12/37] fix(ci): slow runners may need more than 50 minutes for a test --- .forgejo/workflows/testing.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.forgejo/workflows/testing.yml b/.forgejo/workflows/testing.yml index 30d765ab30..03ebf0e983 100644 --- a/.forgejo/workflows/testing.yml +++ b/.forgejo/workflows/testing.yml @@ -82,7 +82,7 @@ jobs: - uses: ./.forgejo/workflows-composite/build-backend - run: | su forgejo -c 'make test-backend test-check' - timeout-minutes: 50 + timeout-minutes: 120 env: RACE_ENABLED: 'true' TAGS: bindata @@ -116,7 +116,7 @@ jobs: separator: '\n' - run: | su forgejo -c 'make generate test-e2e-sqlite' - timeout-minutes: 40 + timeout-minutes: 120 env: USE_REPO_TEST_DIR: 1 PLAYWRIGHT_SKIP_BROWSER_DOWNLOAD: 1 @@ -156,7 +156,7 @@ jobs: - uses: ./.forgejo/workflows-composite/build-backend - run: | su forgejo -c 'make test-remote-cacher test-check' - timeout-minutes: 50 + timeout-minutes: 120 env: RACE_ENABLED: 'true' TAGS: bindata @@ -187,7 +187,7 @@ jobs: - uses: ./.forgejo/workflows-composite/build-backend - run: | su forgejo -c 'make test-mysql-migration test-mysql' - timeout-minutes: 50 + timeout-minutes: 120 env: USE_REPO_TEST_DIR: 1 test-pgsql: @@ -219,7 +219,7 @@ jobs: - uses: ./.forgejo/workflows-composite/build-backend - run: | su forgejo -c 'make test-pgsql-migration test-pgsql' - timeout-minutes: 50 + timeout-minutes: 120 env: RACE_ENABLED: true USE_REPO_TEST_DIR: 1 @@ -240,7 +240,7 @@ jobs: - uses: ./.forgejo/workflows-composite/build-backend - run: | su forgejo -c 'make test-sqlite-migration test-sqlite' - timeout-minutes: 50 + timeout-minutes: 120 env: TAGS: sqlite sqlite_unlock_notify RACE_ENABLED: true From 536e1923b483fdb643be2f52f0fa68c1c2a02ffc Mon Sep 17 00:00:00 2001 From: Gusted Date: Sat, 9 Nov 2024 00:48:49 +0100 Subject: [PATCH 13/37] chore: add extra integration test --- tests/integration/codeowner_test.go | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/tests/integration/codeowner_test.go b/tests/integration/codeowner_test.go index 71661bc56b..b324711cb5 100644 --- a/tests/integration/codeowner_test.go +++ b/tests/integration/codeowner_test.go @@ -6,6 +6,7 @@ package integration import ( "context" "fmt" + "net/http" "net/url" "os" "path" @@ -136,5 +137,27 @@ func TestCodeOwner(t *testing.T) { unittest.AssertExistsIf(t, true, &issues_model.Review{IssueID: pr.IssueID, Type: issues_model.ReviewTypeRequest, ReviewerID: 4}) unittest.AssertExistsIf(t, false, &issues_model.Review{IssueID: pr.IssueID, Type: issues_model.ReviewTypeRequest, ReviewerID: 5}) }) + t.Run("From a forked repository", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + + session := loginUser(t, "user1") + + r := fmt.Sprintf("%suser1/repo1.git", u.String()) + remoteURL, _ := url.Parse(r) + remoteURL.User = url.UserPassword("user1", userPassword) + doGitAddRemote(dstPath, "forked-2", remoteURL)(t) + + err := git.NewCommand(git.DefaultContext, "push", "forked-2", "HEAD:branch").Run(&git.RunOpts{Dir: dstPath}) + require.NoError(t, err) + + req := NewRequestWithValues(t, "POST", repo.FullName()+"/compare/main...user1/repo1:branch", map[string]string{ + "_csrf": GetCSRF(t, session, repo.FullName()+"/compare/main...user1/repo1:branch"), + "title": "pull request", + }) + session.MakeRequest(t, req, http.StatusOK) + + pr := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{BaseRepoID: repo.ID, HeadBranch: "branch"}) + unittest.AssertExistsIf(t, true, &issues_model.Review{IssueID: pr.IssueID, Type: issues_model.ReviewTypeRequest, ReviewerID: 4}) + }) }) } From e58d5d46c1a411d79a1b889ab58c82fd6c975260 Mon Sep 17 00:00:00 2001 From: Ragnar Groot Koerkamp Date: Sat, 9 Nov 2024 21:14:31 +0100 Subject: [PATCH 14/37] [THEME] Copy ansi terminal colours from gitea to forgejo themes --- web_src/css/themes/theme-forgejo-dark.css | 17 +++++++++++++++++ web_src/css/themes/theme-forgejo-light.css | 17 +++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/web_src/css/themes/theme-forgejo-dark.css b/web_src/css/themes/theme-forgejo-dark.css index 9622add8e5..bc321f38a8 100644 --- a/web_src/css/themes/theme-forgejo-dark.css +++ b/web_src/css/themes/theme-forgejo-dark.css @@ -140,6 +140,23 @@ --color-pink-dark-2: #b11d5f; --color-brown-dark-2: #a47252; --color-black-dark-2: #111827; + /* ansi colors used for actions console and console files */ + --color-ansi-black: #1d2328; + --color-ansi-red: #cc4848; + --color-ansi-green: #87ab63; + --color-ansi-yellow: #cc9903; + --color-ansi-blue: #3a8ac6; + --color-ansi-magenta: #d22e8b; + --color-ansi-cyan: #00918a; + --color-ansi-white: var(--color-console-fg-subtle); + --color-ansi-bright-black: #424851; + --color-ansi-bright-red: #d15a5a; + --color-ansi-bright-green: #93b373; + --color-ansi-bright-yellow: #eaaf03; + --color-ansi-bright-blue: #4e96cc; + --color-ansi-bright-magenta: #d74397; + --color-ansi-bright-cyan: #00b6ad; + --color-ansi-bright-white: var(--color-console-fg); /* other colors */ --color-gold: #b1983b; --color-white: #ffffff; diff --git a/web_src/css/themes/theme-forgejo-light.css b/web_src/css/themes/theme-forgejo-light.css index 201818964b..fa89cc2ec8 100644 --- a/web_src/css/themes/theme-forgejo-light.css +++ b/web_src/css/themes/theme-forgejo-light.css @@ -157,6 +157,23 @@ --color-pink-dark-2: #b11d5f; --color-brown-dark-2: #835b42; --color-black-dark-2: #000000; + /* ansi colors used for actions console and console files */ + --color-ansi-black: #1f2326; + --color-ansi-red: #cc4848; + --color-ansi-green: #87ab63; + --color-ansi-yellow: #cc9903; + --color-ansi-blue: #3a8ac6; + --color-ansi-magenta: #d22e8b; + --color-ansi-cyan: #00918a; + --color-ansi-white: var(--color-console-fg-subtle); + --color-ansi-bright-black: #46494d; + --color-ansi-bright-red: #d15a5a; + --color-ansi-bright-green: #93b373; + --color-ansi-bright-yellow: #eaaf03; + --color-ansi-bright-blue: #4e96cc; + --color-ansi-bright-magenta: #d74397; + --color-ansi-bright-cyan: #00b6ad; + --color-ansi-bright-white: var(--color-console-fg); /* other colors */ --color-gold: #b1983b; --color-white: #ffffff; From 506ed7f43faa57a184d900ac515caba00a951e92 Mon Sep 17 00:00:00 2001 From: MrSmoer Date: Thu, 7 Nov 2024 01:08:40 +0100 Subject: [PATCH 15/37] fix: Move "forgot_password"-link to fix login tab order Previously hitting tab in the username field set the focus to the "forgot password" link. Only on the next hit the password field was selected. This is an issue for some password managers (keepassdx android keyboard) and not as nice for accessibility. Now the forgot link is below the sign up link at the bottom of the page. Using "tabindex" didn't work properly with the templating engine because many elements get assigned a tabindex of "0" by default disrupting the tab selection sequence. --- templates/user/auth/signin_inner.tmpl | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/templates/user/auth/signin_inner.tmpl b/templates/user/auth/signin_inner.tmpl index d4ba664e37..56532f4b98 100644 --- a/templates/user/auth/signin_inner.tmpl +++ b/templates/user/auth/signin_inner.tmpl @@ -17,9 +17,8 @@ {{if or (not .DisablePassword) .LinkAccountMode}} -
+
- {{ctx.Locale.Tr "auth.forgot_password"}}
{{end}} @@ -52,11 +51,15 @@
{{template "user/auth/webauthn_error" .}} - {{if .ShowRegistrationButton}}
+ {{if .ShowRegistrationButton}}
{{ctx.Locale.Tr "auth.hint_register" (printf "%s/user/sign_up" AppSubUrl)}} +
+
+ {{end}} +
- {{end}}
From 8587d4997909a9a6ff52bf0f7fc9c6f945db5246 Mon Sep 17 00:00:00 2001 From: MrSmoer Date: Sat, 9 Nov 2024 23:23:59 +0100 Subject: [PATCH 16/37] Remove unused css class "form-field-content-aside-label" This css class was used to display the "forgot password"-link right and above the password field. cd75519a0b moves this link, so this class is now unused --- web_src/css/form.css | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/web_src/css/form.css b/web_src/css/form.css index a8867009bc..fb9364db45 100644 --- a/web_src/css/form.css +++ b/web_src/css/form.css @@ -500,20 +500,6 @@ textarea:focus, } } -/* form fields with additional content besides their label, used on login form - * use like
*/ -.form-field-content-aside-label { - display: grid; - grid-template-columns: 1fr 1fr; -} -.form-field-content-aside-label > *:nth-child(2) { - text-align: right; - margin-bottom: 4px; -} -.form-field-content-aside-label input { - grid-column: span 2; -} - .ui.form .field > .selection.dropdown { min-width: 14em; /* matches the default min width */ } From 71d3e4c3178d47d1ca6aea9d23a1a4daf7db4d16 Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Sun, 10 Nov 2024 00:03:52 +0000 Subject: [PATCH 17/37] Update module golang.org/x/crypto to v0.29.0 --- go.mod | 8 ++++---- go.sum | 20 ++++++++++---------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/go.mod b/go.mod index edd8108f6f..4065ed25e3 100644 --- a/go.mod +++ b/go.mod @@ -100,12 +100,12 @@ require ( github.com/yuin/goldmark v1.7.8 github.com/yuin/goldmark-highlighting/v2 v2.0.0-20230729083705-37449abec8cc go.uber.org/mock v0.4.0 - golang.org/x/crypto v0.28.0 + golang.org/x/crypto v0.29.0 golang.org/x/image v0.21.0 golang.org/x/net v0.30.0 golang.org/x/oauth2 v0.23.0 - golang.org/x/sys v0.26.0 - golang.org/x/text v0.19.0 + golang.org/x/sys v0.27.0 + golang.org/x/text v0.20.0 golang.org/x/tools v0.26.0 google.golang.org/grpc v1.67.1 google.golang.org/protobuf v1.35.1 @@ -281,7 +281,7 @@ require ( go.uber.org/zap v1.27.0 // indirect golang.org/x/exp v0.0.0-20240119083558-1b970713d09a // indirect golang.org/x/mod v0.21.0 // indirect - golang.org/x/sync v0.8.0 // indirect + golang.org/x/sync v0.9.0 // indirect golang.org/x/time v0.5.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20240814211410-ddb44dafa142 // indirect gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect diff --git a/go.sum b/go.sum index 78a867b0cc..726b603059 100644 --- a/go.sum +++ b/go.sum @@ -733,8 +733,8 @@ golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2Uz golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc= golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= -golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw= -golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U= +golang.org/x/crypto v0.29.0 h1:L5SG1JTTXupVV3n6sUqMTeWbjAyfPwoda2DLX8J8FrQ= +golang.org/x/crypto v0.29.0/go.mod h1:+F4F4N5hv6v38hfeYwTdx20oUvLLc+QfrE9Ax9HtgRg= golang.org/x/exp v0.0.0-20240119083558-1b970713d09a h1:Q8/wZp0KX97QFTc2ywcOE0YRjZPVIx+MXInMzdvQqcA= golang.org/x/exp v0.0.0-20240119083558-1b970713d09a/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08= golang.org/x/image v0.21.0 h1:c5qV36ajHpdj4Qi0GnE0jUc/yuo33OLFaa0d+crTD5s= @@ -771,8 +771,8 @@ golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= -golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ= +golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -801,8 +801,8 @@ golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= -golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s= +golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= @@ -812,8 +812,8 @@ golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU= golang.org/x/term v0.15.0/go.mod h1:BDl952bC7+uMoWR75FIrCDx79TPU9oHkTZ9yRbYOrX0= -golang.org/x/term v0.25.0 h1:WtHI/ltw4NvSUig5KARz9h521QvRC8RmF/cuYqifU24= -golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M= +golang.org/x/term v0.26.0 h1:WEQa6V3Gja/BhNxg540hBip/kkaYtRg3cxg4oXSw4AU= +golang.org/x/term v0.26.0/go.mod h1:Si5m1o57C5nBNQo5z1iq+XDijt21BDBDp2bK0QI8e3E= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= @@ -825,8 +825,8 @@ golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= -golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= +golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= From 5932b86af4a2c8466a0d28e12c17cfdc79bc4617 Mon Sep 17 00:00:00 2001 From: Otto Richter Date: Sun, 10 Nov 2024 01:08:56 +0100 Subject: [PATCH 18/37] fix(ui): Details icon in repo settings sidebar Consistent classes between both details/summary constructs in the sidebar, ensuring they have the same style. --- templates/repo/settings/navbar.tmpl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/repo/settings/navbar.tmpl b/templates/repo/settings/navbar.tmpl index df5ba3aba6..0f6cb74d8c 100644 --- a/templates/repo/settings/navbar.tmpl +++ b/templates/repo/settings/navbar.tmpl @@ -5,7 +5,7 @@ {{ctx.Locale.Tr "repo.settings.options"}}
- {{ctx.Locale.Tr "repo.settings.units.units"}} + {{ctx.Locale.Tr "repo.settings.units.units"}} From b6e6a2c36ec23958f288da05eef5b0da1369b2e8 Mon Sep 17 00:00:00 2001 From: Shiny Nematoda Date: Tue, 5 Nov 2024 14:42:36 +0000 Subject: [PATCH 23/37] test: add for issue indexer sort by score --- .../indexer/issues/internal/tests/tests.go | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/modules/indexer/issues/internal/tests/tests.go b/modules/indexer/issues/internal/tests/tests.go index a93b2913e9..e8e6a4e7d1 100644 --- a/modules/indexer/issues/internal/tests/tests.go +++ b/modules/indexer/issues/internal/tests/tests.go @@ -126,6 +126,7 @@ var cases = []*testIndexerCase{ }, SearchOptions: &internal.SearchOptions{ Keyword: "hello", + SortBy: internal.SortByCreatedDesc, }, ExpectedIDs: []int64{1002, 1001, 1000}, ExpectedTotal: 3, @@ -139,6 +140,7 @@ var cases = []*testIndexerCase{ }, SearchOptions: &internal.SearchOptions{ Keyword: "hello world", + SortBy: internal.SortByCreatedDesc, IsFuzzyKeyword: true, }, ExpectedIDs: []int64{1002, 1001, 1000}, @@ -157,6 +159,7 @@ var cases = []*testIndexerCase{ }, SearchOptions: &internal.SearchOptions{ Keyword: "hello", + SortBy: internal.SortByCreatedDesc, RepoIDs: []int64{1, 4}, }, ExpectedIDs: []int64{1006, 1002, 1001}, @@ -175,6 +178,7 @@ var cases = []*testIndexerCase{ }, SearchOptions: &internal.SearchOptions{ Keyword: "hello", + SortBy: internal.SortByCreatedDesc, RepoIDs: []int64{1, 4}, AllPublic: true, }, @@ -597,6 +601,22 @@ var cases = []*testIndexerCase{ } }, }, + { + Name: "SortByScore", + SearchOptions: &internal.SearchOptions{ + Paginator: &db.ListOptionsAll, + SortBy: internal.SortByScore, + }, + Expected: func(t *testing.T, data map[int64]*internal.IndexerData, result *internal.SearchResult) { + assert.Equal(t, len(data), len(result.Hits)) + assert.Equal(t, len(data), int(result.Total)) + for i, v := range result.Hits { + if i < len(result.Hits)-1 { + assert.GreaterOrEqual(t, v.Score, result.Hits[i+1].Score) + } + } + }, + }, { Name: "SortByCreatedAsc", SearchOptions: &internal.SearchOptions{ From 493175e6fdeec5679dfe874d02c797b52a6d6848 Mon Sep 17 00:00:00 2001 From: Earl Warren Date: Sun, 10 Nov 2024 11:34:13 +0100 Subject: [PATCH 24/37] fix(ci): only trigger end-to-end tests when the label is set Use event.label instead of event.pull_request.labels.*.name Prior to Forgejo v9.0.2 it was not set and that was the only workaround. --- .forgejo/workflows/cascade-setup-end-to-end.yml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/.forgejo/workflows/cascade-setup-end-to-end.yml b/.forgejo/workflows/cascade-setup-end-to-end.yml index 404bbe8fa6..3d5237cd00 100644 --- a/.forgejo/workflows/cascade-setup-end-to-end.yml +++ b/.forgejo/workflows/cascade-setup-end-to-end.yml @@ -12,8 +12,10 @@ # whatever is in the default branch instead # # - after it is merged, double check it works by setting the -# run-end-to-end-test on a pull request (any pull request will doe +# run-end-to-end-test on a pull request (any pull request will do) # +name: end-to-end + on: push: branches: @@ -33,10 +35,9 @@ jobs: run: | echo github.event.pull_request.head.repo.fork = ${{ github.event.pull_request.head.repo.fork }} echo github.event.action = ${{ github.event.action }} - echo github.event.pull_request.merged = ${{ github.event.pull_request.merged }} - echo github.event.pull_request.labels.*.name + echo github.event.label cat <<'EOF' - ${{ toJSON(github.event.pull_request.labels.*.name) }} + ${{ toJSON(github.event.label) }} EOF cat <<'EOF' ${{ toJSON(github.event) }} @@ -47,7 +48,7 @@ jobs: !startsWith(vars.ROLE, 'forgejo-') && ( github.event_name == 'push' || ( - github.event.action == 'label_updated' && contains(github.event.pull_request.labels.*.name, 'run-end-to-end-tests') + github.event.action == 'label_updated' && github.event.label.name == 'run-end-to-end-tests' ) ) runs-on: docker From cdf3636ae70847aea9756af27a126aa32a081e8b Mon Sep 17 00:00:00 2001 From: Gusted Date: Sun, 10 Nov 2024 17:19:46 +0100 Subject: [PATCH 25/37] chore: simplify CopyDir Use the standard library function [`os.CopyFS`](https://pkg.go.dev/os#CopyFS) to copy directories. This also should be slightly faster. --- models/unittest/fscopy.go | 91 +-------------------------------------- 1 file changed, 2 insertions(+), 89 deletions(-) diff --git a/models/unittest/fscopy.go b/models/unittest/fscopy.go index 74b12d5057..5cd871ced6 100644 --- a/models/unittest/fscopy.go +++ b/models/unittest/fscopy.go @@ -4,99 +4,12 @@ package unittest import ( - "errors" - "io" "os" - "path" - "strings" - - "code.gitea.io/gitea/modules/util" ) -// Copy copies file from source to target path. -func Copy(src, dest string) error { - // Gather file information to set back later. - si, err := os.Lstat(src) - if err != nil { - return err - } - - // Handle symbolic link. - if si.Mode()&os.ModeSymlink != 0 { - target, err := os.Readlink(src) - if err != nil { - return err - } - // NOTE: os.Chmod and os.Chtimes don't recognize symbolic link, - // which will lead "no such file or directory" error. - return os.Symlink(target, dest) - } - - sr, err := os.Open(src) - if err != nil { - return err - } - defer sr.Close() - - dw, err := os.Create(dest) - if err != nil { - return err - } - defer dw.Close() - - if _, err = io.Copy(dw, sr); err != nil { - return err - } - - // Set back file information. - if err = os.Chtimes(dest, si.ModTime(), si.ModTime()); err != nil { - return err - } - return os.Chmod(dest, si.Mode()) -} - // CopyDir copy files recursively from source to target directory. // -// The filter accepts a function that process the path info. -// and should return true for need to filter. -// // It returns error when error occurs in underlying functions. -func CopyDir(srcPath, destPath string, filters ...func(filePath string) bool) error { - // Check if target directory exists. - if _, err := os.Stat(destPath); !errors.Is(err, os.ErrNotExist) { - return util.NewAlreadyExistErrorf("file or directory already exists: %s", destPath) - } - - err := os.MkdirAll(destPath, os.ModePerm) - if err != nil { - return err - } - - // Gather directory info. - infos, err := util.StatDir(srcPath, true) - if err != nil { - return err - } - - var filter func(filePath string) bool - if len(filters) > 0 { - filter = filters[0] - } - - for _, info := range infos { - if filter != nil && filter(info) { - continue - } - - curPath := path.Join(destPath, info) - if strings.HasSuffix(info, "/") { - err = os.MkdirAll(curPath, os.ModePerm) - } else { - err = Copy(path.Join(srcPath, info), curPath) - } - if err != nil { - return err - } - } - return nil +func CopyDir(srcPath, destPath string) error { + return os.CopyFS(destPath, os.DirFS(srcPath)) } From f352d6db813cfa8bd086b5d12aa5ab75dc29dea6 Mon Sep 17 00:00:00 2001 From: Gusted Date: Sun, 10 Nov 2024 19:41:04 +0100 Subject: [PATCH 26/37] chore: improve database docker instructions - Do not require minio for mariadb docker. - Do not require elasticsearch for mysql. - Fix postgress password parameter. - Add the multistatement query for mysql (this is not optimal but adding Makefile code doesn't seem to work really well either) --- Makefile | 1 + tests/e2e/README.md | 7 +++---- tests/integration/README.md | 9 ++++----- tests/pgsql.ini.tmpl | 2 +- 4 files changed, 9 insertions(+), 10 deletions(-) diff --git a/Makefile b/Makefile index a95a951792..6a8ff8d88e 100644 --- a/Makefile +++ b/Makefile @@ -660,6 +660,7 @@ generate-ini-pgsql: -e 's|{{REPO_TEST_DIR}}|${REPO_TEST_DIR}|g' \ -e 's|{{TEST_LOGGER}}|$(or $(TEST_LOGGER),test$(COMMA)file)|g' \ -e 's|{{TEST_TYPE}}|$(or $(TEST_TYPE),integration)|g' \ + -e 's|{{TEST_STORAGE_TYPE}}|$(or $(TEST_STORAGE_TYPE),minio)|g' \ tests/pgsql.ini.tmpl > tests/pgsql.ini .PHONY: test-pgsql diff --git a/tests/e2e/README.md b/tests/e2e/README.md index 36b9a187c3..4f93cfb64a 100644 --- a/tests/e2e/README.md +++ b/tests/e2e/README.md @@ -126,17 +126,16 @@ You can also perform e2e tests using MariaDB/MySQL or PostgreSQL if you want. Setup a MySQL database inside docker ``` -docker run -e "MYSQL_DATABASE=test" -e "MYSQL_ALLOW_EMPTY_PASSWORD=yes" -p 3306:3306 --rm --name mysql mysql:latest #(just ctrl-c to stop db and clean the container) -docker run -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" --rm --name elasticsearch elasticsearch:7.6.0 #(in a second terminal, just ctrl-c to stop db and clean the container) +docker run -e "MYSQL_DATABASE=test" -e "MYSQL_ALLOW_EMPTY_PASSWORD=yes" -p 3306:3306 --rm --name mysql mysql:latest #(Ctrl-c to stop the database) ``` Start tests based on the database container ``` -TEST_MYSQL_HOST=localhost:3306 TEST_MYSQL_DBNAME=test TEST_MYSQL_USERNAME=root TEST_MYSQL_PASSWORD='' make test-e2e-mysql +TEST_MYSQL_HOST=localhost:3306 TEST_MYSQL_DBNAME=test?multiStatements=true TEST_MYSQL_USERNAME=root TEST_MYSQL_PASSWORD='' make test-e2e-mysql ``` Setup a pgsql database inside docker ``` -docker run -e "POSTGRES_DB=test" -p 5432:5432 --rm --name pgsql postgres:latest #(just ctrl-c to stop db and clean the container) +docker run -e POSTGRES_DB=test -e POSTGRES_PASSWORD=password -p 5432:5432 --rm --name pgsql postgres:latest #(Ctrl-c to stop the database) ``` Start tests based on the database container ``` diff --git a/tests/integration/README.md b/tests/integration/README.md index f0fbf94df9..d83685388e 100644 --- a/tests/integration/README.md +++ b/tests/integration/README.md @@ -61,22 +61,21 @@ make test-sqlite ### Run MySQL integration tests Setup a MySQL database inside docker ``` -docker run -e "MYSQL_DATABASE=test" -e "MYSQL_ALLOW_EMPTY_PASSWORD=yes" -p 3306:3306 --rm --name mysql mysql:latest #(just ctrl-c to stop db and clean the container) -docker run -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" --rm --name elasticsearch elasticsearch:7.6.0 #(in a second terminal, just ctrl-c to stop db and clean the container) +docker run -e MYSQL_DATABASE=test -e MYSQL_ALLOW_EMPTY_PASSWORD=yes -p 3306:3306 --rm --name mysql mysql:latest #(Ctrl-c to stop the database) ``` Start tests based on the database container ``` -TEST_MYSQL_HOST=localhost:3306 TEST_MYSQL_DBNAME=test TEST_MYSQL_USERNAME=root TEST_MYSQL_PASSWORD='' make test-mysql +TEST_MYSQL_HOST=localhost:3306 TEST_MYSQL_DBNAME=test?multiStatements=true TEST_MYSQL_USERNAME=root TEST_MYSQL_PASSWORD='' make test-mysql ``` ### Run pgsql integration tests Setup a pgsql database inside docker ``` -docker run -e "POSTGRES_DB=test" -p 5432:5432 --rm --name pgsql postgres:latest #(just ctrl-c to stop db and clean the container) +docker run -e "POSTGRES_DB=test" -e POSTGRES_PASSWORD=postgres -p 5432:5432 --rm --name pgsql postgres:latest #(Ctrl-c to stop the database) ``` Start tests based on the database container ``` -TEST_PGSQL_HOST=localhost:5432 TEST_PGSQL_DBNAME=test TEST_PGSQL_USERNAME=postgres TEST_PGSQL_PASSWORD=postgres make test-pgsql +TEST_STORAGE_TYPE=local TEST_PGSQL_HOST=localhost:5432 TEST_PGSQL_DBNAME=test TEST_PGSQL_USERNAME=postgres TEST_PGSQL_PASSWORD=postgres make test-pgsql ``` ### Running individual tests diff --git a/tests/pgsql.ini.tmpl b/tests/pgsql.ini.tmpl index b58d753b6c..01d018c5b7 100644 --- a/tests/pgsql.ini.tmpl +++ b/tests/pgsql.ini.tmpl @@ -112,7 +112,7 @@ MINIO_BASE_PATH = avatars/ MINIO_BASE_PATH = repo-avatars/ [storage] -STORAGE_TYPE = minio +STORAGE_TYPE = {{TEST_STORAGE_TYPE}} SERVE_DIRECT = false MINIO_ENDPOINT = minio:9000 MINIO_ACCESS_KEY_ID = 123456 From 582ab21bc34b25752639e064ab722fc58cc0becd Mon Sep 17 00:00:00 2001 From: Gusted Date: Sun, 10 Nov 2024 18:25:41 +0100 Subject: [PATCH 27/37] chore: improve test quality - Merge tests together. - Remove unecessary usage of `onGiteaRun`. - Make proper use of `unittest`. - Make proper use of `test.MockVariable`. - I have not checked all of the testing files yet. --- .../integration/actions_commit_status_test.go | 3 +- tests/integration/api_admin_org_test.go | 83 +++-- tests/integration/api_branch_test.go | 33 +- tests/integration/api_fork_test.go | 30 +- tests/integration/api_nodeinfo_test.go | 34 +-- tests/integration/api_org_test.go | 288 +++++++++--------- tests/integration/last_updated_time_test.go | 73 +++-- tests/integration/pull_commit_test.go | 31 +- tests/integration/pull_review_test.go | 33 +- tests/integration/rename_branch_test.go | 2 - tests/integration/repo_collaborator_test.go | 32 +- tests/integration/repo_migration_ui_test.go | 26 +- tests/integration/repo_tag_test.go | 94 ++---- tests/integration/repo_view_test.go | 40 ++- tests/integration/repofiles_change_test.go | 269 +++++++--------- tests/integration/user_avatar_test.go | 101 +++--- .../integration/user_profile_activity_test.go | 99 +++--- .../integration/user_profile_follows_test.go | 133 ++++---- 18 files changed, 620 insertions(+), 784 deletions(-) diff --git a/tests/integration/actions_commit_status_test.go b/tests/integration/actions_commit_status_test.go index 7be40eb0fa..0dae5db344 100644 --- a/tests/integration/actions_commit_status_test.go +++ b/tests/integration/actions_commit_status_test.go @@ -14,6 +14,7 @@ import ( "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/test" "code.gitea.io/gitea/services/actions" "code.gitea.io/gitea/services/automerge" @@ -23,7 +24,7 @@ import ( func TestActionsAutomerge(t *testing.T) { onGiteaRun(t, func(t *testing.T, u *url.URL) { - assert.True(t, setting.Actions.Enabled, "Actions should be enabled") + defer test.MockVariableValue(&setting.Actions.Enabled, true)() ctx := db.DefaultContext diff --git a/tests/integration/api_admin_org_test.go b/tests/integration/api_admin_org_test.go index a29d0ba1d7..823ef2f136 100644 --- a/tests/integration/api_admin_org_test.go +++ b/tests/integration/api_admin_org_test.go @@ -5,7 +5,6 @@ package integration import ( "net/http" - "net/url" "strings" "testing" @@ -19,57 +18,55 @@ import ( ) func TestAPIAdminOrgCreate(t *testing.T) { - onGiteaRun(t, func(*testing.T, *url.URL) { - session := loginUser(t, "user1") - token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteAdmin) + defer tests.PrepareTestEnv(t)() + session := loginUser(t, "user1") + token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteAdmin) - org := api.CreateOrgOption{ - UserName: "user2_org", - FullName: "User2's organization", - Description: "This organization created by admin for user2", - Website: "https://try.gitea.io", - Location: "Shanghai", - Visibility: "private", - } - req := NewRequestWithJSON(t, "POST", "/api/v1/admin/users/user2/orgs", &org). - AddTokenAuth(token) - resp := MakeRequest(t, req, http.StatusCreated) + org := api.CreateOrgOption{ + UserName: "user2_org", + FullName: "User2's organization", + Description: "This organization created by admin for user2", + Website: "https://try.gitea.io", + Location: "Shanghai", + Visibility: "private", + } + req := NewRequestWithJSON(t, "POST", "/api/v1/admin/users/user2/orgs", &org). + AddTokenAuth(token) + resp := MakeRequest(t, req, http.StatusCreated) - var apiOrg api.Organization - DecodeJSON(t, resp, &apiOrg) + var apiOrg api.Organization + DecodeJSON(t, resp, &apiOrg) - assert.Equal(t, org.UserName, apiOrg.Name) - assert.Equal(t, org.FullName, apiOrg.FullName) - assert.Equal(t, org.Description, apiOrg.Description) - assert.Equal(t, org.Website, apiOrg.Website) - assert.Equal(t, org.Location, apiOrg.Location) - assert.Equal(t, org.Visibility, apiOrg.Visibility) + assert.Equal(t, org.UserName, apiOrg.Name) + assert.Equal(t, org.FullName, apiOrg.FullName) + assert.Equal(t, org.Description, apiOrg.Description) + assert.Equal(t, org.Website, apiOrg.Website) + assert.Equal(t, org.Location, apiOrg.Location) + assert.Equal(t, org.Visibility, apiOrg.Visibility) - unittest.AssertExistsAndLoadBean(t, &user_model.User{ - Name: org.UserName, - LowerName: strings.ToLower(org.UserName), - FullName: org.FullName, - }) + unittest.AssertExistsAndLoadBean(t, &user_model.User{ + Name: org.UserName, + LowerName: strings.ToLower(org.UserName), + FullName: org.FullName, }) } func TestAPIAdminOrgCreateBadVisibility(t *testing.T) { - onGiteaRun(t, func(*testing.T, *url.URL) { - session := loginUser(t, "user1") - token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteAdmin) + defer tests.PrepareTestEnv(t)() + session := loginUser(t, "user1") + token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteAdmin) - org := api.CreateOrgOption{ - UserName: "user2_org", - FullName: "User2's organization", - Description: "This organization created by admin for user2", - Website: "https://try.gitea.io", - Location: "Shanghai", - Visibility: "notvalid", - } - req := NewRequestWithJSON(t, "POST", "/api/v1/admin/users/user2/orgs", &org). - AddTokenAuth(token) - MakeRequest(t, req, http.StatusUnprocessableEntity) - }) + org := api.CreateOrgOption{ + UserName: "user2_org", + FullName: "User2's organization", + Description: "This organization created by admin for user2", + Website: "https://try.gitea.io", + Location: "Shanghai", + Visibility: "notvalid", + } + req := NewRequestWithJSON(t, "POST", "/api/v1/admin/users/user2/orgs", &org). + AddTokenAuth(token) + MakeRequest(t, req, http.StatusUnprocessableEntity) } func TestAPIAdminOrgCreateNotAdmin(t *testing.T) { diff --git a/tests/integration/api_branch_test.go b/tests/integration/api_branch_test.go index 63159f3c41..41b2c2efd1 100644 --- a/tests/integration/api_branch_test.go +++ b/tests/integration/api_branch_test.go @@ -9,14 +9,13 @@ import ( "testing" auth_model "code.gitea.io/gitea/models/auth" - "code.gitea.io/gitea/models/db" git_model "code.gitea.io/gitea/models/git" + "code.gitea.io/gitea/models/unittest" "code.gitea.io/gitea/modules/git" api "code.gitea.io/gitea/modules/structs" "code.gitea.io/gitea/tests" "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" ) func testAPIGetBranch(t *testing.T, branchName string, exists bool) { @@ -234,35 +233,17 @@ func TestAPIBranchProtection(t *testing.T) { } func TestAPICreateBranchWithSyncBranches(t *testing.T) { - defer tests.PrepareTestEnv(t)() - - branches, err := db.Find[git_model.Branch](db.DefaultContext, git_model.FindBranchOptions{ - RepoID: 1, - }) - require.NoError(t, err) - assert.Len(t, branches, 4) - - // make a broke repository with no branch on database - _, err = db.DeleteByBean(db.DefaultContext, git_model.Branch{RepoID: 1}) - require.NoError(t, err) - onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) { + unittest.AssertCount(t, &git_model.Branch{RepoID: 1}, 4) + + // make a broke repository with no branch on database + unittest.AssertSuccessfulDelete(t, &git_model.Branch{RepoID: 1}) + ctx := NewAPITestContext(t, "user2", "repo1", auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser) giteaURL.Path = ctx.GitPath() testAPICreateBranch(t, ctx.Session, "user2", "repo1", "", "new_branch", http.StatusCreated) - }) - branches, err = db.Find[git_model.Branch](db.DefaultContext, git_model.FindBranchOptions{ - RepoID: 1, + unittest.AssertExistsIf(t, true, &git_model.Branch{RepoID: 1, Name: "new_branch"}) }) - require.NoError(t, err) - assert.Len(t, branches, 5) - - branches, err = db.Find[git_model.Branch](db.DefaultContext, git_model.FindBranchOptions{ - RepoID: 1, - Keyword: "new_branch", - }) - require.NoError(t, err) - assert.Len(t, branches, 1) } diff --git a/tests/integration/api_fork_test.go b/tests/integration/api_fork_test.go index b80b4c6645..6a6b05f700 100644 --- a/tests/integration/api_fork_test.go +++ b/tests/integration/api_fork_test.go @@ -7,7 +7,6 @@ package integration import ( "fmt" "net/http" - "net/url" "testing" auth_model "code.gitea.io/gitea/models/auth" @@ -86,25 +85,24 @@ func TestCreateForkNoLogin(t *testing.T) { } func TestAPIDisabledForkRepo(t *testing.T) { - onGiteaRun(t, func(t *testing.T, u *url.URL) { - defer test.MockVariableValue(&setting.Repository.DisableForks, true)() - defer test.MockVariableValue(&testWebRoutes, routers.NormalRoutes())() + defer test.MockVariableValue(&setting.Repository.DisableForks, true)() + defer test.MockVariableValue(&testWebRoutes, routers.NormalRoutes())() + defer tests.PrepareTestEnv(t)() - t.Run("fork listing", func(t *testing.T) { - defer tests.PrintCurrentTest(t)() + t.Run("fork listing", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() - req := NewRequest(t, "GET", "/api/v1/repos/user2/repo1/forks") - MakeRequest(t, req, http.StatusNotFound) - }) + req := NewRequest(t, "GET", "/api/v1/repos/user2/repo1/forks") + MakeRequest(t, req, http.StatusNotFound) + }) - t.Run("forking", func(t *testing.T) { - defer tests.PrintCurrentTest(t)() + t.Run("forking", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() - session := loginUser(t, "user5") - token := getTokenForLoggedInUser(t, session) + session := loginUser(t, "user5") + token := getTokenForLoggedInUser(t, session) - req := NewRequestWithJSON(t, "POST", "/api/v1/repos/user2/repo1/forks", &api.CreateForkOption{}).AddTokenAuth(token) - session.MakeRequest(t, req, http.StatusNotFound) - }) + req := NewRequestWithJSON(t, "POST", "/api/v1/repos/user2/repo1/forks", &api.CreateForkOption{}).AddTokenAuth(token) + session.MakeRequest(t, req, http.StatusNotFound) }) } diff --git a/tests/integration/api_nodeinfo_test.go b/tests/integration/api_nodeinfo_test.go index 33d06ed1b4..d000083717 100644 --- a/tests/integration/api_nodeinfo_test.go +++ b/tests/integration/api_nodeinfo_test.go @@ -5,35 +5,31 @@ package integration import ( "net/http" - "net/url" "testing" "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" + "code.gitea.io/gitea/modules/test" "code.gitea.io/gitea/routers" + "code.gitea.io/gitea/tests" "github.com/stretchr/testify/assert" ) func TestNodeinfo(t *testing.T) { - setting.Federation.Enabled = true - testWebRoutes = routers.NormalRoutes() - defer func() { - setting.Federation.Enabled = false - testWebRoutes = routers.NormalRoutes() - }() + defer test.MockVariableValue(&setting.Federation.Enabled, true)() + defer test.MockVariableValue(&testWebRoutes, routers.NormalRoutes())() + defer tests.PrepareTestEnv(t)() - onGiteaRun(t, func(*testing.T, *url.URL) { - req := NewRequest(t, "GET", "/api/v1/nodeinfo") - resp := MakeRequest(t, req, http.StatusOK) - VerifyJSONSchema(t, resp, "nodeinfo_2.1.json") + req := NewRequest(t, "GET", "/api/v1/nodeinfo") + resp := MakeRequest(t, req, http.StatusOK) + VerifyJSONSchema(t, resp, "nodeinfo_2.1.json") - var nodeinfo api.NodeInfo - DecodeJSON(t, resp, &nodeinfo) - assert.True(t, nodeinfo.OpenRegistrations) - assert.Equal(t, "forgejo", nodeinfo.Software.Name) - assert.Equal(t, 29, nodeinfo.Usage.Users.Total) - assert.Equal(t, 22, nodeinfo.Usage.LocalPosts) - assert.Equal(t, 4, nodeinfo.Usage.LocalComments) - }) + var nodeinfo api.NodeInfo + DecodeJSON(t, resp, &nodeinfo) + assert.True(t, nodeinfo.OpenRegistrations) + assert.Equal(t, "forgejo", nodeinfo.Software.Name) + assert.Equal(t, 29, nodeinfo.Usage.Users.Total) + assert.Equal(t, 22, nodeinfo.Usage.LocalPosts) + assert.Equal(t, 4, nodeinfo.Usage.LocalComments) } diff --git a/tests/integration/api_org_test.go b/tests/integration/api_org_test.go index 70d3a446f7..3a7c81ca3a 100644 --- a/tests/integration/api_org_test.go +++ b/tests/integration/api_org_test.go @@ -6,7 +6,6 @@ package integration import ( "fmt" "net/http" - "net/url" "strings" "testing" @@ -19,150 +18,144 @@ import ( user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" + "code.gitea.io/gitea/modules/test" "code.gitea.io/gitea/tests" "github.com/stretchr/testify/assert" ) func TestAPIOrgCreate(t *testing.T) { - onGiteaRun(t, func(*testing.T, *url.URL) { - token := getUserToken(t, "user1", auth_model.AccessTokenScopeWriteOrganization) + defer tests.PrepareTestEnv(t)() + token := getUserToken(t, "user1", auth_model.AccessTokenScopeWriteOrganization) - org := api.CreateOrgOption{ - UserName: "user1_org", - FullName: "User1's organization", - Description: "This organization created by user1", - Website: "https://try.gitea.io", - Location: "Shanghai", - Visibility: "limited", - } - req := NewRequestWithJSON(t, "POST", "/api/v1/orgs", &org). - AddTokenAuth(token) - resp := MakeRequest(t, req, http.StatusCreated) + org := api.CreateOrgOption{ + UserName: "user1_org", + FullName: "User1's organization", + Description: "This organization created by user1", + Website: "https://try.gitea.io", + Location: "Shanghai", + Visibility: "limited", + } + req := NewRequestWithJSON(t, "POST", "/api/v1/orgs", &org). + AddTokenAuth(token) + resp := MakeRequest(t, req, http.StatusCreated) - var apiOrg api.Organization - DecodeJSON(t, resp, &apiOrg) + var apiOrg api.Organization + DecodeJSON(t, resp, &apiOrg) - assert.Equal(t, org.UserName, apiOrg.Name) - assert.Equal(t, org.FullName, apiOrg.FullName) - assert.Equal(t, org.Description, apiOrg.Description) - assert.Equal(t, org.Website, apiOrg.Website) - assert.Equal(t, org.Location, apiOrg.Location) - assert.Equal(t, org.Visibility, apiOrg.Visibility) + assert.Equal(t, org.UserName, apiOrg.Name) + assert.Equal(t, org.FullName, apiOrg.FullName) + assert.Equal(t, org.Description, apiOrg.Description) + assert.Equal(t, org.Website, apiOrg.Website) + assert.Equal(t, org.Location, apiOrg.Location) + assert.Equal(t, org.Visibility, apiOrg.Visibility) - unittest.AssertExistsAndLoadBean(t, &user_model.User{ - Name: org.UserName, - LowerName: strings.ToLower(org.UserName), - FullName: org.FullName, - }) - - // Check owner team permission - ownerTeam, _ := org_model.GetOwnerTeam(db.DefaultContext, apiOrg.ID) - - for _, ut := range unit_model.AllRepoUnitTypes { - up := perm.AccessModeOwner - if ut == unit_model.TypeExternalTracker || ut == unit_model.TypeExternalWiki { - up = perm.AccessModeRead - } - unittest.AssertExistsAndLoadBean(t, &org_model.TeamUnit{ - OrgID: apiOrg.ID, - TeamID: ownerTeam.ID, - Type: ut, - AccessMode: up, - }) - } - - req = NewRequestf(t, "GET", "/api/v1/orgs/%s", org.UserName). - AddTokenAuth(token) - resp = MakeRequest(t, req, http.StatusOK) - DecodeJSON(t, resp, &apiOrg) - assert.EqualValues(t, org.UserName, apiOrg.Name) - - req = NewRequestf(t, "GET", "/api/v1/orgs/%s/repos", org.UserName). - AddTokenAuth(token) - resp = MakeRequest(t, req, http.StatusOK) - - var repos []*api.Repository - DecodeJSON(t, resp, &repos) - for _, repo := range repos { - assert.False(t, repo.Private) - } - - req = NewRequestf(t, "GET", "/api/v1/orgs/%s/members", org.UserName). - AddTokenAuth(token) - resp = MakeRequest(t, req, http.StatusOK) - - // user1 on this org is public - var users []*api.User - DecodeJSON(t, resp, &users) - assert.Len(t, users, 1) - assert.EqualValues(t, "user1", users[0].UserName) + unittest.AssertExistsAndLoadBean(t, &user_model.User{ + Name: org.UserName, + LowerName: strings.ToLower(org.UserName), + FullName: org.FullName, }) + + // Check owner team permission + ownerTeam, _ := org_model.GetOwnerTeam(db.DefaultContext, apiOrg.ID) + + for _, ut := range unit_model.AllRepoUnitTypes { + up := perm.AccessModeOwner + if ut == unit_model.TypeExternalTracker || ut == unit_model.TypeExternalWiki { + up = perm.AccessModeRead + } + unittest.AssertExistsAndLoadBean(t, &org_model.TeamUnit{ + OrgID: apiOrg.ID, + TeamID: ownerTeam.ID, + Type: ut, + AccessMode: up, + }) + } + + req = NewRequestf(t, "GET", "/api/v1/orgs/%s", org.UserName). + AddTokenAuth(token) + resp = MakeRequest(t, req, http.StatusOK) + DecodeJSON(t, resp, &apiOrg) + assert.EqualValues(t, org.UserName, apiOrg.Name) + + req = NewRequestf(t, "GET", "/api/v1/orgs/%s/repos", org.UserName). + AddTokenAuth(token) + resp = MakeRequest(t, req, http.StatusOK) + + var repos []*api.Repository + DecodeJSON(t, resp, &repos) + for _, repo := range repos { + assert.False(t, repo.Private) + } + + req = NewRequestf(t, "GET", "/api/v1/orgs/%s/members", org.UserName). + AddTokenAuth(token) + resp = MakeRequest(t, req, http.StatusOK) + + // user1 on this org is public + var users []*api.User + DecodeJSON(t, resp, &users) + assert.Len(t, users, 1) + assert.EqualValues(t, "user1", users[0].UserName) } func TestAPIOrgEdit(t *testing.T) { - onGiteaRun(t, func(*testing.T, *url.URL) { - session := loginUser(t, "user1") + defer tests.PrepareTestEnv(t)() + session := loginUser(t, "user1") - token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteOrganization) - org := api.EditOrgOption{ - FullName: "Org3 organization new full name", - Description: "A new description", - Website: "https://try.gitea.io/new", - Location: "Beijing", - Visibility: "private", - } - req := NewRequestWithJSON(t, "PATCH", "/api/v1/orgs/org3", &org). - AddTokenAuth(token) - resp := MakeRequest(t, req, http.StatusOK) + token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteOrganization) + org := api.EditOrgOption{ + FullName: "Org3 organization new full name", + Description: "A new description", + Website: "https://try.gitea.io/new", + Location: "Beijing", + Visibility: "private", + } + req := NewRequestWithJSON(t, "PATCH", "/api/v1/orgs/org3", &org). + AddTokenAuth(token) + resp := MakeRequest(t, req, http.StatusOK) - var apiOrg api.Organization - DecodeJSON(t, resp, &apiOrg) + var apiOrg api.Organization + DecodeJSON(t, resp, &apiOrg) - assert.Equal(t, "org3", apiOrg.Name) - assert.Equal(t, org.FullName, apiOrg.FullName) - assert.Equal(t, org.Description, apiOrg.Description) - assert.Equal(t, org.Website, apiOrg.Website) - assert.Equal(t, org.Location, apiOrg.Location) - assert.Equal(t, org.Visibility, apiOrg.Visibility) - }) + assert.Equal(t, "org3", apiOrg.Name) + assert.Equal(t, org.FullName, apiOrg.FullName) + assert.Equal(t, org.Description, apiOrg.Description) + assert.Equal(t, org.Website, apiOrg.Website) + assert.Equal(t, org.Location, apiOrg.Location) + assert.Equal(t, org.Visibility, apiOrg.Visibility) } func TestAPIOrgEditBadVisibility(t *testing.T) { - onGiteaRun(t, func(*testing.T, *url.URL) { - session := loginUser(t, "user1") + defer tests.PrepareTestEnv(t)() + session := loginUser(t, "user1") - token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteOrganization) - org := api.EditOrgOption{ - FullName: "Org3 organization new full name", - Description: "A new description", - Website: "https://try.gitea.io/new", - Location: "Beijing", - Visibility: "badvisibility", - } - req := NewRequestWithJSON(t, "PATCH", "/api/v1/orgs/org3", &org). - AddTokenAuth(token) - MakeRequest(t, req, http.StatusUnprocessableEntity) - }) + token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteOrganization) + org := api.EditOrgOption{ + FullName: "Org3 organization new full name", + Description: "A new description", + Website: "https://try.gitea.io/new", + Location: "Beijing", + Visibility: "badvisibility", + } + req := NewRequestWithJSON(t, "PATCH", "/api/v1/orgs/org3", &org). + AddTokenAuth(token) + MakeRequest(t, req, http.StatusUnprocessableEntity) } func TestAPIOrgDeny(t *testing.T) { - onGiteaRun(t, func(*testing.T, *url.URL) { - setting.Service.RequireSignInView = true - defer func() { - setting.Service.RequireSignInView = false - }() + defer tests.PrepareTestEnv(t)() + defer test.MockVariableValue(&setting.Service.RequireSignInView, true)() - orgName := "user1_org" - req := NewRequestf(t, "GET", "/api/v1/orgs/%s", orgName) - MakeRequest(t, req, http.StatusNotFound) + orgName := "user1_org" + req := NewRequestf(t, "GET", "/api/v1/orgs/%s", orgName) + MakeRequest(t, req, http.StatusNotFound) - req = NewRequestf(t, "GET", "/api/v1/orgs/%s/repos", orgName) - MakeRequest(t, req, http.StatusNotFound) + req = NewRequestf(t, "GET", "/api/v1/orgs/%s/repos", orgName) + MakeRequest(t, req, http.StatusNotFound) - req = NewRequestf(t, "GET", "/api/v1/orgs/%s/members", orgName) - MakeRequest(t, req, http.StatusNotFound) - }) + req = NewRequestf(t, "GET", "/api/v1/orgs/%s/members", orgName) + MakeRequest(t, req, http.StatusNotFound) } func TestAPIGetAll(t *testing.T) { @@ -192,37 +185,36 @@ func TestAPIGetAll(t *testing.T) { } func TestAPIOrgSearchEmptyTeam(t *testing.T) { - onGiteaRun(t, func(*testing.T, *url.URL) { - token := getUserToken(t, "user1", auth_model.AccessTokenScopeWriteOrganization) - orgName := "org_with_empty_team" + defer tests.PrepareTestEnv(t)() + token := getUserToken(t, "user1", auth_model.AccessTokenScopeWriteOrganization) + orgName := "org_with_empty_team" - // create org - req := NewRequestWithJSON(t, "POST", "/api/v1/orgs", &api.CreateOrgOption{ - UserName: orgName, - }).AddTokenAuth(token) - MakeRequest(t, req, http.StatusCreated) + // create org + req := NewRequestWithJSON(t, "POST", "/api/v1/orgs", &api.CreateOrgOption{ + UserName: orgName, + }).AddTokenAuth(token) + MakeRequest(t, req, http.StatusCreated) - // create team with no member - req = NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/orgs/%s/teams", orgName), &api.CreateTeamOption{ - Name: "Empty", - IncludesAllRepositories: true, - Permission: "read", - Units: []string{"repo.code", "repo.issues", "repo.ext_issues", "repo.wiki", "repo.pulls"}, - }).AddTokenAuth(token) - MakeRequest(t, req, http.StatusCreated) + // create team with no member + req = NewRequestWithJSON(t, "POST", fmt.Sprintf("/api/v1/orgs/%s/teams", orgName), &api.CreateTeamOption{ + Name: "Empty", + IncludesAllRepositories: true, + Permission: "read", + Units: []string{"repo.code", "repo.issues", "repo.ext_issues", "repo.wiki", "repo.pulls"}, + }).AddTokenAuth(token) + MakeRequest(t, req, http.StatusCreated) - // case-insensitive search for teams that have no members - req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/orgs/%s/teams/search?q=%s", orgName, "empty")). - AddTokenAuth(token) - resp := MakeRequest(t, req, http.StatusOK) - data := struct { - Ok bool - Data []*api.Team - }{} - DecodeJSON(t, resp, &data) - assert.True(t, data.Ok) - if assert.Len(t, data.Data, 1) { - assert.EqualValues(t, "Empty", data.Data[0].Name) - } - }) + // case-insensitive search for teams that have no members + req = NewRequest(t, "GET", fmt.Sprintf("/api/v1/orgs/%s/teams/search?q=%s", orgName, "empty")). + AddTokenAuth(token) + resp := MakeRequest(t, req, http.StatusOK) + data := struct { + Ok bool + Data []*api.Team + }{} + DecodeJSON(t, resp, &data) + assert.True(t, data.Ok) + if assert.Len(t, data.Data, 1) { + assert.EqualValues(t, "Empty", data.Data[0].Name) + } } diff --git a/tests/integration/last_updated_time_test.go b/tests/integration/last_updated_time_test.go index 54c0eeb629..1d9240a31f 100644 --- a/tests/integration/last_updated_time_test.go +++ b/tests/integration/last_updated_time_test.go @@ -2,60 +2,59 @@ package integration import ( "net/http" - "net/url" "path" "strings" "testing" + "code.gitea.io/gitea/tests" + "github.com/PuerkitoBio/goquery" "github.com/stretchr/testify/assert" ) func TestRepoLastUpdatedTime(t *testing.T) { - onGiteaRun(t, func(t *testing.T, u *url.URL) { - user := "user2" - session := loginUser(t, user) + defer tests.PrepareTestEnv(t)() + user := "user2" + session := loginUser(t, user) - req := NewRequest(t, "GET", "/explore/repos?q=repo1") - resp := session.MakeRequest(t, req, http.StatusOK) - doc := NewHTMLParser(t, resp.Body) - node := doc.doc.Find(".flex-item-body").First() - { - buf := "" - findTextNonNested(t, node, &buf) - assert.Equal(t, "Updated", strings.TrimSpace(buf)) - } + req := NewRequest(t, "GET", "/explore/repos?q=repo1") + resp := session.MakeRequest(t, req, http.StatusOK) + doc := NewHTMLParser(t, resp.Body) + node := doc.doc.Find(".flex-item-body").First() + { + buf := "" + findTextNonNested(t, node, &buf) + assert.Equal(t, "Updated", strings.TrimSpace(buf)) + } - // Relative time should be present as a descendent - { - relativeTime := node.Find("relative-time").Text() - assert.True(t, strings.HasPrefix(relativeTime, "19")) // ~1970, might underflow with timezone - } - }) + // Relative time should be present as a descendent + { + relativeTime := node.Find("relative-time").Text() + assert.True(t, strings.HasPrefix(relativeTime, "19")) // ~1970, might underflow with timezone + } } func TestBranchLastUpdatedTime(t *testing.T) { - onGiteaRun(t, func(t *testing.T, u *url.URL) { - user := "user2" - repo := "repo1" - session := loginUser(t, user) + defer tests.PrepareTestEnv(t)() + user := "user2" + repo := "repo1" + session := loginUser(t, user) - req := NewRequest(t, "GET", path.Join(user, repo, "branches")) - resp := session.MakeRequest(t, req, http.StatusOK) - doc := NewHTMLParser(t, resp.Body) - node := doc.doc.Find("p:has(span.commit-message)") + req := NewRequest(t, "GET", path.Join(user, repo, "branches")) + resp := session.MakeRequest(t, req, http.StatusOK) + doc := NewHTMLParser(t, resp.Body) + node := doc.doc.Find("p:has(span.commit-message)") - { - buf := "" - findTextNonNested(t, node, &buf) - assert.True(t, strings.Contains(buf, "Updated")) - } + { + buf := "" + findTextNonNested(t, node, &buf) + assert.True(t, strings.Contains(buf, "Updated")) + } - { - relativeTime := node.Find("relative-time").Text() - assert.True(t, strings.HasPrefix(relativeTime, "2017")) - } - }) + { + relativeTime := node.Find("relative-time").Text() + assert.True(t, strings.HasPrefix(relativeTime, "2017")) + } } // Find all text that are direct descendents diff --git a/tests/integration/pull_commit_test.go b/tests/integration/pull_commit_test.go index 477f01725d..5ef6d6ceca 100644 --- a/tests/integration/pull_commit_test.go +++ b/tests/integration/pull_commit_test.go @@ -5,30 +5,29 @@ package integration import ( "net/http" - "net/url" "testing" pull_service "code.gitea.io/gitea/services/pull" + "code.gitea.io/gitea/tests" "github.com/stretchr/testify/assert" ) func TestListPullCommits(t *testing.T) { - onGiteaRun(t, func(t *testing.T, u *url.URL) { - session := loginUser(t, "user5") - req := NewRequest(t, "GET", "/user2/repo1/pulls/3/commits/list") - resp := session.MakeRequest(t, req, http.StatusOK) + defer tests.PrepareTestEnv(t)() + session := loginUser(t, "user5") + req := NewRequest(t, "GET", "/user2/repo1/pulls/3/commits/list") + resp := session.MakeRequest(t, req, http.StatusOK) - var pullCommitList struct { - Commits []pull_service.CommitInfo `json:"commits"` - LastReviewCommitSha string `json:"last_review_commit_sha"` - } - DecodeJSON(t, resp, &pullCommitList) + var pullCommitList struct { + Commits []pull_service.CommitInfo `json:"commits"` + LastReviewCommitSha string `json:"last_review_commit_sha"` + } + DecodeJSON(t, resp, &pullCommitList) - if assert.Len(t, pullCommitList.Commits, 2) { - assert.Equal(t, "5f22f7d0d95d614d25a5b68592adb345a4b5c7fd", pullCommitList.Commits[0].ID) - assert.Equal(t, "4a357436d925b5c974181ff12a994538ddc5a269", pullCommitList.Commits[1].ID) - } - assert.Equal(t, "4a357436d925b5c974181ff12a994538ddc5a269", pullCommitList.LastReviewCommitSha) - }) + if assert.Len(t, pullCommitList.Commits, 2) { + assert.Equal(t, "5f22f7d0d95d614d25a5b68592adb345a4b5c7fd", pullCommitList.Commits[0].ID) + assert.Equal(t, "4a357436d925b5c974181ff12a994538ddc5a269", pullCommitList.Commits[1].ID) + } + assert.Equal(t, "4a357436d925b5c974181ff12a994538ddc5a269", pullCommitList.LastReviewCommitSha) } diff --git a/tests/integration/pull_review_test.go b/tests/integration/pull_review_test.go index fc3e9be4a0..b3380cc6b8 100644 --- a/tests/integration/pull_review_test.go +++ b/tests/integration/pull_review_test.go @@ -18,7 +18,6 @@ import ( repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" - "code.gitea.io/gitea/modules/git" "code.gitea.io/gitea/modules/gitrepo" "code.gitea.io/gitea/modules/test" issue_service "code.gitea.io/gitea/services/issue" @@ -283,32 +282,18 @@ func TestPullView_CodeOwner(t *testing.T) { onGiteaRun(t, func(t *testing.T, u *url.URL) { user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) - // Create the repo. - repo, err := repo_service.CreateRepositoryDirectly(db.DefaultContext, user2, user2, repo_service.CreateRepoOptions{ - Name: "test_codeowner", - Readme: "Default", - AutoInit: true, - ObjectFormatName: git.Sha1ObjectFormat.Name(), - DefaultBranch: "master", - }) - require.NoError(t, err) - - // add CODEOWNERS to default branch - _, err = files_service.ChangeRepoFiles(db.DefaultContext, repo, user2, &files_service.ChangeRepoFilesOptions{ - OldBranch: repo.DefaultBranch, - Files: []*files_service.ChangeRepoFile{ - { - Operation: "create", - TreePath: "CODEOWNERS", - ContentReader: strings.NewReader("README.md @user5\n"), - }, + repo, _, f := tests.CreateDeclarativeRepo(t, user2, "test_codeowner", nil, nil, []*files_service.ChangeRepoFile{ + { + Operation: "create", + TreePath: "CODEOWNERS", + ContentReader: strings.NewReader("README.md @user5\n"), }, }) - require.NoError(t, err) + defer f() t.Run("First Pull Request", func(t *testing.T) { // create a new branch to prepare for pull request - _, err = files_service.ChangeRepoFiles(db.DefaultContext, repo, user2, &files_service.ChangeRepoFilesOptions{ + _, err := files_service.ChangeRepoFiles(db.DefaultContext, repo, user2, &files_service.ChangeRepoFilesOptions{ NewBranch: "codeowner-basebranch", Files: []*files_service.ChangeRepoFile{ { @@ -328,7 +313,7 @@ func TestPullView_CodeOwner(t *testing.T) { unittest.AssertExistsIf(t, true, &issues_model.Review{IssueID: pr.IssueID, Type: issues_model.ReviewTypeRequest, ReviewerID: 5}) require.NoError(t, pr.LoadIssue(db.DefaultContext)) - err := issue_service.ChangeTitle(db.DefaultContext, pr.Issue, user2, "[WIP] Test Pull Request") + err = issue_service.ChangeTitle(db.DefaultContext, pr.Issue, user2, "[WIP] Test Pull Request") require.NoError(t, err) prUpdated1 := unittest.AssertExistsAndLoadBean(t, &issues_model.PullRequest{ID: pr.ID}) require.NoError(t, prUpdated1.LoadIssue(db.DefaultContext)) @@ -342,7 +327,7 @@ func TestPullView_CodeOwner(t *testing.T) { }) // change the default branch CODEOWNERS file to change README.md's codeowner - _, err = files_service.ChangeRepoFiles(db.DefaultContext, repo, user2, &files_service.ChangeRepoFilesOptions{ + _, err := files_service.ChangeRepoFiles(db.DefaultContext, repo, user2, &files_service.ChangeRepoFilesOptions{ Files: []*files_service.ChangeRepoFile{ { Operation: "update", diff --git a/tests/integration/rename_branch_test.go b/tests/integration/rename_branch_test.go index a96cbf5623..20d4c9b48f 100644 --- a/tests/integration/rename_branch_test.go +++ b/tests/integration/rename_branch_test.go @@ -22,8 +22,6 @@ func TestRenameBranch(t *testing.T) { } func testRenameBranch(t *testing.T, u *url.URL) { - defer tests.PrepareTestEnv(t)() - repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) unittest.AssertExistsAndLoadBean(t, &git_model.Branch{RepoID: repo.ID, Name: "master"}) diff --git a/tests/integration/repo_collaborator_test.go b/tests/integration/repo_collaborator_test.go index beeb950f5a..292cd5862b 100644 --- a/tests/integration/repo_collaborator_test.go +++ b/tests/integration/repo_collaborator_test.go @@ -5,33 +5,33 @@ package integration import ( "net/http" - "net/url" "strings" "testing" + "code.gitea.io/gitea/tests" + "github.com/stretchr/testify/assert" ) // TestRepoCollaborators is a test for contents of Collaborators tab in the repo settings // It only covers a few elements and can be extended as needed func TestRepoCollaborators(t *testing.T) { - onGiteaRun(t, func(t *testing.T, u *url.URL) { - session := loginUser(t, "user2") + defer tests.PrepareTestEnv(t)() + session := loginUser(t, "user2") - // Visit Collaborators tab of repo settings - response := session.MakeRequest(t, NewRequest(t, "GET", "/user2/repo1/settings/collaboration"), http.StatusOK) - page := NewHTMLParser(t, response.Body).Find(".repo-setting-content") + // Visit Collaborators tab of repo settings + response := session.MakeRequest(t, NewRequest(t, "GET", "/user2/repo1/settings/collaboration"), http.StatusOK) + page := NewHTMLParser(t, response.Body).Find(".repo-setting-content") - // Veirfy header - assert.EqualValues(t, "Collaborators", strings.TrimSpace(page.Find("h4").Text())) + // Veirfy header + assert.EqualValues(t, "Collaborators", strings.TrimSpace(page.Find("h4").Text())) - // Veirfy button text - page = page.Find("#repo-collab-form") - assert.EqualValues(t, "Add collaborator", strings.TrimSpace(page.Find("button.primary").Text())) + // Veirfy button text + page = page.Find("#repo-collab-form") + assert.EqualValues(t, "Add collaborator", strings.TrimSpace(page.Find("button.primary").Text())) - // Veirfy placeholder - placeholder, exists := page.Find("#search-user-box input").Attr("placeholder") - assert.True(t, exists) - assert.EqualValues(t, "Search users...", placeholder) - }) + // Veirfy placeholder + placeholder, exists := page.Find("#search-user-box input").Attr("placeholder") + assert.True(t, exists) + assert.EqualValues(t, "Search users...", placeholder) } diff --git a/tests/integration/repo_migration_ui_test.go b/tests/integration/repo_migration_ui_test.go index 40688d4a60..594b09b490 100644 --- a/tests/integration/repo_migration_ui_test.go +++ b/tests/integration/repo_migration_ui_test.go @@ -5,26 +5,26 @@ package integration import ( "net/http" - "net/url" "testing" + "code.gitea.io/gitea/tests" + "github.com/PuerkitoBio/goquery" "github.com/stretchr/testify/assert" ) func TestRepoMigrationUI(t *testing.T) { - onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) { - sessionUser1 := loginUser(t, "user1") - // Nothing is tested in plain Git migration form right now - testRepoMigrationFormGitHub(t, sessionUser1) - testRepoMigrationFormGitea(t, sessionUser1) - testRepoMigrationFormGitLab(t, sessionUser1) - testRepoMigrationFormGogs(t, sessionUser1) - testRepoMigrationFormOneDev(t, sessionUser1) - testRepoMigrationFormGitBucket(t, sessionUser1) - testRepoMigrationFormCodebase(t, sessionUser1) - testRepoMigrationFormForgejo(t, sessionUser1) - }) + defer tests.PrepareTestEnv(t)() + sessionUser1 := loginUser(t, "user1") + // Nothing is tested in plain Git migration form right now + testRepoMigrationFormGitHub(t, sessionUser1) + testRepoMigrationFormGitea(t, sessionUser1) + testRepoMigrationFormGitLab(t, sessionUser1) + testRepoMigrationFormGogs(t, sessionUser1) + testRepoMigrationFormOneDev(t, sessionUser1) + testRepoMigrationFormGitBucket(t, sessionUser1) + testRepoMigrationFormCodebase(t, sessionUser1) + testRepoMigrationFormForgejo(t, sessionUser1) } func testRepoMigrationFormGitHub(t *testing.T, session *TestSession) { diff --git a/tests/integration/repo_tag_test.go b/tests/integration/repo_tag_test.go index 808d2e17e6..06b6c30383 100644 --- a/tests/integration/repo_tag_test.go +++ b/tests/integration/repo_tag_test.go @@ -11,8 +11,6 @@ import ( "testing" "code.gitea.io/gitea/models" - "code.gitea.io/gitea/models/db" - git_model "code.gitea.io/gitea/models/git" repo_model "code.gitea.io/gitea/models/repo" "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" @@ -31,20 +29,6 @@ func TestTagViewWithoutRelease(t *testing.T) { repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID}) - defer func() { - releases, err := db.Find[repo_model.Release](db.DefaultContext, repo_model.FindReleasesOptions{ - IncludeTags: true, - TagNames: []string{"no-release"}, - RepoID: repo.ID, - }) - require.NoError(t, err) - - for _, release := range releases { - _, err = db.DeleteByID[repo_model.Release](db.DefaultContext, release.ID) - require.NoError(t, err) - } - }() - err := release.CreateNewTag(git.DefaultContext, owner, repo, "master", "no-release", "release-less tag") require.NoError(t, err) @@ -70,27 +54,27 @@ func TestTagViewWithoutRelease(t *testing.T) { } func TestCreateNewTagProtected(t *testing.T) { - defer tests.PrepareTestEnv(t)() + onGiteaRun(t, func(t *testing.T, u *url.URL) { + repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) + owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID}) - repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) - owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: repo.OwnerID}) + t.Run("Code", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() - t.Run("Code", func(t *testing.T) { - defer tests.PrintCurrentTest(t)() + err := release.CreateNewTag(git.DefaultContext, owner, repo, "master", "t-first", "first tag") + require.NoError(t, err) - err := release.CreateNewTag(git.DefaultContext, owner, repo, "master", "t-first", "first tag") - require.NoError(t, err) + err = release.CreateNewTag(git.DefaultContext, owner, repo, "master", "v-2", "second tag") + require.Error(t, err) + assert.True(t, models.IsErrProtectedTagName(err)) - err = release.CreateNewTag(git.DefaultContext, owner, repo, "master", "v-2", "second tag") - require.Error(t, err) - assert.True(t, models.IsErrProtectedTagName(err)) + err = release.CreateNewTag(git.DefaultContext, owner, repo, "master", "v-1.1", "third tag") + require.NoError(t, err) + }) - err = release.CreateNewTag(git.DefaultContext, owner, repo, "master", "v-1.1", "third tag") - require.NoError(t, err) - }) + t.Run("Git", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() - t.Run("Git", func(t *testing.T) { - onGiteaRun(t, func(t *testing.T, u *url.URL) { httpContext := NewAPITestContext(t, owner.Name, repo.Name) dstPath := t.TempDir() @@ -107,10 +91,10 @@ func TestCreateNewTagProtected(t *testing.T) { require.Error(t, err) assert.Contains(t, err.Error(), "Tag v-2 is protected") }) - }) - t.Run("GitTagForce", func(t *testing.T) { - onGiteaRun(t, func(t *testing.T, u *url.URL) { + t.Run("GitTagForce", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + httpContext := NewAPITestContext(t, owner.Name, repo.Name) dstPath := t.TempDir() @@ -120,13 +104,7 @@ func TestCreateNewTagProtected(t *testing.T) { doGitClone(dstPath, u)(t) - _, _, err := git.NewCommand(git.DefaultContext, "tag", "v-1.1", "-m", "force update", "--force").RunStdString(&git.RunOpts{Dir: dstPath}) - require.NoError(t, err) - - _, _, err = git.NewCommand(git.DefaultContext, "push", "--tags").RunStdString(&git.RunOpts{Dir: dstPath}) - require.NoError(t, err) - - _, _, err = git.NewCommand(git.DefaultContext, "tag", "v-1.1", "-m", "force update v2", "--force").RunStdString(&git.RunOpts{Dir: dstPath}) + _, _, err := git.NewCommand(git.DefaultContext, "tag", "v-1.1", "-m", "force update v2", "--force").RunStdString(&git.RunOpts{Dir: dstPath}) require.NoError(t, err) _, _, err = git.NewCommand(git.DefaultContext, "push", "--tags").RunStdString(&git.RunOpts{Dir: dstPath}) @@ -142,27 +120,6 @@ func TestCreateNewTagProtected(t *testing.T) { assert.Contains(t, tagsTab.Text(), "force update v2") }) }) - - // Cleanup - releases, err := db.Find[repo_model.Release](db.DefaultContext, repo_model.FindReleasesOptions{ - IncludeTags: true, - TagNames: []string{"v-1", "v-1.1"}, - RepoID: repo.ID, - }) - require.NoError(t, err) - - for _, release := range releases { - _, err = db.DeleteByID[repo_model.Release](db.DefaultContext, release.ID) - require.NoError(t, err) - } - - protectedTags, err := git_model.GetProtectedTags(db.DefaultContext, repo.ID) - require.NoError(t, err) - - for _, protectedTag := range protectedTags { - err = git_model.DeleteProtectedTag(db.DefaultContext, protectedTag) - require.NoError(t, err) - } } func TestSyncRepoTags(t *testing.T) { @@ -200,18 +157,5 @@ func TestSyncRepoTags(t *testing.T) { require.NoError(t, repo_module.SyncRepoTags(git.DefaultContext, repo.ID)) testTag(t) }) - - // Cleanup - releases, err := db.Find[repo_model.Release](db.DefaultContext, repo_model.FindReleasesOptions{ - IncludeTags: true, - TagNames: []string{"v2"}, - RepoID: repo.ID, - }) - require.NoError(t, err) - - for _, release := range releases { - _, err = db.DeleteByID[repo_model.Release](db.DefaultContext, release.ID) - require.NoError(t, err) - } }) } diff --git a/tests/integration/repo_view_test.go b/tests/integration/repo_view_test.go index 7c280e2491..46e75063bc 100644 --- a/tests/integration/repo_view_test.go +++ b/tests/integration/repo_view_test.go @@ -62,8 +62,9 @@ func createRepoAndGetContext(t *testing.T, files []string, deleteMdReadme bool) } func TestRepoView_FindReadme(t *testing.T) { - t.Run("PrioOneLocalizedMdReadme", func(t *testing.T) { - onGiteaRun(t, func(t *testing.T, u *url.URL) { + onGiteaRun(t, func(t *testing.T, u *url.URL) { + t.Run("PrioOneLocalizedMdReadme", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() ctx, f := createRepoAndGetContext(t, []string{"README.en.md", "README.en.org", "README.org", "README.txt", "README.tex"}, false) defer f() @@ -73,9 +74,8 @@ func TestRepoView_FindReadme(t *testing.T) { assert.Equal(t, "README.en.md", file.Name()) }) - }) - t.Run("PrioTwoMdReadme", func(t *testing.T) { - onGiteaRun(t, func(t *testing.T, u *url.URL) { + t.Run("PrioTwoMdReadme", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() ctx, f := createRepoAndGetContext(t, []string{"README.en.org", "README.org", "README.txt", "README.tex"}, false) defer f() @@ -85,9 +85,8 @@ func TestRepoView_FindReadme(t *testing.T) { assert.Equal(t, "README.md", file.Name()) }) - }) - t.Run("PrioThreeLocalizedOrgReadme", func(t *testing.T) { - onGiteaRun(t, func(t *testing.T, u *url.URL) { + t.Run("PrioThreeLocalizedOrgReadme", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() ctx, f := createRepoAndGetContext(t, []string{"README.en.org", "README.org", "README.txt", "README.tex"}, true) defer f() @@ -97,9 +96,8 @@ func TestRepoView_FindReadme(t *testing.T) { assert.Equal(t, "README.en.org", file.Name()) }) - }) - t.Run("PrioFourOrgReadme", func(t *testing.T) { - onGiteaRun(t, func(t *testing.T, u *url.URL) { + t.Run("PrioFourOrgReadme", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() ctx, f := createRepoAndGetContext(t, []string{"README.org", "README.txt", "README.tex"}, true) defer f() @@ -109,9 +107,8 @@ func TestRepoView_FindReadme(t *testing.T) { assert.Equal(t, "README.org", file.Name()) }) - }) - t.Run("PrioFiveTxtReadme", func(t *testing.T) { - onGiteaRun(t, func(t *testing.T, u *url.URL) { + t.Run("PrioFiveTxtReadme", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() ctx, f := createRepoAndGetContext(t, []string{"README.txt", "README", "README.tex"}, true) defer f() @@ -121,9 +118,8 @@ func TestRepoView_FindReadme(t *testing.T) { assert.Equal(t, "README.txt", file.Name()) }) - }) - t.Run("PrioSixWithoutExtensionReadme", func(t *testing.T) { - onGiteaRun(t, func(t *testing.T, u *url.URL) { + t.Run("PrioSixWithoutExtensionReadme", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() ctx, f := createRepoAndGetContext(t, []string{"README", "README.tex"}, true) defer f() @@ -133,9 +129,8 @@ func TestRepoView_FindReadme(t *testing.T) { assert.Equal(t, "README", file.Name()) }) - }) - t.Run("PrioSevenAnyReadme", func(t *testing.T) { - onGiteaRun(t, func(t *testing.T, u *url.URL) { + t.Run("PrioSevenAnyReadme", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() ctx, f := createRepoAndGetContext(t, []string{"README.tex"}, true) defer f() @@ -145,9 +140,8 @@ func TestRepoView_FindReadme(t *testing.T) { assert.Equal(t, "README.tex", file.Name()) }) - }) - t.Run("DoNotPickReadmeIfNonPresent", func(t *testing.T) { - onGiteaRun(t, func(t *testing.T, u *url.URL) { + t.Run("DoNotPickReadmeIfNonPresent", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() ctx, f := createRepoAndGetContext(t, []string{}, true) defer f() diff --git a/tests/integration/repofiles_change_test.go b/tests/integration/repofiles_change_test.go index 9790b36183..1896971046 100644 --- a/tests/integration/repofiles_change_test.go +++ b/tests/integration/repofiles_change_test.go @@ -18,6 +18,7 @@ import ( "code.gitea.io/gitea/modules/setting" api "code.gitea.io/gitea/modules/structs" files_service "code.gitea.io/gitea/services/repository/files" + "code.gitea.io/gitea/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" @@ -63,8 +64,8 @@ func getDeleteRepoFilesOptions(repo *repo_model.Repository) *files_service.Chang Files: []*files_service.ChangeRepoFile{ { Operation: "delete", - TreePath: "README.md", - SHA: "4b4851ad51df6a7d9f25c979345979eaeb5b349f", + TreePath: "README_new.md", + SHA: "dbf8d00e022e05b7e5cf7e535de857de57925647", }, }, LastCommitID: "", @@ -244,184 +245,142 @@ func getExpectedFileResponseForRepofilesUpdate(commitID, filename, lastCommitSHA } } -func TestChangeRepoFilesForCreate(t *testing.T) { - // setup +func TestChangeRepoFiles(t *testing.T) { onGiteaRun(t, func(t *testing.T, u *url.URL) { doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) - opts := getCreateRepoFilesOptions(repo) - // test - filesResponse, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, doer, opts) - - // asserts + gitRepo, err := gitrepo.OpenRepository(git.DefaultContext, repo) require.NoError(t, err) - gitRepo, _ := gitrepo.OpenRepository(git.DefaultContext, repo) defer gitRepo.Close() - commitID, _ := gitRepo.GetBranchCommitID(opts.NewBranch) - lastCommit, _ := gitRepo.GetCommitByPath("new/file.txt") - expectedFileResponse := getExpectedFileResponseForRepofilesCreate(commitID, lastCommit.ID.String()) - assert.NotNil(t, expectedFileResponse) - if expectedFileResponse != nil { + t.Run("Create", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + opts := getCreateRepoFilesOptions(repo) + filesResponse, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, doer, opts) + require.NoError(t, err) + + commitID, err := gitRepo.GetBranchCommitID(opts.NewBranch) + require.NoError(t, err) + lastCommit, err := gitRepo.GetCommitByPath("new/file.txt") + require.NoError(t, err) + expectedFileResponse := getExpectedFileResponseForRepofilesCreate(commitID, lastCommit.ID.String()) assert.EqualValues(t, expectedFileResponse.Content, filesResponse.Files[0]) assert.EqualValues(t, expectedFileResponse.Commit.SHA, filesResponse.Commit.SHA) assert.EqualValues(t, expectedFileResponse.Commit.HTMLURL, filesResponse.Commit.HTMLURL) assert.EqualValues(t, expectedFileResponse.Commit.Author.Email, filesResponse.Commit.Author.Email) assert.EqualValues(t, expectedFileResponse.Commit.Author.Name, filesResponse.Commit.Author.Name) - } - }) -} + }) -func TestChangeRepoFilesForUpdate(t *testing.T) { - // setup - onGiteaRun(t, func(t *testing.T, u *url.URL) { - doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) - repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) - opts := getUpdateRepoFilesOptions(repo) + t.Run("Update", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + opts := getUpdateRepoFilesOptions(repo) + filesResponse, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, doer, opts) + require.NoError(t, err) - // test - filesResponse, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, doer, opts) + commit, err := gitRepo.GetBranchCommit(opts.NewBranch) + require.NoError(t, err) + lastCommit, err := commit.GetCommitByPath(opts.Files[0].TreePath) + require.NoError(t, err) + expectedFileResponse := getExpectedFileResponseForRepofilesUpdate(commit.ID.String(), opts.Files[0].TreePath, lastCommit.ID.String()) + assert.EqualValues(t, expectedFileResponse.Content, filesResponse.Files[0]) + assert.EqualValues(t, expectedFileResponse.Commit.SHA, filesResponse.Commit.SHA) + assert.EqualValues(t, expectedFileResponse.Commit.HTMLURL, filesResponse.Commit.HTMLURL) + assert.EqualValues(t, expectedFileResponse.Commit.Author.Email, filesResponse.Commit.Author.Email) + assert.EqualValues(t, expectedFileResponse.Commit.Author.Name, filesResponse.Commit.Author.Name) + }) - // asserts - require.NoError(t, err) - gitRepo, _ := gitrepo.OpenRepository(git.DefaultContext, repo) - defer gitRepo.Close() + t.Run("Update and move", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + opts := getUpdateRepoFilesOptions(repo) + opts.Files[0].SHA = "dbf8d00e022e05b7e5cf7e535de857de57925647" + opts.Files[0].FromTreePath = "README.md" + opts.Files[0].TreePath = "README_new.md" // new file name, README_new.md + filesResponse, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, doer, opts) + require.NoError(t, err) - commit, _ := gitRepo.GetBranchCommit(opts.NewBranch) - lastCommit, _ := commit.GetCommitByPath(opts.Files[0].TreePath) - expectedFileResponse := getExpectedFileResponseForRepofilesUpdate(commit.ID.String(), opts.Files[0].TreePath, lastCommit.ID.String()) - assert.EqualValues(t, expectedFileResponse.Content, filesResponse.Files[0]) - assert.EqualValues(t, expectedFileResponse.Commit.SHA, filesResponse.Commit.SHA) - assert.EqualValues(t, expectedFileResponse.Commit.HTMLURL, filesResponse.Commit.HTMLURL) - assert.EqualValues(t, expectedFileResponse.Commit.Author.Email, filesResponse.Commit.Author.Email) - assert.EqualValues(t, expectedFileResponse.Commit.Author.Name, filesResponse.Commit.Author.Name) - }) -} + commit, err := gitRepo.GetBranchCommit(opts.NewBranch) + require.NoError(t, err) + lastCommit, err := commit.GetCommitByPath(opts.Files[0].TreePath) + require.NoError(t, err) + expectedFileResponse := getExpectedFileResponseForRepofilesUpdate(commit.ID.String(), opts.Files[0].TreePath, lastCommit.ID.String()) -func TestChangeRepoFilesForUpdateWithFileMove(t *testing.T) { - // setup - onGiteaRun(t, func(t *testing.T, u *url.URL) { - doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) - repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) - opts := getUpdateRepoFilesOptions(repo) - opts.Files[0].FromTreePath = "README.md" - opts.Files[0].TreePath = "README_new.md" // new file name, README_new.md + // assert that the old file no longer exists in the last commit of the branch + fromEntry, err := commit.GetTreeEntryByPath(opts.Files[0].FromTreePath) + switch err.(type) { + case git.ErrNotExist: + // correct, continue + default: + t.Fatalf("expected git.ErrNotExist, got:%v", err) + } + toEntry, err := commit.GetTreeEntryByPath(opts.Files[0].TreePath) + require.NoError(t, err) + assert.Nil(t, fromEntry) // Should no longer exist here + assert.NotNil(t, toEntry) // Should exist here + // assert SHA has remained the same but paths use the new file name + assert.EqualValues(t, expectedFileResponse.Content.SHA, filesResponse.Files[0].SHA) + assert.EqualValues(t, expectedFileResponse.Content.Name, filesResponse.Files[0].Name) + assert.EqualValues(t, expectedFileResponse.Content.Path, filesResponse.Files[0].Path) + assert.EqualValues(t, expectedFileResponse.Content.URL, filesResponse.Files[0].URL) + assert.EqualValues(t, expectedFileResponse.Commit.SHA, filesResponse.Commit.SHA) + assert.EqualValues(t, expectedFileResponse.Commit.HTMLURL, filesResponse.Commit.HTMLURL) + }) - // test - filesResponse, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, doer, opts) + t.Run("Change without branch names", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + opts := getUpdateRepoFilesOptions(repo) + opts.OldBranch = "" + opts.NewBranch = "" + opts.Files[0].TreePath = "README_new.md" + opts.Files[0].SHA = "dbf8d00e022e05b7e5cf7e535de857de57925647" - // asserts - require.NoError(t, err) - gitRepo, _ := gitrepo.OpenRepository(git.DefaultContext, repo) - defer gitRepo.Close() + filesResponse, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, doer, opts) + require.NoError(t, err) - commit, _ := gitRepo.GetBranchCommit(opts.NewBranch) - lastCommit, _ := commit.GetCommitByPath(opts.Files[0].TreePath) - expectedFileResponse := getExpectedFileResponseForRepofilesUpdate(commit.ID.String(), opts.Files[0].TreePath, lastCommit.ID.String()) - // assert that the old file no longer exists in the last commit of the branch - fromEntry, err := commit.GetTreeEntryByPath(opts.Files[0].FromTreePath) - switch err.(type) { - case git.ErrNotExist: - // correct, continue - default: - t.Fatalf("expected git.ErrNotExist, got:%v", err) - } - toEntry, err := commit.GetTreeEntryByPath(opts.Files[0].TreePath) - require.NoError(t, err) - assert.Nil(t, fromEntry) // Should no longer exist here - assert.NotNil(t, toEntry) // Should exist here - // assert SHA has remained the same but paths use the new file name - assert.EqualValues(t, expectedFileResponse.Content.SHA, filesResponse.Files[0].SHA) - assert.EqualValues(t, expectedFileResponse.Content.Name, filesResponse.Files[0].Name) - assert.EqualValues(t, expectedFileResponse.Content.Path, filesResponse.Files[0].Path) - assert.EqualValues(t, expectedFileResponse.Content.URL, filesResponse.Files[0].URL) - assert.EqualValues(t, expectedFileResponse.Commit.SHA, filesResponse.Commit.SHA) - assert.EqualValues(t, expectedFileResponse.Commit.HTMLURL, filesResponse.Commit.HTMLURL) - }) -} + commit, _ := gitRepo.GetBranchCommit(repo.DefaultBranch) + lastCommit, _ := commit.GetCommitByPath(opts.Files[0].TreePath) + expectedFileResponse := getExpectedFileResponseForRepofilesUpdate(commit.ID.String(), opts.Files[0].TreePath, lastCommit.ID.String()) + assert.EqualValues(t, expectedFileResponse.Content, filesResponse.Files[0]) + }) -// Test opts with branch names removed, should get same results as above test -func TestChangeRepoFilesWithoutBranchNames(t *testing.T) { - // setup - onGiteaRun(t, func(t *testing.T, u *url.URL) { - doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) - repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) - opts := getUpdateRepoFilesOptions(repo) - opts.OldBranch = "" - opts.NewBranch = "" + t.Run("Delete files", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + opts := getDeleteRepoFilesOptions(repo) - // test - filesResponse, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, doer, opts) + filesResponse, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, doer, opts) + require.NoError(t, err) + expectedFileResponse := getExpectedFileResponseForRepofilesDelete() + assert.NotNil(t, filesResponse) + assert.Nil(t, filesResponse.Files[0]) + assert.EqualValues(t, expectedFileResponse.Commit.Message, filesResponse.Commit.Message) + assert.EqualValues(t, expectedFileResponse.Commit.Author.Identity, filesResponse.Commit.Author.Identity) + assert.EqualValues(t, expectedFileResponse.Commit.Committer.Identity, filesResponse.Commit.Committer.Identity) + assert.EqualValues(t, expectedFileResponse.Verification, filesResponse.Verification) - // asserts - require.NoError(t, err) - gitRepo, _ := gitrepo.OpenRepository(git.DefaultContext, repo) - defer gitRepo.Close() + filesResponse, err = files_service.ChangeRepoFiles(git.DefaultContext, repo, doer, opts) + assert.Nil(t, filesResponse) + expectedError := "repository file does not exist [path: " + opts.Files[0].TreePath + "]" + assert.EqualError(t, err, expectedError) + }) - commit, _ := gitRepo.GetBranchCommit(repo.DefaultBranch) - lastCommit, _ := commit.GetCommitByPath(opts.Files[0].TreePath) - expectedFileResponse := getExpectedFileResponseForRepofilesUpdate(commit.ID.String(), opts.Files[0].TreePath, lastCommit.ID.String()) - assert.EqualValues(t, expectedFileResponse.Content, filesResponse.Files[0]) - }) -} + t.Run("Delete without branch name", func(t *testing.T) { + defer tests.PrintCurrentTest(t)() + opts := getDeleteRepoFilesOptions(repo) + opts.OldBranch = "" + opts.NewBranch = "" + opts.Files[0].SHA = "103ff9234cefeee5ec5361d22b49fbb04d385885" + opts.Files[0].TreePath = "new/file.txt" -func TestChangeRepoFilesForDelete(t *testing.T) { - onGiteaRun(t, testDeleteRepoFiles) -} - -func testDeleteRepoFiles(t *testing.T, u *url.URL) { - // setup - unittest.PrepareTestEnv(t) - doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) - repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) - opts := getDeleteRepoFilesOptions(repo) - - t.Run("Delete README.md file", func(t *testing.T) { - filesResponse, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, doer, opts) - require.NoError(t, err) - expectedFileResponse := getExpectedFileResponseForRepofilesDelete() - assert.NotNil(t, filesResponse) - assert.Nil(t, filesResponse.Files[0]) - assert.EqualValues(t, expectedFileResponse.Commit.Message, filesResponse.Commit.Message) - assert.EqualValues(t, expectedFileResponse.Commit.Author.Identity, filesResponse.Commit.Author.Identity) - assert.EqualValues(t, expectedFileResponse.Commit.Committer.Identity, filesResponse.Commit.Committer.Identity) - assert.EqualValues(t, expectedFileResponse.Verification, filesResponse.Verification) - }) - - t.Run("Verify README.md has been deleted", func(t *testing.T) { - filesResponse, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, doer, opts) - assert.Nil(t, filesResponse) - expectedError := "repository file does not exist [path: " + opts.Files[0].TreePath + "]" - assert.EqualError(t, err, expectedError) - }) -} - -// Test opts with branch names removed, same results -func TestChangeRepoFilesForDeleteWithoutBranchNames(t *testing.T) { - onGiteaRun(t, testDeleteRepoFilesWithoutBranchNames) -} - -func testDeleteRepoFilesWithoutBranchNames(t *testing.T, u *url.URL) { - // setup - unittest.PrepareTestEnv(t) - doer := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) - repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1}) - - opts := getDeleteRepoFilesOptions(repo) - opts.OldBranch = "" - opts.NewBranch = "" - - t.Run("Delete README.md without Branch Name", func(t *testing.T) { - filesResponse, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, doer, opts) - require.NoError(t, err) - expectedFileResponse := getExpectedFileResponseForRepofilesDelete() - assert.NotNil(t, filesResponse) - assert.Nil(t, filesResponse.Files[0]) - assert.EqualValues(t, expectedFileResponse.Commit.Message, filesResponse.Commit.Message) - assert.EqualValues(t, expectedFileResponse.Commit.Author.Identity, filesResponse.Commit.Author.Identity) - assert.EqualValues(t, expectedFileResponse.Commit.Committer.Identity, filesResponse.Commit.Committer.Identity) - assert.EqualValues(t, expectedFileResponse.Verification, filesResponse.Verification) + filesResponse, err := files_service.ChangeRepoFiles(git.DefaultContext, repo, doer, opts) + require.NoError(t, err) + expectedFileResponse := getExpectedFileResponseForRepofilesDelete() + assert.NotNil(t, filesResponse) + assert.Nil(t, filesResponse.Files[0]) + assert.EqualValues(t, expectedFileResponse.Commit.Message, filesResponse.Commit.Message) + assert.EqualValues(t, expectedFileResponse.Commit.Author.Identity, filesResponse.Commit.Author.Identity) + assert.EqualValues(t, expectedFileResponse.Commit.Committer.Identity, filesResponse.Commit.Committer.Identity) + assert.EqualValues(t, expectedFileResponse.Verification, filesResponse.Verification) + }) }) } diff --git a/tests/integration/user_avatar_test.go b/tests/integration/user_avatar_test.go index a5805d0eda..a7c0264aaa 100644 --- a/tests/integration/user_avatar_test.go +++ b/tests/integration/user_avatar_test.go @@ -10,85 +10,78 @@ import ( "io" "mime/multipart" "net/http" - "net/url" "testing" "code.gitea.io/gitea/models/db" "code.gitea.io/gitea/models/unittest" user_model "code.gitea.io/gitea/models/user" "code.gitea.io/gitea/modules/avatar" + "code.gitea.io/gitea/tests" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" ) func TestUserAvatar(t *testing.T) { - onGiteaRun(t, func(t *testing.T, u *url.URL) { - user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) // owner of the repo3, is an org + defer tests.PrepareTestEnv(t)() + user2 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) // owner of the repo3, is an org - seed := user2.Email - if len(seed) == 0 { - seed = user2.Name - } + seed := user2.Email + if len(seed) == 0 { + seed = user2.Name + } - img, err := avatar.RandomImage([]byte(seed)) - if err != nil { - require.NoError(t, err) - return - } + img, err := avatar.RandomImage([]byte(seed)) + if err != nil { + require.NoError(t, err) + return + } - session := loginUser(t, "user2") - csrf := GetCSRF(t, session, "/user/settings") + session := loginUser(t, "user2") + csrf := GetCSRF(t, session, "/user/settings") - imgData := &bytes.Buffer{} + imgData := &bytes.Buffer{} - body := &bytes.Buffer{} + body := &bytes.Buffer{} - // Setup multi-part - writer := multipart.NewWriter(body) - writer.WriteField("source", "local") - part, err := writer.CreateFormFile("avatar", "avatar-for-testuseravatar.png") - if err != nil { - require.NoError(t, err) - return - } + // Setup multi-part + writer := multipart.NewWriter(body) + writer.WriteField("source", "local") + part, err := writer.CreateFormFile("avatar", "avatar-for-testuseravatar.png") + if err != nil { + require.NoError(t, err) + return + } - if err := png.Encode(imgData, img); err != nil { - require.NoError(t, err) - return - } + if err := png.Encode(imgData, img); err != nil { + require.NoError(t, err) + return + } - if _, err := io.Copy(part, imgData); err != nil { - require.NoError(t, err) - return - } + if _, err := io.Copy(part, imgData); err != nil { + require.NoError(t, err) + return + } - if err := writer.Close(); err != nil { - require.NoError(t, err) - return - } + if err := writer.Close(); err != nil { + require.NoError(t, err) + return + } - req := NewRequestWithBody(t, "POST", "/user/settings/avatar", body) - req.Header.Add("X-Csrf-Token", csrf) - req.Header.Add("Content-Type", writer.FormDataContentType()) + req := NewRequestWithBody(t, "POST", "/user/settings/avatar", body) + req.Header.Add("X-Csrf-Token", csrf) + req.Header.Add("Content-Type", writer.FormDataContentType()) - session.MakeRequest(t, req, http.StatusSeeOther) + session.MakeRequest(t, req, http.StatusSeeOther) - user2 = unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) // owner of the repo3, is an org + user2 = unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 2}) // owner of the repo3, is an org - req = NewRequest(t, "GET", user2.AvatarLinkWithSize(db.DefaultContext, 0)) - _ = session.MakeRequest(t, req, http.StatusOK) + req = NewRequest(t, "GET", user2.AvatarLinkWithSize(db.DefaultContext, 0)) + _ = session.MakeRequest(t, req, http.StatusOK) - testGetAvatarRedirect(t, user2) + req = NewRequestf(t, "GET", "/%s.png", user2.Name) + resp := MakeRequest(t, req, http.StatusSeeOther) + assert.EqualValues(t, fmt.Sprintf("/avatars/%s", user2.Avatar), resp.Header().Get("location")) - // Can't test if the response matches because the image is re-generated on upload but checking that this at least doesn't give a 404 should be enough. - }) -} - -func testGetAvatarRedirect(t *testing.T, user *user_model.User) { - t.Run(fmt.Sprintf("getAvatarRedirect_%s", user.Name), func(t *testing.T) { - req := NewRequestf(t, "GET", "/%s.png", user.Name) - resp := MakeRequest(t, req, http.StatusSeeOther) - assert.EqualValues(t, fmt.Sprintf("/avatars/%s", user.Avatar), resp.Header().Get("location")) - }) + // Can't test if the response matches because the image is re-generated on upload but checking that this at least doesn't give a 404 should be enough. } diff --git a/tests/integration/user_profile_activity_test.go b/tests/integration/user_profile_activity_test.go index 8f3042678a..77d188903e 100644 --- a/tests/integration/user_profile_activity_test.go +++ b/tests/integration/user_profile_activity_test.go @@ -5,11 +5,11 @@ package integration import ( "net/http" - "net/url" "strconv" "testing" "code.gitea.io/gitea/modules/structs" + "code.gitea.io/gitea/tests" "github.com/stretchr/testify/assert" ) @@ -23,70 +23,69 @@ import ( // - Profile visibility // - Public activity visibility func TestUserProfileActivity(t *testing.T) { - onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) { - // This test needs multiple users with different access statuses to check for all possible states - userAdmin := loginUser(t, "user1") - userRegular := loginUser(t, "user2") - // Activity availability should be the same for guest and another non-admin user, so this is not tested separately - userGuest := emptyTestSession(t) + defer tests.PrepareTestEnv(t)() + // This test needs multiple users with different access statuses to check for all possible states + userAdmin := loginUser(t, "user1") + userRegular := loginUser(t, "user2") + // Activity availability should be the same for guest and another non-admin user, so this is not tested separately + userGuest := emptyTestSession(t) - // = Public profile, public activity = + // = Public profile, public activity = - // Set activity visibility of user2 to public. This is the default, but won't hurt to set it before testing. - testChangeUserActivityVisibility(t, userRegular, "off") + // Set activity visibility of user2 to public. This is the default, but won't hurt to set it before testing. + testChangeUserActivityVisibility(t, userRegular, "off") - // Verify availability of RSS button and activity tab - testUser2ActivityButtonsAvailability(t, userAdmin, true) - testUser2ActivityButtonsAvailability(t, userRegular, true) - testUser2ActivityButtonsAvailability(t, userGuest, true) + // Verify availability of RSS button and activity tab + testUser2ActivityButtonsAvailability(t, userAdmin, true) + testUser2ActivityButtonsAvailability(t, userRegular, true) + testUser2ActivityButtonsAvailability(t, userGuest, true) - // Verify the hint for all types of users: admin, self, guest - testUser2ActivityVisibility(t, userAdmin, "This activity is visible to everyone, but as an administrator you can also see interactions in private spaces.", true) - hintLink := testUser2ActivityVisibility(t, userRegular, "Your activity is visible to everyone, except for interactions in private spaces. Configure.", true) - testUser2ActivityVisibility(t, userGuest, "", true) + // Verify the hint for all types of users: admin, self, guest + testUser2ActivityVisibility(t, userAdmin, "This activity is visible to everyone, but as an administrator you can also see interactions in private spaces.", true) + hintLink := testUser2ActivityVisibility(t, userRegular, "Your activity is visible to everyone, except for interactions in private spaces. Configure.", true) + testUser2ActivityVisibility(t, userGuest, "", true) - // When viewing own profile, the user is offered to configure activity visibility. Verify that the link is correct and works, also check that it links back to the activity tab. - linkCorrect := assert.EqualValues(t, "/user/settings#keep-activity-private", hintLink) - if linkCorrect { - page := NewHTMLParser(t, userRegular.MakeRequest(t, NewRequest(t, "GET", hintLink), http.StatusOK).Body) - activityLink, exists := page.Find(".field:has(.checkbox#keep-activity-private) .help a").Attr("href") - assert.True(t, exists) - assert.EqualValues(t, "/user2?tab=activity", activityLink) - } + // When viewing own profile, the user is offered to configure activity visibility. Verify that the link is correct and works, also check that it links back to the activity tab. + linkCorrect := assert.EqualValues(t, "/user/settings#keep-activity-private", hintLink) + if linkCorrect { + page := NewHTMLParser(t, userRegular.MakeRequest(t, NewRequest(t, "GET", hintLink), http.StatusOK).Body) + activityLink, exists := page.Find(".field:has(.checkbox#keep-activity-private) .help a").Attr("href") + assert.True(t, exists) + assert.EqualValues(t, "/user2?tab=activity", activityLink) + } - // = Private profile, but public activity = + // = Private profile, but public activity = - // Set profile visibility of user2 to private - testChangeUserProfileVisibility(t, userRegular, structs.VisibleTypePrivate) + // Set profile visibility of user2 to private + testChangeUserProfileVisibility(t, userRegular, structs.VisibleTypePrivate) - // When profile activity is configured as public, but the profile is private, tell the user about this and link to visibility settings. - hintLink = testUser2ActivityVisibility(t, userRegular, "Your activity is only visible to you and the instance administrators because your profile is private. Configure.", true) - assert.EqualValues(t, "/user/settings#visibility-setting", hintLink) + // When profile activity is configured as public, but the profile is private, tell the user about this and link to visibility settings. + hintLink = testUser2ActivityVisibility(t, userRegular, "Your activity is only visible to you and the instance administrators because your profile is private. Configure.", true) + assert.EqualValues(t, "/user/settings#visibility-setting", hintLink) - // When the profile is private, tell the admin about this. - testUser2ActivityVisibility(t, userAdmin, "This activity is visible to you because you're an administrator, but the user wants it to remain private.", true) + // When the profile is private, tell the admin about this. + testUser2ActivityVisibility(t, userAdmin, "This activity is visible to you because you're an administrator, but the user wants it to remain private.", true) - // Set profile visibility of user2 back to public - testChangeUserProfileVisibility(t, userRegular, structs.VisibleTypePublic) + // Set profile visibility of user2 back to public + testChangeUserProfileVisibility(t, userRegular, structs.VisibleTypePublic) - // = Private acitivty = + // = Private acitivty = - // Set activity visibility of user2 to private - testChangeUserActivityVisibility(t, userRegular, "on") + // Set activity visibility of user2 to private + testChangeUserActivityVisibility(t, userRegular, "on") - // Verify availability of RSS button and activity tab - testUser2ActivityButtonsAvailability(t, userAdmin, true) - testUser2ActivityButtonsAvailability(t, userRegular, true) - testUser2ActivityButtonsAvailability(t, userGuest, false) + // Verify availability of RSS button and activity tab + testUser2ActivityButtonsAvailability(t, userAdmin, true) + testUser2ActivityButtonsAvailability(t, userRegular, true) + testUser2ActivityButtonsAvailability(t, userGuest, false) - // Verify the hint for all types of users: admin, self, guest - testUser2ActivityVisibility(t, userAdmin, "This activity is visible to you because you're an administrator, but the user wants it to remain private.", true) - hintLink = testUser2ActivityVisibility(t, userRegular, "Your activity is only visible to you and the instance administrators. Configure.", true) - testUser2ActivityVisibility(t, userGuest, "This user has disabled the public visibility of the activity.", false) + // Verify the hint for all types of users: admin, self, guest + testUser2ActivityVisibility(t, userAdmin, "This activity is visible to you because you're an administrator, but the user wants it to remain private.", true) + hintLink = testUser2ActivityVisibility(t, userRegular, "Your activity is only visible to you and the instance administrators. Configure.", true) + testUser2ActivityVisibility(t, userGuest, "This user has disabled the public visibility of the activity.", false) - // Verify that Configure link is correct - assert.EqualValues(t, "/user/settings#keep-activity-private", hintLink) - }) + // Verify that Configure link is correct + assert.EqualValues(t, "/user/settings#keep-activity-private", hintLink) } // testChangeUserActivityVisibility allows to easily change visibility of public activity for a user diff --git a/tests/integration/user_profile_follows_test.go b/tests/integration/user_profile_follows_test.go index bad0944d88..24b74268e6 100644 --- a/tests/integration/user_profile_follows_test.go +++ b/tests/integration/user_profile_follows_test.go @@ -6,10 +6,11 @@ package integration import ( "fmt" "net/http" - "net/url" "strings" "testing" + "code.gitea.io/gitea/tests" + "github.com/stretchr/testify/assert" ) @@ -19,92 +20,92 @@ import ( // - Followers and Following lists have correct amounts of items // - %d followers and %following counters are always present and always have correct numbers and use correct plurals func TestUserProfileFollows(t *testing.T) { - onGiteaRun(t, func(t *testing.T, giteaURL *url.URL) { - // This test needs 3 users to check for all possible states - // The accounts of user3 and user4 are not functioning - user1 := loginUser(t, "user1") - user2 := loginUser(t, "user2") - user5 := loginUser(t, "user5") + defer tests.PrepareTestEnv(t)() - followersLink := "#profile-avatar-card a[href='/user1?tab=followers']" - followingLink := "#profile-avatar-card a[href='/user1?tab=following']" - listHeader := ".user-cards h2" - listItems := ".user-cards .list" + // This test needs 3 users to check for all possible states + // The accounts of user3 and user4 are not functioning + user1 := loginUser(t, "user1") + user2 := loginUser(t, "user2") + user5 := loginUser(t, "user5") - // = No follows = + followersLink := "#profile-avatar-card a[href='/user1?tab=followers']" + followingLink := "#profile-avatar-card a[href='/user1?tab=following']" + listHeader := ".user-cards h2" + listItems := ".user-cards .list" - var followCount int + // = No follows = - // Request the profile of user1, the Followers tab - response := user1.MakeRequest(t, NewRequest(t, "GET", "/user1?tab=followers"), http.StatusOK) - page := NewHTMLParser(t, response.Body) + var followCount int - // Verify that user1 has no followers - testSelectorEquals(t, page, followersLink, "0 followers") - testSelectorEquals(t, page, listHeader, "Followers") - testListCount(t, page, listItems, followCount) + // Request the profile of user1, the Followers tab + response := user1.MakeRequest(t, NewRequest(t, "GET", "/user1?tab=followers"), http.StatusOK) + page := NewHTMLParser(t, response.Body) - // Request the profile of user1, the Following tab - response = user1.MakeRequest(t, NewRequest(t, "GET", "/user1?tab=following"), http.StatusOK) - page = NewHTMLParser(t, response.Body) + // Verify that user1 has no followers + testSelectorEquals(t, page, followersLink, "0 followers") + testSelectorEquals(t, page, listHeader, "Followers") + testListCount(t, page, listItems, followCount) - // Verify that user1 does not follow anyone - testSelectorEquals(t, page, followingLink, "0 following") - testSelectorEquals(t, page, listHeader, "Following") - testListCount(t, page, listItems, followCount) + // Request the profile of user1, the Following tab + response = user1.MakeRequest(t, NewRequest(t, "GET", "/user1?tab=following"), http.StatusOK) + page = NewHTMLParser(t, response.Body) - // Make user1 and user2 follow each other - testUserFollowUser(t, user1, "user2") - testUserFollowUser(t, user2, "user1") + // Verify that user1 does not follow anyone + testSelectorEquals(t, page, followingLink, "0 following") + testSelectorEquals(t, page, listHeader, "Following") + testListCount(t, page, listItems, followCount) - // = 1 follow each = + // Make user1 and user2 follow each other + testUserFollowUser(t, user1, "user2") + testUserFollowUser(t, user2, "user1") - followCount++ + // = 1 follow each = - // Request the profile of user1, the Followers tab - response = user1.MakeRequest(t, NewRequest(t, "GET", "/user1?tab=followers"), http.StatusOK) - page = NewHTMLParser(t, response.Body) + followCount++ - // Verify it is now followed by 1 user - testSelectorEquals(t, page, followersLink, "1 follower") - testSelectorEquals(t, page, listHeader, "Follower") - testListCount(t, page, listItems, followCount) + // Request the profile of user1, the Followers tab + response = user1.MakeRequest(t, NewRequest(t, "GET", "/user1?tab=followers"), http.StatusOK) + page = NewHTMLParser(t, response.Body) - // Request the profile of user1, the Following tab - response = user1.MakeRequest(t, NewRequest(t, "GET", "/user1?tab=following"), http.StatusOK) - page = NewHTMLParser(t, response.Body) + // Verify it is now followed by 1 user + testSelectorEquals(t, page, followersLink, "1 follower") + testSelectorEquals(t, page, listHeader, "Follower") + testListCount(t, page, listItems, followCount) - // Verify it now follows follows 1 user - testSelectorEquals(t, page, followingLink, "1 following") - testSelectorEquals(t, page, listHeader, "Following") - testListCount(t, page, listItems, followCount) + // Request the profile of user1, the Following tab + response = user1.MakeRequest(t, NewRequest(t, "GET", "/user1?tab=following"), http.StatusOK) + page = NewHTMLParser(t, response.Body) - // Make user1 and user3 follow each other - testUserFollowUser(t, user1, "user5") - testUserFollowUser(t, user5, "user1") + // Verify it now follows follows 1 user + testSelectorEquals(t, page, followingLink, "1 following") + testSelectorEquals(t, page, listHeader, "Following") + testListCount(t, page, listItems, followCount) - // = 2 follows = + // Make user1 and user3 follow each other + testUserFollowUser(t, user1, "user5") + testUserFollowUser(t, user5, "user1") - followCount++ + // = 2 follows = - // Request the profile of user1, the Followers tab - response = user1.MakeRequest(t, NewRequest(t, "GET", "/user1?tab=followers"), http.StatusOK) - page = NewHTMLParser(t, response.Body) + followCount++ - // Verify it is now followed by 2 users - testSelectorEquals(t, page, followersLink, "2 followers") - testSelectorEquals(t, page, listHeader, "Followers") - testListCount(t, page, listItems, followCount) + // Request the profile of user1, the Followers tab + response = user1.MakeRequest(t, NewRequest(t, "GET", "/user1?tab=followers"), http.StatusOK) + page = NewHTMLParser(t, response.Body) - // Request the profile of user1, the Following tab - response = user1.MakeRequest(t, NewRequest(t, "GET", "/user1?tab=following"), http.StatusOK) - page = NewHTMLParser(t, response.Body) + // Verify it is now followed by 2 users + testSelectorEquals(t, page, followersLink, "2 followers") + testSelectorEquals(t, page, listHeader, "Followers") + testListCount(t, page, listItems, followCount) - // Verify it now follows follows 2 users - testSelectorEquals(t, page, followingLink, "2 following") - testSelectorEquals(t, page, listHeader, "Following") - testListCount(t, page, listItems, followCount) - }) + // Request the profile of user1, the Following tab + response = user1.MakeRequest(t, NewRequest(t, "GET", "/user1?tab=following"), http.StatusOK) + page = NewHTMLParser(t, response.Body) + + // Verify it now follows follows 2 users + testSelectorEquals(t, page, followingLink, "2 following") + testSelectorEquals(t, page, listHeader, "Following") + testListCount(t, page, listItems, followCount) } // testUserFollowUser simply follows a user `following` by session of user `follower` From 7e1aa8a5cd6a4f2eda4cc5c86dc06a80762f9950 Mon Sep 17 00:00:00 2001 From: wxiaoguang Date: Mon, 4 Nov 2024 19:30:00 +0800 Subject: [PATCH 28/37] [PORT] Refactor DateUtils and merge TimeSince (gitea#32409) Follow #32383 and #32402 --- Conflict resolution: Magic, painful. (cherry picked from commit b068dbd40ee3b4dc7d18cdcf168f0c24cea234c0) --- modules/templates/helper.go | 15 +-- modules/templates/util_date.go | 111 ++++++++++++++++-- modules/templates/util_date_test.go | 23 +++- modules/timeutil/datetime.go | 60 ---------- modules/timeutil/since.go | 41 +------ routers/web/repo/blame.go | 3 +- routers/web/repo/issue_content_history.go | 5 +- services/context/context.go | 1 - templates/admin/auth/list.tmpl | 4 +- templates/admin/cron.tmpl | 4 +- templates/admin/notice.tmpl | 2 +- templates/admin/org/list.tmpl | 2 +- templates/admin/packages/list.tmpl | 2 +- templates/admin/repo/list.tmpl | 4 +- templates/admin/stacktrace-row.tmpl | 2 +- templates/admin/user/list.tmpl | 4 +- templates/devtest/gitea-ui.tmpl | 14 +-- templates/explore/repo_list.tmpl | 2 +- templates/explore/user_list.tmpl | 2 +- .../package/shared/cleanup_rules/preview.tmpl | 2 +- templates/package/shared/list.tmpl | 2 +- templates/package/shared/versionlist.tmpl | 2 +- templates/package/view.tmpl | 6 +- templates/repo/actions/runs_list.tmpl | 2 +- templates/repo/branch/list.tmpl | 6 +- .../code/recently_pushed_new_branches.tmpl | 2 +- templates/repo/commit_page.tmpl | 4 +- templates/repo/commits_list.tmpl | 4 +- templates/repo/diff/comments.tmpl | 2 +- templates/repo/diff/compare.tmpl | 2 +- templates/repo/empty.tmpl | 2 +- templates/repo/graph/commits.tmpl | 2 +- templates/repo/header.tmpl | 2 +- templates/repo/home.tmpl | 2 +- templates/repo/issue/card.tmpl | 2 +- templates/repo/issue/milestone_issues.tmpl | 4 +- templates/repo/issue/milestones.tmpl | 6 +- templates/repo/issue/view_content.tmpl | 2 +- .../repo/issue/view_content/comments.tmpl | 12 +- .../repo/issue/view_content/conversation.tmpl | 2 +- templates/repo/issue/view_content/pull.tmpl | 2 +- .../view_content/sidebar/due_deadline.tmpl | 2 +- templates/repo/issue/view_title.tmpl | 4 +- templates/repo/pulse.tmpl | 14 +-- templates/repo/release/list.tmpl | 2 +- templates/repo/settings/deploy_keys.tmpl | 2 +- templates/repo/settings/lfs.tmpl | 2 +- templates/repo/settings/lfs_file_find.tmpl | 2 +- templates/repo/settings/lfs_locks.tmpl | 2 +- templates/repo/settings/options.tmpl | 4 +- templates/repo/settings/webhook/history.tmpl | 2 +- templates/repo/tag/list.tmpl | 2 +- templates/repo/user_cards.tmpl | 2 +- templates/repo/view_file.tmpl | 2 +- templates/repo/view_list.tmpl | 4 +- templates/repo/wiki/pages.tmpl | 2 +- templates/repo/wiki/revision.tmpl | 2 +- templates/repo/wiki/view.tmpl | 2 +- templates/shared/actions/runner_edit.tmpl | 4 +- templates/shared/actions/runner_list.tmpl | 2 +- templates/shared/issuelist.tmpl | 4 +- templates/shared/searchbottom.tmpl | 2 +- templates/shared/secrets/add_list.tmpl | 2 +- templates/shared/user/profile_big_avatar.tmpl | 2 +- templates/shared/variables/variable_list.tmpl | 2 +- templates/user/dashboard/feeds.tmpl | 2 +- templates/user/dashboard/milestones.tmpl | 6 +- .../user/notification/notification_div.tmpl | 4 +- templates/user/settings/applications.tmpl | 2 +- templates/user/settings/grants_oauth2.tmpl | 2 +- templates/user/settings/keys_gpg.tmpl | 4 +- templates/user/settings/keys_principal.tmpl | 2 +- templates/user/settings/keys_ssh.tmpl | 2 +- .../user/settings/security/webauthn.tmpl | 2 +- 74 files changed, 241 insertions(+), 228 deletions(-) delete mode 100644 modules/timeutil/datetime.go diff --git a/modules/templates/helper.go b/modules/templates/helper.go index a1f3f1aa2d..55de85646c 100644 --- a/modules/templates/helper.go +++ b/modules/templates/helper.go @@ -20,7 +20,6 @@ import ( "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/svg" "code.gitea.io/gitea/modules/templates/eval" - "code.gitea.io/gitea/modules/timeutil" "code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/services/gitdiff" ) @@ -65,16 +64,18 @@ func NewFuncMap() template.FuncMap { // ----------------------------------------------------------------- // time / number / format - "FileSize": FileSizePanic, - "CountFmt": base.FormatNumberSI, - "TimeSince": timeutil.TimeSince, - "TimeSinceUnix": timeutil.TimeSinceUnix, - "DateTime": dateTimeLegacy, // for backward compatibility only, do not use it anymore - "Sec2Time": util.SecToTime, + "FileSize": FileSizePanic, + "CountFmt": base.FormatNumberSI, + "Sec2Time": util.SecToTime, "LoadTimes": func(startTime time.Time) string { return fmt.Sprint(time.Since(startTime).Nanoseconds()/1e6) + "ms" }, + // for backward compatibility only, do not use them anymore + "TimeSince": timeSinceLegacy, + "TimeSinceUnix": timeSinceLegacy, + "DateTime": dateTimeLegacy, + // ----------------------------------------------------------------- // setting "AppName": func() string { diff --git a/modules/templates/util_date.go b/modules/templates/util_date.go index 10f7cdb508..f521b39b79 100644 --- a/modules/templates/util_date.go +++ b/modules/templates/util_date.go @@ -4,35 +4,40 @@ package templates import ( - "context" + "fmt" + "html" "html/template" + "strings" "time" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/timeutil" + "code.gitea.io/gitea/modules/translation" ) -type DateUtils struct { - ctx context.Context -} +type DateUtils struct{} -func NewDateUtils(ctx context.Context) *DateUtils { - return &DateUtils{ctx} +func NewDateUtils() *DateUtils { + return (*DateUtils)(nil) // the util is stateless, and we do not need to create an instance } // AbsoluteShort renders in "Jan 01, 2006" format func (du *DateUtils) AbsoluteShort(time any) template.HTML { - return timeutil.DateTime("short", time) + return dateTimeFormat("short", time) } // AbsoluteLong renders in "January 01, 2006" format func (du *DateUtils) AbsoluteLong(time any) template.HTML { - return timeutil.DateTime("long", time) + return dateTimeFormat("long", time) } // FullTime renders in "Jan 01, 2006 20:33:44" format func (du *DateUtils) FullTime(time any) template.HTML { - return timeutil.DateTime("full", time) + return dateTimeFormat("full", time) +} + +func (du *DateUtils) TimeSince(time any) template.HTML { + return TimeSince(time) } // ParseLegacy parses the datetime in legacy format, eg: "2016-01-02" in server's timezone. @@ -56,5 +61,91 @@ func dateTimeLegacy(format string, datetime any, _ ...string) template.HTML { if s, ok := datetime.(string); ok { datetime = parseLegacy(s) } - return timeutil.DateTime(format, datetime) + return dateTimeFormat(format, datetime) +} + +func timeSinceLegacy(time any, _ translation.Locale) template.HTML { + if !setting.IsProd || setting.IsInTesting { + panic("timeSinceLegacy is for backward compatibility only, do not use it in new code") + } + return TimeSince(time) +} + +func anyToTime(any any) (t time.Time, isZero bool) { + switch v := any.(type) { + case nil: + // it is zero + case *time.Time: + if v != nil { + t = *v + } + case time.Time: + t = v + case timeutil.TimeStamp: + t = v.AsTime() + case timeutil.TimeStampNano: + t = v.AsTime() + case int: + t = timeutil.TimeStamp(v).AsTime() + case int64: + t = timeutil.TimeStamp(v).AsTime() + default: + panic(fmt.Sprintf("Unsupported time type %T", any)) + } + return t, t.IsZero() || t.Unix() == 0 +} + +func dateTimeFormat(format string, datetime any) template.HTML { + t, isZero := anyToTime(datetime) + if isZero { + return "-" + } + var textEscaped string + datetimeEscaped := html.EscapeString(t.Format(time.RFC3339)) + if format == "full" { + textEscaped = html.EscapeString(t.Format("2006-01-02 15:04:05 -07:00")) + } else { + textEscaped = html.EscapeString(t.Format("2006-01-02")) + } + + attrs := []string{`weekday=""`, `year="numeric"`} + switch format { + case "short", "long": // date only + attrs = append(attrs, `month="`+format+`"`, `day="numeric"`) + return template.HTML(fmt.Sprintf(`%s`, strings.Join(attrs, " "), datetimeEscaped, textEscaped)) + case "full": // full date including time + attrs = append(attrs, `format="datetime"`, `month="short"`, `day="numeric"`, `hour="numeric"`, `minute="numeric"`, `second="numeric"`, `data-tooltip-content`, `data-tooltip-interactive="true"`) + return template.HTML(fmt.Sprintf(`%s`, strings.Join(attrs, " "), datetimeEscaped, textEscaped)) + default: + panic(fmt.Sprintf("Unsupported format %s", format)) + } +} + +func timeSinceTo(then any, now time.Time) template.HTML { + thenTime, isZero := anyToTime(then) + if isZero { + return "-" + } + + friendlyText := thenTime.Format("2006-01-02 15:04:05 -07:00") + + // document: https://github.com/github/relative-time-element + attrs := `tense="past"` + isFuture := now.Before(thenTime) + if isFuture { + attrs = `tense="future"` + } + + // declare data-tooltip-content attribute to switch from "title" tooltip to "tippy" tooltip + htm := fmt.Sprintf(`%s`, + attrs, thenTime.Format(time.RFC3339), friendlyText) + return template.HTML(htm) +} + +// TimeSince renders relative time HTML given a time +func TimeSince(then any) template.HTML { + if setting.UI.PreferredTimestampTense == "absolute" { + return dateTimeFormat("full", then) + } + return timeSinceTo(then, time.Now()) } diff --git a/modules/templates/util_date_test.go b/modules/templates/util_date_test.go index e3dec5c8db..2f5c79f762 100644 --- a/modules/templates/util_date_test.go +++ b/modules/templates/util_date_test.go @@ -22,7 +22,7 @@ func TestDateTime(t *testing.T) { defer test.MockVariableValue(&setting.DefaultUILocation, testTz)() defer test.MockVariableValue(&setting.IsInTesting, false)() - du := NewDateUtils(nil) + du := NewDateUtils() refTimeStr := "2018-01-01T00:00:00Z" refDateStr := "2018-01-01" @@ -59,3 +59,24 @@ func TestDateTime(t *testing.T) { actual = du.FullTime(refTimeStamp) assert.EqualValues(t, `2017-12-31 19:00:00 -05:00`, actual) } + +func TestTimeSince(t *testing.T) { + testTz, _ := time.LoadLocation("America/New_York") + defer test.MockVariableValue(&setting.DefaultUILocation, testTz)() + defer test.MockVariableValue(&setting.IsInTesting, false)() + + du := NewDateUtils() + assert.EqualValues(t, "-", du.TimeSince(nil)) + + refTimeStr := "2018-01-01T00:00:00Z" + refTime, _ := time.Parse(time.RFC3339, refTimeStr) + + actual := du.TimeSince(refTime) + assert.EqualValues(t, `2018-01-01 00:00:00 +00:00`, actual) + + actual = timeSinceTo(&refTime, time.Time{}) + assert.EqualValues(t, `2018-01-01 00:00:00 +00:00`, actual) + + actual = timeSinceLegacy(timeutil.TimeStampNano(refTime.UnixNano()), nil) + assert.EqualValues(t, `2017-12-31 19:00:00 -05:00`, actual) +} diff --git a/modules/timeutil/datetime.go b/modules/timeutil/datetime.go deleted file mode 100644 index 664e0320b0..0000000000 --- a/modules/timeutil/datetime.go +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright 2023 The Gitea Authors. All rights reserved. -// SPDX-License-Identifier: MIT - -package timeutil - -import ( - "fmt" - "html" - "html/template" - "strings" - "time" -) - -// DateTime renders an absolute time HTML element by datetime. -func DateTime(format string, datetime any) template.HTML { - if p, ok := datetime.(*time.Time); ok { - datetime = *p - } - if p, ok := datetime.(*TimeStamp); ok { - datetime = *p - } - switch v := datetime.(type) { - case TimeStamp: - datetime = v.AsTime() - case int: - datetime = TimeStamp(v).AsTime() - case int64: - datetime = TimeStamp(v).AsTime() - } - - var datetimeEscaped, textEscaped string - switch v := datetime.(type) { - case nil: - return "-" - case time.Time: - if v.IsZero() || v.Unix() == 0 { - return "-" - } - datetimeEscaped = html.EscapeString(v.Format(time.RFC3339)) - if format == "full" { - textEscaped = html.EscapeString(v.Format("2006-01-02 15:04:05 -07:00")) - } else { - textEscaped = html.EscapeString(v.Format("2006-01-02")) - } - default: - panic(fmt.Sprintf("Unsupported time type %T", datetime)) - } - - attrs := []string{`weekday=""`, `year="numeric"`} - switch format { - case "short", "long": // date only - attrs = append(attrs, `month="`+format+`"`, `day="numeric"`) - return template.HTML(fmt.Sprintf(`%s`, strings.Join(attrs, " "), datetimeEscaped, textEscaped)) - case "full": // full date including time - attrs = append(attrs, `format="datetime"`, `month="short"`, `day="numeric"`, `hour="numeric"`, `minute="numeric"`, `second="numeric"`, `data-tooltip-content`, `data-tooltip-interactive="true"`) - return template.HTML(fmt.Sprintf(`%s`, strings.Join(attrs, " "), datetimeEscaped, textEscaped)) - default: - panic(fmt.Sprintf("Unsupported format %s", format)) - } -} diff --git a/modules/timeutil/since.go b/modules/timeutil/since.go index dba42c793a..2c89ae38d5 100644 --- a/modules/timeutil/since.go +++ b/modules/timeutil/since.go @@ -4,12 +4,9 @@ package timeutil import ( - "fmt" - "html/template" "strings" "time" - "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/translation" ) @@ -81,16 +78,11 @@ func computeTimeDiffFloor(diff int64, lang translation.Locale) (int64, string) { return diff, diffStr } -// MinutesToFriendly returns a user friendly string with number of minutes +// MinutesToFriendly returns a user-friendly string with number of minutes // converted to hours and minutes. func MinutesToFriendly(minutes int, lang translation.Locale) string { duration := time.Duration(minutes) * time.Minute - return TimeSincePro(time.Now().Add(-duration), lang) -} - -// TimeSincePro calculates the time interval and generate full user-friendly string. -func TimeSincePro(then time.Time, lang translation.Locale) string { - return timeSincePro(then, time.Now(), lang) + return timeSincePro(time.Now().Add(-duration), time.Now(), lang) } func timeSincePro(then, now time.Time, lang translation.Locale) string { @@ -114,32 +106,3 @@ func timeSincePro(then, now time.Time, lang translation.Locale) string { } return strings.TrimPrefix(timeStr, ", ") } - -func timeSinceUnix(then, now time.Time, _ translation.Locale) template.HTML { - friendlyText := then.Format("2006-01-02 15:04:05 -07:00") - - // document: https://github.com/github/relative-time-element - attrs := `tense="past"` - isFuture := now.Before(then) - if isFuture { - attrs = `tense="future"` - } - - // declare data-tooltip-content attribute to switch from "title" tooltip to "tippy" tooltip - htm := fmt.Sprintf(`%s`, - attrs, then.Format(time.RFC3339), friendlyText) - return template.HTML(htm) -} - -// TimeSince renders relative time HTML given a time.Time -func TimeSince(then time.Time, lang translation.Locale) template.HTML { - if setting.UI.PreferredTimestampTense == "absolute" { - return DateTime("full", then) - } - return timeSinceUnix(then, time.Now(), lang) -} - -// TimeSinceUnix renders relative time HTML given a TimeStamp -func TimeSinceUnix(then TimeStamp, lang translation.Locale) template.HTML { - return TimeSince(then.AsLocalTime(), lang) -} diff --git a/routers/web/repo/blame.go b/routers/web/repo/blame.go index eea3d4dc00..4f962d4c19 100644 --- a/routers/web/repo/blame.go +++ b/routers/web/repo/blame.go @@ -17,7 +17,6 @@ import ( "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/templates" - "code.gitea.io/gitea/modules/timeutil" "code.gitea.io/gitea/modules/util" "code.gitea.io/gitea/services/context" files_service "code.gitea.io/gitea/services/repository/files" @@ -254,7 +253,7 @@ func renderBlame(ctx *context.Context, blameParts []*git.BlamePart, commitNames commitCnt++ // User avatar image - commitSince := timeutil.TimeSinceUnix(timeutil.TimeStamp(commit.Author.When.Unix()), ctx.Locale) + commitSince := templates.TimeSince(commit.Author.When) var avatar string if commit.User != nil { diff --git a/routers/web/repo/issue_content_history.go b/routers/web/repo/issue_content_history.go index 16b250abda..4ce76b2bb9 100644 --- a/routers/web/repo/issue_content_history.go +++ b/routers/web/repo/issue_content_history.go @@ -14,7 +14,6 @@ import ( "code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/setting" "code.gitea.io/gitea/modules/templates" - "code.gitea.io/gitea/modules/timeutil" "code.gitea.io/gitea/services/context" "github.com/sergi/go-diff/diffmatchpatch" @@ -73,10 +72,10 @@ func GetContentHistoryList(ctx *context.Context) { class := avatars.DefaultAvatarClass + " tw-mr-2" name := html.EscapeString(username) avatarHTML := string(templates.AvatarHTML(src, 28, class, username)) - timeSinceText := string(timeutil.TimeSinceUnix(item.EditedUnix, ctx.Locale)) + timeSinceHTML := string(templates.TimeSince(item.EditedUnix)) results = append(results, map[string]any{ - "name": avatarHTML + "" + name + " " + actionText + " " + timeSinceText, + "name": avatarHTML + "" + name + " " + actionText + " " + timeSinceHTML, "value": item.HistoryID, }) } diff --git a/services/context/context.go b/services/context/context.go index 65796c3ee7..91e7b1849d 100644 --- a/services/context/context.go +++ b/services/context/context.go @@ -102,7 +102,6 @@ func NewTemplateContextForWeb(ctx *Context) TemplateContext { tmplCtx := NewTemplateContext(ctx) tmplCtx["Locale"] = ctx.Base.Locale tmplCtx["AvatarUtils"] = templates.NewAvatarUtils(ctx) - tmplCtx["DateUtils"] = templates.NewDateUtils(ctx) return tmplCtx } diff --git a/templates/admin/auth/list.tmpl b/templates/admin/auth/list.tmpl index 5b5affad8a..c162b7b74d 100644 --- a/templates/admin/auth/list.tmpl +++ b/templates/admin/auth/list.tmpl @@ -26,8 +26,8 @@ {{.Name}} {{.TypeName}} {{if .IsActive}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}} - {{ctx.DateUtils.AbsoluteShort .UpdatedUnix}} - {{ctx.DateUtils.AbsoluteShort .CreatedUnix}} + {{DateUtils.AbsoluteShort .UpdatedUnix}} + {{DateUtils.AbsoluteShort .CreatedUnix}} {{svg "octicon-pencil"}} {{end}} diff --git a/templates/admin/cron.tmpl b/templates/admin/cron.tmpl index 64ae7858ba..ee37f6ca75 100644 --- a/templates/admin/cron.tmpl +++ b/templates/admin/cron.tmpl @@ -23,8 +23,8 @@ {{ctx.Locale.Tr (printf "admin.dashboard.%s" .Name)}} {{.Spec}} - {{ctx.DateUtils.FullTime .Next}} - {{if gt .Prev.Year 1}}{{ctx.DateUtils.FullTime .Prev}}{{else}}-{{end}} + {{DateUtils.FullTime .Next}} + {{if gt .Prev.Year 1}}{{DateUtils.FullTime .Prev}}{{else}}-{{end}} {{.ExecTimes}} {{if eq .Status ""}}—{{else if eq .Status "finished"}}{{svg "octicon-check" 16}}{{else}}{{svg "octicon-x" 16}}{{end}} diff --git a/templates/admin/notice.tmpl b/templates/admin/notice.tmpl index 2db0384f6d..04a0b64432 100644 --- a/templates/admin/notice.tmpl +++ b/templates/admin/notice.tmpl @@ -21,7 +21,7 @@ {{.ID}} {{ctx.Locale.Tr .TrStr}} {{.Description}} - {{ctx.DateUtils.AbsoluteShort .CreatedUnix}} + {{DateUtils.AbsoluteShort .CreatedUnix}} {{svg "octicon-note" 16}} {{end}} diff --git a/templates/admin/org/list.tmpl b/templates/admin/org/list.tmpl index 6a6dc14609..d0805c85bc 100644 --- a/templates/admin/org/list.tmpl +++ b/templates/admin/org/list.tmpl @@ -63,7 +63,7 @@ {{.NumTeams}} {{.NumMembers}} {{.NumRepos}} - {{ctx.DateUtils.AbsoluteShort .CreatedUnix}} + {{DateUtils.AbsoluteShort .CreatedUnix}} {{svg "octicon-pencil"}} {{end}} diff --git a/templates/admin/packages/list.tmpl b/templates/admin/packages/list.tmpl index 9cc08772b7..aa38731d4f 100644 --- a/templates/admin/packages/list.tmpl +++ b/templates/admin/packages/list.tmpl @@ -71,7 +71,7 @@ {{end}} {{ctx.Locale.TrSize .CalculateBlobSize}} - {{ctx.DateUtils.AbsoluteShort .Version.CreatedUnix}} + {{DateUtils.AbsoluteShort .Version.CreatedUnix}} {{svg "octicon-trash"}} {{end}} diff --git a/templates/admin/repo/list.tmpl b/templates/admin/repo/list.tmpl index 992933154d..c4924c3fac 100644 --- a/templates/admin/repo/list.tmpl +++ b/templates/admin/repo/list.tmpl @@ -82,8 +82,8 @@ {{.NumIssues}} {{ctx.Locale.TrSize .GitSize}} {{ctx.Locale.TrSize .LFSSize}} - {{ctx.DateUtils.AbsoluteShort .UpdatedUnix}} - {{ctx.DateUtils.AbsoluteShort .CreatedUnix}} + {{DateUtils.AbsoluteShort .UpdatedUnix}} + {{DateUtils.AbsoluteShort .CreatedUnix}} {{svg "octicon-trash"}} {{end}} diff --git a/templates/admin/stacktrace-row.tmpl b/templates/admin/stacktrace-row.tmpl index 694bf56d96..97c361ff90 100644 --- a/templates/admin/stacktrace-row.tmpl +++ b/templates/admin/stacktrace-row.tmpl @@ -13,7 +13,7 @@
{{.Process.Description}}
-
{{if ne .Process.Type "none"}}{{TimeSince .Process.Start ctx.Locale}}{{end}}
+
{{if ne .Process.Type "none"}}{{DateUtils.TimeSince .Process.Start}}{{end}}
{{if or (eq .Process.Type "request") (eq .Process.Type "normal")}} diff --git a/templates/admin/user/list.tmpl b/templates/admin/user/list.tmpl index 42879d7917..9b3447f44a 100644 --- a/templates/admin/user/list.tmpl +++ b/templates/admin/user/list.tmpl @@ -96,9 +96,9 @@ {{if .IsActive}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}} {{if .IsRestricted}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}} {{if index $.UsersTwoFaStatus .ID}}{{svg "octicon-check"}}{{else}}{{svg "octicon-x"}}{{end}} - {{ctx.DateUtils.AbsoluteShort .CreatedUnix}} + {{DateUtils.AbsoluteShort .CreatedUnix}} {{if .LastLoginUnix}} - {{ctx.DateUtils.AbsoluteShort .LastLoginUnix}} + {{DateUtils.AbsoluteShort .LastLoginUnix}} {{else}} {{ctx.Locale.Tr "admin.users.never_login"}} {{end}} diff --git a/templates/devtest/gitea-ui.tmpl b/templates/devtest/gitea-ui.tmpl index 8c5db4d887..5490f71784 100644 --- a/templates/devtest/gitea-ui.tmpl +++ b/templates/devtest/gitea-ui.tmpl @@ -167,13 +167,13 @@

TimeSince

-
Now: {{TimeSince .TimeNow ctx.Locale}}
-
5s past: {{TimeSince .TimePast5s ctx.Locale}}
-
5s future: {{TimeSince .TimeFuture5s ctx.Locale}}
-
2m past: {{TimeSince .TimePast2m ctx.Locale}}
-
2m future: {{TimeSince .TimeFuture2m ctx.Locale}}
-
1y past: {{TimeSince .TimePast1y ctx.Locale}}
-
1y future: {{TimeSince .TimeFuture1y ctx.Locale}}
+
Now: {{DateUtils.TimeSince .TimeNow}}
+
5s past: {{DateUtils.TimeSince .TimePast5s}}
+
5s future: {{DateUtils.TimeSince .TimeFuture5s}}
+
2m past: {{DateUtils.TimeSince .TimePast2m}}
+
2m future: {{DateUtils.TimeSince .TimeFuture2m}}
+
1y past: {{DateUtils.TimeSince .TimePast1y}}
+
1y future: {{DateUtils.TimeSince .TimeFuture1y}}
diff --git a/templates/explore/repo_list.tmpl b/templates/explore/repo_list.tmpl index 59bc6c8a95..f11f2e94ef 100644 --- a/templates/explore/repo_list.tmpl +++ b/templates/explore/repo_list.tmpl @@ -62,7 +62,7 @@ {{end}}
{{end}} -
{{ctx.Locale.Tr "org.repo_updated" (TimeSinceUnix .UpdatedUnix ctx.Locale)}}
+
{{ctx.Locale.Tr "org.repo_updated" (DateUtils.TimeSince .UpdatedUnix)}}
{{else}} diff --git a/templates/explore/user_list.tmpl b/templates/explore/user_list.tmpl index ff46f13c17..4128a489aa 100644 --- a/templates/explore/user_list.tmpl +++ b/templates/explore/user_list.tmpl @@ -21,7 +21,7 @@ {{.Email}} {{end}} - {{svg "octicon-calendar"}}{{ctx.Locale.Tr "user.joined_on" (ctx.DateUtils.AbsoluteShort .CreatedUnix)}} + {{svg "octicon-calendar"}}{{ctx.Locale.Tr "user.joined_on" (DateUtils.AbsoluteShort .CreatedUnix)}} diff --git a/templates/package/shared/cleanup_rules/preview.tmpl b/templates/package/shared/cleanup_rules/preview.tmpl index ced1e5c11b..da034fec7a 100644 --- a/templates/package/shared/cleanup_rules/preview.tmpl +++ b/templates/package/shared/cleanup_rules/preview.tmpl @@ -22,7 +22,7 @@ {{.Version.Version}} {{.Creator.Name}} {{ctx.Locale.TrSize .CalculateBlobSize}} - {{ctx.DateUtils.AbsoluteShort .Version.CreatedUnix}} + {{DateUtils.AbsoluteShort .Version.CreatedUnix}} {{else}} diff --git a/templates/package/shared/list.tmpl b/templates/package/shared/list.tmpl index 36f8bc1522..19b41d0bc8 100644 --- a/templates/package/shared/list.tmpl +++ b/templates/package/shared/list.tmpl @@ -24,7 +24,7 @@ {{svg .Package.Type.SVGName 16}} {{.Package.Type.Name}}
- {{$timeStr := TimeSinceUnix .Version.CreatedUnix ctx.Locale}} + {{$timeStr := DateUtils.TimeSince .Version.CreatedUnix}} {{$hasRepositoryAccess := false}} {{if .Repository}} {{$hasRepositoryAccess = index $.RepositoryAccessMap .Repository.ID}} diff --git a/templates/package/shared/versionlist.tmpl b/templates/package/shared/versionlist.tmpl index e5c568e059..7a1059e262 100644 --- a/templates/package/shared/versionlist.tmpl +++ b/templates/package/shared/versionlist.tmpl @@ -25,7 +25,7 @@
{{.Version.LowerVersion}}
- {{ctx.Locale.Tr "packages.published_by" (TimeSinceUnix .Version.CreatedUnix ctx.Locale) .Creator.HomeLink .Creator.GetDisplayName}} + {{ctx.Locale.Tr "packages.published_by" (DateUtils.TimeSince .Version.CreatedUnix) .Creator.HomeLink .Creator.GetDisplayName}}
diff --git a/templates/package/view.tmpl b/templates/package/view.tmpl index 59e4e53f12..170f38388d 100644 --- a/templates/package/view.tmpl +++ b/templates/package/view.tmpl @@ -8,7 +8,7 @@

{{.PackageDescriptor.Package.Name}} ({{.PackageDescriptor.Version.Version}})

- {{$timeStr := TimeSinceUnix .PackageDescriptor.Version.CreatedUnix ctx.Locale}} + {{$timeStr := DateUtils.TimeSince .PackageDescriptor.Version.CreatedUnix}} {{if .HasRepositoryAccess}} {{ctx.Locale.Tr "packages.published_by_in" $timeStr .PackageDescriptor.Creator.HomeLink .PackageDescriptor.Creator.GetDisplayName .PackageDescriptor.Repository.Link .PackageDescriptor.Repository.FullName}} {{else}} @@ -48,7 +48,7 @@ {{if .HasRepositoryAccess}}
{{svg "octicon-repo" 16 "tw-mr-2"}} {{.PackageDescriptor.Repository.FullName}}
{{end}} -
{{svg "octicon-calendar" 16 "tw-mr-2"}} {{TimeSinceUnix .PackageDescriptor.Version.CreatedUnix ctx.Locale}}
+
{{svg "octicon-calendar" 16 "tw-mr-2"}} {{DateUtils.TimeSince .PackageDescriptor.Version.CreatedUnix}}
{{svg "octicon-download" 16 "tw-mr-2"}} {{.PackageDescriptor.Version.DownloadCount}}
{{template "package/metadata/alpine" .}} {{template "package/metadata/arch" .}} @@ -94,7 +94,7 @@ {{range .LatestVersions}}
{{.Version}} - {{ctx.DateUtils.AbsoluteShort .CreatedUnix}} + {{DateUtils.AbsoluteShort .CreatedUnix}}
{{end}}
diff --git a/templates/repo/actions/runs_list.tmpl b/templates/repo/actions/runs_list.tmpl index 7bab492d7b..ef764fa357 100644 --- a/templates/repo/actions/runs_list.tmpl +++ b/templates/repo/actions/runs_list.tmpl @@ -33,7 +33,7 @@ {{.PrettyRef}} {{end}}
-
{{svg "octicon-calendar" 16}}{{TimeSinceUnix .Updated ctx.Locale}}
+
{{svg "octicon-calendar" 16}}{{DateUtils.TimeSince .Updated}}
{{svg "octicon-stopwatch" 16}}{{.Duration}}
diff --git a/templates/repo/branch/list.tmpl b/templates/repo/branch/list.tmpl index f5bffb097e..c60017ba87 100644 --- a/templates/repo/branch/list.tmpl +++ b/templates/repo/branch/list.tmpl @@ -27,7 +27,7 @@ {{template "repo/commit_statuses" dict "Status" (index $.CommitStatus .DefaultBranchBranch.DBBranch.CommitID) "Statuses" (index $.CommitStatuses .DefaultBranchBranch.DBBranch.CommitID)}} -

{{svg "octicon-git-commit" 16 "tw-mr-1"}}{{ShortSha .DefaultBranchBranch.DBBranch.CommitID}} · {{RenderCommitMessage $.Context .DefaultBranchBranch.DBBranch.CommitMessage (.Repository.ComposeMetas ctx)}} · {{ctx.Locale.Tr "org.repo_updated" (TimeSince .DefaultBranchBranch.DBBranch.CommitTime.AsTime ctx.Locale)}} {{if .DefaultBranchBranch.DBBranch.Pusher}}  {{template "shared/user/avatarlink" dict "user" .DefaultBranchBranch.DBBranch.Pusher}}{{template "shared/user/namelink" .DefaultBranchBranch.DBBranch.Pusher}}{{end}}

+

{{svg "octicon-git-commit" 16 "tw-mr-1"}}{{ShortSha .DefaultBranchBranch.DBBranch.CommitID}} · {{RenderCommitMessage $.Context .DefaultBranchBranch.DBBranch.CommitMessage (.Repository.ComposeMetas ctx)}} · {{ctx.Locale.Tr "org.repo_updated" (DateUtils.TimeSince .DefaultBranchBranch.DBBranch.CommitTime)}}{{if .DefaultBranchBranch.DBBranch.Pusher}}  {{template "shared/user/avatarlink" dict "user" .DefaultBranchBranch.DBBranch.Pusher}}{{template "shared/user/namelink" .DefaultBranchBranch.DBBranch.Pusher}}{{end}}

{{if and $.IsWriter (not $.Repository.IsArchived) (not .IsDeleted)}} @@ -92,7 +92,7 @@ {{.DBBranch.Name}} -

{{ctx.Locale.Tr "repo.branch.deleted_by" .DBBranch.DeletedBy.Name}} {{TimeSinceUnix .DBBranch.DeletedUnix ctx.Locale}}

+

{{ctx.Locale.Tr "repo.branch.deleted_by" .DBBranch.DeletedBy.Name}} {{DateUtils.TimeSince .DBBranch.DeletedUnix}}

{{else}}
{{.DBBranch.Name}} @@ -102,7 +102,7 @@ {{template "repo/commit_statuses" dict "Status" (index $.CommitStatus .DBBranch.CommitID) "Statuses" (index $.CommitStatuses .DBBranch.CommitID)}}
-

{{svg "octicon-git-commit" 16 "tw-mr-1"}}{{ShortSha .DBBranch.CommitID}} · {{RenderCommitMessage $.Context .DBBranch.CommitMessage ($.Repository.ComposeMetas ctx)}} · {{ctx.Locale.Tr "org.repo_updated" (TimeSince .DBBranch.CommitTime.AsTime ctx.Locale)}} {{if .DBBranch.Pusher}}  {{template "shared/user/avatarlink" dict "user" .DBBranch.Pusher}}  {{template "shared/user/namelink" .DBBranch.Pusher}}{{end}}

+

{{svg "octicon-git-commit" 16 "tw-mr-1"}}{{ShortSha .DBBranch.CommitID}} · {{RenderCommitMessage $.Context .DBBranch.CommitMessage ($.Repository.ComposeMetas ctx)}} · {{ctx.Locale.Tr "org.repo_updated" (DateUtils.TimeSince .DBBranch.CommitTime)}}{{if .DBBranch.Pusher}}  {{template "shared/user/avatarlink" dict "user" .DBBranch.Pusher}}  {{template "shared/user/namelink" .DBBranch.Pusher}}{{end}}

{{end}} diff --git a/templates/repo/code/recently_pushed_new_branches.tmpl b/templates/repo/code/recently_pushed_new_branches.tmpl index d996acc5b2..dd663762db 100644 --- a/templates/repo/code/recently_pushed_new_branches.tmpl +++ b/templates/repo/code/recently_pushed_new_branches.tmpl @@ -1,7 +1,7 @@ {{range .RecentlyPushedNewBranches}}
- {{$timeSince := TimeSince .CommitTime.AsTime ctx.Locale}} + {{$timeSince := DateUtils.TimeSince .CommitTime}} {{$repo := .GetRepo $.Context}} {{$name := .Name}} {{if ne $repo.ID $.Repository.ID}} diff --git a/templates/repo/commit_page.tmpl b/templates/repo/commit_page.tmpl index 96ce8cf747..a25b450dbe 100644 --- a/templates/repo/commit_page.tmpl +++ b/templates/repo/commit_page.tmpl @@ -152,7 +152,7 @@ {{ctx.AvatarUtils.AvatarByEmail .Commit.Author.Email .Commit.Author.Email 28 "tw-mr-2"}} {{.Commit.Author.Name}} {{end}} - {{TimeSince .Commit.Author.When ctx.Locale}} + {{DateUtils.TimeSince .Commit.Author.When}} {{if or (ne .Commit.Committer.Name .Commit.Author.Name) (ne .Commit.Committer.Email .Commit.Author.Email)}} {{ctx.Locale.Tr "repo.diff.committed_by"}} @@ -274,7 +274,7 @@ {{else}} {{.NoteCommit.Author.Name}} {{end}} - {{TimeSince .NoteCommit.Author.When ctx.Locale}} + {{DateUtils.TimeSince .NoteCommit.Author.When}}
{{.NoteRendered | SanitizeHTML}}
diff --git a/templates/repo/commits_list.tmpl b/templates/repo/commits_list.tmpl index c8c695e332..b23de20583 100644 --- a/templates/repo/commits_list.tmpl +++ b/templates/repo/commits_list.tmpl @@ -74,9 +74,9 @@ {{end}} {{if .Committer}} - {{TimeSince .Committer.When ctx.Locale}} + {{DateUtils.TimeSince .Committer.When}} {{else}} - {{TimeSince .Author.When ctx.Locale}} + {{DateUtils.TimeSince .Author.When}} {{end}} diff --git a/templates/repo/diff/comments.tmpl b/templates/repo/diff/comments.tmpl index e2597af0e3..b36f20269e 100644 --- a/templates/repo/diff/comments.tmpl +++ b/templates/repo/diff/comments.tmpl @@ -1,6 +1,6 @@ {{range .comments}} -{{$createdStr:= TimeSinceUnix .CreatedUnix ctx.Locale}} +{{$createdStr:= DateUtils.TimeSince .CreatedUnix}}
{{if .OriginalAuthor}} {{ctx.AvatarUtils.Avatar nil}} diff --git a/templates/repo/diff/compare.tmpl b/templates/repo/diff/compare.tmpl index 26c6b77971..612d08ec4f 100644 --- a/templates/repo/diff/compare.tmpl +++ b/templates/repo/diff/compare.tmpl @@ -212,7 +212,7 @@ {{if .Repository.ArchivedUnix.IsZero}} {{ctx.Locale.Tr "repo.archive.title"}} {{else}} - {{ctx.Locale.Tr "repo.archive.title_date" (ctx.DateUtils.AbsoluteLong .Repository.ArchivedUnix)}} + {{ctx.Locale.Tr "repo.archive.title_date" (DateUtils.AbsoluteLong .Repository.ArchivedUnix)}} {{end}}
{{end}} diff --git a/templates/repo/empty.tmpl b/templates/repo/empty.tmpl index d7f05223af..d3a81bc51d 100644 --- a/templates/repo/empty.tmpl +++ b/templates/repo/empty.tmpl @@ -10,7 +10,7 @@ {{if .Repository.ArchivedUnix.IsZero}} {{ctx.Locale.Tr "repo.archive.title"}} {{else}} - {{ctx.Locale.Tr "repo.archive.title_date" (ctx.DateUtils.AbsoluteLong .Repository.ArchivedUnix)}} + {{ctx.Locale.Tr "repo.archive.title_date" (DateUtils.AbsoluteLong .Repository.ArchivedUnix)}} {{end}}
{{end}} diff --git a/templates/repo/graph/commits.tmpl b/templates/repo/graph/commits.tmpl index 2ec4166308..f0ff0d2970 100644 --- a/templates/repo/graph/commits.tmpl +++ b/templates/repo/graph/commits.tmpl @@ -71,7 +71,7 @@ {{$userName}} {{end}} - {{ctx.DateUtils.FullTime $commit.Date}} + {{DateUtils.FullTime $commit.Date}} {{end}} {{end}} diff --git a/templates/repo/header.tmpl b/templates/repo/header.tmpl index 777453e4b1..2215c27886 100644 --- a/templates/repo/header.tmpl +++ b/templates/repo/header.tmpl @@ -74,7 +74,7 @@
{{ctx.Locale.Tr "repo.mirror_from"}} {{$.PullMirror.RemoteAddress}} - {{if $.PullMirror.UpdatedUnix}}{{ctx.Locale.Tr "repo.mirror_sync"}} {{TimeSinceUnix $.PullMirror.UpdatedUnix ctx.Locale}}{{end}} + {{if $.PullMirror.UpdatedUnix}}{{ctx.Locale.Tr "repo.mirror_sync"}} {{DateUtils.TimeSince $.PullMirror.UpdatedUnix}}{{end}}
{{end}} {{if .IsFork}}
{{ctx.Locale.Tr "repo.forked_from"}} {{.BaseRepo.FullName}}
{{end}} diff --git a/templates/repo/home.tmpl b/templates/repo/home.tmpl index d16e616a81..5fa31f15c2 100644 --- a/templates/repo/home.tmpl +++ b/templates/repo/home.tmpl @@ -53,7 +53,7 @@ {{if .Repository.ArchivedUnix.IsZero}} {{ctx.Locale.Tr "repo.archive.title"}} {{else}} - {{ctx.Locale.Tr "repo.archive.title_date" (ctx.DateUtils.AbsoluteLong .Repository.ArchivedUnix)}} + {{ctx.Locale.Tr "repo.archive.title_date" (DateUtils.AbsoluteLong .Repository.ArchivedUnix)}} {{end}}
{{end}} diff --git a/templates/repo/issue/card.tmpl b/templates/repo/issue/card.tmpl index 0b255d6705..c29c14a54b 100644 --- a/templates/repo/issue/card.tmpl +++ b/templates/repo/issue/card.tmpl @@ -24,7 +24,7 @@
{{if not $.Page.Repository}}{{.Repo.FullName}}{{end}}#{{.Index}} - {{$timeStr := TimeSinceUnix .GetLastEventTimestamp ctx.Locale}} + {{$timeStr := DateUtils.TimeSince .GetLastEventTimestamp}} {{if .OriginalAuthor}} {{ctx.Locale.Tr .GetLastEventLabelFake $timeStr .OriginalAuthor}} {{else if gt .Poster.ID 0}} diff --git a/templates/repo/issue/milestone_issues.tmpl b/templates/repo/issue/milestone_issues.tmpl index bfd64a3205..8b8b194f46 100644 --- a/templates/repo/issue/milestone_issues.tmpl +++ b/templates/repo/issue/milestone_issues.tmpl @@ -30,7 +30,7 @@
- {{$closedDate:= TimeSinceUnix .Milestone.ClosedDateUnix ctx.Locale}} + {{$closedDate:= DateUtils.TimeSince .Milestone.ClosedDateUnix}} {{if .IsClosed}} {{svg "octicon-clock"}} {{ctx.Locale.Tr "repo.milestones.closed" $closedDate}} {{else}} @@ -38,7 +38,7 @@ {{if .Milestone.DeadlineString}} {{svg "octicon-calendar"}} - {{ctx.DateUtils.AbsoluteShort (.Milestone.DeadlineString|ctx.DateUtils.ParseLegacy)}} + {{DateUtils.AbsoluteShort (.Milestone.DeadlineString|DateUtils.ParseLegacy)}} {{else}} {{svg "octicon-calendar"}} diff --git a/templates/repo/issue/milestones.tmpl b/templates/repo/issue/milestones.tmpl index 978f81598e..fab483c79d 100644 --- a/templates/repo/issue/milestones.tmpl +++ b/templates/repo/issue/milestones.tmpl @@ -49,19 +49,19 @@ {{if .UpdatedUnix}}
{{svg "octicon-clock"}} - {{ctx.Locale.Tr "repo.milestones.update_ago" (TimeSinceUnix .UpdatedUnix ctx.Locale)}} + {{ctx.Locale.Tr "repo.milestones.update_ago" (DateUtils.TimeSince .UpdatedUnix)}}
{{end}}
{{if .IsClosed}} - {{$closedDate:= TimeSinceUnix .ClosedDateUnix ctx.Locale}} + {{$closedDate:= DateUtils.TimeSince .ClosedDateUnix}} {{svg "octicon-clock" 14}} {{ctx.Locale.Tr "repo.milestones.closed" $closedDate}} {{else}} {{if .DeadlineString}} {{svg "octicon-calendar" 14}} - {{ctx.DateUtils.AbsoluteShort (.DeadlineString|ctx.DateUtils.ParseLegacy)}} + {{DateUtils.AbsoluteShort (.DeadlineString|DateUtils.ParseLegacy)}} {{else}} {{svg "octicon-calendar" 14}} diff --git a/templates/repo/issue/view_content.tmpl b/templates/repo/issue/view_content.tmpl index 947a480df1..bd52198264 100644 --- a/templates/repo/issue/view_content.tmpl +++ b/templates/repo/issue/view_content.tmpl @@ -6,7 +6,7 @@ - {{$createdStr:= TimeSinceUnix .Issue.CreatedUnix ctx.Locale}} + {{$createdStr:= DateUtils.TimeSince .Issue.CreatedUnix}}
diff --git a/templates/repo/issue/view_content/comments.tmpl b/templates/repo/issue/view_content/comments.tmpl index 828191e5e1..c8eabb9345 100644 --- a/templates/repo/issue/view_content/comments.tmpl +++ b/templates/repo/issue/view_content/comments.tmpl @@ -1,7 +1,7 @@ {{template "base/alert"}} {{range .Issue.Comments}} {{if call $.ShouldShowCommentType .Type}} - {{$createdStr:= TimeSinceUnix .CreatedUnix ctx.Locale}} + {{$createdStr:= DateUtils.TimeSince .CreatedUnix}} @@ -173,7 +173,7 @@

{{ctx.Locale.Tr "repo.activity.opened_prs_label"}} #{{.Index}} {{RenderRefIssueTitle $.Context .Issue.Title}} - {{TimeSinceUnix .Issue.CreatedUnix ctx.Locale}} + {{DateUtils.TimeSince .Issue.CreatedUnix}}

{{end}}
@@ -192,7 +192,7 @@

{{ctx.Locale.Tr "repo.activity.closed_issue_label"}} #{{.Index}} {{RenderRefIssueTitle $.Context .Title}} - {{TimeSinceUnix .ClosedUnix ctx.Locale}} + {{DateUtils.TimeSince .ClosedUnix}}

{{end}}
@@ -211,7 +211,7 @@

{{ctx.Locale.Tr "repo.activity.new_issue_label"}} #{{.Index}} {{RenderRefIssueTitle $.Context .Title}} - {{TimeSinceUnix .CreatedUnix ctx.Locale}} + {{DateUtils.TimeSince .CreatedUnix}}

{{end}}
@@ -232,7 +232,7 @@ {{else}} {{RenderRefIssueTitle $.Context .Title}} {{end}} - {{TimeSinceUnix .UpdatedUnix ctx.Locale}} + {{DateUtils.TimeSince .UpdatedUnix}}

{{end}}
diff --git a/templates/repo/release/list.tmpl b/templates/repo/release/list.tmpl index 4c7f13dda7..a760e0730e 100644 --- a/templates/repo/release/list.tmpl +++ b/templates/repo/release/list.tmpl @@ -51,7 +51,7 @@ {{ctx.Locale.Tr "repo.released_this"}} {{if $release.CreatedUnix}} - {{TimeSinceUnix $release.CreatedUnix ctx.Locale}} + {{DateUtils.TimeSince $release.CreatedUnix}} {{end}} {{if and (not $release.IsDraft) ($.Permission.CanRead $.UnitTypeCode)}} | {{ctx.Locale.Tr "repo.release.ahead.commits" $release.NumCommitsBehind}} {{ctx.Locale.Tr "repo.release.ahead.target" $release.TargetBehind}} diff --git a/templates/repo/settings/deploy_keys.tmpl b/templates/repo/settings/deploy_keys.tmpl index 9c7e1f38cd..91ef1df623 100644 --- a/templates/repo/settings/deploy_keys.tmpl +++ b/templates/repo/settings/deploy_keys.tmpl @@ -55,7 +55,7 @@ {{.Fingerprint}}
-

{{ctx.Locale.Tr "settings.added_on" (ctx.DateUtils.AbsoluteShort .CreatedUnix)}} — {{svg "octicon-info"}} {{if .HasUsed}}{{ctx.Locale.Tr "settings.last_used"}} {{ctx.DateUtils.AbsoluteShort .UpdatedUnix}}{{else}}{{ctx.Locale.Tr "settings.no_activity"}}{{end}} - {{ctx.Locale.Tr "settings.can_read_info"}}{{if not .IsReadOnly}} / {{ctx.Locale.Tr "settings.can_write_info"}} {{end}}

+

{{ctx.Locale.Tr "settings.added_on" (DateUtils.AbsoluteShort .CreatedUnix)}} — {{svg "octicon-info"}} {{if .HasUsed}}{{ctx.Locale.Tr "settings.last_used"}} {{DateUtils.AbsoluteShort .UpdatedUnix}}{{else}}{{ctx.Locale.Tr "settings.no_activity"}}{{end}} - {{ctx.Locale.Tr "settings.can_read_info"}}{{if not .IsReadOnly}} / {{ctx.Locale.Tr "settings.can_write_info"}} {{end}}

diff --git a/templates/repo/settings/lfs.tmpl b/templates/repo/settings/lfs.tmpl index 6d7aac229d..069fdecb33 100644 --- a/templates/repo/settings/lfs.tmpl +++ b/templates/repo/settings/lfs.tmpl @@ -17,7 +17,7 @@ {{ctx.Locale.TrSize .Size}} - {{TimeSince .CreatedUnix.AsTime ctx.Locale}} + {{DateUtils.TimeSince .CreatedUnix}} {{ctx.Locale.Tr "repo.settings.lfs_findcommits"}}
- {{TimeSince .Delivered.AsTime ctx.Locale}} + {{DateUtils.TimeSince .Delivered}}
diff --git a/templates/repo/tag/list.tmpl b/templates/repo/tag/list.tmpl index 82f3dc04a9..8aa4a806c8 100644 --- a/templates/repo/tag/list.tmpl +++ b/templates/repo/tag/list.tmpl @@ -27,7 +27,7 @@
{{if $.Permission.CanRead $.UnitTypeCode}} {{if .CreatedUnix}} - {{svg "octicon-clock" 16 "tw-mr-1"}}{{TimeSinceUnix .CreatedUnix ctx.Locale}} + {{svg "octicon-clock" 16 "tw-mr-1"}}{{DateUtils.TimeSince .CreatedUnix}} {{end}} {{svg "octicon-git-commit" 16 "tw-mr-1"}}{{ShortSha .Sha1}} diff --git a/templates/repo/user_cards.tmpl b/templates/repo/user_cards.tmpl index abf70a9607..fbd4ef0cee 100644 --- a/templates/repo/user_cards.tmpl +++ b/templates/repo/user_cards.tmpl @@ -20,7 +20,7 @@ {{else if .Location}} {{svg "octicon-location"}} {{.Location}} {{else}} - {{svg "octicon-calendar"}} {{ctx.Locale.Tr "user.joined_on" (ctx.DateUtils.AbsoluteShort .CreatedUnix)}} + {{svg "octicon-calendar"}} {{ctx.Locale.Tr "user.joined_on" (DateUtils.AbsoluteShort .CreatedUnix)}} {{end}}
diff --git a/templates/repo/view_file.tmpl b/templates/repo/view_file.tmpl index d127c2ef24..b2443e82c4 100644 --- a/templates/repo/view_file.tmpl +++ b/templates/repo/view_file.tmpl @@ -18,7 +18,7 @@ {{if .LatestCommit}} {{if .LatestCommit.Committer}}
- {{TimeSince .LatestCommit.Committer.When ctx.Locale}} + {{DateUtils.TimeSince .LatestCommit.Committer.When}}
{{end}} {{end}} diff --git a/templates/repo/view_list.tmpl b/templates/repo/view_list.tmpl index b750e9129e..6d6af58c48 100644 --- a/templates/repo/view_list.tmpl +++ b/templates/repo/view_list.tmpl @@ -8,7 +8,7 @@ - {{if .LatestCommit}}{{if .LatestCommit.Committer}}{{TimeSince .LatestCommit.Committer.When ctx.Locale}}{{end}}{{end}} + {{if .LatestCommit}}{{if .LatestCommit.Committer}}{{DateUtils.TimeSince .LatestCommit.Committer.When}}{{end}}{{end}} @@ -62,7 +62,7 @@ {{end}} - {{if $commit}}{{TimeSince $commit.Committer.When ctx.Locale}}{{end}} + {{if $commit}}{{DateUtils.TimeSince $commit.Committer.When}}{{end}} {{end}} diff --git a/templates/repo/wiki/pages.tmpl b/templates/repo/wiki/pages.tmpl index 42c36a9f46..43ab0f9a14 100644 --- a/templates/repo/wiki/pages.tmpl +++ b/templates/repo/wiki/pages.tmpl @@ -19,7 +19,7 @@ {{.Name}} {{svg "octicon-chevron-right"}} - {{$timeSince := TimeSinceUnix .UpdatedUnix ctx.Locale}} + {{$timeSince := DateUtils.TimeSince .UpdatedUnix}} {{ctx.Locale.Tr "repo.wiki.last_updated" $timeSince}} {{end}} diff --git a/templates/repo/wiki/revision.tmpl b/templates/repo/wiki/revision.tmpl index 7fca703843..045cc41d81 100644 --- a/templates/repo/wiki/revision.tmpl +++ b/templates/repo/wiki/revision.tmpl @@ -9,7 +9,7 @@ {{.revision}} {{svg "octicon-home"}} {{$title}}
- {{$timeSince := TimeSince .Author.When ctx.Locale}} + {{$timeSince := DateUtils.TimeSince .Author.When}} {{ctx.Locale.Tr "repo.wiki.last_commit_info" .Author.Name $timeSince}}
diff --git a/templates/repo/wiki/view.tmpl b/templates/repo/wiki/view.tmpl index 40af307524..9f77976f35 100644 --- a/templates/repo/wiki/view.tmpl +++ b/templates/repo/wiki/view.tmpl @@ -48,7 +48,7 @@ {{.CommitCount}} {{svg "octicon-history"}} {{$title}}
- {{$timeSince := TimeSince .Author.When ctx.Locale}} + {{$timeSince := DateUtils.TimeSince .Author.When}} {{ctx.Locale.Tr "repo.wiki.last_commit_info" .Author.Name $timeSince}}
diff --git a/templates/shared/actions/runner_edit.tmpl b/templates/shared/actions/runner_edit.tmpl index d60f10b71f..54250f830b 100644 --- a/templates/shared/actions/runner_edit.tmpl +++ b/templates/shared/actions/runner_edit.tmpl @@ -13,7 +13,7 @@
- {{if .Runner.LastOnline}}{{TimeSinceUnix .Runner.LastOnline ctx.Locale}}{{else}}{{ctx.Locale.Tr "never"}}{{end}} + {{if .Runner.LastOnline}}{{DateUtils.TimeSince .Runner.LastOnline}}{{else}}{{ctx.Locale.Tr "never"}}{{end}}
@@ -70,7 +70,7 @@ {{ShortSha .CommitSHA}} {{if .IsStopped}} - {{TimeSinceUnix .Stopped ctx.Locale}} + {{DateUtils.TimeSince .Stopped}} {{else}}-{{end}} {{end}} diff --git a/templates/shared/actions/runner_list.tmpl b/templates/shared/actions/runner_list.tmpl index abbf2204a8..5bc61f4f64 100644 --- a/templates/shared/actions/runner_list.tmpl +++ b/templates/shared/actions/runner_list.tmpl @@ -73,7 +73,7 @@ {{range .AgentLabels}}{{.}}{{end}} - {{if .LastOnline}}{{TimeSinceUnix .LastOnline ctx.Locale}}{{else}}{{ctx.Locale.Tr "never"}}{{end}} + {{if .LastOnline}}{{DateUtils.TimeSince .LastOnline}}{{else}}{{ctx.Locale.Tr "never"}}{{end}} {{if .Editable $.RunnerOwnerID $.RunnerRepoID}} {{svg "octicon-pencil"}} diff --git a/templates/shared/issuelist.tmpl b/templates/shared/issuelist.tmpl index 941a444612..7ce7cd6795 100644 --- a/templates/shared/issuelist.tmpl +++ b/templates/shared/issuelist.tmpl @@ -60,7 +60,7 @@ #{{.Index}} {{end}} - {{$timeStr := TimeSinceUnix .GetLastEventTimestamp ctx.Locale}} + {{$timeStr := DateUtils.TimeSince .GetLastEventTimestamp}} {{if .OriginalAuthor}} {{ctx.Locale.Tr .GetLastEventLabelFake $timeStr .OriginalAuthor}} {{else if gt .Poster.ID 0}} @@ -117,7 +117,7 @@ {{svg "octicon-calendar" 14}} - {{ctx.DateUtils.AbsoluteShort .DeadlineUnix}} + {{DateUtils.AbsoluteShort .DeadlineUnix}} {{end}} diff --git a/templates/shared/searchbottom.tmpl b/templates/shared/searchbottom.tmpl index bee0397259..4e0bd9570b 100644 --- a/templates/shared/searchbottom.tmpl +++ b/templates/shared/searchbottom.tmpl @@ -7,7 +7,7 @@
{{if not .result.UpdatedUnix.IsZero}} - {{ctx.Locale.Tr "explore.code_last_indexed_at" (TimeSinceUnix .result.UpdatedUnix ctx.Locale)}} + {{ctx.Locale.Tr "explore.code_last_indexed_at" (DateUtils.TimeSince .result.UpdatedUnix)}} {{end}}
diff --git a/templates/shared/secrets/add_list.tmpl b/templates/shared/secrets/add_list.tmpl index 011635a20d..59596d1013 100644 --- a/templates/shared/secrets/add_list.tmpl +++ b/templates/shared/secrets/add_list.tmpl @@ -28,7 +28,7 @@
- {{ctx.Locale.Tr "settings.added_on" (ctx.DateUtils.AbsoluteShort .CreatedUnix)}} + {{ctx.Locale.Tr "settings.added_on" (DateUtils.AbsoluteShort .CreatedUnix)}}
- {{ctx.Locale.Tr "settings.added_on" (ctx.DateUtils.AbsoluteShort .CreatedUnix)}} + {{ctx.Locale.Tr "settings.added_on" (DateUtils.AbsoluteShort .CreatedUnix)}}