aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaulo Gomes <pjbgf@linux.com>2023-07-01 15:37:24 +0100
committerPaulo Gomes <pjbgf@linux.com>2023-07-01 15:37:24 +0100
commitabe49196b80e367f7cc123a095b32958f8d0470b (patch)
tree83e0b1ad994b912fe235e8d4ed59a8db0d2675ad
parent35f7e6770361a2c16c9b6c44acdc38ae04c75bd3 (diff)
downloadgo-git-abe49196b80e367f7cc123a095b32958f8d0470b.tar.gz
plumbing: http, Fix empty repos on Git v2.41+
Git v2.41.0 comes with [changes](https://github.com/git/git/commit/933e3a4ee205353d8f093d5dfcd226fa432c4e58) that breaks go-git's assumptions for when detecting empty repositories. Go-git expects a flush instead of the first hash line. Instead, a dummy capabilities^{} with zero-id is returned. The change aims to allow for identifying the object format even when cloning empty repositories. Signed-off-by: Paulo Gomes <pjbgf@linux.com>
-rw-r--r--plumbing/protocol/packp/advrefs_decode.go1
-rw-r--r--plumbing/protocol/packp/advrefs_decode_test.go10
-rw-r--r--plumbing/transport/http/common.go11
-rw-r--r--remote.go9
4 files changed, 27 insertions, 4 deletions
diff --git a/plumbing/protocol/packp/advrefs_decode.go b/plumbing/protocol/packp/advrefs_decode.go
index 63bbe5a..f8d26a2 100644
--- a/plumbing/protocol/packp/advrefs_decode.go
+++ b/plumbing/protocol/packp/advrefs_decode.go
@@ -133,6 +133,7 @@ func decodeFirstHash(p *advRefsDecoder) decoderStateFn {
return nil
}
+ // TODO: Use object-format (when available) for hash size. Git 2.41+
if len(p.line) < hashSize {
p.error("cannot read hash, pkt-line too short")
return nil
diff --git a/plumbing/protocol/packp/advrefs_decode_test.go b/plumbing/protocol/packp/advrefs_decode_test.go
index 83b0b01..d127145 100644
--- a/plumbing/protocol/packp/advrefs_decode_test.go
+++ b/plumbing/protocol/packp/advrefs_decode_test.go
@@ -218,6 +218,16 @@ func (s *AdvRefsDecodeSuite) TestCaps(c *C) {
{Name: capability.SymRef, Values: []string{"HEAD:refs/heads/master"}},
{Name: capability.Agent, Values: []string{"foo=bar"}},
},
+ }, {
+ input: []string{
+ "0000000000000000000000000000000000000000 capabilities^{}\x00report-status report-status-v2 delete-refs side-band-64k quiet atomic ofs-delta object-format=sha1 agent=git/2.41.0\n",
+ pktline.FlushString,
+ },
+ capabilities: []entry{
+ {Name: capability.ReportStatus, Values: []string(nil)},
+ {Name: capability.ObjectFormat, Values: []string{"sha1"}},
+ {Name: capability.Agent, Values: []string{"git/2.41.0"}},
+ },
}} {
ar := s.testDecodeOK(c, test.input)
for _, fixCap := range test.capabilities {
diff --git a/plumbing/transport/http/common.go b/plumbing/transport/http/common.go
index f9b7a0e..a7cdc1e 100644
--- a/plumbing/transport/http/common.go
+++ b/plumbing/transport/http/common.go
@@ -73,6 +73,17 @@ func advertisedReferences(ctx context.Context, s *session, serviceName string) (
return nil, err
}
+ // Git 2.41+ returns a zero-id plus capabilities when an empty
+ // repository is being cloned. This skips the existing logic within
+ // advrefs_decode.decodeFirstHash, which expects a flush-pkt instead.
+ //
+ // This logic aligns with plumbing/transport/internal/common/common.go.
+ if ar.IsEmpty() &&
+ // Empty repositories are valid for git-receive-pack.
+ transport.ReceivePackServiceName != serviceName {
+ return nil, transport.ErrEmptyRemoteRepository
+ }
+
transport.FilterUnsupportedCapabilities(ar.Capabilities)
s.advRefs = ar
diff --git a/remote.go b/remote.go
index 25ec093..679e0af 100644
--- a/remote.go
+++ b/remote.go
@@ -224,11 +224,13 @@ func (r *Remote) PushContext(ctx context.Context, o *PushOptions) (err error) {
return err
}
- if err = rs.Error(); err != nil {
- return err
+ if rs != nil {
+ if err = rs.Error(); err != nil {
+ return err
+ }
}
- return r.updateRemoteReferenceStorage(req, rs)
+ return r.updateRemoteReferenceStorage(req)
}
func (r *Remote) useRefDeltas(ar *packp.AdvRefs) bool {
@@ -347,7 +349,6 @@ func (r *Remote) newReferenceUpdateRequest(
func (r *Remote) updateRemoteReferenceStorage(
req *packp.ReferenceUpdateRequest,
- result *packp.ReportStatus,
) error {
for _, spec := range r.c.Fetch {