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>2022-08-01 11:54:11 +0300
committerSami Hiltunen <shiltunen@gitlab.com>2022-08-01 11:54:11 +0300
commitc61904befa4e882cc3990db5f9021c4a559cd8f1 (patch)
tree0804b95f8491c8f9964050d29f6201d52b8919b8
parent32e72fea8fc391e76812cd1cde295b12c34d5174 (diff)
parent018958fb1cb4a8550d15bbd096b55fdee9f2a3b4 (diff)
Merge branch 'pks-objectpool-fetch-df-conflict' into 'master'
objectpool: Fix conflicting references when fetching into pools Closes #4373 See merge request gitlab-org/gitaly!4745
-rw-r--r--internal/git/gittest/commit.go20
-rw-r--r--internal/git/gittest/commit_test.go14
-rw-r--r--internal/git/gittest/delta_islands.go31
-rw-r--r--internal/git/housekeeping/objects_test.go2
-rw-r--r--internal/git/objectpool/fetch.go141
-rw-r--r--internal/git/objectpool/fetch_test.go52
-rw-r--r--internal/gitaly/service/objectpool/fetch_into_object_pool_test.go228
-rw-r--r--internal/gitaly/service/repository/gc_test.go2
-rw-r--r--internal/gitaly/service/repository/repack_test.go2
-rw-r--r--internal/metadata/featureflag/ff_fetch_into_object_pool_prune_refs.go11
-rw-r--r--internal/praefect/protoregistry/find_oid_test.go1
-rw-r--r--proto/go/gitalypb/objectpool.pb.go144
-rw-r--r--proto/go/gitalypb/objectpool_grpc.pb.go10
-rw-r--r--proto/objectpool.proto20
-rw-r--r--ruby/proto/gitaly/objectpool_pb.rb1
-rw-r--r--ruby/proto/gitaly/objectpool_services_pb.rb5
16 files changed, 534 insertions, 150 deletions
diff --git a/internal/git/gittest/commit.go b/internal/git/gittest/commit.go
index 526e73545..3ffc1035a 100644
--- a/internal/git/gittest/commit.go
+++ b/internal/git/gittest/commit.go
@@ -32,7 +32,7 @@ var (
)
type writeCommitConfig struct {
- branch string
+ reference string
parents []git.ObjectID
authorDate time.Time
authorName string
@@ -47,14 +47,20 @@ type writeCommitConfig struct {
// WriteCommitOption is an option which can be passed to WriteCommit.
type WriteCommitOption func(*writeCommitConfig)
-// WithBranch is an option for WriteCommit which will cause it to update the update the given branch
-// name to the new commit.
-func WithBranch(branch string) WriteCommitOption {
+// WithReference is an option for WriteCommit which will cause it to update the given reference to
+// point to the new commit. This function requires the fully-qualified reference name.
+func WithReference(reference string) WriteCommitOption {
return func(cfg *writeCommitConfig) {
- cfg.branch = branch
+ cfg.reference = reference
}
}
+// WithBranch is an option for WriteCommit which will cause it to update the given branch name to
+// the new commit.
+func WithBranch(branch string) WriteCommitOption {
+ return WithReference("refs/heads/" + branch)
+}
+
// WithMessage is an option for WriteCommit which will set the commit message.
func WithMessage(message string) WriteCommitOption {
return func(cfg *writeCommitConfig) {
@@ -218,10 +224,10 @@ func WriteCommit(t testing.TB, cfg config.Cfg, repoPath string, opts ...WriteCom
oid, err := DefaultObjectHash.FromHex(text.ChompBytes(stdout))
require.NoError(t, err)
- if writeCommitConfig.branch != "" {
+ if writeCommitConfig.reference != "" {
ExecOpts(t, cfg, ExecConfig{
Env: env,
- }, "-C", repoPath, "update-ref", "refs/heads/"+writeCommitConfig.branch, oid.String())
+ }, "-C", repoPath, "update-ref", writeCommitConfig.reference, oid.String())
}
return oid
diff --git a/internal/git/gittest/commit_test.go b/internal/git/gittest/commit_test.go
index d1f279554..b4fa49a17 100644
--- a/internal/git/gittest/commit_test.go
+++ b/internal/git/gittest/commit_test.go
@@ -125,6 +125,20 @@ func TestWriteCommit(t *testing.T) {
expectedRevUpdate: "refs/heads/foo",
},
{
+ desc: "with reference",
+ opts: []WriteCommitOption{
+ WithReference("refs/custom/namespace"),
+ },
+ expectedCommit: strings.Join([]string{
+ "tree " + DefaultObjectHash.EmptyTreeOID.String(),
+ "author " + DefaultCommitterSignature,
+ "committer " + DefaultCommitterSignature,
+ "",
+ "message",
+ }, "\n"),
+ expectedRevUpdate: "refs/custom/namespace",
+ },
+ {
desc: "with tree entry",
opts: []WriteCommitOption{
WithTreeEntries(treeEntryA),
diff --git a/internal/git/gittest/delta_islands.go b/internal/git/gittest/delta_islands.go
index c582d0813..485afe95e 100644
--- a/internal/git/gittest/delta_islands.go
+++ b/internal/git/gittest/delta_islands.go
@@ -11,8 +11,19 @@ import (
)
// TestDeltaIslands checks whether functions that repack objects in a repository correctly set up
-// delta islands. Based on https://github.com/git/git/blob/master/t/t5320-delta-islands.sh.
-func TestDeltaIslands(t *testing.T, cfg config.Cfg, repoPath string, isPoolRepo bool, repack func() error) {
+// delta islands. Based on https://github.com/git/git/blob/master/t/t5320-delta-islands.sh. Note
+// that this function accepts two different repository paths: one repo to modify that shall grow the
+// new references and objects, and one repository that we ultimately end up repacking. In the
+// general case these should refer to the same repository, but for object pools these may be the
+// pool member and the pool, respectively.
+func TestDeltaIslands(
+ t *testing.T,
+ cfg config.Cfg,
+ repoPathToModify string,
+ repoPathToRepack string,
+ isPoolRepo bool,
+ repack func() error,
+) {
t.Helper()
// Create blobs that we expect Git to use delta compression on.
@@ -32,25 +43,25 @@ func TestDeltaIslands(t *testing.T, cfg config.Cfg, repoPath string, isPoolRepo
}
// Make the first two blobs reachable via references that are part of the delta island.
- blob1ID := commitBlob(t, cfg, repoPath, refsPrefix+"/heads/branch1", blob1)
- blob2ID := commitBlob(t, cfg, repoPath, refsPrefix+"/tags/tag2", blob2)
+ blob1ID := commitBlob(t, cfg, repoPathToModify, refsPrefix+"/heads/branch1", blob1)
+ blob2ID := commitBlob(t, cfg, repoPathToModify, refsPrefix+"/tags/tag2", blob2)
// The bad blob will only be reachable via a reference that is not covered by a delta
// island. Because of that it should be excluded from delta chains in the main island.
- badBlobID := commitBlob(t, cfg, repoPath, refsPrefix+"/bad/ref3", badBlob)
+ badBlobID := commitBlob(t, cfg, repoPathToModify, refsPrefix+"/bad/ref3", badBlob)
// Repack all objects into a single pack so that we can verify that delta chains are built
// by Git as expected. Most notably, we don't use the delta islands here yet and thus the
// delta base for both blob1 and blob2 should be the bad blob.
- Exec(t, cfg, "-C", repoPath, "repack", "-ad")
- require.Equal(t, badBlobID, deltaBase(t, cfg, repoPath, blob1ID), "expect blob 1 delta base to be bad blob after test setup")
- require.Equal(t, badBlobID, deltaBase(t, cfg, repoPath, blob2ID), "expect blob 2 delta base to be bad blob after test setup")
+ Exec(t, cfg, "-C", repoPathToModify, "repack", "-ad")
+ require.Equal(t, badBlobID, deltaBase(t, cfg, repoPathToModify, blob1ID), "expect blob 1 delta base to be bad blob after test setup")
+ require.Equal(t, badBlobID, deltaBase(t, cfg, repoPathToModify, blob2ID), "expect blob 2 delta base to be bad blob after test setup")
// Now we run the repacking function provided to us by the caller. We expect it to use delta
// chains, and thus neither of the two blobs should use the bad blob as delta base.
require.NoError(t, repack(), "repack after delta island setup")
- require.Equal(t, blob2ID, deltaBase(t, cfg, repoPath, blob1ID), "blob 1 delta base should be blob 2 after repack")
- require.Equal(t, DefaultObjectHash.ZeroOID.String(), deltaBase(t, cfg, repoPath, blob2ID), "blob 2 should not be delta compressed after repack")
+ require.Equal(t, blob2ID, deltaBase(t, cfg, repoPathToRepack, blob1ID), "blob 1 delta base should be blob 2 after repack")
+ require.Equal(t, DefaultObjectHash.ZeroOID.String(), deltaBase(t, cfg, repoPathToRepack, blob2ID), "blob 2 should not be delta compressed after repack")
}
func commitBlob(t *testing.T, cfg config.Cfg, repoPath, ref string, content string) string {
diff --git a/internal/git/housekeeping/objects_test.go b/internal/git/housekeeping/objects_test.go
index 6156c65bf..156a58ff2 100644
--- a/internal/git/housekeeping/objects_test.go
+++ b/internal/git/housekeeping/objects_test.go
@@ -60,7 +60,7 @@ func TestRepackObjects(t *testing.T) {
})
repo := localrepo.NewTestRepo(t, cfg, repoProto)
- gittest.TestDeltaIslands(t, cfg, repoPath, IsPoolRepository(repoProto), func() error {
+ gittest.TestDeltaIslands(t, cfg, repoPath, repoPath, IsPoolRepository(repoProto), func() error {
return RepackObjects(ctx, repo, RepackObjectsConfig{
FullRepack: true,
})
diff --git a/internal/git/objectpool/fetch.go b/internal/git/objectpool/fetch.go
index 2c491d9a0..0ee7d6d0a 100644
--- a/internal/git/objectpool/fetch.go
+++ b/internal/git/objectpool/fetch.go
@@ -16,8 +16,13 @@ import (
"gitlab.com/gitlab-org/gitaly/v15/internal/git"
"gitlab.com/gitlab-org/gitaly/v15/internal/git/localrepo"
"gitlab.com/gitlab-org/gitaly/v15/internal/git/updateref"
+ "gitlab.com/gitlab-org/gitaly/v15/internal/gitaly/transaction"
+ "gitlab.com/gitlab-org/gitaly/v15/internal/metadata/featureflag"
+ "gitlab.com/gitlab-org/gitaly/v15/internal/transaction/voting"
)
+var objectPoolRefspec = fmt.Sprintf("+refs/*:%s/*", git.ObjectPoolRefNamespace)
+
// FetchFromOrigin initializes the pool and fetches the objects from its origin repository
func (o *ObjectPool) FetchFromOrigin(ctx context.Context, origin *localrepo.Repo) error {
if err := o.Init(ctx); err != nil {
@@ -37,7 +42,28 @@ func (o *ObjectPool) FetchFromOrigin(ctx context.Context, origin *localrepo.Repo
return fmt.Errorf("computing stats before fetch: %w", err)
}
- refSpec := fmt.Sprintf("+refs/*:%s/*", git.ObjectPoolRefNamespace)
+ // Ideally we wouldn't want to prune old references at all so that we can keep alive all
+ // objects without having to create loads of dangling references. But unfortunately keeping
+ // around old refs can lead to D/F conflicts between old references that have since
+ // been deleted in the pool and new references that have been added in the pool member we're
+ // fetching from. E.g. if we have the old reference `refs/heads/branch` and the pool member
+ // has replaced that since with a new reference `refs/heads/branch/conflict` then
+ // the fetch would now always fail because of that conflict.
+ //
+ // Due to the lack of an alternative to resolve that conflict we are thus forced to enable
+ // pruning. This isn't too bad given that we know to keep alive the old objects via dangling
+ // refs anyway, but I'd sleep easier if we didn't have to do this.
+ //
+ // Note that we need to perform the pruning separately from the fetch: if the fetch is using
+ // `--atomic` and `--prune` together then it still wouldn't be able to recover from the D/F
+ // conflict. So we first to a preliminary prune that only prunes refs without fetching
+ // objects yet to avoid that scenario.
+ if featureflag.FetchIntoObjectPoolPruneRefs.IsEnabled(ctx) {
+ if err := o.pruneReferences(ctx, origin); err != nil {
+ return fmt.Errorf("pruning references: %w", err)
+ }
+ }
+
var stderr bytes.Buffer
if err := o.Repo.ExecAndWait(ctx,
git.SubCmd{
@@ -54,7 +80,7 @@ func (o *ObjectPool) FetchFromOrigin(ctx context.Context, origin *localrepo.Repo
// references.
git.Flag{Name: "--no-write-fetch-head"},
},
- Args: []string{originPath, refSpec},
+ Args: []string{originPath, objectPoolRefspec},
},
git.WithRefTxHook(o.Repo),
git.WithStderr(&stderr),
@@ -78,6 +104,117 @@ func (o *ObjectPool) FetchFromOrigin(ctx context.Context, origin *localrepo.Repo
return nil
}
+// pruneReferences prunes any references that have been deleted in the origin repository.
+func (o *ObjectPool) pruneReferences(ctx context.Context, origin *localrepo.Repo) error {
+ originPath, err := origin.Path()
+ if err != nil {
+ return fmt.Errorf("computing origin repo's path: %w", err)
+ }
+
+ // Ideally, we'd just use `git remote prune` directly. But unfortunately, this command does
+ // not support atomic updates, but will instead use a separate reference transaction for
+ // updating the packed-refs file and for updating each of the loose references. This can be
+ // really expensive in case we are about to prune a lot of references given that every time,
+ // the reference-transaction hook needs to vote on the deletion and reach quorum.
+ //
+ // Instead we ask for a dry-run, parse the output and queue up every reference into a
+ // git-update-ref(1) process. While ugly, it works around the performance issues.
+ prune, err := o.Repo.Exec(ctx,
+ git.SubSubCmd{
+ Name: "remote",
+ Action: "prune",
+ Args: []string{"origin"},
+ Flags: []git.Option{
+ git.Flag{Name: "--dry-run"},
+ },
+ },
+ git.WithConfig(git.ConfigPair{Key: "remote.origin.url", Value: originPath}),
+ git.WithConfig(git.ConfigPair{Key: "remote.origin.fetch", Value: objectPoolRefspec}),
+ // This is a dry-run, only, so we don't have to enable hooks.
+ git.WithDisabledHooks(),
+ )
+ if err != nil {
+ return fmt.Errorf("spawning prune: %w", err)
+ }
+
+ updater, err := updateref.New(ctx, o.Repo)
+ if err != nil {
+ return fmt.Errorf("spawning updater: %w", err)
+ }
+
+ // We need to manually compute a vote because all deletions we queue up here are
+ // force-deletions. We are forced to filter out force-deletions because these may also
+ // happen when evicting references from the packed-refs file.
+ voteHash := voting.NewVoteHash()
+
+ scanner := bufio.NewScanner(prune)
+ for scanner.Scan() {
+ line := scanner.Bytes()
+
+ // We need to skip the first two lines that represent the header of git-remote(1)'s
+ // output. While we should ideally just use a state machine here, it doesn't feel
+ // worth it given that the output is comparatively simple and given that the pruned
+ // branches are distinguished by a special prefix.
+ switch {
+ case bytes.Equal(line, []byte("Pruning origin")):
+ continue
+ case bytes.HasPrefix(line, []byte("URL: ")):
+ continue
+ case bytes.HasPrefix(line, []byte(" * [would prune] ")):
+ // The references announced by git-remote(1) only have the remote's name as
+ // prefix, which is "origin". We thus have to reassemble the complete name
+ // of every reference here.
+ deletedRef := "refs/remotes/" + string(bytes.TrimPrefix(line, []byte(" * [would prune] ")))
+
+ if _, err := io.Copy(voteHash, strings.NewReader(fmt.Sprintf("%[1]s %[1]s %s\n", git.ObjectHashSHA1.ZeroOID, deletedRef))); err != nil {
+ return fmt.Errorf("hashing reference deletion: %w", err)
+ }
+
+ if err := updater.Delete(git.ReferenceName(deletedRef)); err != nil {
+ return fmt.Errorf("queueing ref for deletion: %w", err)
+ }
+ default:
+ return fmt.Errorf("unexpected line: %q", line)
+ }
+ }
+
+ if err := scanner.Err(); err != nil {
+ return fmt.Errorf("scanning deleted refs: %w", err)
+ }
+
+ if err := prune.Wait(); err != nil {
+ return fmt.Errorf("waiting for prune: %w", err)
+ }
+
+ vote, err := voteHash.Vote()
+ if err != nil {
+ return fmt.Errorf("computing vote: %w", err)
+ }
+
+ // Prepare references so that they're locked and cannot be written by any concurrent
+ // processes. This also verifies that we can indeed delete the references.
+ if err := updater.Prepare(); err != nil {
+ return fmt.Errorf("preparing deletion of references: %w", err)
+ }
+
+ // Vote on the references we're about to delete.
+ if err := transaction.VoteOnContext(ctx, o.txManager, vote, voting.Prepared); err != nil {
+ return fmt.Errorf("preparational vote on pruned references: %w", err)
+ }
+
+ // Commit the pruned references to disk so that the change gets applied.
+ if err := updater.Commit(); err != nil {
+ return fmt.Errorf("deleting references: %w", err)
+ }
+
+ // And then confirm that we actually deleted the references.
+ if err := transaction.VoteOnContext(ctx, o.txManager, vote, voting.Committed); err != nil {
+ return fmt.Errorf("preparational vote on pruned references: %w", err)
+ }
+
+ return nil
+}
+
const danglingObjectNamespace = "refs/dangling/"
// rescueDanglingObjects creates refs for all dangling objects if finds
diff --git a/internal/git/objectpool/fetch_test.go b/internal/git/objectpool/fetch_test.go
index 514927555..2df9a769d 100644
--- a/internal/git/objectpool/fetch_test.go
+++ b/internal/git/objectpool/fetch_test.go
@@ -3,6 +3,7 @@
package objectpool
import (
+ "context"
"fmt"
"os"
"path/filepath"
@@ -16,13 +17,18 @@ import (
"gitlab.com/gitlab-org/gitaly/v15/internal/git/localrepo"
"gitlab.com/gitlab-org/gitaly/v15/internal/gitaly/config"
"gitlab.com/gitlab-org/gitaly/v15/internal/helper/text"
+ "gitlab.com/gitlab-org/gitaly/v15/internal/metadata/featureflag"
"gitlab.com/gitlab-org/gitaly/v15/internal/testhelper"
)
func TestFetchFromOrigin_dangling(t *testing.T) {
t.Parallel()
+ testhelper.NewFeatureSets(featureflag.FetchIntoObjectPoolPruneRefs).Run(t, testFetchFromOriginDangling)
+}
+
+func testFetchFromOriginDangling(t *testing.T, ctx context.Context) {
+ t.Parallel()
- ctx := testhelper.Context(t)
cfg, pool, repoProto := setupObjectPool(t, ctx)
repo := localrepo.NewTestRepo(t, cfg, repoProto)
@@ -92,8 +98,12 @@ func TestFetchFromOrigin_dangling(t *testing.T) {
func TestFetchFromOrigin_fsck(t *testing.T) {
t.Parallel()
+ testhelper.NewFeatureSets(featureflag.FetchIntoObjectPoolPruneRefs).Run(t, testFetchFromOriginFsck)
+}
+
+func testFetchFromOriginFsck(t *testing.T, ctx context.Context) {
+ t.Parallel()
- ctx := testhelper.Context(t)
cfg, pool, repoProto := setupObjectPool(t, ctx)
repo := localrepo.NewTestRepo(t, cfg, repoProto)
repoPath := filepath.Join(cfg.Storages[0].Path, repo.GetRelativePath())
@@ -117,8 +127,12 @@ func TestFetchFromOrigin_fsck(t *testing.T) {
func TestFetchFromOrigin_deltaIslands(t *testing.T) {
t.Parallel()
+ testhelper.NewFeatureSets(featureflag.FetchIntoObjectPoolPruneRefs).Run(t, testFetchFromOriginDeltaIslands)
+}
+
+func testFetchFromOriginDeltaIslands(t *testing.T, ctx context.Context) {
+ t.Parallel()
- ctx := testhelper.Context(t)
cfg, pool, repoProto := setupObjectPool(t, ctx)
repo := localrepo.NewTestRepo(t, cfg, repoProto)
@@ -128,24 +142,22 @@ func TestFetchFromOrigin_deltaIslands(t *testing.T) {
require.NoError(t, pool.FetchFromOrigin(ctx, repo), "seed pool")
require.NoError(t, pool.Link(ctx, repo))
- gittest.TestDeltaIslands(t, cfg, pool.FullPath(), true, func() error {
- // The first fetch has already fetched all objects into the pool repository, so
- // there is nothing new to fetch anymore. Consequentially, FetchFromOrigin doesn't
- // alter the object database and thus OptimizeRepository would notice that nothing
- // needs to be optimized.
- //
- // We thus write a new commit into the pool member's repository so that we end up
- // with two packfiles after the fetch.
- gittest.WriteCommit(t, cfg, repoPath, gittest.WithBranch("changed-ref"))
-
+ // The setup of delta islands is done in the normal repository, and thus we pass `false`
+ // for `isPoolRepo`. Verification whether we correctly handle repacking though happens in
+ // the pool repository.
+ gittest.TestDeltaIslands(t, cfg, repoPath, pool.FullPath(), false, func() error {
return pool.FetchFromOrigin(ctx, repo)
})
}
func TestFetchFromOrigin_bitmapHashCache(t *testing.T) {
t.Parallel()
+ testhelper.NewFeatureSets(featureflag.FetchIntoObjectPoolPruneRefs).Run(t, testFetchFromOriginBitmapHashCache)
+}
+
+func testFetchFromOriginBitmapHashCache(t *testing.T, ctx context.Context) {
+ t.Parallel()
- ctx := testhelper.Context(t)
cfg, pool, repoProto := setupObjectPool(t, ctx)
repo := localrepo.NewTestRepo(t, cfg, repoProto)
@@ -170,8 +182,12 @@ func TestFetchFromOrigin_bitmapHashCache(t *testing.T) {
func TestFetchFromOrigin_refUpdates(t *testing.T) {
t.Parallel()
+ testhelper.NewFeatureSets(featureflag.FetchIntoObjectPoolPruneRefs).Run(t, testFetchFromOriginRefUpdates)
+}
+
+func testFetchFromOriginRefUpdates(t *testing.T, ctx context.Context) {
+ t.Parallel()
- ctx := testhelper.Context(t)
cfg, pool, repoProto := setupObjectPool(t, ctx)
repo := localrepo.NewTestRepo(t, cfg, repoProto)
repoPath := filepath.Join(cfg.Storages[0].Path, repo.GetRelativePath())
@@ -223,8 +239,12 @@ func TestFetchFromOrigin_refUpdates(t *testing.T) {
func TestFetchFromOrigin_refs(t *testing.T) {
t.Parallel()
+ testhelper.NewFeatureSets(featureflag.FetchIntoObjectPoolPruneRefs).Run(t, testFetchFromOriginRefs)
+}
+
+func testFetchFromOriginRefs(t *testing.T, ctx context.Context) {
+ t.Parallel()
- ctx := testhelper.Context(t)
cfg, pool, _ := setupObjectPool(t, ctx)
poolPath := pool.FullPath()
diff --git a/internal/gitaly/service/objectpool/fetch_into_object_pool_test.go b/internal/gitaly/service/objectpool/fetch_into_object_pool_test.go
index c9c6aaa10..03262537b 100644
--- a/internal/gitaly/service/objectpool/fetch_into_object_pool_test.go
+++ b/internal/gitaly/service/objectpool/fetch_into_object_pool_test.go
@@ -3,8 +3,11 @@
package objectpool
import (
+ "context"
+ "fmt"
"os"
"path/filepath"
+ "sync"
"testing"
"time"
@@ -19,21 +22,30 @@ import (
"gitlab.com/gitlab-org/gitaly/v15/internal/git/housekeeping"
"gitlab.com/gitlab-org/gitaly/v15/internal/gitaly/config"
"gitlab.com/gitlab-org/gitaly/v15/internal/gitaly/transaction"
+ "gitlab.com/gitlab-org/gitaly/v15/internal/helper"
+ "gitlab.com/gitlab-org/gitaly/v15/internal/metadata"
+ "gitlab.com/gitlab-org/gitaly/v15/internal/metadata/featureflag"
"gitlab.com/gitlab-org/gitaly/v15/internal/testhelper"
"gitlab.com/gitlab-org/gitaly/v15/internal/testhelper/testcfg"
"gitlab.com/gitlab-org/gitaly/v15/internal/testhelper/testserver"
+ "gitlab.com/gitlab-org/gitaly/v15/internal/transaction/txinfo"
+ "gitlab.com/gitlab-org/gitaly/v15/internal/transaction/voting"
"gitlab.com/gitlab-org/gitaly/v15/proto/go/gitalypb"
"gitlab.com/gitlab-org/labkit/log"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/credentials/insecure"
- "google.golang.org/grpc/status"
+ "google.golang.org/grpc/peer"
)
func TestFetchIntoObjectPool_Success(t *testing.T) {
t.Parallel()
+ testhelper.NewFeatureSets(featureflag.FetchIntoObjectPoolPruneRefs).Run(t, testFetchIntoObjectPoolSuccess)
+}
+
+func testFetchIntoObjectPoolSuccess(t *testing.T, ctx context.Context) {
+ t.Parallel()
- ctx := testhelper.Context(t)
cfg, repo, repoPath, locator, client := setup(ctx, t)
repoCommit := gittest.WriteCommit(t, cfg, repoPath, gittest.WithBranch(t.Name()))
@@ -48,7 +60,6 @@ func TestFetchIntoObjectPool_Success(t *testing.T) {
req := &gitalypb.FetchIntoObjectPoolRequest{
ObjectPool: pool.ToProto(),
Origin: repo,
- Repack: true,
}
_, err = client.FetchIntoObjectPool(ctx, req)
@@ -85,16 +96,37 @@ func TestFetchIntoObjectPool_Success(t *testing.T) {
require.Error(t, err, "Expected refs/heads/broken to be deleted")
}
-func TestFetchIntoObjectPool_hooks(t *testing.T) {
- cfg := testcfg.Build(t)
- gitCmdFactory := gittest.NewCommandFactory(t, cfg, git.WithHooksPath(testhelper.TempDir(t)))
+func TestFetchIntoObjectPool_transactional(t *testing.T) {
+ t.Parallel()
+ testhelper.NewFeatureSets(featureflag.FetchIntoObjectPoolPruneRefs).Run(t, testFetchIntoObjectPoolTransactional)
+}
- cfg.SocketPath = runObjectPoolServer(t, cfg, config.NewLocator(cfg), testhelper.NewDiscardingLogger(t), testserver.WithGitCommandFactory(gitCmdFactory))
+func testFetchIntoObjectPoolTransactional(t *testing.T, ctx context.Context) {
+ t.Parallel()
- ctx := testhelper.Context(t)
- repo, _ := gittest.CreateRepository(ctx, t, cfg, gittest.CreateRepositoryConfig{
- Seed: gittest.SeedGitLabTest,
- })
+ var votes []voting.Vote
+ var votesMutex sync.Mutex
+ txManager := transaction.MockManager{
+ VoteFn: func(_ context.Context, _ txinfo.Transaction, vote voting.Vote, _ voting.Phase) error {
+ votesMutex.Lock()
+ defer votesMutex.Unlock()
+ votes = append(votes, vote)
+ return nil
+ },
+ }
+
+ cfg := testcfg.Build(t)
+ cfg.SocketPath = runObjectPoolServer(
+ t, cfg, config.NewLocator(cfg),
+ testhelper.NewDiscardingLogger(t),
+ testserver.WithTransactionManager(&txManager),
+ // We need to disable Praefect given that we replace transactions with our own logic
+ // here.
+ testserver.WithDisablePraefect(),
+ )
+ testcfg.BuildGitalyHooks(t, cfg)
+
+ repo, repoPath := gittest.CreateRepository(ctx, t, cfg)
conn, err := grpc.Dial(cfg.SocketPath, grpc.WithTransportCredentials(insecure.NewCredentials()))
require.NoError(t, err)
@@ -109,24 +141,109 @@ func TestFetchIntoObjectPool_hooks(t *testing.T) {
})
require.NoError(t, err)
- // Set up a custom reference-transaction hook which simply exits failure. This asserts that
- // the RPC doesn't invoke any reference-transaction.
- testhelper.WriteExecutable(t, filepath.Join(gitCmdFactory.HooksPath(ctx), "reference-transaction"), []byte("#!/bin/sh\nexit 1\n"))
+ // CreateObjectPool has a bug because it will leave the configuration of the origin remote
+ // in the gitconfig. This will get cleaned up at a later point by our housekeeping logic, so
+ // it doesn't hurt much in the first place to have it. But the cleanup logic would trigger
+ // another transactional vote which we want to avoid, so we simply unset the configuration
+ // here.
+ gittest.Exec(t, cfg, "-C", pool.FullPath(), "config", "--unset", "remote.origin.url")
- req := &gitalypb.FetchIntoObjectPoolRequest{
- ObjectPool: pool.ToProto(),
- Origin: repo,
- Repack: true,
- }
+ // Inject transaction information so that FetchInotObjectPool knows to perform
+ // transactional voting.
+ ctx, err = txinfo.InjectTransaction(peer.NewContext(ctx, &peer.Peer{}), 1, "node", true)
+ require.NoError(t, err)
+ ctx = metadata.IncomingToOutgoing(ctx)
- _, err = client.FetchIntoObjectPool(ctx, req)
- testhelper.RequireGrpcError(t, status.Error(codes.Internal, "fetch into object pool: exit status 128, stderr: \"fatal: ref updates aborted by hook\\n\""), err)
+ t.Run("without changed data", func(t *testing.T) {
+ votes = nil
+
+ _, err = client.FetchIntoObjectPool(ctx, &gitalypb.FetchIntoObjectPoolRequest{
+ ObjectPool: pool.ToProto(),
+ Origin: repo,
+ })
+ require.NoError(t, err)
+
+ if featureflag.FetchIntoObjectPoolPruneRefs.IsEnabled(ctx) {
+ require.Equal(t, []voting.Vote{
+ // We expect to see two votes that demonstrate we're voting on no deleted
+ // references.
+ voting.VoteFromData(nil), voting.VoteFromData(nil),
+ // It is a bug though that we don't have a vote on the unchanged references
+ // in git-fetch(1).
+ }, votes)
+ } else {
+ require.Nil(t, votes)
+ }
+ })
+
+ t.Run("with a new reference", func(t *testing.T) {
+ votes = nil
+
+ // Create a new reference that we'd in fact fetch into the object pool so that we
+ // know that something will be voted on.
+ repoCommit := gittest.WriteCommit(t, cfg, repoPath, gittest.WithParents(), gittest.WithBranch("new-branch"))
+
+ _, err = client.FetchIntoObjectPool(ctx, &gitalypb.FetchIntoObjectPoolRequest{
+ ObjectPool: pool.ToProto(),
+ Origin: repo,
+ })
+ require.NoError(t, err)
+
+ vote := voting.VoteFromData([]byte(fmt.Sprintf(
+ "%s %s refs/remotes/origin/heads/new-branch\n", git.ObjectHashSHA1.ZeroOID, repoCommit,
+ )))
+ if featureflag.FetchIntoObjectPoolPruneRefs.IsEnabled(ctx) {
+ require.Equal(t, []voting.Vote{
+ // The first two votes stem from the fact that we're voting on no
+ // deleted references.
+ voting.VoteFromData(nil), voting.VoteFromData(nil),
+ // And the other two votes are from the new branch we pull in.
+ vote, vote,
+ }, votes)
+ } else {
+ require.Equal(t, []voting.Vote{vote, vote}, votes)
+ }
+ })
+
+ t.Run("with a stale reference in pool", func(t *testing.T) {
+ votes = nil
+
+ reference := "refs/remotes/origin/heads/to-be-pruned"
+
+ // Create a commit in the pool repository itself. Right now, we don't touch this
+ // commit at all, but this will change in one of the next commits.
+ gittest.WriteCommit(t, cfg, pool.FullPath(), gittest.WithParents(), gittest.WithReference(reference))
+
+ _, err = client.FetchIntoObjectPool(ctx, &gitalypb.FetchIntoObjectPoolRequest{
+ ObjectPool: pool.ToProto(),
+ Origin: repo,
+ })
+ require.NoError(t, err)
+
+ if featureflag.FetchIntoObjectPoolPruneRefs.IsEnabled(ctx) {
+ // We expect a single vote on the reference we have deleted.
+ vote := voting.VoteFromData([]byte(fmt.Sprintf(
+ "%[1]s %[1]s %s\n", git.ObjectHashSHA1.ZeroOID, reference,
+ )))
+ require.Equal(t, []voting.Vote{vote, vote}, votes)
+ } else {
+ require.Nil(t, votes)
+ }
+
+ exists, err := pool.Repo.HasRevision(ctx, git.Revision(reference))
+ require.NoError(t, err)
+ require.Equal(t, exists, featureflag.FetchIntoObjectPoolPruneRefs.IsDisabled(ctx))
+ })
}
func TestFetchIntoObjectPool_CollectLogStatistics(t *testing.T) {
t.Parallel()
+ testhelper.NewFeatureSets(featureflag.FetchIntoObjectPoolPruneRefs).Run(t, testFetchIntoObjectPoolCollectLogStatistics)
+}
+
+func testFetchIntoObjectPoolCollectLogStatistics(t *testing.T, ctx context.Context) {
+ t.Parallel()
- ctx := testhelper.Context(t)
cfg := testcfg.Build(t)
testcfg.BuildGitalyHooks(t, cfg)
@@ -155,7 +272,6 @@ func TestFetchIntoObjectPool_CollectLogStatistics(t *testing.T) {
req := &gitalypb.FetchIntoObjectPoolRequest{
ObjectPool: pool.ToProto(),
Origin: repo,
- Repack: true,
}
_, err = client.FetchIntoObjectPool(ctx, req)
@@ -252,3 +368,69 @@ func TestFetchIntoObjectPool_Failure(t *testing.T) {
})
}
}
+
+func TestFetchIntoObjectPool_dfConflict(t *testing.T) {
+ t.Parallel()
+ testhelper.NewFeatureSets(featureflag.FetchIntoObjectPoolPruneRefs).Run(t, testFetchIntoObjectPoolDfConflict)
+}
+
+func testFetchIntoObjectPoolDfConflict(t *testing.T, ctx context.Context) {
+ t.Parallel()
+
+ cfg, repo, repoPath, _, client := setup(ctx, t)
+
+ pool := initObjectPool(t, cfg, cfg.Storages[0])
+ _, err := client.CreateObjectPool(ctx, &gitalypb.CreateObjectPoolRequest{
+ ObjectPool: pool.ToProto(),
+ Origin: repo,
+ })
+ require.NoError(t, err)
+
+ gittest.WriteCommit(t, cfg, repoPath, gittest.WithBranch("branch"))
+
+ // Perform an initial fetch into the object pool with the given object that exists in the
+ // pool member's repository.
+ _, err = client.FetchIntoObjectPool(ctx, &gitalypb.FetchIntoObjectPoolRequest{
+ ObjectPool: pool.ToProto(),
+ Origin: repo,
+ })
+ require.NoError(t, err)
+
+ // Now we delete the reference in the pool member and create a new reference that has the
+ // same prefix, but is stored in a subdirectory. This will create a D/F conflict.
+ gittest.Exec(t, cfg, "-C", repoPath, "update-ref", "-d", "refs/heads/branch")
+ gittest.WriteCommit(t, cfg, repoPath, gittest.WithBranch("branch/conflict"))
+
+ gitVersion, err := gittest.NewCommandFactory(t, cfg).GitVersion(ctx)
+ require.NoError(t, err)
+
+ // Due to a bug in old Git versions we may get an unexpected exit status.
+ expectedExitStatus := 254
+ if !gitVersion.FlushesUpdaterefStatus() {
+ expectedExitStatus = 1
+ }
+
+ // Verify that we can still fetch into the object pool regardless of the D/F conflict. While
+ // it is not possible to store both references at the same time due to the conflict, we
+ // should know to delete the old conflicting reference and replace it with the new one.
+ _, err = client.FetchIntoObjectPool(ctx, &gitalypb.FetchIntoObjectPoolRequest{
+ ObjectPool: pool.ToProto(),
+ Origin: repo,
+ })
+ if featureflag.FetchIntoObjectPoolPruneRefs.IsEnabled(ctx) {
+ require.NoError(t, err)
+
+ poolPath, err := config.NewLocator(cfg).GetRepoPath(gittest.RewrittenRepository(ctx, t, cfg, pool.ToProto().GetRepository()))
+ require.NoError(t, err)
+
+ // Verify that the conflicting reference exists now.
+ gittest.Exec(t, cfg, "-C", poolPath, "rev-parse", "refs/remotes/origin/heads/branch/conflict")
+ } else {
+ // But right now it fails due to a bug.
+ testhelper.RequireGrpcError(t, helper.ErrInternalf(
+ "fetch into object pool: exit status %d, stderr: %q",
+ expectedExitStatus,
+ "error: cannot lock ref 'refs/remotes/origin/heads/branch/conflict': 'refs/remotes/origin/heads/branch' exists; cannot create 'refs/remotes/origin/heads/branch/conflict'\n",
+ ), err)
+ }
+}
diff --git a/internal/gitaly/service/repository/gc_test.go b/internal/gitaly/service/repository/gc_test.go
index feaeab138..3dcdb3a02 100644
--- a/internal/gitaly/service/repository/gc_test.go
+++ b/internal/gitaly/service/repository/gc_test.go
@@ -536,7 +536,7 @@ func TestGarbageCollectDeltaIslands(t *testing.T) {
ctx := testhelper.Context(t)
cfg, repo, repoPath, client := setupRepositoryService(ctx, t)
- gittest.TestDeltaIslands(t, cfg, repoPath, false, func() error {
+ gittest.TestDeltaIslands(t, cfg, repoPath, repoPath, false, func() error {
//nolint:staticcheck
_, err := client.GarbageCollect(ctx, &gitalypb.GarbageCollectRequest{Repository: repo})
return err
diff --git a/internal/gitaly/service/repository/repack_test.go b/internal/gitaly/service/repository/repack_test.go
index e89f25cb9..eb3d8b912 100644
--- a/internal/gitaly/service/repository/repack_test.go
+++ b/internal/gitaly/service/repository/repack_test.go
@@ -300,7 +300,7 @@ func TestRepackFullDeltaIslands(t *testing.T) {
ctx := testhelper.Context(t)
cfg, repo, repoPath, client := setupRepositoryService(ctx, t)
- gittest.TestDeltaIslands(t, cfg, repoPath, false, func() error {
+ gittest.TestDeltaIslands(t, cfg, repoPath, repoPath, false, func() error {
//nolint:staticcheck
_, err := client.RepackFull(ctx, &gitalypb.RepackFullRequest{Repository: repo})
return err
diff --git a/internal/metadata/featureflag/ff_fetch_into_object_pool_prune_refs.go b/internal/metadata/featureflag/ff_fetch_into_object_pool_prune_refs.go
new file mode 100644
index 000000000..21d8eb3f0
--- /dev/null
+++ b/internal/metadata/featureflag/ff_fetch_into_object_pool_prune_refs.go
@@ -0,0 +1,11 @@
+package featureflag
+
+// FetchIntoObjectPoolPruneRefs enables pruning of references in object pools. This is required in
+// order to fix cases where updating pools doesn't work anymore due to preexisting references
+// conflicting with new references in the pool member.
+var FetchIntoObjectPoolPruneRefs = NewFeatureFlag(
+ "fetch_into_object_pool_prune_refs",
+ "v15.3.0",
+ "https://gitlab.com/gitlab-org/gitaly/-/issues/4394",
+ false,
+)
diff --git a/internal/praefect/protoregistry/find_oid_test.go b/internal/praefect/protoregistry/find_oid_test.go
index a6dbcf745..d4b01f25a 100644
--- a/internal/praefect/protoregistry/find_oid_test.go
+++ b/internal/praefect/protoregistry/find_oid_test.go
@@ -78,7 +78,6 @@ func TestProtoRegistryTargetRepo(t *testing.T) {
pbMsg: &gitalypb.FetchIntoObjectPoolRequest{
Origin: testRepos[0],
ObjectPool: &gitalypb.ObjectPool{Repository: testRepos[1]},
- Repack: false,
},
expectRepo: testRepos[1],
expectAdditionalRepo: testRepos[0],
diff --git a/proto/go/gitalypb/objectpool.pb.go b/proto/go/gitalypb/objectpool.pb.go
index 3099253e4..6f052357b 100644
--- a/proto/go/gitalypb/objectpool.pb.go
+++ b/proto/go/gitalypb/objectpool.pb.go
@@ -480,18 +480,16 @@ func (*DisconnectGitAlternatesResponse) Descriptor() ([]byte, []int) {
return file_objectpool_proto_rawDescGZIP(), []int{9}
}
-// This comment is left unintentionally blank.
+// FetchIntoObjectPoolRequest is a request for the FetchIntoObjectPool RPC.
type FetchIntoObjectPoolRequest struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
- // This comment is left unintentionally blank.
+ // Origin is the repository to fetch changes from.
Origin *Repository `protobuf:"bytes,1,opt,name=origin,proto3" json:"origin,omitempty"`
- // This comment is left unintentionally blank.
+ // ObjectPool is the repository to fetch changes into.
ObjectPool *ObjectPool `protobuf:"bytes,2,opt,name=object_pool,json=objectPool,proto3" json:"object_pool,omitempty"`
- // This comment is left unintentionally blank.
- Repack bool `protobuf:"varint,3,opt,name=repack,proto3" json:"repack,omitempty"`
}
func (x *FetchIntoObjectPoolRequest) Reset() {
@@ -540,14 +538,7 @@ func (x *FetchIntoObjectPoolRequest) GetObjectPool() *ObjectPool {
return nil
}
-func (x *FetchIntoObjectPoolRequest) GetRepack() bool {
- if x != nil {
- return x.Repack
- }
- return false
-}
-
-// This comment is left unintentionally blank.
+// FetchIntoObjectPoolResponse is a response for the FetchIntoObjectPool RPC.
type FetchIntoObjectPoolResponse struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -735,7 +726,7 @@ var file_objectpool_proto_rawDesc = []byte{
0x79, 0x42, 0x04, 0x98, 0xc6, 0x2c, 0x01, 0x52, 0x0a, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74,
0x6f, 0x72, 0x79, 0x22, 0x21, 0x0a, 0x1f, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63,
0x74, 0x47, 0x69, 0x74, 0x41, 0x6c, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x65, 0x73, 0x52, 0x65,
- 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0xa1, 0x01, 0x0a, 0x1a, 0x46, 0x65, 0x74, 0x63, 0x68,
+ 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x97, 0x01, 0x0a, 0x1a, 0x46, 0x65, 0x74, 0x63, 0x68,
0x49, 0x6e, 0x74, 0x6f, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x50, 0x6f, 0x6f, 0x6c, 0x52, 0x65,
0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x30, 0x0a, 0x06, 0x6f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x18,
0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x52,
@@ -744,71 +735,70 @@ var file_objectpool_proto_rawDesc = []byte{
0x74, 0x5f, 0x70, 0x6f, 0x6f, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x67,
0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x50, 0x6f, 0x6f, 0x6c,
0x42, 0x04, 0x98, 0xc6, 0x2c, 0x01, 0x52, 0x0a, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x50, 0x6f,
- 0x6f, 0x6c, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x70, 0x61, 0x63, 0x6b, 0x18, 0x03, 0x20, 0x01,
- 0x28, 0x08, 0x52, 0x06, 0x72, 0x65, 0x70, 0x61, 0x63, 0x6b, 0x22, 0x1d, 0x0a, 0x1b, 0x46, 0x65,
- 0x74, 0x63, 0x68, 0x49, 0x6e, 0x74, 0x6f, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x50, 0x6f, 0x6f,
- 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x50, 0x0a, 0x14, 0x47, 0x65, 0x74,
- 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x50, 0x6f, 0x6f, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
- 0x74, 0x12, 0x38, 0x0a, 0x0a, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x18,
- 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x52,
- 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x42, 0x04, 0x98, 0xc6, 0x2c, 0x01, 0x52,
- 0x0a, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x22, 0x4c, 0x0a, 0x15, 0x47,
- 0x65, 0x74, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x50, 0x6f, 0x6f, 0x6c, 0x52, 0x65, 0x73, 0x70,
- 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x33, 0x0a, 0x0b, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x70,
- 0x6f, 0x6f, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x67, 0x69, 0x74, 0x61,
- 0x6c, 0x79, 0x2e, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x50, 0x6f, 0x6f, 0x6c, 0x52, 0x0a, 0x6f,
- 0x62, 0x6a, 0x65, 0x63, 0x74, 0x50, 0x6f, 0x6f, 0x6c, 0x32, 0xee, 0x05, 0x0a, 0x11, 0x4f, 0x62,
- 0x6a, 0x65, 0x63, 0x74, 0x50, 0x6f, 0x6f, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12,
- 0x5d, 0x0a, 0x10, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x50,
- 0x6f, 0x6f, 0x6c, 0x12, 0x1f, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x43, 0x72, 0x65,
- 0x61, 0x74, 0x65, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x50, 0x6f, 0x6f, 0x6c, 0x52, 0x65, 0x71,
- 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x43, 0x72,
- 0x65, 0x61, 0x74, 0x65, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x50, 0x6f, 0x6f, 0x6c, 0x52, 0x65,
- 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x01, 0x12, 0x5d,
- 0x0a, 0x10, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x50, 0x6f,
- 0x6f, 0x6c, 0x12, 0x1f, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x44, 0x65, 0x6c, 0x65,
- 0x74, 0x65, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x50, 0x6f, 0x6f, 0x6c, 0x52, 0x65, 0x71, 0x75,
- 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x44, 0x65, 0x6c,
- 0x65, 0x74, 0x65, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x50, 0x6f, 0x6f, 0x6c, 0x52, 0x65, 0x73,
- 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x01, 0x12, 0x7b, 0x0a,
- 0x1a, 0x4c, 0x69, 0x6e, 0x6b, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x54,
- 0x6f, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x50, 0x6f, 0x6f, 0x6c, 0x12, 0x29, 0x2e, 0x67, 0x69,
- 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x4c, 0x69, 0x6e, 0x6b, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74,
- 0x6f, 0x72, 0x79, 0x54, 0x6f, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x50, 0x6f, 0x6f, 0x6c, 0x52,
- 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e,
- 0x4c, 0x69, 0x6e, 0x6b, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x54, 0x6f,
- 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x50, 0x6f, 0x6f, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
- 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x01, 0x12, 0x6c, 0x0a, 0x15, 0x52, 0x65,
- 0x64, 0x75, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74,
- 0x6f, 0x72, 0x79, 0x12, 0x24, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x52, 0x65, 0x64,
- 0x75, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f,
- 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x25, 0x2e, 0x67, 0x69, 0x74, 0x61,
- 0x6c, 0x79, 0x2e, 0x52, 0x65, 0x64, 0x75, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x65,
- 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65,
- 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x01, 0x12, 0x72, 0x0a, 0x17, 0x44, 0x69, 0x73, 0x63,
- 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x47, 0x69, 0x74, 0x41, 0x6c, 0x74, 0x65, 0x72, 0x6e, 0x61,
- 0x74, 0x65, 0x73, 0x12, 0x26, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x44, 0x69, 0x73,
- 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x47, 0x69, 0x74, 0x41, 0x6c, 0x74, 0x65, 0x72, 0x6e,
- 0x61, 0x74, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x67, 0x69,
- 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x47,
- 0x69, 0x74, 0x41, 0x6c, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70,
- 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x01, 0x12, 0x66, 0x0a, 0x13,
- 0x46, 0x65, 0x74, 0x63, 0x68, 0x49, 0x6e, 0x74, 0x6f, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x50,
- 0x6f, 0x6f, 0x6c, 0x12, 0x22, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x46, 0x65, 0x74,
- 0x63, 0x68, 0x49, 0x6e, 0x74, 0x6f, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x50, 0x6f, 0x6f, 0x6c,
- 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79,
- 0x2e, 0x46, 0x65, 0x74, 0x63, 0x68, 0x49, 0x6e, 0x74, 0x6f, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74,
+ 0x6f, 0x6c, 0x4a, 0x04, 0x08, 0x03, 0x10, 0x04, 0x52, 0x06, 0x72, 0x65, 0x70, 0x61, 0x63, 0x6b,
+ 0x22, 0x1d, 0x0a, 0x1b, 0x46, 0x65, 0x74, 0x63, 0x68, 0x49, 0x6e, 0x74, 0x6f, 0x4f, 0x62, 0x6a,
+ 0x65, 0x63, 0x74, 0x50, 0x6f, 0x6f, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22,
+ 0x50, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x50, 0x6f, 0x6f, 0x6c,
+ 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x38, 0x0a, 0x0a, 0x72, 0x65, 0x70, 0x6f, 0x73,
+ 0x69, 0x74, 0x6f, 0x72, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x67, 0x69,
+ 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x42,
+ 0x04, 0x98, 0xc6, 0x2c, 0x01, 0x52, 0x0a, 0x72, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72,
+ 0x79, 0x22, 0x4c, 0x0a, 0x15, 0x47, 0x65, 0x74, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x50, 0x6f,
+ 0x6f, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x33, 0x0a, 0x0b, 0x6f, 0x62,
+ 0x6a, 0x65, 0x63, 0x74, 0x5f, 0x70, 0x6f, 0x6f, 0x6c, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32,
+ 0x12, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x50,
+ 0x6f, 0x6f, 0x6c, 0x52, 0x0a, 0x6f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x50, 0x6f, 0x6f, 0x6c, 0x32,
+ 0xee, 0x05, 0x0a, 0x11, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x50, 0x6f, 0x6f, 0x6c, 0x53, 0x65,
+ 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x5d, 0x0a, 0x10, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4f,
+ 0x62, 0x6a, 0x65, 0x63, 0x74, 0x50, 0x6f, 0x6f, 0x6c, 0x12, 0x1f, 0x2e, 0x67, 0x69, 0x74, 0x61,
+ 0x6c, 0x79, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x50,
+ 0x6f, 0x6f, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x67, 0x69, 0x74,
+ 0x61, 0x6c, 0x79, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74,
0x50, 0x6f, 0x6f, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97,
- 0x28, 0x02, 0x08, 0x01, 0x12, 0x54, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x4f, 0x62, 0x6a, 0x65, 0x63,
- 0x74, 0x50, 0x6f, 0x6f, 0x6c, 0x12, 0x1c, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x47,
- 0x65, 0x74, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x50, 0x6f, 0x6f, 0x6c, 0x52, 0x65, 0x71, 0x75,
- 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x47, 0x65, 0x74,
+ 0x28, 0x02, 0x08, 0x01, 0x12, 0x5d, 0x0a, 0x10, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4f, 0x62,
+ 0x6a, 0x65, 0x63, 0x74, 0x50, 0x6f, 0x6f, 0x6c, 0x12, 0x1f, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c,
+ 0x79, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x50, 0x6f,
+ 0x6f, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x20, 0x2e, 0x67, 0x69, 0x74, 0x61,
+ 0x6c, 0x79, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x50,
+ 0x6f, 0x6f, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28,
+ 0x02, 0x08, 0x01, 0x12, 0x7b, 0x0a, 0x1a, 0x4c, 0x69, 0x6e, 0x6b, 0x52, 0x65, 0x70, 0x6f, 0x73,
+ 0x69, 0x74, 0x6f, 0x72, 0x79, 0x54, 0x6f, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x50, 0x6f, 0x6f,
+ 0x6c, 0x12, 0x29, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x4c, 0x69, 0x6e, 0x6b, 0x52,
+ 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x54, 0x6f, 0x4f, 0x62, 0x6a, 0x65, 0x63,
+ 0x74, 0x50, 0x6f, 0x6f, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2a, 0x2e, 0x67,
+ 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x4c, 0x69, 0x6e, 0x6b, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69,
+ 0x74, 0x6f, 0x72, 0x79, 0x54, 0x6f, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x50, 0x6f, 0x6f, 0x6c,
+ 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x01,
+ 0x12, 0x6c, 0x0a, 0x15, 0x52, 0x65, 0x64, 0x75, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x65, 0x52,
+ 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x12, 0x24, 0x2e, 0x67, 0x69, 0x74, 0x61,
+ 0x6c, 0x79, 0x2e, 0x52, 0x65, 0x64, 0x75, 0x70, 0x6c, 0x69, 0x63, 0x61, 0x74, 0x65, 0x52, 0x65,
+ 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a,
+ 0x25, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x52, 0x65, 0x64, 0x75, 0x70, 0x6c, 0x69,
+ 0x63, 0x61, 0x74, 0x65, 0x52, 0x65, 0x70, 0x6f, 0x73, 0x69, 0x74, 0x6f, 0x72, 0x79, 0x52, 0x65,
+ 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x01, 0x12, 0x72,
+ 0x0a, 0x17, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x47, 0x69, 0x74, 0x41,
+ 0x6c, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x65, 0x73, 0x12, 0x26, 0x2e, 0x67, 0x69, 0x74, 0x61,
+ 0x6c, 0x79, 0x2e, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x47, 0x69, 0x74,
+ 0x41, 0x6c, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x74, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73,
+ 0x74, 0x1a, 0x27, 0x2e, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x44, 0x69, 0x73, 0x63, 0x6f,
+ 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x47, 0x69, 0x74, 0x41, 0x6c, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x74,
+ 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02,
+ 0x08, 0x01, 0x12, 0x66, 0x0a, 0x13, 0x46, 0x65, 0x74, 0x63, 0x68, 0x49, 0x6e, 0x74, 0x6f, 0x4f,
+ 0x62, 0x6a, 0x65, 0x63, 0x74, 0x50, 0x6f, 0x6f, 0x6c, 0x12, 0x22, 0x2e, 0x67, 0x69, 0x74, 0x61,
+ 0x6c, 0x79, 0x2e, 0x46, 0x65, 0x74, 0x63, 0x68, 0x49, 0x6e, 0x74, 0x6f, 0x4f, 0x62, 0x6a, 0x65,
+ 0x63, 0x74, 0x50, 0x6f, 0x6f, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e,
+ 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x46, 0x65, 0x74, 0x63, 0x68, 0x49, 0x6e, 0x74, 0x6f,
0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x50, 0x6f, 0x6f, 0x6c, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e,
- 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x02, 0x42, 0x34, 0x5a, 0x32, 0x67, 0x69,
- 0x74, 0x6c, 0x61, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67, 0x69, 0x74, 0x6c, 0x61, 0x62, 0x2d,
- 0x6f, 0x72, 0x67, 0x2f, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x2f, 0x76, 0x31, 0x35, 0x2f, 0x70,
- 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x2f, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79, 0x70, 0x62,
- 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
+ 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x01, 0x12, 0x54, 0x0a, 0x0d, 0x47, 0x65,
+ 0x74, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x50, 0x6f, 0x6f, 0x6c, 0x12, 0x1c, 0x2e, 0x67, 0x69,
+ 0x74, 0x61, 0x6c, 0x79, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x50, 0x6f,
+ 0x6f, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x67, 0x69, 0x74, 0x61,
+ 0x6c, 0x79, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74, 0x50, 0x6f, 0x6f, 0x6c,
+ 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x06, 0xfa, 0x97, 0x28, 0x02, 0x08, 0x02,
+ 0x42, 0x34, 0x5a, 0x32, 0x67, 0x69, 0x74, 0x6c, 0x61, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x67,
+ 0x69, 0x74, 0x6c, 0x61, 0x62, 0x2d, 0x6f, 0x72, 0x67, 0x2f, 0x67, 0x69, 0x74, 0x61, 0x6c, 0x79,
+ 0x2f, 0x76, 0x31, 0x35, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x2f, 0x67, 0x6f, 0x2f, 0x67, 0x69,
+ 0x74, 0x61, 0x6c, 0x79, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33,
}
var (
diff --git a/proto/go/gitalypb/objectpool_grpc.pb.go b/proto/go/gitalypb/objectpool_grpc.pb.go
index e4b1038c6..4acbe3aa1 100644
--- a/proto/go/gitalypb/objectpool_grpc.pb.go
+++ b/proto/go/gitalypb/objectpool_grpc.pb.go
@@ -32,7 +32,10 @@ type ObjectPoolServiceClient interface {
ReduplicateRepository(ctx context.Context, in *ReduplicateRepositoryRequest, opts ...grpc.CallOption) (*ReduplicateRepositoryResponse, error)
// This comment is left unintentionally blank.
DisconnectGitAlternates(ctx context.Context, in *DisconnectGitAlternatesRequest, opts ...grpc.CallOption) (*DisconnectGitAlternatesResponse, error)
- // This comment is left unintentionally blank.
+ // FetchIntoObjectPool fetches all references from a pool member into an object pool so that
+ // objects shared between this repository and other pool members can be deduplicated. This RPC
+ // will perform housekeeping tasks after the object pool has been updated to ensure that the pool
+ // is in an optimal state.
FetchIntoObjectPool(ctx context.Context, in *FetchIntoObjectPoolRequest, opts ...grpc.CallOption) (*FetchIntoObjectPoolResponse, error)
// This comment is left unintentionally blank.
GetObjectPool(ctx context.Context, in *GetObjectPoolRequest, opts ...grpc.CallOption) (*GetObjectPoolResponse, error)
@@ -123,7 +126,10 @@ type ObjectPoolServiceServer interface {
ReduplicateRepository(context.Context, *ReduplicateRepositoryRequest) (*ReduplicateRepositoryResponse, error)
// This comment is left unintentionally blank.
DisconnectGitAlternates(context.Context, *DisconnectGitAlternatesRequest) (*DisconnectGitAlternatesResponse, error)
- // This comment is left unintentionally blank.
+ // FetchIntoObjectPool fetches all references from a pool member into an object pool so that
+ // objects shared between this repository and other pool members can be deduplicated. This RPC
+ // will perform housekeeping tasks after the object pool has been updated to ensure that the pool
+ // is in an optimal state.
FetchIntoObjectPool(context.Context, *FetchIntoObjectPoolRequest) (*FetchIntoObjectPoolResponse, error)
// This comment is left unintentionally blank.
GetObjectPool(context.Context, *GetObjectPoolRequest) (*GetObjectPoolResponse, error)
diff --git a/proto/objectpool.proto b/proto/objectpool.proto
index 4d9a36d23..9634f62c7 100644
--- a/proto/objectpool.proto
+++ b/proto/objectpool.proto
@@ -48,7 +48,10 @@ service ObjectPoolService {
};
}
- // This comment is left unintentionally blank.
+ // FetchIntoObjectPool fetches all references from a pool member into an object pool so that
+ // objects shared between this repository and other pool members can be deduplicated. This RPC
+ // will perform housekeeping tasks after the object pool has been updated to ensure that the pool
+ // is in an optimal state.
rpc FetchIntoObjectPool(FetchIntoObjectPoolRequest) returns (FetchIntoObjectPoolResponse) {
option (op_type) = {
op: MUTATOR
@@ -120,17 +123,20 @@ message DisconnectGitAlternatesRequest {
message DisconnectGitAlternatesResponse {
}
-// This comment is left unintentionally blank.
+// FetchIntoObjectPoolRequest is a request for the FetchIntoObjectPool RPC.
message FetchIntoObjectPoolRequest {
- // This comment is left unintentionally blank.
+ // Origin is the repository to fetch changes from.
Repository origin = 1 [(additional_repository)=true];
- // This comment is left unintentionally blank.
+ // ObjectPool is the repository to fetch changes into.
ObjectPool object_pool = 2 [(target_repository)=true];
- // This comment is left unintentionally blank.
- bool repack = 3;
+
+ // Repack had the intent to control whether FetchIntoObjectPool would perform housekeeping tasks
+ // in the pool repository or not. This flag wasn't ever honored though and is thus doing nothing.
+ reserved 3;
+ reserved "repack";
}
-// This comment is left unintentionally blank.
+// FetchIntoObjectPoolResponse is a response for the FetchIntoObjectPool RPC.
message FetchIntoObjectPoolResponse {
}
diff --git a/ruby/proto/gitaly/objectpool_pb.rb b/ruby/proto/gitaly/objectpool_pb.rb
index ebbe7fa8f..f022a19d6 100644
--- a/ruby/proto/gitaly/objectpool_pb.rb
+++ b/ruby/proto/gitaly/objectpool_pb.rb
@@ -37,7 +37,6 @@ Google::Protobuf::DescriptorPool.generated_pool.build do
add_message "gitaly.FetchIntoObjectPoolRequest" do
optional :origin, :message, 1, "gitaly.Repository"
optional :object_pool, :message, 2, "gitaly.ObjectPool"
- optional :repack, :bool, 3
end
add_message "gitaly.FetchIntoObjectPoolResponse" do
end
diff --git a/ruby/proto/gitaly/objectpool_services_pb.rb b/ruby/proto/gitaly/objectpool_services_pb.rb
index d0529fa3d..fe12b6ab2 100644
--- a/ruby/proto/gitaly/objectpool_services_pb.rb
+++ b/ruby/proto/gitaly/objectpool_services_pb.rb
@@ -28,7 +28,10 @@ module Gitaly
rpc :ReduplicateRepository, ::Gitaly::ReduplicateRepositoryRequest, ::Gitaly::ReduplicateRepositoryResponse
# This comment is left unintentionally blank.
rpc :DisconnectGitAlternates, ::Gitaly::DisconnectGitAlternatesRequest, ::Gitaly::DisconnectGitAlternatesResponse
- # This comment is left unintentionally blank.
+ # FetchIntoObjectPool fetches all references from a pool member into an object pool so that
+ # objects shared between this repository and other pool members can be deduplicated. This RPC
+ # will perform housekeeping tasks after the object pool has been updated to ensure that the pool
+ # is in an optimal state.
rpc :FetchIntoObjectPool, ::Gitaly::FetchIntoObjectPoolRequest, ::Gitaly::FetchIntoObjectPoolResponse
# This comment is left unintentionally blank.
rpc :GetObjectPool, ::Gitaly::GetObjectPoolRequest, ::Gitaly::GetObjectPoolResponse