aboutsummaryrefslogtreecommitdiff
path: root/internal/testgit/repo_pack_objects_is_thin.go
blob: afc704d17986cf5d492af46fbf11578dea87780c (about) (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
package testgit

import (
	"os/exec"
	"strings"
	"testing"
)

// PackObjectsIsThin reports whether git emits one thin pack for the given revs.
//
// It streams `git pack-objects --stdout --revs --thin` into `git index-pack
// --stdin` in one scratch bare repository. A failure in index-pack due to
// unresolved deltas is treated as confirmation that the emitted pack is thin.
func (testRepo *TestRepo) PackObjectsIsThin(tb testing.TB, revs []string) bool {
	tb.Helper()

	scratch := NewRepo(tb, RepoOptions{ObjectFormat: testRepo.algo, Bare: true})

	packArgs := []string{"pack-objects", "--stdout", "--revs", "--thin"}
	//nolint:noctx
	packCmd := exec.Command("git", packArgs...) //#nosec G204
	packCmd.Dir = testRepo.dir
	packCmd.Env = testRepo.env
	packCmd.Stdin = strings.NewReader(strings.Join(revs, "\n") + "\n")
	packStderr := &strings.Builder{}
	packCmd.Stderr = packStderr

	packStdout, err := packCmd.StdoutPipe()
	if err != nil {
		tb.Fatalf("git %v stdout pipe: %v", packArgs, err)
	}

	indexArgs := []string{"index-pack", "--stdin"}
	//nolint:noctx
	indexCmd := exec.Command("git", indexArgs...) //#nosec G204
	indexCmd.Dir = scratch.dir
	indexCmd.Env = scratch.env
	indexCmd.Stdin = packStdout
	indexStderr := &strings.Builder{}
	indexCmd.Stderr = indexStderr

	err = indexCmd.Start()
	if err != nil {
		tb.Fatalf("git %v start failed: %v", indexArgs, err)
	}

	err = packCmd.Start()
	if err != nil {
		_ = indexCmd.Process.Kill()
		_ = indexCmd.Wait()
		tb.Fatalf("git %v start failed: %v", packArgs, err)
	}

	packErr := packCmd.Wait()
	if packErr != nil {
		tb.Fatalf("git %v failed: %v\n%s", packArgs, packErr, packStderr.String())
	}

	indexErr := indexCmd.Wait()
	if indexErr == nil {
		return false
	}

	stderr := strings.ToLower(indexStderr.String())
	if strings.Contains(stderr, "unresolved") && strings.Contains(stderr, "delta") {
		return true
	}
	if strings.Contains(stderr, "missing") && strings.Contains(stderr, "base") {
		return true
	}

	tb.Fatalf("git %v failed unexpectedly: %v\n%s", indexArgs, indexErr, indexStderr.String())

	return false
}