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:
authorPatrick Steinhardt <psteinhardt@gitlab.com>2022-07-18 14:57:25 +0300
committerPatrick Steinhardt <psteinhardt@gitlab.com>2022-07-18 15:20:40 +0300
commit0df249b77e79dca793021edd273b6ef080a99f9b (patch)
treee6c8ff5ede05b8b5df63afc8b112c53908094a34
parentd8c2902881d174d6ebf79da2dff6a05f1b7721f0 (diff)
git: Add logic to detect object hash for a repositorypks-git-objectids-sha256
Add a new funciton `DetectObjectHash()` that, given a repository, can detect the object hash that's used by the repository by inspecting the `extensions.objectFormat` config entry.
-rw-r--r--internal/git/gittest/repo.go5
-rw-r--r--internal/git/object_id.go31
-rw-r--r--internal/git/object_id_test.go91
3 files changed, 127 insertions, 0 deletions
diff --git a/internal/git/gittest/repo.go b/internal/git/gittest/repo.go
index a9ff1e75e..1b4b08bb3 100644
--- a/internal/git/gittest/repo.go
+++ b/internal/git/gittest/repo.go
@@ -239,6 +239,8 @@ func RewrittenRepository(ctx context.Context, t testing.TB, cfg config.Cfg, repo
type InitRepoOpts struct {
// WithRelativePath determines the relative path of this repository.
WithRelativePath string
+ // ObjectFormat overrides the object format used by the repository.
+ ObjectFormat string
}
// InitRepo creates a new empty repository in the given storage. You can either pass no or exactly
@@ -260,6 +262,9 @@ func InitRepo(t testing.TB, cfg config.Cfg, storage config.Storage, opts ...Init
args := []string{"init", "--bare"}
args = append(args, initRepoExtraArgs...)
args = append(args, repoPath)
+ if opt.ObjectFormat != "" {
+ args = append(args, "--object-format", opt.ObjectFormat)
+ }
Exec(t, cfg, args...)
diff --git a/internal/git/object_id.go b/internal/git/object_id.go
index fcaf7225c..4d6083a12 100644
--- a/internal/git/object_id.go
+++ b/internal/git/object_id.go
@@ -1,10 +1,15 @@
package git
import (
+ "bytes"
+ "context"
"encoding/hex"
"errors"
"fmt"
"regexp"
+
+ "gitlab.com/gitlab-org/gitaly/v15/internal/command"
+ "gitlab.com/gitlab-org/gitaly/v15/internal/helper/text"
)
var (
@@ -36,6 +41,32 @@ type ObjectHash struct {
ZeroOID ObjectID
}
+// DetectObjectHash detects the object-hash used by the given repository.
+func DetectObjectHash(ctx context.Context, repoExecutor RepositoryExecutor) (ObjectHash, error) {
+ var stdout bytes.Buffer
+
+ if err := repoExecutor.ExecAndWait(ctx, SubCmd{
+ Name: "config",
+ Args: []string{"extensions.objectFormat"},
+ }, WithStdout(&stdout)); err != nil {
+ if status, ok := command.ExitStatus(err); ok && status == 1 {
+ return ObjectHashSHA1, nil
+ }
+
+ return ObjectHash{}, fmt.Errorf("reading object format: %w", err)
+ }
+
+ objectFormat := text.ChompBytes(stdout.Bytes())
+ switch objectFormat {
+ case "sha1":
+ return ObjectHashSHA1, nil
+ case "sha256":
+ return ObjectHashSHA256, nil
+ default:
+ return ObjectHash{}, fmt.Errorf("unknown object format: %q", objectFormat)
+ }
+}
+
// FromHex constructs a new ObjectID from the given hex representation of the object ID. Returns
// ErrInvalidObjectID if the given object ID is not valid.
func (h ObjectHash) FromHex(hex string) (ObjectID, error) {
diff --git a/internal/git/object_id_test.go b/internal/git/object_id_test.go
index f637fec3e..a6b62ffdc 100644
--- a/internal/git/object_id_test.go
+++ b/internal/git/object_id_test.go
@@ -6,13 +6,104 @@ import (
"bytes"
"encoding/hex"
"fmt"
+ "path/filepath"
"strings"
"testing"
"github.com/stretchr/testify/require"
"gitlab.com/gitlab-org/gitaly/v15/internal/git"
+ "gitlab.com/gitlab-org/gitaly/v15/internal/git/gittest"
+ "gitlab.com/gitlab-org/gitaly/v15/internal/git/localrepo"
+ "gitlab.com/gitlab-org/gitaly/v15/internal/helper/text"
+ "gitlab.com/gitlab-org/gitaly/v15/internal/testhelper"
+ "gitlab.com/gitlab-org/gitaly/v15/internal/testhelper/testcfg"
+ "gitlab.com/gitlab-org/gitaly/v15/proto/go/gitalypb"
)
+func TestDetectObjectHash(t *testing.T) {
+ cfg := testcfg.Build(t)
+ ctx := testhelper.Context(t)
+
+ for _, tc := range []struct {
+ desc string
+ setup func(t *testing.T) *gitalypb.Repository
+ expectedErr error
+ expectedHash git.ObjectHash
+ }{
+ {
+ desc: "defaults to SHA1",
+ setup: func(t *testing.T) *gitalypb.Repository {
+ repo, repoPath := gittest.InitRepo(t, cfg, cfg.Storages[0], gittest.InitRepoOpts{
+ ObjectFormat: "sha1",
+ })
+
+ // Verify that the repo doesn't explicitly mention it's using SHA1
+ // as object hash.
+ content := testhelper.MustReadFile(t, filepath.Join(repoPath, "config"))
+ require.NotContains(t, text.ChompBytes(content), "sha1")
+
+ return repo
+ },
+ expectedHash: git.ObjectHashSHA1,
+ },
+ {
+ desc: "explicitly set to SHA1",
+ setup: func(t *testing.T) *gitalypb.Repository {
+ repo, repoPath := gittest.InitRepo(t, cfg, cfg.Storages[0], gittest.InitRepoOpts{
+ ObjectFormat: "sha1",
+ })
+
+ // Explicitly set the object format to SHA1.
+ gittest.Exec(t, cfg, "-C", repoPath, "config", "extensions.objectFormat", "sha1")
+
+ return repo
+ },
+ expectedHash: git.ObjectHashSHA1,
+ },
+ {
+ desc: "explicitly set to SHA256",
+ setup: func(t *testing.T) *gitalypb.Repository {
+ repo, repoPath := gittest.InitRepo(t, cfg, cfg.Storages[0], gittest.InitRepoOpts{
+ ObjectFormat: "sha256",
+ })
+
+ require.Equal(t,
+ "sha256",
+ text.ChompBytes(gittest.Exec(t, cfg, "-C", repoPath, "config", "extensions.objectFormat")),
+ )
+
+ return repo
+ },
+ expectedHash: git.ObjectHashSHA256,
+ },
+ {
+ desc: "unknown hash",
+ setup: func(t *testing.T) *gitalypb.Repository {
+ repo, repoPath := gittest.InitRepo(t, cfg, cfg.Storages[0])
+
+ // Explicitly set the object format to something unknown.
+ gittest.Exec(t, cfg, "-C", repoPath, "config", "extensions.objectFormat", "blake2")
+
+ return repo
+ },
+ expectedErr: fmt.Errorf("reading object format: exit status 128"),
+ },
+ } {
+ t.Run(tc.desc, func(t *testing.T) {
+ repoProto := tc.setup(t)
+ repo := localrepo.NewTestRepo(t, cfg, repoProto)
+
+ hash, err := git.DetectObjectHash(ctx, repo)
+ if tc.expectedErr != nil {
+ require.EqualError(t, err, tc.expectedErr.Error())
+ } else {
+ require.NoError(t, err)
+ }
+ require.Equal(t, tc.expectedHash, hash)
+ })
+ }
+}
+
func TestObjectHash_ValidateHex(t *testing.T) {
for _, hash := range []struct {
desc string