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:
authorJustin Tobler <jtobler@gitlab.com>2023-10-24 20:07:45 +0300
committerJustin Tobler <jtobler@gitlab.com>2023-10-24 20:07:45 +0300
commitf62690c83d825e9d6783606fb47e2615115d6c97 (patch)
tree714a5229a1c8b2cb69d5696c6d4774113afd20fe
parent5d40e30edf7b2a2387bbe6b32b8a638a2d83d318 (diff)
parentb3db07f9cedffb4f20f0e1144c990e04ff83bd29 (diff)
Merge branch 'smh-transactional-create-repository' into 'master'
Handle repository creations transactionally See merge request https://gitlab.com/gitlab-org/gitaly/-/merge_requests/6492 Merged-by: Justin Tobler <jtobler@gitlab.com> Approved-by: Justin Tobler <jtobler@gitlab.com> Approved-by: karthik nayak <knayak@gitlab.com> Reviewed-by: Sami Hiltunen <shiltunen@gitlab.com> Co-authored-by: Sami Hiltunen <shiltunen@gitlab.com>
-rw-r--r--internal/gitaly/service/repository/create_repository_from_bundle_test.go12
-rw-r--r--internal/gitaly/service/repository/create_repository_from_snapshot_test.go24
-rw-r--r--internal/gitaly/service/repository/create_repository_from_url_test.go14
-rw-r--r--internal/gitaly/service/repository/fsck_test.go12
-rw-r--r--internal/gitaly/service/smarthttp/receive_pack_test.go2
-rw-r--r--internal/gitaly/service/ssh/receive_pack_test.go2
-rw-r--r--internal/gitaly/storage/storagemgr/middleware.go9
7 files changed, 47 insertions, 28 deletions
diff --git a/internal/gitaly/service/repository/create_repository_from_bundle_test.go b/internal/gitaly/service/repository/create_repository_from_bundle_test.go
index 59692b3af..54c3e0579 100644
--- a/internal/gitaly/service/repository/create_repository_from_bundle_test.go
+++ b/internal/gitaly/service/repository/create_repository_from_bundle_test.go
@@ -11,7 +11,6 @@ import (
"gitlab.com/gitlab-org/gitaly/v16/internal/git"
"gitlab.com/gitlab-org/gitaly/v16/internal/git/gittest"
"gitlab.com/gitlab-org/gitaly/v16/internal/git/localrepo"
- "gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/config"
"gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/storage"
"gitlab.com/gitlab-org/gitaly/v16/internal/gitaly/transaction"
"gitlab.com/gitlab-org/gitaly/v16/internal/grpc/metadata"
@@ -223,8 +222,13 @@ func TestCreateRepositoryFromBundle_transactional(t *testing.T) {
return transaction.PhasedVote{Vote: vote, Phase: phase}
}
- createdRepoPath, err := config.NewLocator(cfg).GetRepoPath(gittest.RewrittenRepository(t, ctx, cfg, createdRepo))
- require.NoError(t, err)
+ // This test is asserting storage layout as part of computing the expected vote hash. In particular,
+ // the references are not necessarily packed when the transaction is committed. Compute the expected
+ // vote thus from the state of the bundled repository. For the vote to match, we have to first modify
+ // the state to match what the RPC handler would produce. The created repository has its default branch
+ // set to master and has references packed.
+ gittest.Exec(t, cfg, "-C", repoPath, "symbolic-ref", "HEAD", "refs/heads/master")
+ gittest.Exec(t, cfg, "-C", repoPath, "pack-refs", "--all")
// Compute the vote hash to assert that we really hash exactly the files that we
// expect to hash. Furthermore, this is required for cross-platform compatibility given that
@@ -235,7 +239,7 @@ func TestCreateRepositoryFromBundle_transactional(t *testing.T) {
"config",
"packed-refs",
} {
- file, err := os.Open(filepath.Join(createdRepoPath, filePath))
+ file, err := os.Open(filepath.Join(repoPath, filePath))
require.NoError(t, err)
_, err = io.Copy(hash, file)
diff --git a/internal/gitaly/service/repository/create_repository_from_snapshot_test.go b/internal/gitaly/service/repository/create_repository_from_snapshot_test.go
index fa0c6b310..a0dee4caa 100644
--- a/internal/gitaly/service/repository/create_repository_from_snapshot_test.go
+++ b/internal/gitaly/service/repository/create_repository_from_snapshot_test.go
@@ -70,6 +70,12 @@ func generateTarFile(t *testing.T, path string) ([]byte, []string) {
}
func TestCreateRepositoryFromSnapshot_success(t *testing.T) {
+ if testhelper.IsWALEnabled() && gittest.DefaultObjectHash.Format == git.ObjectHashSHA256.Format {
+ t.Skip(`
+CreateRepositoryFromSnapshot is broken with SHA256 but the test failures only surface with transactions
+enabled. For more details, see: https://gitlab.com/gitlab-org/gitaly/-/issues/5662`)
+ }
+
t.Parallel()
ctx := testhelper.Context(t)
@@ -104,6 +110,16 @@ func TestCreateRepositoryFromSnapshot_success(t *testing.T) {
repoAbsolutePath := filepath.Join(cfg.Storages[0].Path, gittest.GetReplicaPath(t, ctx, cfg, repo))
require.DirExists(t, repoAbsolutePath)
for _, entry := range entries {
+ if testhelper.IsWALEnabled() {
+ // The transaction manager repacks the objects from the snapshot into a single pack file.
+ // Skip asserting the exact objects on the disk and assert afterwards that the objects
+ // from the source repo exist in the target repo.
+ switch {
+ case strings.HasPrefix(entry, "./objects"):
+ continue
+ }
+ }
+
if strings.HasSuffix(entry, "/") {
require.DirExists(t, filepath.Join(repoAbsolutePath, entry), "directory %q not unpacked", entry)
} else {
@@ -113,6 +129,14 @@ func TestCreateRepositoryFromSnapshot_success(t *testing.T) {
// hooks/ and config were excluded, but the RPC should create them
require.FileExists(t, filepath.Join(repoAbsolutePath, "config"), "Config file not created")
+
+ targetPath, err := config.NewLocator(cfg).GetRepoPath(gittest.RewrittenRepository(t, ctx, cfg, repo))
+ require.NoError(t, err)
+
+ require.ElementsMatch(t,
+ gittest.ListObjects(t, cfg, sourceRepoPath),
+ gittest.ListObjects(t, cfg, targetPath),
+ )
}
func TestCreateRepositoryFromSnapshot_repositoryExists(t *testing.T) {
diff --git a/internal/gitaly/service/repository/create_repository_from_url_test.go b/internal/gitaly/service/repository/create_repository_from_url_test.go
index b7573f0da..02c71223b 100644
--- a/internal/gitaly/service/repository/create_repository_from_url_test.go
+++ b/internal/gitaly/service/repository/create_repository_from_url_test.go
@@ -106,9 +106,10 @@ func TestCreateRepositoryFromURL_existingTarget(t *testing.T) {
ctx := testhelper.Context(t)
testCases := []struct {
- desc string
- repoPath string
- isDir bool
+ desc string
+ repoPath string
+ isDir bool
+ skipWithWAL string
}{
{
desc: "target is a directory",
@@ -117,11 +118,18 @@ func TestCreateRepositoryFromURL_existingTarget(t *testing.T) {
{
desc: "target is a file",
isDir: false,
+ skipWithWAL: `
+The transaction commit fails as the TransactionManager fails to initialize with the state
+directory being a file. This is testing storage details rather than the RPC implementation
+testing of this scenario should be left to the relevant package.
+`,
},
}
for _, testCase := range testCases {
t.Run(testCase.desc, func(t *testing.T) {
+ testhelper.SkipWithWAL(t, testCase.skipWithWAL)
+
cfg, client := setupRepositoryService(t)
importedRepo := &gitalypb.Repository{
diff --git a/internal/gitaly/service/repository/fsck_test.go b/internal/gitaly/service/repository/fsck_test.go
index 93156fbaf..0d78d1327 100644
--- a/internal/gitaly/service/repository/fsck_test.go
+++ b/internal/gitaly/service/repository/fsck_test.go
@@ -1,7 +1,6 @@
package repository
import (
- "fmt"
"os"
"path/filepath"
"strings"
@@ -14,8 +13,6 @@ import (
"gitlab.com/gitlab-org/gitaly/v16/internal/structerr"
"gitlab.com/gitlab-org/gitaly/v16/internal/testhelper"
"gitlab.com/gitlab-org/gitaly/v16/proto/go/gitalypb"
- "google.golang.org/grpc/codes"
- "google.golang.org/grpc/status"
)
func TestFsck(t *testing.T) {
@@ -80,15 +77,6 @@ func TestFsck(t *testing.T) {
require.NoError(t, os.RemoveAll(filepath.Join(repoPath, "objects")))
require.NoError(t, os.WriteFile(filepath.Join(repoPath, "objects"), nil, perm.SharedFile))
- if testhelper.IsWALEnabled() {
- return setupData{
- repo: repo,
- expectedErr: status.Error(codes.Internal,
- fmt.Sprintf("begin transaction: get partition: assign partition ID: get alternate partition ID: read alternates file: open: open %s/objects/info/alternates: not a directory", repoPath),
- ),
- }
- }
-
return setupData{
repo: repo,
requireResponse: func(actual *gitalypb.FsckResponse) {
diff --git a/internal/gitaly/service/smarthttp/receive_pack_test.go b/internal/gitaly/service/smarthttp/receive_pack_test.go
index 2e503ae70..f5ef91820 100644
--- a/internal/gitaly/service/smarthttp/receive_pack_test.go
+++ b/internal/gitaly/service/smarthttp/receive_pack_test.go
@@ -130,7 +130,7 @@ func TestPostReceivePack_successful(t *testing.T) {
var transactionID storage.TransactionID
if testhelper.IsWALEnabled() {
- transactionID = 1
+ transactionID = 2
}
require.Equal(t, git.HooksPayload{
diff --git a/internal/gitaly/service/ssh/receive_pack_test.go b/internal/gitaly/service/ssh/receive_pack_test.go
index 83ddb0bb4..923b5d2e2 100644
--- a/internal/gitaly/service/ssh/receive_pack_test.go
+++ b/internal/gitaly/service/ssh/receive_pack_test.go
@@ -199,7 +199,7 @@ func TestReceivePack_success(t *testing.T) {
var transactionID storage.TransactionID
if testhelper.IsWALEnabled() {
- transactionID = 2
+ transactionID = 4
}
require.Equal(t, git.HooksPayload{
diff --git a/internal/gitaly/storage/storagemgr/middleware.go b/internal/gitaly/storage/storagemgr/middleware.go
index 1ed793387..101376463 100644
--- a/internal/gitaly/storage/storagemgr/middleware.go
+++ b/internal/gitaly/storage/storagemgr/middleware.go
@@ -37,13 +37,8 @@ var nonTransactionalRPCs = map[string]struct{}{
"/gitaly.ObjectPoolService/GetObjectPool": {},
// GetSnapshot is testing logic with object pools as well.
"/gitaly.RepositoryService/GetSnapshot": {},
-
- // Repository creations are not yet handled through the WAL.
- "/gitaly.RepositoryService/CreateRepository": {},
- "/gitaly.RepositoryService/CreateRepositoryFromURL": {},
- "/gitaly.RepositoryService/CreateRepositoryFromBundle": {},
- "/gitaly.RepositoryService/CreateFork": {},
- "/gitaly.RepositoryService/CreateRepositoryFromSnapshot": {},
+ // CreateFork relies on object pools.
+ "/gitaly.RepositoryService/CreateFork": {},
// ReplicateRepository is replicating the attributes and config which the
// WAL won't support. This is pending removal of their replication.