Skip to content

Commit ac34449

Browse files
authored
Prevent update pull refs manually and will not affect other refs update (#31931)
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.
1 parent 052a8fe commit ac34449

File tree

3 files changed

+37
-0
lines changed

3 files changed

+37
-0
lines changed

Diff for: cmd/hook.go

+14
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

Diff for: tests/integration/git_push_test.go

+22
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+
}

Diff for: tests/test_utils.go

+1
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)