Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitaly.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSami Hiltunen <shiltunen@gitlab.com>2023-05-15 20:26:10 +0300
committerSami Hiltunen <shiltunen@gitlab.com>2023-05-16 14:34:35 +0300
commit4702511ffb7ab317b8fdfed7ece570777996526f (patch)
treea7cd770494740aa630671d82dd153141995f7e13
parent30b6b1d1d37515e94fb504ff3b165c36eea614f5 (diff)
Integrate WAL into UserCommitFiles for testing
This commit changes UserCommitFiles to use the WAL for comitting its writes if enabled. When enabled, a transaction is begun through PartitionManager for the repository, the objects are written into the transaction's quarantine directory, and ultimately both reference changes and objects are committed through TransactionManager. WAL is enabled if PartitionManager is set on the server instance. For now it is only set when the `GITALY_TEST_WAL` environment variable is set when running the test. A Makefile target will later be added for testing the WAL and a CI job. There are slight behavior changes with the hooks which are left be for now: - 'reference-transaction prepared' is currently not acquiring locks nor verifying the reference changes. We'll likely have to extend the TransactionManager to handle this before we can roll WAL out given this affects Praefect's behavior. - 'update' hook is invoked with the objects still in the quarantine as opposed to the non-WAL variant. This will likely have to remain so. The objects are only written into the repository when the transaction is committed. For local execution, this shouldn't matter much since the quarantine directory is configured in the invocation. For loopback calls like what Rails does with pre-receive hook, this would be a breaking change.
-rw-r--r--internal/gitaly/hook/updateref/update_with_hooks.go135
-rw-r--r--internal/gitaly/hook/updateref/update_with_hooks_test.go5
-rw-r--r--internal/gitaly/service/conflicts/resolve_conflicts.go1
-rw-r--r--internal/gitaly/service/operations/apply_patch.go2
-rw-r--r--internal/gitaly/service/operations/branches.go6
-rw-r--r--internal/gitaly/service/operations/cherry_pick.go2
-rw-r--r--internal/gitaly/service/operations/commit_files.go7
-rw-r--r--internal/gitaly/service/operations/merge.go4
-rw-r--r--internal/gitaly/service/operations/rebase.go1
-rw-r--r--internal/gitaly/service/operations/revert.go2
-rw-r--r--internal/gitaly/service/operations/server.go30
-rw-r--r--internal/gitaly/service/operations/submodules.go1
-rw-r--r--internal/gitaly/service/operations/tags.go4
-rw-r--r--internal/gitaly/service/operations/update_with_hooks.go4
14 files changed, 148 insertions, 56 deletions
diff --git a/internal/gitaly/hook/updateref/update_with_hooks.go b/internal/gitaly/hook/updateref/update_with_hooks.go
index 2c7f15c99..12e4f2b91 100644
--- a/internal/gitaly/hook/updateref/update_with_hooks.go
+++ b/internal/gitaly/hook/updateref/update_with_hooks.go
@@ -14,6 +14,7 @@ import (
"gitlab.com/gitlab-org/gitaly/v16/internal/git/quarantine"
"gitlab.com/gitlab-org/gitaly/v16/internal/git/repository"
"gitlab.com/gitlab-org/gitaly/v16/internal/git/updateref"
+ "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly"
"gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/config"
"gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/hook"
"gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/storage"
@@ -145,8 +146,12 @@ func NewUpdaterWithHooks(
// with the quarantined repository as returned by the quarantine structure. If these hooks succeed,
// quarantined objects will be migrated and all subsequent hooks are executed via the unquarantined
// repository.
+//
+// If transaction is set, the actual update is done through the WAL by calling Commit on it. The
+// quarantine directory is taken from the transaction, and the other quarantineDir parameter is ignored.
func (u *UpdaterWithHooks) UpdateReference(
ctx context.Context,
+ tx *gitaly.Transaction,
repoProto *gitalypb.Repository,
user *gitalypb.User,
quarantineDir *quarantine.Dir,
@@ -192,7 +197,22 @@ func (u *UpdaterWithHooks) UpdateReference(
// then subsequently passed to Rails, which can use the quarantine directory to more
// efficiently query which objects are new.
quarantinedRepo := repoProto
- if quarantineDir != nil {
+ if tx != nil {
+ quarantineDir, err := tx.QuarantineDirectory()
+ if err != nil {
+ return fmt.Errorf("quarantine directory: %w", err)
+ }
+
+ repoPath, err := repo.Path()
+ if err != nil {
+ return fmt.Errorf("repo path: %w", err)
+ }
+
+ quarantinedRepo, err = quarantine.Apply(repoPath, repoProto, quarantineDir)
+ if err != nil {
+ return fmt.Errorf("quarantine repo: %w", err)
+ }
+ } else if quarantineDir != nil {
quarantinedRepo = quarantineDir.QuarantinedRepo()
}
@@ -218,6 +238,9 @@ func (u *UpdaterWithHooks) UpdateReference(
// We only need to update the hooks payload to the unquarantined repo in case we
// had a quarantine environment. Otherwise, the initial hooks payload is for the
// real repository anyway.
+ //
+ // With WAL, the update and reference transaction hooks must still execute with the quarantine
+ // as the objects are only written into the repository once the transaction has been committed.
hooksPayload, err = git.NewHooksPayload(u.cfg, repoProto, objectHash, transaction, &receiveHooksPayload, git.ReceivePackHooks, featureflag.FromContext(ctx)).Env()
if err != nil {
return fmt.Errorf("constructing quarantined hooks payload: %w", err)
@@ -228,52 +251,84 @@ func (u *UpdaterWithHooks) UpdateReference(
return fmt.Errorf("running update hooks: %w", wrapHookError(err, git.UpdateHook, stdout.String(), stderr.String()))
}
- // We are already manually invoking the reference-transaction hook, so there is no need to
- // set up hooks again here. One could argue that it would be easier to just have git handle
- // execution of the reference-transaction hook. But unfortunately, it has proven to be
- // problematic: if we queue a deletion, and the reference to be deleted exists both as
- // packed-ref and as loose ref, then we would see two transactions: first a transaction
- // deleting the packed-ref which would otherwise get unshadowed by deleting the loose ref,
- // and only then do we see the deletion of the loose ref. So this depends on how well a repo
- // is packed, which is obviously a bad thing as Gitaly nodes may be differently packed. We
- // thus continue to manually drive the reference-transaction hook here, which doesn't have
- // this problem.
- updater, err := updateref.New(ctx, repo, updateref.WithDisabledTransactions())
- if err != nil {
- return fmt.Errorf("creating updater: %w", err)
- }
+ if tx != nil {
+ // The prepared step deviates from the non-WAL behavior as it doesn't verify nor lock the references
+ // prior to casting the prepared vote.
+ if err := u.hookManager.ReferenceTransactionHook(ctx, hook.ReferenceTransactionPrepared, []string{hooksPayload}, strings.NewReader(changes)); err != nil {
+ return fmt.Errorf("executing preparatory reference-transaction hook: %w", err)
+ }
- // We need to explicitly cancel the update here such that we release the lock when this
- // function exits if there is any error between locking and committing.
- defer func() { _ = updater.Close() }()
+ tx.UpdateReferences(gitaly.ReferenceUpdates{
+ reference: {OldOID: oldrev, NewOID: newrev},
+ })
+
+ if err := tx.Commit(ctx); err != nil {
+ var errReferenceVerification gitaly.ReferenceVerificationError
+ if errors.As(err, &errReferenceVerification) {
+ return Error{
+ Reference: errReferenceVerification.ReferenceName,
+ OldOID: oldrev,
+ NewOID: newrev,
+ }
+ }
+
+ return fmt.Errorf("commit: %w", err)
+ }
- if err := updater.Start(); err != nil {
- return fmt.Errorf("start reference transaction: %w", err)
- }
+ // The quarantined objects are written into the repository following a commit and the quarantine directory
+ // removed. Replace the quarantined repository with the normal repository in the payload.
+ hooksPayload, err = git.NewHooksPayload(u.cfg, repoProto, objectHash, transaction, &receiveHooksPayload, git.ReceivePackHooks, featureflag.FromContext(ctx)).Env()
+ if err != nil {
+ return fmt.Errorf("constructing quarantined hooks payload: %w", err)
+ }
+ } else {
+ // We are already manually invoking the reference-transaction hook, so there is no need to
+ // set up hooks again here. One could argue that it would be easier to just have git handle
+ // execution of the reference-transaction hook. But unfortunately, it has proven to be
+ // problematic: if we queue a deletion, and the reference to be deleted exists both as
+ // packed-ref and as loose ref, then we would see two transactions: first a transaction
+ // deleting the packed-ref which would otherwise get unshadowed by deleting the loose ref,
+ // and only then do we see the deletion of the loose ref. So this depends on how well a repo
+ // is packed, which is obviously a bad thing as Gitaly nodes may be differently packed. We
+ // thus continue to manually drive the reference-transaction hook here, which doesn't have
+ // this problem.
+ updater, err := updateref.New(ctx, repo, updateref.WithDisabledTransactions())
+ if err != nil {
+ return fmt.Errorf("creating updater: %w", err)
+ }
- if err := updater.Update(reference, newrev, oldrev); err != nil {
- return fmt.Errorf("queueing ref update: %w", err)
- }
+ // We need to explicitly cancel the update here such that we release the lock when this
+ // function exits if there is any error between locking and committing.
+ defer func() { _ = updater.Close() }()
- // We need to lock the reference before executing the reference-transaction hook such that
- // there cannot be any concurrent modification.
- if err := updater.Prepare(); err != nil {
- return Error{
- Reference: reference,
- OldOID: oldrev,
- NewOID: newrev,
+ if err := updater.Start(); err != nil {
+ return fmt.Errorf("start reference transaction: %w", err)
}
- }
- if err := u.hookManager.ReferenceTransactionHook(ctx, hook.ReferenceTransactionPrepared, []string{hooksPayload}, strings.NewReader(changes)); err != nil {
- return fmt.Errorf("executing preparatory reference-transaction hook: %w", err)
- }
+ if err := updater.Update(reference, newrev, oldrev); err != nil {
+ return fmt.Errorf("queueing ref update: %w", err)
+ }
+
+ // We need to lock the reference before executing the reference-transaction hook such that
+ // there cannot be any concurrent modification.
+ if err := updater.Prepare(); err != nil {
+ return Error{
+ Reference: reference,
+ OldOID: oldrev,
+ NewOID: newrev,
+ }
+ }
+
+ if err := u.hookManager.ReferenceTransactionHook(ctx, hook.ReferenceTransactionPrepared, []string{hooksPayload}, strings.NewReader(changes)); err != nil {
+ return fmt.Errorf("executing preparatory reference-transaction hook: %w", err)
+ }
- if err := updater.Commit(); err != nil {
- return Error{
- Reference: reference,
- OldOID: oldrev,
- NewOID: newrev,
+ if err := updater.Commit(); err != nil {
+ return Error{
+ Reference: reference,
+ OldOID: oldrev,
+ NewOID: newrev,
+ }
}
}
diff --git a/internal/gitaly/hook/updateref/update_with_hooks_test.go b/internal/gitaly/hook/updateref/update_with_hooks_test.go
index 31b74f902..3dd06a6b4 100644
--- a/internal/gitaly/hook/updateref/update_with_hooks_test.go
+++ b/internal/gitaly/hook/updateref/update_with_hooks_test.go
@@ -87,7 +87,7 @@ func TestUpdaterWithHooks_UpdateReference_invalidParameters(t *testing.T) {
for _, tc := range testCases {
t.Run(tc.desc, func(t *testing.T) {
- err := updater.UpdateReference(ctx, repo, gittest.TestUser, nil, tc.ref, tc.newRev, tc.oldRev)
+ err := updater.UpdateReference(ctx, nil, repo, gittest.TestUser, nil, tc.ref, tc.newRev, tc.oldRev)
require.Equal(t, tc.expectedErr, err)
})
}
@@ -279,7 +279,7 @@ func TestUpdaterWithHooks_UpdateReference(t *testing.T) {
gitCmdFactory := gittest.NewCommandFactory(t, cfg)
updater := updateref.NewUpdaterWithHooks(cfg, config.NewLocator(cfg), hookManager, gitCmdFactory, nil)
- err := updater.UpdateReference(ctx, repo, gittest.TestUser, nil, git.ReferenceName("refs/heads/main"), gittest.DefaultObjectHash.ZeroOID, commitID)
+ err := updater.UpdateReference(ctx, nil, repo, gittest.TestUser, nil, git.ReferenceName("refs/heads/main"), gittest.DefaultObjectHash.ZeroOID, commitID)
if tc.expectedErr == "" {
require.NoError(t, err)
} else {
@@ -387,6 +387,7 @@ func TestUpdaterWithHooks_quarantine(t *testing.T) {
require.NoError(t, updateref.NewUpdaterWithHooks(cfg, locator, hookManager, gitCmdFactory, nil).UpdateReference(
ctx,
+ nil,
repoProto,
&gitalypb.User{
GlId: "1234",
diff --git a/internal/gitaly/service/conflicts/resolve_conflicts.go b/internal/gitaly/service/conflicts/resolve_conflicts.go
index 3ff55ecbc..2e6c6d9fb 100644
--- a/internal/gitaly/service/conflicts/resolve_conflicts.go
+++ b/internal/gitaly/service/conflicts/resolve_conflicts.go
@@ -198,6 +198,7 @@ func (s *server) resolveConflicts(header *gitalypb.ResolveConflictsRequestHeader
if err := s.updater.UpdateReference(
ctx,
+ nil,
header.Repository,
header.User,
quarantineDir,
diff --git a/internal/gitaly/service/operations/apply_patch.go b/internal/gitaly/service/operations/apply_patch.go
index 9cb9a5ee6..7c181c9c1 100644
--- a/internal/gitaly/service/operations/apply_patch.go
+++ b/internal/gitaly/service/operations/apply_patch.go
@@ -193,7 +193,7 @@ func (s *Server) userApplyPatch(ctx context.Context, header *gitalypb.UserApplyP
}
}
- if err := s.updateReferenceWithHooks(ctx, header.Repository, header.User, nil, targetBranch, patchedCommit, currentCommit); err != nil {
+ if err := s.updateReferenceWithHooks(ctx, nil, header.Repository, header.User, nil, targetBranch, patchedCommit, currentCommit); err != nil {
return fmt.Errorf("update reference: %w", err)
}
diff --git a/internal/gitaly/service/operations/branches.go b/internal/gitaly/service/operations/branches.go
index a5559ceea..67b3c9faa 100644
--- a/internal/gitaly/service/operations/branches.go
+++ b/internal/gitaly/service/operations/branches.go
@@ -58,7 +58,7 @@ func (s *Server) UserCreateBranch(ctx context.Context, req *gitalypb.UserCreateB
referenceName := git.NewReferenceNameFromBranchName(string(req.BranchName))
- if err := s.updateReferenceWithHooks(ctx, req.GetRepository(), req.User, quarantineDir, referenceName, startPointOID, git.ObjectHashSHA1.ZeroOID); err != nil {
+ if err := s.updateReferenceWithHooks(ctx, nil, req.GetRepository(), req.User, quarantineDir, referenceName, startPointOID, git.ObjectHashSHA1.ZeroOID); err != nil {
var customHookErr updateref.CustomHookError
if errors.As(err, &customHookErr) {
@@ -140,7 +140,7 @@ func (s *Server) UserUpdateBranch(ctx context.Context, req *gitalypb.UserUpdateB
return nil, err
}
- if err := s.updateReferenceWithHooks(ctx, req.GetRepository(), req.User, quarantineDir, referenceName, newOID, oldOID); err != nil {
+ if err := s.updateReferenceWithHooks(ctx, nil, req.GetRepository(), req.User, quarantineDir, referenceName, newOID, oldOID); err != nil {
var customHookErr updateref.CustomHookError
if errors.As(err, &customHookErr) {
return &gitalypb.UserUpdateBranchResponse{
@@ -203,7 +203,7 @@ func (s *Server) UserDeleteBranch(ctx context.Context, req *gitalypb.UserDeleteB
}
}
- if err := s.updateReferenceWithHooks(ctx, req.Repository, req.User, nil, referenceName, git.ObjectHashSHA1.ZeroOID, referenceValue); err != nil {
+ if err := s.updateReferenceWithHooks(ctx, nil, req.Repository, req.User, nil, referenceName, git.ObjectHashSHA1.ZeroOID, referenceValue); err != nil {
var notAllowedError hook.NotAllowedError
var customHookErr updateref.CustomHookError
var updateRefError updateref.Error
diff --git a/internal/gitaly/service/operations/cherry_pick.go b/internal/gitaly/service/operations/cherry_pick.go
index 06b3f52be..797ad3ecf 100644
--- a/internal/gitaly/service/operations/cherry_pick.go
+++ b/internal/gitaly/service/operations/cherry_pick.go
@@ -145,7 +145,7 @@ func (s *Server) UserCherryPick(ctx context.Context, req *gitalypb.UserCherryPic
}
}
- if err := s.updateReferenceWithHooks(ctx, req.GetRepository(), req.User, quarantineDir, referenceName, newrev, oldrev); err != nil {
+ if err := s.updateReferenceWithHooks(ctx, nil, req.GetRepository(), req.User, quarantineDir, referenceName, newrev, oldrev); err != nil {
var customHookErr updateref.CustomHookError
if errors.As(err, &customHookErr) {
return nil, structerr.NewFailedPrecondition("access check failed").WithDetail(
diff --git a/internal/gitaly/service/operations/commit_files.go b/internal/gitaly/service/operations/commit_files.go
index 32804947b..588de9e9a 100644
--- a/internal/gitaly/service/operations/commit_files.go
+++ b/internal/gitaly/service/operations/commit_files.go
@@ -126,10 +126,11 @@ func validatePath(rootPath, relPath string) (string, error) {
}
func (s *Server) userCommitFiles(ctx context.Context, header *gitalypb.UserCommitFilesRequestHeader, stream gitalypb.OperationService_UserCommitFilesServer) error {
- quarantineDir, quarantineRepo, err := s.quarantinedRepo(ctx, header.GetRepository())
+ tx, quarantineDir, quarantineRepo, clean, err := s.begin(ctx, header.GetRepository())
if err != nil {
- return err
+ return fmt.Errorf("begin: %w", err)
}
+ defer func() { _ = clean() }()
repoPath, err := quarantineRepo.Path()
if err != nil {
@@ -339,7 +340,7 @@ func (s *Server) userCommitFiles(ctx context.Context, header *gitalypb.UserCommi
}
}
- if err := s.updateReferenceWithHooks(ctx, header.GetRepository(), header.User, quarantineDir, targetBranchName, commitID, oldRevision); err != nil {
+ if err := s.updateReferenceWithHooks(ctx, tx, header.GetRepository(), header.User, quarantineDir, targetBranchName, commitID, oldRevision); err != nil {
if errors.As(err, &updateref.Error{}) {
return structerr.NewFailedPrecondition("%w", err)
}
diff --git a/internal/gitaly/service/operations/merge.go b/internal/gitaly/service/operations/merge.go
index ea5194fa4..d2c6d8c9c 100644
--- a/internal/gitaly/service/operations/merge.go
+++ b/internal/gitaly/service/operations/merge.go
@@ -193,7 +193,7 @@ func (s *Server) UserMergeBranch(stream gitalypb.OperationService_UserMergeBranc
return structerr.NewFailedPrecondition("merge aborted by client")
}
- if err := s.updateReferenceWithHooks(ctx, firstRequest.GetRepository(), firstRequest.User, quarantineDir, referenceName, mergeOID, revision); err != nil {
+ if err := s.updateReferenceWithHooks(ctx, nil, firstRequest.GetRepository(), firstRequest.User, quarantineDir, referenceName, mergeOID, revision); err != nil {
var notAllowedError hook.NotAllowedError
var customHookErr updateref.CustomHookError
var updateRefError updateref.Error
@@ -331,7 +331,7 @@ func (s *Server) UserFFBranch(ctx context.Context, in *gitalypb.UserFFBranchRequ
return nil, structerr.NewFailedPrecondition("not fast forward")
}
- if err := s.updateReferenceWithHooks(ctx, in.GetRepository(), in.User, quarantineDir, referenceName, commitID, revision); err != nil {
+ if err := s.updateReferenceWithHooks(ctx, nil, in.GetRepository(), in.User, quarantineDir, referenceName, commitID, revision); err != nil {
var customHookErr updateref.CustomHookError
if errors.As(err, &customHookErr) {
return &gitalypb.UserFFBranchResponse{
diff --git a/internal/gitaly/service/operations/rebase.go b/internal/gitaly/service/operations/rebase.go
index 9441120cc..9e2282a1e 100644
--- a/internal/gitaly/service/operations/rebase.go
+++ b/internal/gitaly/service/operations/rebase.go
@@ -110,6 +110,7 @@ func (s *Server) UserRebaseConfirmable(stream gitalypb.OperationService_UserReba
if err := s.updateReferenceWithHooks(
ctx,
+ nil,
header.GetRepository(),
header.User,
quarantineDir,
diff --git a/internal/gitaly/service/operations/revert.go b/internal/gitaly/service/operations/revert.go
index 48bc6bb51..8f2bd15b2 100644
--- a/internal/gitaly/service/operations/revert.go
+++ b/internal/gitaly/service/operations/revert.go
@@ -120,7 +120,7 @@ func (s *Server) UserRevert(ctx context.Context, req *gitalypb.UserRevertRequest
}
}
- if err := s.updateReferenceWithHooks(ctx, req.GetRepository(), req.User, quarantineDir, referenceName, newrev, oldrev); err != nil {
+ if err := s.updateReferenceWithHooks(ctx, nil, req.GetRepository(), req.User, quarantineDir, referenceName, newrev, oldrev); err != nil {
var customHookErr updateref.CustomHookError
if errors.As(err, &customHookErr) {
return &gitalypb.UserRevertResponse{
diff --git a/internal/gitaly/service/operations/server.go b/internal/gitaly/service/operations/server.go
index b9be0ff24..b379dacd6 100644
--- a/internal/gitaly/service/operations/server.go
+++ b/internal/gitaly/service/operations/server.go
@@ -2,6 +2,7 @@ package operations
import (
"context"
+ "fmt"
"gitlab.com/gitlab-org/gitaly/v16/client"
"gitlab.com/gitlab-org/gitaly/v16/internal/git"
@@ -62,6 +63,35 @@ func (s *Server) localrepo(repo repository.GitRepo) *localrepo.Repo {
return localrepo.New(s.locator, s.gitCmdFactory, s.catfileCache, repo)
}
+func (s *Server) begin(ctx context.Context, repo *gitalypb.Repository) (_ *gitaly.Transaction, _ *quarantine.Dir, _ *localrepo.Repo, _ func() error, returnedErr error) {
+ if s.partitionManager != nil {
+ tx, err := s.partitionManager.Begin(ctx, repo)
+ if err != nil {
+ return nil, nil, nil, nil, fmt.Errorf("begin: %w", err)
+ }
+ defer func() {
+ if returnedErr != nil {
+ _ = tx.Rollback()
+ }
+ }()
+
+ quarantineDir, err := tx.QuarantineDirectory()
+ if err != nil {
+ return nil, nil, nil, nil, fmt.Errorf("quarantine directory: %w", err)
+ }
+
+ quarantineRepo, err := s.localrepo(repo).Quarantine(quarantineDir)
+ if err != nil {
+ return nil, nil, nil, nil, fmt.Errorf("quarantine repo: %w", err)
+ }
+
+ return tx, nil, quarantineRepo, tx.Rollback, nil
+ }
+
+ quarantineDir, quarantinedRepo, err := s.quarantinedRepo(ctx, repo)
+ return nil, quarantineDir, quarantinedRepo, func() error { return nil }, err
+}
+
func (s *Server) quarantinedRepo(
ctx context.Context, repo *gitalypb.Repository,
) (*quarantine.Dir, *localrepo.Repo, error) {
diff --git a/internal/gitaly/service/operations/submodules.go b/internal/gitaly/service/operations/submodules.go
index 45d93dc6f..af10c681d 100644
--- a/internal/gitaly/service/operations/submodules.go
+++ b/internal/gitaly/service/operations/submodules.go
@@ -258,6 +258,7 @@ func (s *Server) userUpdateSubmodule(ctx context.Context, req *gitalypb.UserUpda
if err := s.updateReferenceWithHooks(
ctx,
+ nil,
req.GetRepository(),
req.GetUser(),
quarantineDir,
diff --git a/internal/gitaly/service/operations/tags.go b/internal/gitaly/service/operations/tags.go
index d7518d2d0..b328ade66 100644
--- a/internal/gitaly/service/operations/tags.go
+++ b/internal/gitaly/service/operations/tags.go
@@ -63,7 +63,7 @@ func (s *Server) UserDeleteTag(ctx context.Context, req *gitalypb.UserDeleteTagR
}
}
- if err := s.updateReferenceWithHooks(ctx, req.Repository, req.User, nil, referenceName, git.ObjectHashSHA1.ZeroOID, revision); err != nil {
+ if err := s.updateReferenceWithHooks(ctx, nil, req.Repository, req.User, nil, referenceName, git.ObjectHashSHA1.ZeroOID, revision); err != nil {
var customHookErr updateref.CustomHookError
if errors.As(err, &customHookErr) {
return &gitalypb.UserDeleteTagResponse{
@@ -160,7 +160,7 @@ func (s *Server) UserCreateTag(ctx context.Context, req *gitalypb.UserCreateTagR
)
}
- if err := s.updateReferenceWithHooks(ctx, req.Repository, req.User, quarantineDir, referenceName, tagID, git.ObjectHashSHA1.ZeroOID); err != nil {
+ if err := s.updateReferenceWithHooks(ctx, nil, req.Repository, req.User, quarantineDir, referenceName, tagID, git.ObjectHashSHA1.ZeroOID); err != nil {
var notAllowedError hook.NotAllowedError
var customHookErr updateref.CustomHookError
var updateRefError updateref.Error
diff --git a/internal/gitaly/service/operations/update_with_hooks.go b/internal/gitaly/service/operations/update_with_hooks.go
index 73df5e153..4965edfc4 100644
--- a/internal/gitaly/service/operations/update_with_hooks.go
+++ b/internal/gitaly/service/operations/update_with_hooks.go
@@ -5,11 +5,13 @@ import (
"gitlab.com/gitlab-org/gitaly/v16/internal/git"
"gitlab.com/gitlab-org/gitaly/v16/internal/git/quarantine"
+ "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly"
"gitlab.com/gitlab-org/gitaly/v16/proto/go/gitalypb"
)
func (s *Server) updateReferenceWithHooks(
ctx context.Context,
+ tx *gitaly.Transaction,
repo *gitalypb.Repository,
user *gitalypb.User,
quarantine *quarantine.Dir,
@@ -17,5 +19,5 @@ func (s *Server) updateReferenceWithHooks(
newrev, oldrev git.ObjectID,
pushOptions ...string,
) error {
- return s.updater.UpdateReference(ctx, repo, user, quarantine, reference, newrev, oldrev, pushOptions...)
+ return s.updater.UpdateReference(ctx, tx, repo, user, quarantine, reference, newrev, oldrev, pushOptions...)
}