Skip to content
Open
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
2 changes: 1 addition & 1 deletion .github/workflows/go-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ jobs:
go-version: "1.21"
- name: Install git.
run: |
sudo apt-get install -y libcurl4-openssl-dev
sudo apt-get install -y libcurl4-openssl-dev cargo
git clone https://github.com/git/git.git
git -C git checkout next
sudo make -j 16 -C git prefix=/usr NO_GETTEXT=YesPlease all install
Expand Down
40 changes: 33 additions & 7 deletions internal/spokes/spokes.go
Original file line number Diff line number Diff line change
Expand Up @@ -1078,18 +1078,16 @@ func (r *spokesReceivePack) performCheckConnectivity(ctx context.Context, comman
_ = devNull.Close()
}()

cmd := exec.CommandContext(
ctx,
"git",
args := []string{
"rev-list",
"--objects",
"--no-object-names",
"--stdin",
"--not",
"--exclude-hidden=receive",
"--all",
"--alternate-refs",
)
}
args = append(args, r.connectivityStopperArgs(ctx)...)

cmd := exec.CommandContext(ctx, "git", args...)
cmd.Stderr = devNull
cmd.Env = os.Environ()
cmd.Env = append(cmd.Env, r.getAlternateObjectDirsEnv()...)
Expand Down Expand Up @@ -1124,6 +1122,34 @@ func (r *spokesReceivePack) performCheckConnectivity(ctx context.Context, comman
return nil
}

// connectivityStopperArgs returns the rev-list arguments that mark the
// pre-existing object graph as uninteresting for the connectivity check.
func (r *spokesReceivePack) connectivityStopperArgs(ctx context.Context) []string {
if !sockstat.GetBool("spokes_receive_pack_narrow_connectivity_stopper") {
return []string{"--exclude-hidden=receive", "--all", "--alternate-refs"}
}

args := []string{"--exclude=*/*", "--branches"}
if r.headResolves(ctx) {
args = append(args, "HEAD")
}
return args
Comment thread
newren marked this conversation as resolved.
}

// headResolves reports whether `git rev-parse --verify --quiet HEAD`
// succeeds in the current directory.
func (r *spokesReceivePack) headResolves(ctx context.Context) bool {
cmd := exec.CommandContext(ctx, "git", "rev-parse", "--verify", "--quiet", "HEAD")
cmd.Env = os.Environ()
cmd.Env = append(cmd.Env, r.getAlternateObjectDirsEnv()...)
// Discard stdout (the resolved OID on success) and stderr so we
// neither corrupt the receive-pack protocol stream on stdout nor
// leak diagnostics on stderr.
cmd.Stdout = io.Discard
cmd.Stderr = io.Discard
return cmd.Run() == nil
Comment thread
newren marked this conversation as resolved.
}

func commandsForConnectivityCheck(commands []command) []command {
var res []command
for _, c := range commands {
Expand Down
50 changes: 50 additions & 0 deletions internal/spokes/spokes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,12 @@ import (
"context"
"fmt"
"os"
"os/exec"
"path/filepath"
"testing"

"github.com/github/spokes-receive-pack/internal/config"
"github.com/github/spokes-receive-pack/internal/sockstat"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
Expand Down Expand Up @@ -271,3 +274,50 @@ func TestPerformReferenceDiscovery(t *testing.T) {
assert.NoError(t, r.performReferenceDiscovery(context.Background()))
assert.Equal(t, expectedReferenceList, buf.String())
}

func TestConnectivityStopperArgs(t *testing.T) {
origwd, err := os.Getwd()
require.NoError(t, err)
// A valid quarantine directory is required so that
// getAlternateObjectDirsEnv produces well-formed environment
// variables (an empty GIT_OBJECT_DIRECTORY would make git refuse
// to operate).
quarantine := t.TempDir()

t.Run("flag off uses legacy stoppers", func(t *testing.T) {
t.Setenv(sockstat.Prefix+"spokes_receive_pack_narrow_connectivity_stopper", "")
// No filesystem operations are required: the legacy path
// never invokes git.
r := &spokesReceivePack{}
got := r.connectivityStopperArgs(context.Background())
assert.Equal(t, []string{"--exclude-hidden=receive", "--all", "--alternate-refs"}, got)
})

t.Run("flag on uses --exclude=*/* --branches HEAD when HEAD resolves", func(t *testing.T) {
t.Setenv(sockstat.Prefix+"spokes_receive_pack_narrow_connectivity_stopper", "bool:true")
require.NoError(t, os.Chdir("testdata/lots-of-refs.git"))
t.Cleanup(func() { _ = os.Chdir(origwd) })
wd, _ := os.Getwd()
r := &spokesReceivePack{repoPath: wd, quarantineFolder: quarantine}
got := r.connectivityStopperArgs(context.Background())
assert.Equal(t, []string{"--exclude=*/*", "--branches", "HEAD"}, got)
})

t.Run("flag on omits HEAD when HEAD does not resolve", func(t *testing.T) {
t.Setenv(sockstat.Prefix+"spokes_receive_pack_narrow_connectivity_stopper", "bool:true")
// A fresh repo with no commits has HEAD pointing at an
// unborn branch, so rev-parse --verify HEAD fails. Use a
// non-bare repo to side-step any safe.bareRepository
// configuration the caller may have set.
dir := t.TempDir()
require.NoError(t, exec.Command("git", "init", dir).Run())
require.NoError(t, os.Chdir(dir))
t.Cleanup(func() { _ = os.Chdir(origwd) })
r := &spokesReceivePack{
repoPath: filepath.Join(dir, ".git"),
quarantineFolder: quarantine,
}
got := r.connectivityStopperArgs(context.Background())
assert.Equal(t, []string{"--exclude=*/*", "--branches"}, got)
})
}
Loading