Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Skip 'bad date' check for some imports #92

Merged
merged 6 commits into from
Dec 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ go-test-integration:

# Add our compiled `spokes-receive-pack` to the PATH while running tests:
PATH="$(CURDIR)/bin:$(PATH)" \
GIT_CONFIG_SYSTEM="$(CURDIR)/internal/integration/testdata/gitconfig" \
$(GO) test $(TESTINTEGRATIONFLAGS) $(TESTSUITE) 2>&1

@echo "$(M) disabling failpoints ..."
Expand Down
30 changes: 30 additions & 0 deletions internal/integration/integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,14 @@ committer Spokes Receive Pack <[email protected]> 1234567890 +0000
This commit object intentionally broken
`

var suiteDir string = func() string {
pwd, err := os.Getwd()
if err != nil {
panic(err)
}
return pwd
}()

type SpokesReceivePackTestSuite struct {
suite.Suite
localRepo, remoteRepo string
Expand Down Expand Up @@ -181,6 +189,28 @@ func (suite *SpokesReceivePackTestSuite) TestSpokesReceivePackHiddenRefs() {
"should partially fail")
}

func (suite *SpokesReceivePackTestSuite) TestBadDate() {
cmd := exec.Command("git", "-C", filepath.Join(suiteDir, "testdata/bad-date/sha1.git"),
"push", "--receive-pack=spokes-receive-pack-wrapper", suite.remoteRepo, "main")
out, err := cmd.CombinedOutput()
suite.T().Logf("$ %s\n%s", strings.Join(cmd.Args, " "), out)
assert.Error(suite.T(), err, "expect an error a repo with a malformed committer line in a commit")
assert.Contains(suite.T(), string(out), " badDate:", "should complain about a bad date")
}

func (suite *SpokesReceivePackTestSuite) TestBadDateAllowedWithOverride() {
cmd := exec.Command("git", "-C", filepath.Join(suiteDir, "testdata/bad-date/sha1.git"),
"push", "--receive-pack=spokes-receive-pack-wrapper", suite.remoteRepo, "main")
cmd.Env = append(os.Environ(),
"GIT_SOCKSTAT_VAR_is_importing=bool:true",
"GIT_SOCKSTAT_VAR_allow_baddate_in_import=bool:true",
)
out, err := cmd.CombinedOutput()
suite.T().Logf("$ %s\n%s", strings.Join(cmd.Args, " "), out)
assert.NoError(suite.T(), err, "expect the push to succeed")
assert.Contains(suite.T(), string(out), " badDate:", "should still complain about a bad date")
}

func (suite *SpokesReceivePackTestSuite) TestWithGovernor() {
started := make(chan any)
govSock, msgs, cleanup := startFakeGovernor(suite.T(), started, nil)
Expand Down
176 changes: 131 additions & 45 deletions internal/integration/missingobjects_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,37 +13,136 @@ import (
"testing"
"time"

"github.com/github/spokes-receive-pack/internal/objectformat"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)

func TestMissingObjects(t *testing.T) {
var info struct {

x := setUpMissingObjectsTestRepo(t)
testRepo := x.TestRepo
info := x.Info

ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()

srp := startSpokesReceivePack(ctx, t, testRepo)

refs, _, err := readAdv(srp.Out)
require.NoError(t, err)
assert.Equal(t, refs, map[string]string{
info.Ref: info.OldOID,
info.DelRef: info.OldOID,
})

// Send the pack that's missing a commit.
pack, err := os.Open("testdata/missing-objects/bad.pack")
require.NoError(t, err)
defer pack.Close()

writePushData(
t, srp,
[]refUpdate{
// Try to update the ref that's already there to commit C (but we won't
// push its parent and the remote doesn't have the parent either).
{info.OldOID, info.NewOID, info.Ref},
},
pack,
)

refStatus, unpackRes, _, err := readResult(t, srp.Out)
require.NoError(t, err)
assert.Equal(t, map[string]string{
info.Ref: "ng error processing packfiles: exit status 128",
}, refStatus)
assert.Equal(t, "unpack index-pack failed\n", unpackRes)
}

func TestDeleteAndUpdate(t *testing.T) {
const refToCreate = "refs/heads/new-branch"

x := setUpMissingObjectsTestRepo(t)
testRepo := x.TestRepo
info := x.Info

ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()

srp := startSpokesReceivePack(ctx, t, testRepo)

refs, _, err := readAdv(srp.Out)
require.NoError(t, err)
assert.Equal(t, refs, map[string]string{
info.Ref: info.OldOID,
info.DelRef: info.OldOID,
})

// Send the pack that's missing a commit.
pack, err := os.Open("testdata/missing-objects/empty.pack")
require.NoError(t, err)
defer pack.Close()

writePushData(
t, srp,
[]refUpdate{
// Try to create another ref with a commit that the remote already has.
{objectformat.NullOIDSHA1, info.OldOID, refToCreate},
// Try to delete a ref.
{info.OldOID, objectformat.NullOIDSHA1, info.DelRef},
},
pack,
)

refStatus, unpackRes, _, err := readResult(t, srp.Out)
require.NoError(t, err)
assert.Equal(t, map[string]string{
refToCreate: "ok",
info.DelRef: "ok",
}, refStatus)
assert.Equal(t, "unpack ok\n", unpackRes)
}

type missingObjectsTestInfo struct {
TestRepo string
Info struct {
OldOID string `json:"push_from"`
NewOID string `json:"push_to"`
Ref string `json:"ref"`
DelRef string `json:"extra_ref"`
}
}

func setUpMissingObjectsTestRepo(t *testing.T) missingObjectsTestInfo {
const (
remote = "testdata/missing-objects/remote.git"
badPack = "testdata/missing-objects/bad.pack"
infoFile = "testdata/missing-objects/info.json"
refToCreate = "refs/heads/new-branch"
remote = "testdata/missing-objects/remote.git"
badPack = "testdata/missing-objects/bad.pack"
infoFile = "testdata/missing-objects/info.json"
)

var res missingObjectsTestInfo

infoJSON, err := os.ReadFile(infoFile)
require.NoError(t, err)
require.NoError(t, json.Unmarshal(infoJSON, &info))
require.NoError(t, json.Unmarshal(infoJSON, &res.Info))

origin, err := filepath.Abs(remote)
require.NoError(t, err)

testRepo := t.TempDir()
requireRun(t, "git", "clone", "--mirror", origin, testRepo)
res.TestRepo = t.TempDir()
requireRun(t, "git", "clone", "--mirror", origin, res.TestRepo)

ctx, cancel := context.WithTimeout(context.Background(), time.Second)
defer cancel()
return res
}

type spokesReceivePackProcess struct {
Cmd *exec.Cmd
In io.WriteCloser
Out io.Reader
Err chan error
}

func startSpokesReceivePack(ctx context.Context, t *testing.T, testRepo string) spokesReceivePackProcess {
srp := exec.CommandContext(ctx, "spokes-receive-pack", ".")
srp.Dir = testRepo
srp.Env = append(os.Environ(),
Expand All @@ -59,47 +158,34 @@ func TestMissingObjects(t *testing.T) {

bufSRPOut := bufio.NewReader(srpOut)

refs, _, err := readAdv(bufSRPOut)
require.NoError(t, err)
assert.Equal(t, refs, map[string]string{
info.Ref: info.OldOID,
info.DelRef: info.OldOID,
})

// Try to update the ref that's already there to commit C (but we won't
// push its parent and the remote doesn't have the parent either).
require.NoError(t, writePktlinef(srpIn,
"%s %s %s\x00report-status report-status-v2 side-band-64k object-format=sha1\n",
info.OldOID, info.NewOID, info.Ref))
return spokesReceivePackProcess{
Cmd: srp,
In: srpIn,
Out: bufSRPOut,
Err: srpErr,
}
}

// Try to create another ref with a commit that the remote already has.
require.NoError(t, writePktlinef(srpIn,
"%040d %s %s",
0, info.OldOID, refToCreate))
type refUpdate struct {
OldOID, NewOID, Ref string
}

// Try to delete another ref.
require.NoError(t, writePktlinef(srpIn,
"%s %040d %s",
info.OldOID, 0, info.DelRef))
func writePushData(t *testing.T, srp spokesReceivePackProcess, updates []refUpdate, pack io.Reader) {
caps := "\x00report-status report-status-v2 side-band-64k object-format=sha1\n"
for _, up := range updates {
require.NoError(t, writePktlinef(srp.In,
"%s %s %s%s",
up.OldOID, up.NewOID, up.Ref,
caps))
caps = ""
}

_, err = srpIn.Write([]byte("0000"))
_, err := srp.In.Write([]byte("0000"))
require.NoError(t, err)

// Send the pack that's missing a commit.
pack, err := os.Open("testdata/missing-objects/bad.pack")
require.NoError(t, err)
if _, err := io.Copy(srpIn, pack); err != nil {
if _, err := io.Copy(srp.In, pack); err != nil {
t.Logf("error writing pack to spokes-receive-pack input: %v", err)
}

require.NoError(t, srpIn.Close())

refStatus, unpackRes, _, err := readResult(t, bufSRPOut)
require.NoError(t, err)
assert.Equal(t, map[string]string{
info.Ref: "ng missing necessary objects",
info.DelRef: "ok",
refToCreate: "ok",
}, refStatus)
assert.Equal(t, "unpack ok\n", unpackRes)
require.NoError(t, srp.In.Close())
}
1 change: 1 addition & 0 deletions internal/integration/testdata/bad-date/sha1.git/HEAD
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ref: refs/heads/main
4 changes: 4 additions & 0 deletions internal/integration/testdata/bad-date/sha1.git/config
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
[core]
repositoryformatversion = 0
filemode = true
bare = true
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Unnamed repository; edit this file 'description' to name the repository.
1 change: 1 addition & 0 deletions internal/integration/testdata/bad-date/sha1.git/info/refs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
e1971a634e8b1e52b09eba0d21d03ec291c6b690 refs/heads/main
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
P pack-01f7c523f4ab85d86dbe8b116ab6cd69e87497f3.pack

Binary file not shown.
Binary file not shown.
Binary file not shown.
2 changes: 2 additions & 0 deletions internal/integration/testdata/bad-date/sha1.git/packed-refs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# pack-refs with: peeled fully-peeled sorted
e1971a634e8b1e52b09eba0d21d03ec291c6b690 refs/heads/main
Empty file.
1 change: 1 addition & 0 deletions internal/integration/testdata/bad-date/sha256.git/HEAD
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ref: refs/heads/main
6 changes: 6 additions & 0 deletions internal/integration/testdata/bad-date/sha256.git/config
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
[core]
repositoryformatversion = 1
filemode = true
bare = true
[extensions]
objectformat = sha256
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Unnamed repository; edit this file 'description' to name the repository.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
8ae390f74dd659799c5e9f9bff315143347f30961df0a61f2b23132521f25a47 refs/heads/main
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
P pack-1a1bc6a0c21b6c3b7683df993586a57ec40580603ee77348431ab8d4f72b55f0.pack

Binary file not shown.
Binary file not shown.
Binary file not shown.
2 changes: 2 additions & 0 deletions internal/integration/testdata/bad-date/sha256.git/packed-refs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# pack-refs with: peeled fully-peeled sorted
8ae390f74dd659799c5e9f9bff315143347f30961df0a61f2b23132521f25a47 refs/heads/main
Empty file.
4 changes: 4 additions & 0 deletions internal/integration/testdata/gitconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# This file has a subset of options from our prod /etc/gitconfig.

[receive]
fsckObjects = true
Binary file not shown.
Loading