From 13ffa287b1a2edd788fa21cfef447766dbd77821 Mon Sep 17 00:00:00 2001 From: Lunny Xiao Date: Mon, 3 Jul 2023 22:17:30 +0800 Subject: [PATCH] Fix bug of branches API with tests(#25578) (#25579) Backport #25578 This PR added a repository's check when creating/deleting branches via API. Mirror repository and archive repository cannot do that. --- models/fixtures/mirror.yml | 49 +++++++ models/fixtures/repository.yml | 2 +- routers/api/v1/repo/branch.go | 37 ++++- templates/swagger/v1_json.tmpl | 3 + .../user3/repo5.git/HEAD | 1 + .../user3/repo5.git/config | 6 + .../user3/repo5.git/description | 1 + .../user3/repo5.git/hooks/post-receive | 7 + .../repo5.git/hooks/post-receive.d/gitea | 2 + .../user3/repo5.git/hooks/pre-receive | 7 + .../user3/repo5.git/hooks/pre-receive.d/gitea | 2 + .../user3/repo5.git/hooks/update | 7 + .../user3/repo5.git/hooks/update.d/gitea | 2 + .../user3/repo5.git/info/exclude | 6 + .../20/ade30d25e0ecaeec84e7f542a8456900858240 | Bin 0 -> 84 bytes .../27/74debeea6dc742cc4971a92db0e08b95b60588 | Bin 0 -> 51 bytes .../2a/47ca4b614a9f5a43abbd5ad851a54a616ffee6 | Bin 0 -> 760 bytes .../2f/9b22fd3159a43b7b4e5dd806fcd544edf8716f | Bin 0 -> 37 bytes .../d2/2b4d4daa5be07329fcef6ed458f00cf3392da0 | Bin 0 -> 814 bytes .../d5/6a3073c1dbb7b15963110a049d50cdb5db99fc | Bin 0 -> 42 bytes .../ec/f0db3c1ec806522de4b491fb9a3c7457398c61 | Bin 0 -> 62 bytes .../ee/16d127df463aa491e08958120f2108b02468df | Bin 0 -> 84 bytes .../user3/repo5.git/refs/heads/master | 1 + .../user3/repo5.git/refs/heads/test_branch | 1 + tests/integration/api_repo_branch_test.go | 136 ++++++++++++++++++ tests/integration/empty_repo_test.go | 2 +- 26 files changed, 268 insertions(+), 4 deletions(-) create mode 100644 models/fixtures/mirror.yml create mode 100644 tests/gitea-repositories-meta/user3/repo5.git/HEAD create mode 100644 tests/gitea-repositories-meta/user3/repo5.git/config create mode 100644 tests/gitea-repositories-meta/user3/repo5.git/description create mode 100755 tests/gitea-repositories-meta/user3/repo5.git/hooks/post-receive create mode 100755 tests/gitea-repositories-meta/user3/repo5.git/hooks/post-receive.d/gitea create mode 100755 tests/gitea-repositories-meta/user3/repo5.git/hooks/pre-receive create mode 100755 tests/gitea-repositories-meta/user3/repo5.git/hooks/pre-receive.d/gitea create mode 100755 tests/gitea-repositories-meta/user3/repo5.git/hooks/update create mode 100755 tests/gitea-repositories-meta/user3/repo5.git/hooks/update.d/gitea create mode 100644 tests/gitea-repositories-meta/user3/repo5.git/info/exclude create mode 100644 tests/gitea-repositories-meta/user3/repo5.git/objects/20/ade30d25e0ecaeec84e7f542a8456900858240 create mode 100644 tests/gitea-repositories-meta/user3/repo5.git/objects/27/74debeea6dc742cc4971a92db0e08b95b60588 create mode 100644 tests/gitea-repositories-meta/user3/repo5.git/objects/2a/47ca4b614a9f5a43abbd5ad851a54a616ffee6 create mode 100644 tests/gitea-repositories-meta/user3/repo5.git/objects/2f/9b22fd3159a43b7b4e5dd806fcd544edf8716f create mode 100644 tests/gitea-repositories-meta/user3/repo5.git/objects/d2/2b4d4daa5be07329fcef6ed458f00cf3392da0 create mode 100644 tests/gitea-repositories-meta/user3/repo5.git/objects/d5/6a3073c1dbb7b15963110a049d50cdb5db99fc create mode 100644 tests/gitea-repositories-meta/user3/repo5.git/objects/ec/f0db3c1ec806522de4b491fb9a3c7457398c61 create mode 100644 tests/gitea-repositories-meta/user3/repo5.git/objects/ee/16d127df463aa491e08958120f2108b02468df create mode 100644 tests/gitea-repositories-meta/user3/repo5.git/refs/heads/master create mode 100644 tests/gitea-repositories-meta/user3/repo5.git/refs/heads/test_branch create mode 100644 tests/integration/api_repo_branch_test.go diff --git a/models/fixtures/mirror.yml b/models/fixtures/mirror.yml new file mode 100644 index 0000000000..97bc4ae60d --- /dev/null +++ b/models/fixtures/mirror.yml @@ -0,0 +1,49 @@ +- + id: 1 + repo_id: 5 + interval: 3600 + enable_prune: false + updated_unix: 0 + next_update_unix: 0 + lfs_enabled: false + lfs_endpoint: "" + +- + id: 2 + repo_id: 25 + interval: 3600 + enable_prune: false + updated_unix: 0 + next_update_unix: 0 + lfs_enabled: false + lfs_endpoint: "" + +- + id: 3 + repo_id: 26 + interval: 3600 + enable_prune: false + updated_unix: 0 + next_update_unix: 0 + lfs_enabled: false + lfs_endpoint: "" + +- + id: 4 + repo_id: 27 + interval: 3600 + enable_prune: false + updated_unix: 0 + next_update_unix: 0 + lfs_enabled: false + lfs_endpoint: "" + +- + id: 5 + repo_id: 28 + interval: 3600 + enable_prune: false + updated_unix: 0 + next_update_unix: 0 + lfs_enabled: false + lfs_endpoint: "" diff --git a/models/fixtures/repository.yml b/models/fixtures/repository.yml index ef7730780f..050a9e2d06 100644 --- a/models/fixtures/repository.yml +++ b/models/fixtures/repository.yml @@ -141,7 +141,7 @@ num_projects: 0 num_closed_projects: 0 is_private: true - is_empty: true + is_empty: false is_archived: false is_mirror: true status: 0 diff --git a/routers/api/v1/repo/branch.go b/routers/api/v1/repo/branch.go index 5336ccb797..04d179dfaa 100644 --- a/routers/api/v1/repo/branch.go +++ b/routers/api/v1/repo/branch.go @@ -116,6 +116,21 @@ func DeleteBranch(ctx *context.APIContext) { // "404": // "$ref": "#/responses/notFound" + if ctx.Repo.Repository.IsEmpty { + ctx.Error(http.StatusNotFound, "", "Git Repository is empty.") + return + } + + if ctx.Repo.Repository.IsArchived { + ctx.Error(http.StatusForbidden, "", "Git Repository is archived.") + return + } + + if ctx.Repo.Repository.IsMirror { + ctx.Error(http.StatusForbidden, "", "Git Repository is a mirror.") + return + } + branchName := ctx.Params("*") if err := repo_service.DeleteBranch(ctx, ctx.Doer, ctx.Repo.Repository, ctx.Repo.GitRepo, branchName); err != nil { @@ -162,17 +177,30 @@ func CreateBranch(ctx *context.APIContext) { // responses: // "201": // "$ref": "#/responses/Branch" + // "403": + // description: The branch is archived or a mirror. // "404": // description: The old branch does not exist. // "409": // description: The branch with the same name already exists. - opt := web.GetForm(ctx).(*api.CreateBranchRepoOption) if ctx.Repo.Repository.IsEmpty { ctx.Error(http.StatusNotFound, "", "Git Repository is empty.") return } + if ctx.Repo.Repository.IsArchived { + ctx.Error(http.StatusForbidden, "", "Git Repository is archived.") + return + } + + if ctx.Repo.Repository.IsMirror { + ctx.Error(http.StatusForbidden, "", "Git Repository is a mirror.") + return + } + + opt := web.GetForm(ctx).(*api.CreateBranchRepoOption) + var oldCommit *git.Commit var err error @@ -280,7 +308,12 @@ func ListBranches(ctx *context.APIContext) { listOptions := utils.GetListOptions(ctx) - if !ctx.Repo.Repository.IsEmpty && ctx.Repo.GitRepo != nil { + if !ctx.Repo.Repository.IsEmpty { + if ctx.Repo.GitRepo == nil { + ctx.Error(http.StatusInternalServerError, "Load git repository failed", nil) + return + } + rules, err := git_model.FindRepoProtectedBranchRules(ctx, ctx.Repo.Repository.ID) if err != nil { ctx.Error(http.StatusInternalServerError, "FindMatchedProtectedBranchRules", err) diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index 11abeac77c..e7d1cc1fe5 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -3478,6 +3478,9 @@ "201": { "$ref": "#/responses/Branch" }, + "403": { + "description": "The branch is archived or a mirror." + }, "404": { "description": "The old branch does not exist." }, diff --git a/tests/gitea-repositories-meta/user3/repo5.git/HEAD b/tests/gitea-repositories-meta/user3/repo5.git/HEAD new file mode 100644 index 0000000000..cb089cd89a --- /dev/null +++ b/tests/gitea-repositories-meta/user3/repo5.git/HEAD @@ -0,0 +1 @@ +ref: refs/heads/master diff --git a/tests/gitea-repositories-meta/user3/repo5.git/config b/tests/gitea-repositories-meta/user3/repo5.git/config new file mode 100644 index 0000000000..e6da231579 --- /dev/null +++ b/tests/gitea-repositories-meta/user3/repo5.git/config @@ -0,0 +1,6 @@ +[core] + repositoryformatversion = 0 + filemode = true + bare = true + ignorecase = true + precomposeunicode = true diff --git a/tests/gitea-repositories-meta/user3/repo5.git/description b/tests/gitea-repositories-meta/user3/repo5.git/description new file mode 100644 index 0000000000..498b267a8c --- /dev/null +++ b/tests/gitea-repositories-meta/user3/repo5.git/description @@ -0,0 +1 @@ +Unnamed repository; edit this file 'description' to name the repository. diff --git a/tests/gitea-repositories-meta/user3/repo5.git/hooks/post-receive b/tests/gitea-repositories-meta/user3/repo5.git/hooks/post-receive new file mode 100755 index 0000000000..4b3d452abc --- /dev/null +++ b/tests/gitea-repositories-meta/user3/repo5.git/hooks/post-receive @@ -0,0 +1,7 @@ +#!/usr/bin/env bash +ORI_DIR=`pwd` +SHELL_FOLDER=$(cd "$(dirname "$0")";pwd) +cd "$ORI_DIR" +for i in `ls "$SHELL_FOLDER/post-receive.d"`; do + sh "$SHELL_FOLDER/post-receive.d/$i" +done \ No newline at end of file diff --git a/tests/gitea-repositories-meta/user3/repo5.git/hooks/post-receive.d/gitea b/tests/gitea-repositories-meta/user3/repo5.git/hooks/post-receive.d/gitea new file mode 100755 index 0000000000..43a948da3a --- /dev/null +++ b/tests/gitea-repositories-meta/user3/repo5.git/hooks/post-receive.d/gitea @@ -0,0 +1,2 @@ +#!/usr/bin/env bash +"$GITEA_ROOT/gitea" hook --config="$GITEA_ROOT/$GITEA_CONF" post-receive diff --git a/tests/gitea-repositories-meta/user3/repo5.git/hooks/pre-receive b/tests/gitea-repositories-meta/user3/repo5.git/hooks/pre-receive new file mode 100755 index 0000000000..4127013053 --- /dev/null +++ b/tests/gitea-repositories-meta/user3/repo5.git/hooks/pre-receive @@ -0,0 +1,7 @@ +#!/usr/bin/env bash +ORI_DIR=`pwd` +SHELL_FOLDER=$(cd "$(dirname "$0")";pwd) +cd "$ORI_DIR" +for i in `ls "$SHELL_FOLDER/pre-receive.d"`; do + sh "$SHELL_FOLDER/pre-receive.d/$i" +done \ No newline at end of file diff --git a/tests/gitea-repositories-meta/user3/repo5.git/hooks/pre-receive.d/gitea b/tests/gitea-repositories-meta/user3/repo5.git/hooks/pre-receive.d/gitea new file mode 100755 index 0000000000..49d0940636 --- /dev/null +++ b/tests/gitea-repositories-meta/user3/repo5.git/hooks/pre-receive.d/gitea @@ -0,0 +1,2 @@ +#!/usr/bin/env bash +"$GITEA_ROOT/gitea" hook --config="$GITEA_ROOT/$GITEA_CONF" pre-receive diff --git a/tests/gitea-repositories-meta/user3/repo5.git/hooks/update b/tests/gitea-repositories-meta/user3/repo5.git/hooks/update new file mode 100755 index 0000000000..c186fe4a18 --- /dev/null +++ b/tests/gitea-repositories-meta/user3/repo5.git/hooks/update @@ -0,0 +1,7 @@ +#!/usr/bin/env bash +ORI_DIR=`pwd` +SHELL_FOLDER=$(cd "$(dirname "$0")";pwd) +cd "$ORI_DIR" +for i in `ls "$SHELL_FOLDER/update.d"`; do + sh "$SHELL_FOLDER/update.d/$i" $1 $2 $3 +done \ No newline at end of file diff --git a/tests/gitea-repositories-meta/user3/repo5.git/hooks/update.d/gitea b/tests/gitea-repositories-meta/user3/repo5.git/hooks/update.d/gitea new file mode 100755 index 0000000000..38101c2426 --- /dev/null +++ b/tests/gitea-repositories-meta/user3/repo5.git/hooks/update.d/gitea @@ -0,0 +1,2 @@ +#!/usr/bin/env bash +"$GITEA_ROOT/gitea" hook --config="$GITEA_ROOT/$GITEA_CONF" update $1 $2 $3 diff --git a/tests/gitea-repositories-meta/user3/repo5.git/info/exclude b/tests/gitea-repositories-meta/user3/repo5.git/info/exclude new file mode 100644 index 0000000000..a5196d1be8 --- /dev/null +++ b/tests/gitea-repositories-meta/user3/repo5.git/info/exclude @@ -0,0 +1,6 @@ +# git ls-files --others --exclude-from=.git/info/exclude +# Lines that start with '#' are comments. +# For a project mostly in C, the following would be a good set of +# exclude patterns (uncomment them if you want to use them): +# *.[oa] +# *~ diff --git a/tests/gitea-repositories-meta/user3/repo5.git/objects/20/ade30d25e0ecaeec84e7f542a8456900858240 b/tests/gitea-repositories-meta/user3/repo5.git/objects/20/ade30d25e0ecaeec84e7f542a8456900858240 new file mode 100644 index 0000000000000000000000000000000000000000..9f3ffe5f27eab55ddf77a4eef3620a63549a1a32 GIT binary patch literal 84 zcmV-a0IUCa0V^p=O;s>6XD~D{Ff%bx2y%6F@paY9O<}m2Wl((Z_V$gD$%0%ga|6z9 qy*=}fi2)EOq~s?vsF&Q^_bT_e(;3ggmAV@qbWh#J+5rIM${q^x(I*%H literal 0 HcmV?d00001 diff --git a/tests/gitea-repositories-meta/user3/repo5.git/objects/27/74debeea6dc742cc4971a92db0e08b95b60588 b/tests/gitea-repositories-meta/user3/repo5.git/objects/27/74debeea6dc742cc4971a92db0e08b95b60588 new file mode 100644 index 0000000000000000000000000000000000000000..5d9226f7a1240630524be4a3f27f4f31b1972c4c GIT binary patch literal 51 zcmV-30L=e*0V^p=O;s>9VK6i>Ff%bxNXbvu%S~a>pRM%QFmj1?wO{NFwm(;0-u@`e J2LKmL5A5=Z6&nBm literal 0 HcmV?d00001 diff --git a/tests/gitea-repositories-meta/user3/repo5.git/objects/2a/47ca4b614a9f5a43abbd5ad851a54a616ffee6 b/tests/gitea-repositories-meta/user3/repo5.git/objects/2a/47ca4b614a9f5a43abbd5ad851a54a616ffee6 new file mode 100644 index 0000000000000000000000000000000000000000..ca60d2314fcda692990183d659d83ee440c1b995 GIT binary patch literal 760 zcmVYOx;klMR72dt4;0R+*~O8>}``PUZ2-qtxFX@ zzcQJ_^G_pOnRY=y&KS-~OX8!%s4VQG3+deL$vl6&|{~De2HSfz`)_^n-GuEXHwgRaeKV9=$9fPOJ1R0w&iIoy1PPwU+nK$I{bkEo7A`*gjm6CvD_e$1?jz#N~O za$_(}1e~skAZ#g_cMrB?V4Go^>n-WyBM+oNMmAPyk=}4>>B#PS@I$%`bj(%?W#cq$vH`uuPA-Xd;t|(ab9y}n`qJEc`7=3+E55E z$e1f~*2Cub*`mHJ?;X>J)^ki#5tAz#O#)(g5k031yqQOfK2UuUvU(xh?s>+q2#7WU zPQ_aDQ+K*Pm0NN_6;C(xXkDE?Y6;G%0+#1q=Fn1)S{}>pfgYb)I$r|Fv`LJBTSVP( zb>$Z|pyzbAWM`N|X)pQxLk(E=9`8a`Kus_6?#{1_diM>Af6P%>n&^txCj_v@gI-fg qUZ|GWE4B7C{oDJ4oXQ&c&k4mk{mKZW?!Q*Q-a`ZP8Tki~F*%6l+q`%%--?Q3*9;fw#G`w_Am_K7;=uqdh2LKN*4QBuV literal 0 HcmV?d00001 diff --git a/tests/gitea-repositories-meta/user3/repo5.git/objects/d2/2b4d4daa5be07329fcef6ed458f00cf3392da0 b/tests/gitea-repositories-meta/user3/repo5.git/objects/d2/2b4d4daa5be07329fcef6ed458f00cf3392da0 new file mode 100644 index 0000000000000000000000000000000000000000..e319f8ce3447ea6a2a5c36db6841d582ed4fd02c GIT binary patch literal 814 zcmV+}1JV3=0hNet()&&B`aCw{mU`%owRF4;Pzn% z@u^AqrtIh8?4O&RxUMO+3wpTC10PEVuvM4oI{lE(FLu}mbB_3ly;d=}h>m*a}70U@7KwMj5g?@Ptm9v&D}q^RpA z@wF3D?oP{r!GEMHLslWW$BeUIoJcp><1kNB*vr(AJ@%-}Fz^xFHPNcBHG?5);#}+; z1D?{03~4{OdsRKh*D*6wWz%hwL&b4r?-{wsyORf6To4#=$DLWSqszS^Ay!mpG!KQ( zllokZjEQ~eozR#B3YHdCylD01>Z<6TBD2jpsFS7EG2?TCo%v<+7hRJ%;1%Zm4 z!4Bh>S>!JXRe`GSi!Y>n7UybKW_iz4#)R@d!a!R*Z+7W>8irN-fAY=HhZmElw`VEGWs$&r?XtFM6XD~D{Ff%bx2y%6F@paY9O<{QR;kJ$33AP~JCtD`|o@G-K qZrPJ)VgLjRDf!6^>LvH~y~;iAbjGuArS66Y-BY)*b^rk6+8wjRASSs0 literal 0 HcmV?d00001 diff --git a/tests/gitea-repositories-meta/user3/repo5.git/refs/heads/master b/tests/gitea-repositories-meta/user3/repo5.git/refs/heads/master new file mode 100644 index 0000000000..ccee722d52 --- /dev/null +++ b/tests/gitea-repositories-meta/user3/repo5.git/refs/heads/master @@ -0,0 +1 @@ +2a47ca4b614a9f5a43abbd5ad851a54a616ffee6 diff --git a/tests/gitea-repositories-meta/user3/repo5.git/refs/heads/test_branch b/tests/gitea-repositories-meta/user3/repo5.git/refs/heads/test_branch new file mode 100644 index 0000000000..dfe0c6a128 --- /dev/null +++ b/tests/gitea-repositories-meta/user3/repo5.git/refs/heads/test_branch @@ -0,0 +1 @@ +d22b4d4daa5be07329fcef6ed458f00cf3392da0 diff --git a/tests/integration/api_repo_branch_test.go b/tests/integration/api_repo_branch_test.go new file mode 100644 index 0000000000..ef67a97cfd --- /dev/null +++ b/tests/integration/api_repo_branch_test.go @@ -0,0 +1,136 @@ +// Copyright 2021 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package integration + +import ( + "bytes" + "fmt" + "io" + "net/http" + "net/url" + "sort" + "testing" + + auth_model "code.gitea.io/gitea/models/auth" + 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/json" + "code.gitea.io/gitea/modules/setting" + api "code.gitea.io/gitea/modules/structs" + "code.gitea.io/gitea/tests" + + "github.com/stretchr/testify/assert" +) + +func TestAPIRepoBranchesPlain(t *testing.T) { + onGiteaRun(t, func(*testing.T, *url.URL) { + repo3 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 3}) + user1 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1}) + session := loginUser(t, user1.LowerName) + token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository) + + link, _ := url.Parse(fmt.Sprintf("/api/v1/repos/user3/%s/branches", repo3.Name)) // a plain repo + link.RawQuery = url.Values{"token": {token}}.Encode() + resp := MakeRequest(t, NewRequest(t, "GET", link.String()), http.StatusOK) + bs, err := io.ReadAll(resp.Body) + assert.NoError(t, err) + + var branches []*api.Branch + assert.NoError(t, json.Unmarshal(bs, &branches)) + assert.Len(t, branches, 2) + sort.Slice(branches, func(i, j int) bool { + return branches[i].Name > branches[j].Name + }) + assert.EqualValues(t, "test_branch", branches[0].Name) + assert.EqualValues(t, "master", branches[1].Name) + + link2, _ := url.Parse(fmt.Sprintf("/api/v1/repos/user3/%s/branches/test_branch", repo3.Name)) + link2.RawQuery = url.Values{"token": {token}}.Encode() + resp = MakeRequest(t, NewRequest(t, "GET", link2.String()), http.StatusOK) + bs, err = io.ReadAll(resp.Body) + assert.NoError(t, err) + var branch api.Branch + assert.NoError(t, json.Unmarshal(bs, &branch)) + assert.EqualValues(t, "test_branch", branch.Name) + + req := NewRequest(t, "POST", link.String()) + req.Header.Add("Content-Type", "application/json") + req.Body = io.NopCloser(bytes.NewBufferString(`{"new_branch_name":"test_branch2", "old_branch_name": "test_branch", "old_ref_name":"refs/heads/test_branch"}`)) + resp = MakeRequest(t, req, http.StatusCreated) + bs, err = io.ReadAll(resp.Body) + assert.NoError(t, err) + var branch2 api.Branch + assert.NoError(t, json.Unmarshal(bs, &branch2)) + assert.EqualValues(t, "test_branch2", branch2.Name) + assert.EqualValues(t, branch.Commit.ID, branch2.Commit.ID) + + resp = MakeRequest(t, NewRequest(t, "GET", link.String()), http.StatusOK) + bs, err = io.ReadAll(resp.Body) + assert.NoError(t, err) + + branches = []*api.Branch{} + assert.NoError(t, json.Unmarshal(bs, &branches)) + assert.Len(t, branches, 3) + sort.Slice(branches, func(i, j int) bool { + return branches[i].Name > branches[j].Name + }) + assert.EqualValues(t, "test_branch2", branches[0].Name) + assert.EqualValues(t, "test_branch", branches[1].Name) + assert.EqualValues(t, "master", branches[2].Name) + + link3, _ := url.Parse(fmt.Sprintf("/api/v1/repos/user3/%s/branches/test_branch2", repo3.Name)) + MakeRequest(t, NewRequest(t, "DELETE", link3.String()), http.StatusNotFound) + + link3.RawQuery = url.Values{"token": {token}}.Encode() + MakeRequest(t, NewRequest(t, "DELETE", link3.String()), http.StatusNoContent) + assert.NoError(t, err) + }) +} + +func TestAPIRepoBranchesMirror(t *testing.T) { + defer tests.PrepareTestEnv(t)() + + repo5 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 5}) + user1 := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: 1}) + session := loginUser(t, user1.LowerName) + token := getTokenForLoggedInUser(t, session, auth_model.AccessTokenScopeWriteRepository) + + link, _ := url.Parse(fmt.Sprintf("/api/v1/repos/user3/%s/branches", repo5.Name)) // a mirror repo + link.RawQuery = url.Values{"token": {token}}.Encode() + resp := MakeRequest(t, NewRequest(t, "GET", link.String()), http.StatusOK) + bs, err := io.ReadAll(resp.Body) + assert.NoError(t, err) + + var branches []*api.Branch + assert.NoError(t, json.Unmarshal(bs, &branches)) + assert.Len(t, branches, 2) + sort.Slice(branches, func(i, j int) bool { + return branches[i].Name > branches[j].Name + }) + assert.EqualValues(t, "test_branch", branches[0].Name) + assert.EqualValues(t, "master", branches[1].Name) + + link2, _ := url.Parse(fmt.Sprintf("/api/v1/repos/user3/%s/branches/test_branch", repo5.Name)) + link2.RawQuery = url.Values{"token": {token}}.Encode() + resp = MakeRequest(t, NewRequest(t, "GET", link2.String()), http.StatusOK) + bs, err = io.ReadAll(resp.Body) + assert.NoError(t, err) + var branch api.Branch + assert.NoError(t, json.Unmarshal(bs, &branch)) + assert.EqualValues(t, "test_branch", branch.Name) + + req := NewRequest(t, "POST", link.String()) + req.Header.Add("Content-Type", "application/json") + req.Body = io.NopCloser(bytes.NewBufferString(`{"new_branch_name":"test_branch2", "old_branch_name": "test_branch", "old_ref_name":"refs/heads/test_branch"}`)) + resp = MakeRequest(t, req, http.StatusForbidden) + bs, err = io.ReadAll(resp.Body) + assert.NoError(t, err) + assert.EqualValues(t, "{\"message\":\"Git Repository is a mirror.\",\"url\":\""+setting.AppURL+"api/swagger\"}\n", string(bs)) + + resp = MakeRequest(t, NewRequest(t, "DELETE", link2.String()), http.StatusForbidden) + bs, err = io.ReadAll(resp.Body) + assert.NoError(t, err) + assert.EqualValues(t, "{\"message\":\"Git Repository is a mirror.\",\"url\":\""+setting.AppURL+"api/swagger\"}\n", string(bs)) +} diff --git a/tests/integration/empty_repo_test.go b/tests/integration/empty_repo_test.go index f0022f4db3..d604391dab 100644 --- a/tests/integration/empty_repo_test.go +++ b/tests/integration/empty_repo_test.go @@ -34,7 +34,7 @@ func TestEmptyRepo(t *testing.T) { "commit/1ae57b34ccf7e18373", "graph", } - emptyRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 5}) + emptyRepo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 6}) assert.True(t, emptyRepo.IsEmpty) owner := unittest.AssertExistsAndLoadBean(t, &user_model.User{ID: emptyRepo.OwnerID}) for _, subPath := range subPaths {