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:
Diffstat (limited to 'internal/gitaly/service/cleanup/rewrite_history.go')
-rw-r--r--internal/gitaly/service/cleanup/rewrite_history.go56
1 files changed, 56 insertions, 0 deletions
diff --git a/internal/gitaly/service/cleanup/rewrite_history.go b/internal/gitaly/service/cleanup/rewrite_history.go
index 85e45ab55..e6fceefc5 100644
--- a/internal/gitaly/service/cleanup/rewrite_history.go
+++ b/internal/gitaly/service/cleanup/rewrite_history.go
@@ -1,6 +1,7 @@
package cleanup
import (
+ "bufio"
"bytes"
"context"
"errors"
@@ -113,10 +114,31 @@ func (s *server) rewriteHistory(
return fmt.Errorf("setting up staging repo: %w", err)
}
+ // Check state of source repository prior to running filter-repo.
+ initialChecksum, err := checksumRepo(ctx, s.gitCmdFactory, repo)
+ if err != nil {
+ return fmt.Errorf("calculate initial checksum: %w", err)
+ }
+
if err := s.runFilterRepo(ctx, repo, stagingRepo, blobsToRemove, redactions); err != nil {
return fmt.Errorf("rewriting repository history: %w", err)
}
+ // Recheck repository state to confirm no changes occurred while filter-repo ran. The
+ // repository may not be fully rewritten if it was modified after git-fast-export(1)
+ // completed.
+ validationChecksum, err := checksumRepo(ctx, s.gitCmdFactory, repo)
+ if err != nil {
+ return fmt.Errorf("recalculate checksum: %w", err)
+ }
+
+ if initialChecksum != validationChecksum {
+ return structerr.NewAborted("source repository checksum altered").WithMetadataItems(
+ structerr.MetadataItem{Key: "initial checksum", Value: initialChecksum},
+ structerr.MetadataItem{Key: "validation checksum", Value: validationChecksum},
+ )
+ }
+
var stderr strings.Builder
if err := repo.ExecAndWait(ctx,
git.Command{
@@ -300,3 +322,37 @@ func writeArgFile(name string, dir string, input []byte) (string, error) {
return path, nil
}
+
+func checksumRepo(ctx context.Context, cmdFactory git.CommandFactory, repo *localrepo.Repo) (string, error) {
+ var stderr strings.Builder
+ cmd, err := cmdFactory.New(ctx, repo, git.Command{
+ Name: "show-ref",
+ Flags: []git.Option{
+ git.Flag{Name: "--head"},
+ },
+ }, git.WithSetupStdout(), git.WithStderr(&stderr))
+ if err != nil {
+ return "", fmt.Errorf("spawning git-show-ref: %w", err)
+ }
+
+ var checksum git.Checksum
+
+ scanner := bufio.NewScanner(cmd)
+ for scanner.Scan() {
+ checksum.AddBytes(scanner.Bytes())
+ }
+
+ if err := scanner.Err(); err != nil {
+ return "", err
+ }
+
+ if err := cmd.Wait(); err != nil {
+ var exitErr *exec.ExitError
+ if errors.As(err, &exitErr) {
+ return "", structerr.New("git-show-ref failed with exit code %d", exitErr.ExitCode()).WithMetadata("stderr", stderr.String())
+ }
+ return "", fmt.Errorf("running git-show-ref: %w", err)
+ }
+
+ return checksum.String(), nil
+}