Skip to content

Commit 6f5748c

Browse files
GiteaBotlunny
andauthored
Prevent update pull refs manually and will not affect other refs update (#31931) (#31955)
Backport #31931 by @lunny All refs under `refs/pull` should only be changed from Gitea inside but not by pushing from outside of Gitea. This PR will prevent the pull refs update but allow other refs to be updated on the same pushing with `--mirror` operations. The main changes are to add checks on `update` hook but not `pre-receive` because `update` will be invoked by every ref but `pre-receive` will revert all changes once one ref update fails. Co-authored-by: Lunny Xiao <[email protected]>
1 parent cc15202 commit 6f5748c

File tree

3 files changed

+37
-0
lines changed

3 files changed

+37
-0
lines changed

cmd/hook.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -290,8 +290,22 @@ Gitea or set your environment appropriately.`, "")
290290
return nil
291291
}
292292

293+
// runHookUpdate avoid to do heavy operations on update hook because it will be
294+
// invoked for every ref update which does not like pre-receive and post-receive
293295
func runHookUpdate(c *cli.Context) error {
296+
if isInternal, _ := strconv.ParseBool(os.Getenv(repo_module.EnvIsInternal)); isInternal {
297+
return nil
298+
}
299+
294300
// Update is empty and is kept only for backwards compatibility
301+
if len(os.Args) < 3 {
302+
return nil
303+
}
304+
refName := git.RefName(os.Args[len(os.Args)-3])
305+
if refName.IsPull() {
306+
// ignore update to refs/pull/xxx/head, so we don't need to output any information
307+
os.Exit(1)
308+
}
295309
return nil
296310
}
297311

tests/integration/git_push_test.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@ package integration
66
import (
77
"fmt"
88
"net/url"
9+
"strings"
910
"testing"
1011

12+
auth_model "code.gitea.io/gitea/models/auth"
1113
"code.gitea.io/gitea/models/db"
1214
git_model "code.gitea.io/gitea/models/git"
1315
"code.gitea.io/gitea/models/unittest"
@@ -192,3 +194,23 @@ func runTestGitPush(t *testing.T, u *url.URL, gitOperation func(t *testing.T, gi
192194

193195
require.NoError(t, repo_service.DeleteRepositoryDirectly(db.DefaultContext, user, repo.ID))
194196
}
197+
198+
func TestPushPullRefs(t *testing.T) {
199+
onGiteaRun(t, func(t *testing.T, u *url.URL) {
200+
baseAPITestContext := NewAPITestContext(t, "user2", "repo1", auth_model.AccessTokenScopeWriteRepository, auth_model.AccessTokenScopeWriteUser)
201+
202+
u.Path = baseAPITestContext.GitPath()
203+
u.User = url.UserPassword("user2", userPassword)
204+
205+
dstPath := t.TempDir()
206+
doGitClone(dstPath, u)(t)
207+
208+
cmd := git.NewCommand(git.DefaultContext, "push", "--delete", "origin", "refs/pull/2/head")
209+
stdout, stderr, err := cmd.RunStdString(&git.RunOpts{
210+
Dir: dstPath,
211+
})
212+
assert.Error(t, err)
213+
assert.Empty(t, stdout)
214+
assert.False(t, strings.Contains(stderr, "[deleted]"), "stderr: %s", stderr)
215+
})
216+
}

tests/test_utils.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,7 @@ func PrepareTestEnv(t testing.TB, skip ...int) func() {
223223
_ = os.MkdirAll(filepath.Join(setting.RepoRootPath, ownerDir.Name(), repoDir.Name(), "objects", "info"), 0o755)
224224
_ = os.MkdirAll(filepath.Join(setting.RepoRootPath, ownerDir.Name(), repoDir.Name(), "refs", "heads"), 0o755)
225225
_ = os.MkdirAll(filepath.Join(setting.RepoRootPath, ownerDir.Name(), repoDir.Name(), "refs", "tag"), 0o755)
226+
_ = os.MkdirAll(filepath.Join(setting.RepoRootPath, ownerDir.Name(), repoDir.Name(), "refs", "pull"), 0o755)
226227
}
227228
}
228229

0 commit comments

Comments
 (0)