diff options
| author | 2026-03-25 16:22:03 +0000 | |
|---|---|---|
| committer | 2026-03-25 16:22:03 +0000 | |
| commit | 311edcd50f3a84f4b860bde3cb887451d74eaa11 (patch) | |
| tree | be7aa5e9a51e636358f33b1c90637b5024b70dc3 /protocol/v0v1 | |
| parent | README: Split off contrib, benchmarks, remove history for now I guess, etc. (diff) | |
| signature | No signature | |
network/protocol: Rename from protocol v0.1.110
Diffstat (limited to 'protocol/v0v1')
20 files changed, 0 insertions, 1726 deletions
diff --git a/protocol/v0v1/doc.go b/protocol/v0v1/doc.go deleted file mode 100644 index 2c96ea23..00000000 --- a/protocol/v0v1/doc.go +++ /dev/null @@ -1,2 +0,0 @@ -// Package v0v1 provides common constants and routines for the V0 and V1 protocols. -package v0v1 diff --git a/protocol/v0v1/server/advertise.go b/protocol/v0v1/server/advertise.go deleted file mode 100644 index be1b1f02..00000000 --- a/protocol/v0v1/server/advertise.go +++ /dev/null @@ -1,55 +0,0 @@ -package server - -import ( - "fmt" - "strings" - - objectid "codeberg.org/lindenii/furgit/object/id" -) - -// AdvertiseRefs writes one server ref advertisement. -func (session *Session) AdvertiseRefs(ad Advertisement, capabilityTokens []string) error { - if session.opts.Version == Version1 { - err := session.enc.WriteData([]byte("version 1\n")) - if err != nil { - return err - } - } - - capList := strings.Join(capabilityTokens, " ") - - refs := sortAdvertisedRefs(ad.Refs) - if len(refs) == 0 { - line := fmt.Sprintf("%s capabilities^{}\x00%s\n", objectid.Zero(session.opts.Algorithm), capList) - - err := session.enc.WriteData([]byte(line)) - if err != nil { - return err - } - - return session.WriteFlush() - } - - for i, entry := range refs { - line := fmt.Sprintf("%s %s", entry.ID, entry.Name) - if i == 0 { - line += "\x00" + capList - } - - err := session.enc.WriteData([]byte(line + "\n")) - if err != nil { - return err - } - - if entry.Peeled != nil { - peeled := fmt.Sprintf("%s %s^{}\n", *entry.Peeled, entry.Name) - - err = session.enc.WriteData([]byte(peeled)) - if err != nil { - return err - } - } - } - - return session.WriteFlush() -} diff --git a/protocol/v0v1/server/advertise_test.go b/protocol/v0v1/server/advertise_test.go deleted file mode 100644 index 287bb61d..00000000 --- a/protocol/v0v1/server/advertise_test.go +++ /dev/null @@ -1,101 +0,0 @@ -package server_test - -import ( - "strings" - "testing" - - "codeberg.org/lindenii/furgit/internal/testgit" - objectid "codeberg.org/lindenii/furgit/object/id" - server "codeberg.org/lindenii/furgit/protocol/v0v1/server" -) - -func TestAdvertiseRefsWritesVersionOneHeadCapsAndPeeledTag(t *testing.T) { - t.Parallel() - - //nolint:thelper - testgit.ForEachAlgorithm(t, func(t *testing.T, algo objectid.Algorithm) { - t.Parallel() - - headID := mustHexID(t, algo, "1") - tagID := mustHexID(t, algo, "2") - peeledID := mustHexID(t, algo, "3") - mainID := mustHexID(t, algo, "4") - - var out bufferWriteFlusher - - session := server.NewSession( - strings.NewReader(""), - &out, - server.Options{ - Version: server.Version1, - Algorithm: algo, - }, - ) - - err := session.AdvertiseRefs(server.Advertisement{ - Refs: []server.AdvertisedRef{ - {Name: "refs/tags/v1", ID: tagID, Peeled: &peeledID}, - {Name: "HEAD", ID: headID}, - {Name: "refs/heads/main", ID: mainID}, - }, - }, []string{ - "report-status", - "delete-refs", - "object-format=" + algo.String(), - "agent=furgit-test/1", - }) - if err != nil { - t.Fatalf("AdvertiseRefs: %v", err) - } - - got := out.String() - wantParts := []string{ - "000eversion 1\n", - headID.String() + " HEAD\x00report-status delete-refs object-format=" + algo.String() + " agent=furgit-test/1\n", - mainID.String() + " refs/heads/main\n", - tagID.String() + " refs/tags/v1\n", - peeledID.String() + " refs/tags/v1^{}\n", - "0000", - } - - for _, part := range wantParts { - if !strings.Contains(got, part) { - t.Fatalf("advertisement missing %q in %q", part, got) - } - } - }) -} - -func TestAdvertiseRefsWritesNoRefsCapabilitiesLine(t *testing.T) { - t.Parallel() - - //nolint:thelper - testgit.ForEachAlgorithm(t, func(t *testing.T, algo objectid.Algorithm) { - t.Parallel() - - var out bufferWriteFlusher - - session := server.NewSession( - strings.NewReader(""), - &out, - server.Options{ - Algorithm: algo, - }, - ) - - err := session.AdvertiseRefs(server.Advertisement{}, []string{ - "report-status", - "object-format=" + algo.String(), - }) - if err != nil { - t.Fatalf("AdvertiseRefs: %v", err) - } - - got := out.String() - - want := objectid.Zero(algo).String() + " capabilities^{}\x00report-status object-format=" + algo.String() + "\n" - if !strings.Contains(got, want) { - t.Fatalf("unexpected no-refs advertisement %q", got) - } - }) -} diff --git a/protocol/v0v1/server/advertised_ref.go b/protocol/v0v1/server/advertised_ref.go deleted file mode 100644 index cf6ddcc8..00000000 --- a/protocol/v0v1/server/advertised_ref.go +++ /dev/null @@ -1,22 +0,0 @@ -package server - -import objectid "codeberg.org/lindenii/furgit/object/id" - -// AdvertisedRef is one ref entry in one v0/v1 server advertisement. -type AdvertisedRef struct { - // Name is the advertised reference name. It may be HEAD or one full - // reference name. - Name string - // ID is the object ID currently advertised for Name. - ID objectid.ObjectID - // Peeled is the peeled annotated-tag target when available. - // - // If set, advertisement writes one immediate "<name>^{}" line after the - // main entry, matching Git's advertisement rules. - Peeled *objectid.ObjectID -} - -// Advertisement is one server-side ref advertisement. -type Advertisement struct { - Refs []AdvertisedRef -} diff --git a/protocol/v0v1/server/doc.go b/protocol/v0v1/server/doc.go deleted file mode 100644 index ea0b3f18..00000000 --- a/protocol/v0v1/server/doc.go +++ /dev/null @@ -1,2 +0,0 @@ -// Package server implements shared server-side Git protocol v0/v1 framing. -package server diff --git a/protocol/v0v1/server/errors.go b/protocol/v0v1/server/errors.go deleted file mode 100644 index 6a456234..00000000 --- a/protocol/v0v1/server/errors.go +++ /dev/null @@ -1,18 +0,0 @@ -package server - -// ProtocolError reports one malformed or unsupported protocol input. -type ProtocolError struct { - Reason string -} - -// Error returns the formatted error string. -func (err *ProtocolError) Error() string { - return "protocol/v0v1/server: protocol error: " + err.Reason -} - -// ErrUnexpectedPacket reports one unexpected pkt-line control packet. -var ErrUnexpectedPacket = &ProtocolError{Reason: "unexpected control packet"} - -// ErrSideBandNotEnabled reports one attempt to write sideband frames without a -// negotiated side-band-64k session. -var ErrSideBandNotEnabled = &ProtocolError{Reason: "side-band-64k not enabled"} diff --git a/protocol/v0v1/server/frame.go b/protocol/v0v1/server/frame.go deleted file mode 100644 index 3cccba08..00000000 --- a/protocol/v0v1/server/frame.go +++ /dev/null @@ -1,20 +0,0 @@ -package server - -import "codeberg.org/lindenii/furgit/protocol/pktline" - -// FrameType identifies one low-level v0/v1 server pkt-line frame type. -type FrameType = pktline.PacketType - -const ( - // FrameData is one data pkt-line. - FrameData = pktline.PacketData - // FrameFlush is one flush-pkt. - FrameFlush = pktline.PacketFlush - // FrameDelim is one delim-pkt. - FrameDelim = pktline.PacketDelim - // FrameResponseEnd is one response-end-pkt. - FrameResponseEnd = pktline.PacketResponseEnd -) - -// Frame is one decoded low-level pkt-line frame. -type Frame = pktline.Frame diff --git a/protocol/v0v1/server/helpers.go b/protocol/v0v1/server/helpers.go deleted file mode 100644 index 9a62f714..00000000 --- a/protocol/v0v1/server/helpers.go +++ /dev/null @@ -1,29 +0,0 @@ -package server - -import ( - "slices" -) - -func sortAdvertisedRefs(refs []AdvertisedRef) []AdvertisedRef { - out := append([]AdvertisedRef(nil), refs...) - slices.SortFunc(out, func(left, right AdvertisedRef) int { - if left.Name == "HEAD" && right.Name != "HEAD" { - return -1 - } - - if left.Name != "HEAD" && right.Name == "HEAD" { - return 1 - } - - switch { - case left.Name < right.Name: - return -1 - case left.Name > right.Name: - return 1 - default: - return 0 - } - }) - - return out -} diff --git a/protocol/v0v1/server/helpers_test.go b/protocol/v0v1/server/helpers_test.go deleted file mode 100644 index 261bbdc5..00000000 --- a/protocol/v0v1/server/helpers_test.go +++ /dev/null @@ -1,28 +0,0 @@ -package server_test - -import ( - "bytes" - "strings" - "testing" - - objectid "codeberg.org/lindenii/furgit/object/id" -) - -type bufferWriteFlusher struct { - bytes.Buffer -} - -func (bufferWriteFlusher) Flush() error { - return nil -} - -func mustHexID(tb testing.TB, algo objectid.Algorithm, digit string) objectid.ObjectID { - tb.Helper() - - id, err := objectid.ParseHex(algo, strings.Repeat(digit, algo.HexLen())) - if err != nil { - tb.Fatalf("objectid.ParseHex(%q): %v", strings.Repeat(digit, algo.HexLen()), err) - } - - return id -} diff --git a/protocol/v0v1/server/receivepack/capabilities.go b/protocol/v0v1/server/receivepack/capabilities.go deleted file mode 100644 index e0ff51a3..00000000 --- a/protocol/v0v1/server/receivepack/capabilities.go +++ /dev/null @@ -1,192 +0,0 @@ -package receivepack - -import ( - "fmt" - "slices" - "strings" - - objectid "codeberg.org/lindenii/furgit/object/id" -) - -// Capabilities describes one receive-pack capability set. -type Capabilities struct { - ReportStatus bool - ReportStatusV2 bool - DeleteRefs bool - SideBand64K bool - Quiet bool - Atomic bool - OfsDelta bool - PushOptions bool - PushCertNonce string - ObjectFormat objectid.Algorithm - SessionID string - Agent string -} - -// Normalize returns one normalized copy of caps. -func (caps Capabilities) Normalize(defaultAlgorithm objectid.Algorithm) Capabilities { - if caps.ObjectFormat == objectid.AlgorithmUnknown { - caps.ObjectFormat = defaultAlgorithm - } - - return caps -} - -// Tokens returns capabilities in Git advertisement order. -func (caps Capabilities) Tokens(defaultAlgorithm objectid.Algorithm) []string { - caps = caps.Normalize(defaultAlgorithm) - - tokens := make([]string, 0, 11) - if caps.ReportStatus { - tokens = append(tokens, "report-status") - } - - if caps.ReportStatusV2 { - tokens = append(tokens, "report-status-v2") - } - - if caps.DeleteRefs { - tokens = append(tokens, "delete-refs") - } - - if caps.SideBand64K { - tokens = append(tokens, "side-band-64k") - } - - if caps.Quiet { - tokens = append(tokens, "quiet") - } - - if caps.Atomic { - tokens = append(tokens, "atomic") - } - - if caps.OfsDelta { - tokens = append(tokens, "ofs-delta") - } - - if caps.PushCertNonce != "" { - tokens = append(tokens, "push-cert="+caps.PushCertNonce) - } - - if caps.PushOptions { - tokens = append(tokens, "push-options") - } - - if caps.SessionID != "" { - tokens = append(tokens, "session-id="+caps.SessionID) - } - - if caps.ObjectFormat != objectid.AlgorithmUnknown { - tokens = append(tokens, "object-format="+caps.ObjectFormat.String()) - } - - if caps.Agent != "" { - tokens = append(tokens, "agent="+caps.Agent) - } - - return tokens -} - -func (caps Capabilities) supportsToken(token string, defaultAlgorithm objectid.Algorithm) bool { - name, value, _ := strings.Cut(token, "=") - - switch name { - case "report-status": - return caps.ReportStatus && value == "" - case "report-status-v2": - return caps.ReportStatusV2 && value == "" - case "delete-refs": - return caps.DeleteRefs && value == "" - case "side-band-64k": - return caps.SideBand64K && value == "" - case "quiet": - return caps.Quiet && value == "" - case "atomic": - return caps.Atomic && value == "" - case "ofs-delta": - return caps.OfsDelta && value == "" - case "push-options": - return caps.PushOptions && value == "" - case "push-cert": - return caps.PushCertNonce != "" && value != "" - case "object-format": - if value == "" { - return false - } - - algo, ok := objectid.ParseAlgorithm(value) - - return ok && algo == caps.Normalize(defaultAlgorithm).ObjectFormat - case "session-id": - return caps.SessionID != "" && value != "" - case "agent": - return caps.Agent != "" && value != "" - default: - return false - } -} - -func parseCapabilityList(s string) ([]string, error) { - s = strings.TrimSuffix(s, "\n") - if s == "" { - return nil, nil - } - - tokens := strings.Fields(s) - if slices.Contains(tokens, "") { - return nil, &ProtocolError{Reason: "empty capability token"} - } - - return tokens, nil -} - -func parseRequestedCapabilities( - tokens []string, - supported Capabilities, - defaultAlgorithm objectid.Algorithm, -) (Capabilities, error) { - var requested Capabilities - - requested.ObjectFormat = defaultAlgorithm - - for _, token := range tokens { - if !supported.supportsToken(token, defaultAlgorithm) { - return Capabilities{}, &ProtocolError{ - Reason: fmt.Sprintf("unsupported capability %q", token), - } - } - - name, value, _ := strings.Cut(token, "=") - switch name { - case "report-status": - requested.ReportStatus = true - case "report-status-v2": - requested.ReportStatusV2 = true - case "delete-refs": - requested.DeleteRefs = true - case "side-band-64k": - requested.SideBand64K = true - case "quiet": - requested.Quiet = true - case "atomic": - requested.Atomic = true - case "ofs-delta": - requested.OfsDelta = true - case "push-options": - requested.PushOptions = true - case "push-cert": - requested.PushCertNonce = value - case "object-format": - algo, _ := objectid.ParseAlgorithm(value) - requested.ObjectFormat = algo - case "session-id": - requested.SessionID = value - case "agent": - requested.Agent = value - } - } - - return requested, nil -} diff --git a/protocol/v0v1/server/receivepack/doc.go b/protocol/v0v1/server/receivepack/doc.go deleted file mode 100644 index 65793831..00000000 --- a/protocol/v0v1/server/receivepack/doc.go +++ /dev/null @@ -1,2 +0,0 @@ -// Package receivepack implements the receive-pack-specific server side of Git protocol v0/v1. -package receivepack diff --git a/protocol/v0v1/server/receivepack/errors.go b/protocol/v0v1/server/receivepack/errors.go deleted file mode 100644 index d89f8959..00000000 --- a/protocol/v0v1/server/receivepack/errors.go +++ /dev/null @@ -1,11 +0,0 @@ -package receivepack - -// ProtocolError reports one malformed or unsupported receive-pack protocol input. -type ProtocolError struct { - Reason string -} - -// Error returns the formatted error string. -func (err *ProtocolError) Error() string { - return "protocol/v0v1/server/receivepack: protocol error: " + err.Reason -} diff --git a/protocol/v0v1/server/receivepack/helpers_test.go b/protocol/v0v1/server/receivepack/helpers_test.go deleted file mode 100644 index 5db8e6a6..00000000 --- a/protocol/v0v1/server/receivepack/helpers_test.go +++ /dev/null @@ -1,28 +0,0 @@ -package receivepack_test - -import ( - "bytes" - "strings" - "testing" - - objectid "codeberg.org/lindenii/furgit/object/id" -) - -type bufferWriteFlusher struct { - bytes.Buffer -} - -func (bufferWriteFlusher) Flush() error { - return nil -} - -func mustHexID(tb testing.TB, algo objectid.Algorithm, digit string) objectid.ObjectID { - tb.Helper() - - id, err := objectid.ParseHex(algo, strings.Repeat(digit, algo.HexLen())) - if err != nil { - tb.Fatalf("objectid.ParseHex(%q): %v", strings.Repeat(digit, algo.HexLen()), err) - } - - return id -} diff --git a/protocol/v0v1/server/receivepack/parse_test.go b/protocol/v0v1/server/receivepack/parse_test.go deleted file mode 100644 index 534edcb2..00000000 --- a/protocol/v0v1/server/receivepack/parse_test.go +++ /dev/null @@ -1,255 +0,0 @@ -package receivepack_test - -import ( - "errors" - "strings" - "testing" - - "codeberg.org/lindenii/furgit/internal/testgit" - objectid "codeberg.org/lindenii/furgit/object/id" - "codeberg.org/lindenii/furgit/protocol/pktline" - common "codeberg.org/lindenii/furgit/protocol/v0v1/server" - receivepack "codeberg.org/lindenii/furgit/protocol/v0v1/server/receivepack" -) - -func TestReadRequestParsesCommandsAndPushOptions(t *testing.T) { - t.Parallel() - - //nolint:thelper - testgit.ForEachAlgorithm(t, func(t *testing.T, algo objectid.Algorithm) { - t.Parallel() - - oldZero := objectid.Zero(algo).String() - oneID := mustHexID(t, algo, "1") - - var wire bufferWriteFlusher - - enc := pktline.NewEncoder(&wire) - - err := enc.WriteData([]byte( - oldZero + " " + oneID.String() + " refs/heads/main\x00report-status push-options object-format=" + algo.String() + "\n", - )) - if err != nil { - t.Fatalf("WriteData(first): %v", err) - } - - err = enc.WriteData([]byte( - oneID.String() + " " + oldZero + " refs/heads/old\n", - )) - if err != nil { - t.Fatalf("WriteData(second): %v", err) - } - - err = enc.WriteFlush() - if err != nil { - t.Fatalf("WriteFlush(commands): %v", err) - } - - err = enc.WriteData([]byte("ci.skip\n")) - if err != nil { - t.Fatalf("WriteData(push-option): %v", err) - } - - err = enc.WriteFlush() - if err != nil { - t.Fatalf("WriteFlush(push-options): %v", err) - } - - base := common.NewSession(strings.NewReader(wire.String()), &bufferWriteFlusher{}, common.Options{ - Algorithm: algo, - }) - session := receivepack.NewSession(base, receivepack.Capabilities{ - ReportStatus: true, - PushOptions: true, - ObjectFormat: algo, - }) - - req, err := session.ReadRequest() - if err != nil { - t.Fatalf("ReadRequest: %v", err) - } - - if len(req.Commands) != 2 { - t.Fatalf("len(req.Commands) = %d, want 2", len(req.Commands)) - } - - if !req.Capabilities.ReportStatus || !req.Capabilities.PushOptions { - t.Fatalf("capabilities = %#v", req.Capabilities) - } - - if len(req.PushOptions) != 1 || req.PushOptions[0] != "ci.skip" { - t.Fatalf("push options = %#v", req.PushOptions) - } - - if !req.PackExpected { - t.Fatalf("PackExpected = false, want true") - } - - if req.DeleteOnly { - t.Fatalf("DeleteOnly = true, want false") - } - }) -} - -func TestReadRequestDeleteOnlyDoesNotExpectPack(t *testing.T) { - t.Parallel() - - //nolint:thelper - testgit.ForEachAlgorithm(t, func(t *testing.T, algo objectid.Algorithm) { - t.Parallel() - - oneID := mustHexID(t, algo, "1") - - var wire bufferWriteFlusher - - enc := pktline.NewEncoder(&wire) - - err := enc.WriteData([]byte( - oneID.String() + " " + objectid.Zero(algo).String() + " refs/heads/old\x00delete-refs object-format=" + algo.String() + "\n", - )) - if err != nil { - t.Fatalf("WriteData: %v", err) - } - - err = enc.WriteFlush() - if err != nil { - t.Fatalf("WriteFlush: %v", err) - } - - base := common.NewSession(strings.NewReader(wire.String()), &bufferWriteFlusher{}, common.Options{ - Algorithm: algo, - }) - session := receivepack.NewSession(base, receivepack.Capabilities{ - DeleteRefs: true, - ObjectFormat: algo, - }) - - req, err := session.ReadRequest() - if err != nil { - t.Fatalf("ReadRequest: %v", err) - } - - if req.PackExpected { - t.Fatalf("PackExpected = true, want false") - } - - if !req.DeleteOnly { - t.Fatalf("DeleteOnly = false, want true") - } - }) -} - -func TestReadRequestRejectsUnsupportedCapability(t *testing.T) { - t.Parallel() - - //nolint:thelper - testgit.ForEachAlgorithm(t, func(t *testing.T, algo objectid.Algorithm) { - t.Parallel() - - oneID := mustHexID(t, algo, "1") - - var wire bufferWriteFlusher - - enc := pktline.NewEncoder(&wire) - - err := enc.WriteData([]byte( - objectid.Zero(algo).String() + " " + oneID.String() + " refs/heads/main\x00atomic object-format=" + algo.String() + "\n", - )) - if err != nil { - t.Fatalf("WriteData: %v", err) - } - - err = enc.WriteFlush() - if err != nil { - t.Fatalf("WriteFlush: %v", err) - } - - base := common.NewSession(strings.NewReader(wire.String()), &bufferWriteFlusher{}, common.Options{ - Algorithm: algo, - }) - session := receivepack.NewSession(base, receivepack.Capabilities{ObjectFormat: algo}) - - _, err = session.ReadRequest() - if err == nil { - t.Fatalf("ReadRequest error = nil, want error") - } - - protocolErr, ok := errors.AsType[*receivepack.ProtocolError](err) - if !ok { - t.Fatalf("errors.AsType[*receivepack.ProtocolError](%T) = false", err) - } - - if !strings.Contains(protocolErr.Reason, "unsupported capability") { - t.Fatalf("ProtocolError.Reason = %q", protocolErr.Reason) - } - }) -} - -func TestReadRequestParsesPushCertificate(t *testing.T) { - t.Parallel() - - //nolint:thelper - testgit.ForEachAlgorithm(t, func(t *testing.T, algo objectid.Algorithm) { - t.Parallel() - - oneID := mustHexID(t, algo, "1") - - var wire bufferWriteFlusher - - enc := pktline.NewEncoder(&wire) - - err := enc.WriteData([]byte("push-cert\x00push-cert=nonce object-format=" + algo.String() + "\n")) - if err != nil { - t.Fatalf("WriteData(push-cert): %v", err) - } - - lines := []string{ - "certificate version 0.1\n", - "pusher Example <example@example.com>\n", - "nonce nonce\n", - "push-option ci.skip\n", - "\n", - objectid.Zero(algo).String() + " " + oneID.String() + " refs/heads/main\n", - "-----BEGIN PGP SIGNATURE-----\n", - "abcdef\n", - "push-cert-end\n", - } - - for _, line := range lines { - err = enc.WriteData([]byte(line)) - if err != nil { - t.Fatalf("WriteData(%q): %v", line, err) - } - } - - err = enc.WriteFlush() - if err != nil { - t.Fatalf("WriteFlush: %v", err) - } - - base := common.NewSession(strings.NewReader(wire.String()), &bufferWriteFlusher{}, common.Options{ - Algorithm: algo, - }) - session := receivepack.NewSession(base, receivepack.Capabilities{ - PushCertNonce: "server-nonce", - ObjectFormat: algo, - }) - - req, err := session.ReadRequest() - if err != nil { - t.Fatalf("ReadRequest: %v", err) - } - - if req.PushCert == nil { - t.Fatalf("PushCert = nil, want parsed certificate") - } - - if len(req.Commands) != 1 { - t.Fatalf("len(req.Commands) = %d, want 1", len(req.Commands)) - } - - if len(req.PushCert.EmbeddedOption) != 1 || req.PushCert.EmbeddedOption[0] != "ci.skip" { - t.Fatalf("embedded options = %#v", req.PushCert.EmbeddedOption) - } - }) -} diff --git a/protocol/v0v1/server/receivepack/report_status.go b/protocol/v0v1/server/receivepack/report_status.go deleted file mode 100644 index f6ac4985..00000000 --- a/protocol/v0v1/server/receivepack/report_status.go +++ /dev/null @@ -1,185 +0,0 @@ -package receivepack - -import ( - "fmt" - - "codeberg.org/lindenii/furgit/protocol/pktline" -) - -// WriteReportStatus writes one classic report-status response. -func (session *Session) WriteReportStatus(result ReportStatusResult) error { - unpackResult := "ok" - if result.UnpackError != "" { - unpackResult = result.UnpackError - } - - if !session.negotiated.SideBand64K { - err := session.base.WriteData(fmt.Appendf(nil, "unpack %s\n", unpackResult)) - if err != nil { - return err - } - - for _, command := range result.Commands { - line := fmt.Sprintf("ok %s\n", command.Name) - if command.Error != "" { - line = fmt.Sprintf("ng %s %s\n", command.Name, command.Error) - } - - err = session.base.WriteData([]byte(line)) - if err != nil { - return err - } - } - - return session.base.WriteFlush() - } - - buf, err := pktline.AppendData(nil, fmt.Appendf(nil, "unpack %s\n", unpackResult)) - if err != nil { - return err - } - - for _, command := range result.Commands { - line := fmt.Sprintf("ok %s\n", command.Name) - if command.Error != "" { - line = fmt.Sprintf("ng %s %s\n", command.Name, command.Error) - } - - buf, err = pktline.AppendData(buf, []byte(line)) - if err != nil { - return err - } - } - - buf = pktline.AppendFlushPkt(buf) - - w := session.base.PrimaryDataWriter() - - _, err = w.Write(buf) - if err != nil { - return err - } - - return session.base.WriteFlush() -} - -// WriteReportStatusV2 writes one report-status-v2 response. -func (session *Session) WriteReportStatusV2(result ReportStatusResult) error { - unpackResult := "ok" - if result.UnpackError != "" { - unpackResult = result.UnpackError - } - - if !session.negotiated.SideBand64K { //nolint:nestif - err := session.base.WriteData(fmt.Appendf(nil, "unpack %s\n", unpackResult)) - if err != nil { - return err - } - - for _, command := range result.Commands { - if command.Error != "" { - err = session.base.WriteData(fmt.Appendf(nil, "ng %s %s\n", command.Name, command.Error)) - if err != nil { - return err - } - - continue - } - - err = session.base.WriteData(fmt.Appendf(nil, "ok %s\n", command.Name)) - if err != nil { - return err - } - - if command.RefName != "" { - err = session.base.WriteData(fmt.Appendf(nil, "option refname %s\n", command.RefName)) - if err != nil { - return err - } - } - - if command.OldID != nil { - err = session.base.WriteData(fmt.Appendf(nil, "option old-oid %s\n", *command.OldID)) - if err != nil { - return err - } - } - - if command.NewID != nil { - err = session.base.WriteData(fmt.Appendf(nil, "option new-oid %s\n", *command.NewID)) - if err != nil { - return err - } - } - - if command.ForcedUpdate { - err = session.base.WriteData([]byte("option forced-update\n")) - if err != nil { - return err - } - } - } - - return session.base.WriteFlush() - } - - buf, err := pktline.AppendData(nil, fmt.Appendf(nil, "unpack %s\n", unpackResult)) - if err != nil { - return err - } - - for _, command := range result.Commands { - if command.Error != "" { - buf, err = pktline.AppendData(buf, fmt.Appendf(nil, "ng %s %s\n", command.Name, command.Error)) - if err != nil { - return err - } - - continue - } - - buf, err = pktline.AppendData(buf, fmt.Appendf(nil, "ok %s\n", command.Name)) - if err != nil { - return err - } - - if command.RefName != "" { - buf, err = pktline.AppendData(buf, fmt.Appendf(nil, "option refname %s\n", command.RefName)) - if err != nil { - return err - } - } - - if command.OldID != nil { - buf, err = pktline.AppendData(buf, fmt.Appendf(nil, "option old-oid %s\n", *command.OldID)) - if err != nil { - return err - } - } - - if command.NewID != nil { - buf, err = pktline.AppendData(buf, fmt.Appendf(nil, "option new-oid %s\n", *command.NewID)) - if err != nil { - return err - } - } - - if command.ForcedUpdate { - buf, err = pktline.AppendData(buf, []byte("option forced-update\n")) - if err != nil { - return err - } - } - } - - buf = pktline.AppendFlushPkt(buf) - - w := session.base.PrimaryDataWriter() - - _, err = w.Write(buf) - if err != nil { - return err - } - - return session.base.WriteFlush() -} diff --git a/protocol/v0v1/server/receivepack/report_status_test.go b/protocol/v0v1/server/receivepack/report_status_test.go deleted file mode 100644 index 0f22612b..00000000 --- a/protocol/v0v1/server/receivepack/report_status_test.go +++ /dev/null @@ -1,293 +0,0 @@ -package receivepack_test - -import ( - "errors" - "io" - "strings" - "testing" - - "codeberg.org/lindenii/furgit/internal/testgit" - objectid "codeberg.org/lindenii/furgit/object/id" - "codeberg.org/lindenii/furgit/protocol/pktline" - "codeberg.org/lindenii/furgit/protocol/sideband64k" - common "codeberg.org/lindenii/furgit/protocol/v0v1/server" - receivepack "codeberg.org/lindenii/furgit/protocol/v0v1/server/receivepack" -) - -func TestWriteReportStatusWritesClassicStatus(t *testing.T) { - t.Parallel() - - var out bufferWriteFlusher - - base := common.NewSession(strings.NewReader(""), &out, common.Options{}) - session := receivepack.NewSession(base, receivepack.Capabilities{}) - - err := session.WriteReportStatus(receivepack.ReportStatusResult{ - Commands: []receivepack.CommandResult{ - {Name: "refs/heads/main"}, - {Name: "refs/heads/dev", Error: "non-fast-forward"}, - }, - }) - if err != nil { - t.Fatalf("WriteReportStatus: %v", err) - } - - got := out.String() - wantParts := []string{ - "unpack ok\n", - "ok refs/heads/main\n", - "ng refs/heads/dev non-fast-forward\n", - "0000", - } - - for _, part := range wantParts { - if !strings.Contains(got, part) { - t.Fatalf("report-status missing %q in %q", part, got) - } - } -} - -func TestWriteReportStatusUsesSideBand64KWhenNegotiated(t *testing.T) { - t.Parallel() - - //nolint:thelper - testgit.ForEachAlgorithm(t, func(t *testing.T, algo objectid.Algorithm) { - t.Parallel() - - var requestWire bufferWriteFlusher - - requestEnc := pktline.NewEncoder(&requestWire) - - err := requestEnc.WriteData([]byte( - objectid.Zero(algo).String() + " " + mustHexID(t, algo, "1").String() + " refs/heads/main\x00report-status side-band-64k object-format=" + algo.String() + "\n", - )) - if err != nil { - t.Fatalf("WriteData(request): %v", err) - } - - err = requestEnc.WriteFlush() - if err != nil { - t.Fatalf("WriteFlush(request): %v", err) - } - - var out bufferWriteFlusher - - base := common.NewSession(strings.NewReader(requestWire.String()), &out, common.Options{ - Algorithm: algo, - }) - session := receivepack.NewSession(base, receivepack.Capabilities{ - ReportStatus: true, - SideBand64K: true, - ObjectFormat: algo, - }) - - _, err = session.ReadRequest() - if err != nil { - t.Fatalf("ReadRequest: %v", err) - } - - err = session.WriteReportStatus(receivepack.ReportStatusResult{ - Commands: []receivepack.CommandResult{ - {Name: "refs/heads/main"}, - }, - }) - if err != nil { - t.Fatalf("WriteReportStatus: %v", err) - } - - dec := sideband64k.NewDecoder(strings.NewReader(out.String()), sideband64k.ReadOptions{}) - - frame, err := dec.ReadFrame() - if err != nil { - t.Fatalf("ReadFrame(unpack): %v", err) - } - - if frame.Type != sideband64k.FrameData { - t.Fatalf("first frame = %#v", frame) - } - - statusDec := pktline.NewDecoder(strings.NewReader(string(frame.Payload)), pktline.ReadOptions{}) - - statusFrame, err := statusDec.ReadFrame() - if err != nil { - t.Fatalf("ReadFrame(unpack status): %v", err) - } - - if statusFrame.Type != pktline.PacketData || string(statusFrame.Payload) != "unpack ok\n" { - t.Fatalf("first status frame = %#v", statusFrame) - } - - statusFrame, err = statusDec.ReadFrame() - if err != nil { - t.Fatalf("ReadFrame(ok status): %v", err) - } - - if statusFrame.Type != pktline.PacketData || string(statusFrame.Payload) != "ok refs/heads/main\n" { - t.Fatalf("second status frame = %#v", statusFrame) - } - - statusFrame, err = statusDec.ReadFrame() - if err != nil { - t.Fatalf("ReadFrame(status flush): %v", err) - } - - if statusFrame.Type != pktline.PacketFlush { - t.Fatalf("status flush frame.Type = %v, want FrameFlush", statusFrame.Type) - } - - frame, err = dec.ReadFrame() - if err != nil { - t.Fatalf("ReadFrame(outer flush): %v", err) - } - - if frame.Type != sideband64k.FrameFlush { - t.Fatalf("outer flush frame.Type = %v, want FrameFlush", frame.Type) - } - }) -} - -func TestWriteReportStatusV2WritesOptionLines(t *testing.T) { - t.Parallel() - - //nolint:thelper - testgit.ForEachAlgorithm(t, func(t *testing.T, algo objectid.Algorithm) { - t.Parallel() - - oldID := mustHexID(t, algo, "1") - newID := mustHexID(t, algo, "2") - - var out bufferWriteFlusher - - base := common.NewSession(strings.NewReader(""), &out, common.Options{}) - session := receivepack.NewSession(base, receivepack.Capabilities{}) - - err := session.WriteReportStatusV2(receivepack.ReportStatusResult{ - Commands: []receivepack.CommandResult{ - { - Name: "refs/pseudo/proc", - RefName: "refs/heads/main", - OldID: &oldID, - NewID: &newID, - ForcedUpdate: true, - }, - {Name: "refs/heads/dev", Error: "rejected"}, - }, - }) - if err != nil { - t.Fatalf("WriteReportStatusV2: %v", err) - } - - got := out.String() - wantParts := []string{ - "unpack ok\n", - "ok refs/pseudo/proc\n", - "option refname refs/heads/main\n", - "option old-oid " + oldID.String() + "\n", - "option new-oid " + newID.String() + "\n", - "option forced-update\n", - "ng refs/heads/dev rejected\n", - "0000", - } - - for _, part := range wantParts { - if !strings.Contains(got, part) { - t.Fatalf("report-status-v2 missing %q in %q", part, got) - } - } - }) -} - -func TestWriteProgressRequiresSideBand64K(t *testing.T) { - t.Parallel() - - base := common.NewSession(strings.NewReader(""), &bufferWriteFlusher{}, common.Options{}) - session := receivepack.NewSession(base, receivepack.Capabilities{}) - - err := session.WriteProgress([]byte("progress\n")) - if !errors.Is(err, common.ErrSideBandNotEnabled) { - t.Fatalf("WriteProgress error = %v, want %v", err, common.ErrSideBandNotEnabled) - } -} - -func TestProgressWriterDiscardsWithoutSideBand64K(t *testing.T) { - t.Parallel() - - var out bufferWriteFlusher - - base := common.NewSession(strings.NewReader(""), &out, common.Options{}) - session := receivepack.NewSession(base, receivepack.Capabilities{}) - - n, err := io.WriteString(session.ProgressWriter(), "progress line\n") - if err != nil { - t.Fatalf("ProgressWriter.Write: %v", err) - } - - if n != len("progress line\n") { - t.Fatalf("ProgressWriter.Write n = %d, want %d", n, len("progress line\n")) - } - - if out.String() != "" { - t.Fatalf("unexpected wire output without side-band-64k: %q", out.String()) - } -} - -func TestProgressWriterUsesSideBand64KWhenNegotiated(t *testing.T) { - t.Parallel() - - //nolint:thelper - testgit.ForEachAlgorithm(t, func(t *testing.T, algo objectid.Algorithm) { - t.Parallel() - - var requestWire bufferWriteFlusher - - requestEnc := pktline.NewEncoder(&requestWire) - - err := requestEnc.WriteData([]byte( - objectid.Zero(algo).String() + " " + mustHexID(t, algo, "1").String() + " refs/heads/main\x00report-status side-band-64k object-format=" + algo.String() + "\n", - )) - if err != nil { - t.Fatalf("WriteData(request): %v", err) - } - - err = requestEnc.WriteFlush() - if err != nil { - t.Fatalf("WriteFlush(request): %v", err) - } - - var out bufferWriteFlusher - - base := common.NewSession(strings.NewReader(requestWire.String()), &out, common.Options{ - Algorithm: algo, - }) - session := receivepack.NewSession(base, receivepack.Capabilities{ - ReportStatus: true, - SideBand64K: true, - ObjectFormat: algo, - }) - - _, err = session.ReadRequest() - if err != nil { - t.Fatalf("ReadRequest: %v", err) - } - - _, err = io.WriteString(session.ProgressWriter(), "remote: stage 1\r") - if err != nil { - t.Fatalf("ProgressWriter.Write: %v", err) - } - - dec := sideband64k.NewDecoder(strings.NewReader(out.String()), sideband64k.ReadOptions{}) - - frame, err := dec.ReadFrame() - if err != nil { - t.Fatalf("ReadFrame(progress): %v", err) - } - - if frame.Type != sideband64k.FrameProgress { - t.Fatalf("frame.Type = %v, want FrameProgress", frame.Type) - } - - if string(frame.Payload) != "remote: stage 1\r" { - t.Fatalf("frame.Payload = %q, want %q", frame.Payload, "remote: stage 1\r") - } - }) -} diff --git a/protocol/v0v1/server/receivepack/session.go b/protocol/v0v1/server/receivepack/session.go deleted file mode 100644 index 1ea4ab35..00000000 --- a/protocol/v0v1/server/receivepack/session.go +++ /dev/null @@ -1,295 +0,0 @@ -package receivepack - -import ( - "fmt" - "io" - "strings" - - objectid "codeberg.org/lindenii/furgit/object/id" - common "codeberg.org/lindenii/furgit/protocol/v0v1/server" -) - -// Session is one stateful server-side receive-pack protocol session. -type Session struct { - base *common.Session - supported Capabilities - negotiated Capabilities -} - -// NewSession creates one receive-pack session over one common server session. -func NewSession(base *common.Session, supported Capabilities) *Session { - return &Session{ - base: base, - supported: supported, - } -} - -// AdvertiseRefs writes one receive-pack ref advertisement. -func (session *Session) AdvertiseRefs(ad common.Advertisement) error { - return session.base.AdvertiseRefs(ad, session.supported.Tokens(session.base.Algorithm())) -} - -// ReadRequest reads one receive-pack request through optional push-options. -func (session *Session) ReadRequest() (*Request, error) { - req := &Request{} - - var sawCommands bool - - for { - frame, err := session.base.ReadFrame() - if err != nil { - return nil, err - } - - switch frame.Type { - case common.FrameFlush: - goto afterCommands - case common.FrameData: - case common.FrameDelim, common.FrameResponseEnd: - return nil, &ProtocolError{Reason: fmt.Sprintf("unexpected packet type %v", frame.Type)} - } - - payload := string(frame.Payload) - if strings.HasPrefix(payload, "shallow ") { - line := trimOneLF(payload) - - shallowID, err := parseObjectID(session.base.Algorithm(), line[len("shallow "):]) - if err != nil { - return nil, err - } - - req.Shallow = append(req.Shallow, shallowID) - - continue - } - - if strings.HasPrefix(payload, "push-cert\x00") { - if sawCommands { - return nil, &ProtocolError{Reason: "got both push certificate and unsigned commands"} - } - - capabilityTokens, err := parseCapabilityList(payload[len("push-cert\x00"):]) - if err != nil { - return nil, err - } - - requested, err := parseRequestedCapabilities( - capabilityTokens, - session.supported, - session.base.Algorithm(), - ) - if err != nil { - return nil, err - } - - req.Capabilities = requested - - cert, err := session.readPushCertificate() - if err != nil { - return nil, err - } - - req.PushCert = cert - req.Commands = append(req.Commands, cert.Commands...) - sawCommands = true - - continue - } - - line := trimOneLF(payload) - if !sawCommands && strings.Contains(line, "\x00") { - commandPart, capPart, _ := strings.Cut(line, "\x00") - - capabilityTokens, err := parseCapabilityList(capPart) - if err != nil { - return nil, err - } - - requested, err := parseRequestedCapabilities( - capabilityTokens, - session.supported, - session.base.Algorithm(), - ) - if err != nil { - return nil, err - } - - req.Capabilities = requested - line = commandPart - } - - cmd, err := parseCommand(session.base.Algorithm(), line) - if err != nil { - return nil, err - } - - req.Commands = append(req.Commands, cmd) - sawCommands = true - } - -afterCommands: - if req.Capabilities.PushOptions { - for { - frame, err := session.base.ReadFrame() - if err != nil { - return nil, err - } - - switch frame.Type { - case common.FrameFlush: - goto afterPushOptions - case common.FrameData: - req.PushOptions = append(req.PushOptions, trimOneLF(string(frame.Payload))) - case common.FrameDelim, common.FrameResponseEnd: - return nil, &ProtocolError{Reason: fmt.Sprintf("unexpected packet type %v", frame.Type)} - } - } - } - -afterPushOptions: - req.DeleteOnly = deleteOnly(req.Commands) - - req.PackExpected = len(req.Commands) > 0 && !req.DeleteOnly - - session.negotiated = req.Capabilities - - if req.Capabilities.SideBand64K { - session.base.EnableSideBand64K() - } - - return req, nil -} - -// WriteProgress writes one progress packet. -func (session *Session) WriteProgress(p []byte) error { - return session.base.WriteProgress(p) -} - -// ProgressWriter returns one chunking writer for sideband progress output. -// -// When side-band-64k was not negotiated, writes are discarded. -func (session *Session) ProgressWriter() io.Writer { - return session.base.ProgressWriter() -} - -// WriteError writes one fatal error packet. -func (session *Session) WriteError(p []byte) error { - return session.base.WriteError(p) -} - -// ErrorWriter returns one chunking writer for sideband error output. -// -// When side-band-64k was not negotiated, writes are discarded. -func (session *Session) ErrorWriter() io.Writer { - return session.base.ErrorWriter() -} - -func trimOneLF(s string) string { - return strings.TrimSuffix(s, "\n") -} - -func parseObjectID(algo objectid.Algorithm, s string) (objectid.ObjectID, error) { - id, err := objectid.ParseHex(algo, s) - if err != nil { - return objectid.ObjectID{}, &ProtocolError{ - Reason: fmt.Sprintf("invalid object id %q", s), - } - } - - return id, nil -} - -func commandIsDelete(cmd Command) bool { - return cmd.NewID == objectid.Zero(cmd.NewID.Algorithm()) -} - -func deleteOnly(commands []Command) bool { - if len(commands) == 0 { - return false - } - - for _, cmd := range commands { - if !commandIsDelete(cmd) { - return false - } - } - - return true -} - -func parseCommand(algo objectid.Algorithm, line string) (Command, error) { - fields := strings.Fields(line) - if len(fields) != 3 { - return Command{}, &ProtocolError{Reason: fmt.Sprintf("malformed command %q", line)} - } - - oldID, err := parseObjectID(algo, fields[0]) - if err != nil { - return Command{}, err - } - - newID, err := parseObjectID(algo, fields[1]) - if err != nil { - return Command{}, err - } - - return Command{OldID: oldID, NewID: newID, Name: fields[2]}, nil -} - -func (session *Session) readPushCertificate() (*PushCertificate, error) { - cert := &PushCertificate{} - inCommands := false - inSignature := false - - for { - frame, err := session.base.ReadFrame() - if err != nil { - return nil, err - } - - switch frame.Type { - case common.FrameFlush: - return nil, &ProtocolError{Reason: "unexpected flush inside push certificate"} - case common.FrameData: - case common.FrameDelim, common.FrameResponseEnd: - return nil, &ProtocolError{Reason: fmt.Sprintf("unexpected packet type %v", frame.Type)} - } - - line := string(frame.Payload) - if line == "push-cert-end\n" { - return cert, nil - } - - if !inCommands { - if line == "\n" { - inCommands = true - - continue - } - - trimmed := trimOneLF(line) - cert.HeaderLines = append(cert.HeaderLines, trimmed) - - if strings.HasPrefix(trimmed, "push-option ") { - cert.EmbeddedOption = append(cert.EmbeddedOption, trimmed[len("push-option "):]) - } - - continue - } - - if !inSignature { - trimmed := trimOneLF(line) - - cmd, err := parseCommand(session.base.Algorithm(), trimmed) - if err == nil { - cert.Commands = append(cert.Commands, cmd) - - continue - } - - inSignature = true - } - - cert.SignatureLines = append(cert.SignatureLines, trimOneLF(line)) - } -} diff --git a/protocol/v0v1/server/receivepack/types.go b/protocol/v0v1/server/receivepack/types.go deleted file mode 100644 index b281a86b..00000000 --- a/protocol/v0v1/server/receivepack/types.go +++ /dev/null @@ -1,45 +0,0 @@ -package receivepack - -import objectid "codeberg.org/lindenii/furgit/object/id" - -// Command is one requested reference update. -type Command struct { - OldID objectid.ObjectID - NewID objectid.ObjectID - Name string -} - -// PushCertificate is one parsed push certificate block. -type PushCertificate struct { - HeaderLines []string - EmbeddedOption []string - Commands []Command - SignatureLines []string -} - -// Request is one parsed receive-pack request. -type Request struct { - Capabilities Capabilities - Shallow []objectid.ObjectID - Commands []Command - PushCert *PushCertificate - PushOptions []string - PackExpected bool - DeleteOnly bool -} - -// CommandResult is one per-command report-status result. -type CommandResult struct { - Name string - Error string - RefName string - OldID *objectid.ObjectID - NewID *objectid.ObjectID - ForcedUpdate bool -} - -// ReportStatusResult is one report-status payload. -type ReportStatusResult struct { - UnpackError string - Commands []CommandResult -} diff --git a/protocol/v0v1/server/session.go b/protocol/v0v1/server/session.go deleted file mode 100644 index 81939540..00000000 --- a/protocol/v0v1/server/session.go +++ /dev/null @@ -1,131 +0,0 @@ -package server - -import ( - "io" - - objectid "codeberg.org/lindenii/furgit/object/id" - "codeberg.org/lindenii/furgit/protocol/pktline" - "codeberg.org/lindenii/furgit/protocol/sideband64k" -) - -// Options configures one server-side v0/v1 session. -type Options struct { - // Version selects protocol v0 or v1 framing. - Version Version - // Algorithm is the repository object ID algorithm for this session. - Algorithm objectid.Algorithm -} - -// Session is one stateful server-side v0/v1 server protocol session. -type Session struct { - dec *pktline.Decoder - enc *pktline.Encoder - sideband *sideband64k.Encoder - opts Options - useSideBand bool -} - -// NewSession creates one v0/v1 server session over r and w. -func NewSession(r io.Reader, w pktline.WriteFlusher, opts Options) *Session { - return &Session{ - dec: pktline.NewDecoder(r, pktline.ReadOptions{}), - enc: pktline.NewEncoder(w), - sideband: sideband64k.NewEncoder(w), - opts: opts, - } -} - -// Algorithm returns the session object ID algorithm. -func (session *Session) Algorithm() objectid.Algorithm { - return session.opts.Algorithm -} - -// ReadFrame reads one low-level pkt-line frame from the session input. -func (session *Session) ReadFrame() (Frame, error) { - return session.dec.ReadFrame() -} - -// EnableSideBand64K enables side-band-64k output framing for subsequent data, -// progress, error, and flush writes. -func (session *Session) EnableSideBand64K() { - session.useSideBand = true -} - -// WriteData writes one primary output packet. -func (session *Session) WriteData(p []byte) error { - if session.useSideBand { - return session.sideband.WriteData(p) - } - - return session.enc.WriteData(p) -} - -// WriteProgress writes one progress packet. -func (session *Session) WriteProgress(p []byte) error { - if !session.useSideBand { - return ErrSideBandNotEnabled - } - - return session.sideband.WriteProgress(p) -} - -// WriteError writes one fatal error packet. -func (session *Session) WriteError(p []byte) error { - if !session.useSideBand { - return ErrSideBandNotEnabled - } - - return session.sideband.WriteError(p) -} - -// WriteFlush writes one trailing flush packet. -func (session *Session) WriteFlush() error { - if session.useSideBand { - return session.sideband.WriteFlush() - } - - return session.enc.WriteFlush() -} - -// FlushIO flushes buffered transport output without emitting pkt-line frames. -func (session *Session) FlushIO() error { - if session.useSideBand { - return session.sideband.FlushIO() - } - - return session.enc.FlushIO() -} - -// ProgressWriter returns one chunking writer for sideband progress output. -// -// When side-band-64k was not negotiated, writes are discarded. -func (session *Session) ProgressWriter() io.Writer { - if !session.useSideBand { - return io.Discard - } - - return sideband64k.NewChunkWriter(session.sideband, sideband64k.BandProgress) -} - -// ErrorWriter returns one chunking writer for sideband error output. -// -// When side-band-64k was not negotiated, writes are discarded. -func (session *Session) ErrorWriter() io.Writer { - if !session.useSideBand { - return io.Discard - } - - return sideband64k.NewChunkWriter(session.sideband, sideband64k.BandError) -} - -// PrimaryDataWriter returns one chunking writer for primary output bytes. -// -// When side-band-64k is enabled, writes are chunked into band-1 sideband -// frames. Otherwise writes are chunked into direct pkt-line data frames. -func (session *Session) PrimaryDataWriter() io.Writer { - if session.useSideBand { - return sideband64k.NewChunkWriter(session.sideband, sideband64k.BandData) - } - - return pktline.NewChunkWriter(session.enc) -} diff --git a/protocol/v0v1/server/version.go b/protocol/v0v1/server/version.go deleted file mode 100644 index 23ae9466..00000000 --- a/protocol/v0v1/server/version.go +++ /dev/null @@ -1,12 +0,0 @@ -package server - -// Version identifies the protocol version used on one v0/v1 server session. -type Version uint8 - -const ( - // Version0 is the original protocol framing with no leading version line. - Version0 Version = iota - // Version1 is protocol v1, which is v0 plus one leading "version 1\n" - // pkt-line before ref advertisement. - Version1 -) |
