From fe1fc1aa7dca3e0f6e54ab17f0acfa45f269e58c Mon Sep 17 00:00:00 2001 From: Máximo Cuadros Date: Sat, 31 Oct 2015 00:40:50 +0100 Subject: clients: Capabilities parsing improvement and GitUploadPackInfo encoding --- clients/common/common.go | 75 ++++++++++++++++++++++++++++++++++--------- clients/common/common_test.go | 39 ++++++++++++++++++++-- 2 files changed, 97 insertions(+), 17 deletions(-) (limited to 'clients') diff --git a/clients/common/common.go b/clients/common/common.go index 0140847..105e242 100644 --- a/clients/common/common.go +++ b/clients/common/common.go @@ -50,6 +50,40 @@ func parseCapabilities(line string) Capabilities { return Capabilities(values) } +func (c Capabilities) Decode(raw string) { + parts := strings.SplitN(raw, "HEAD", 2) + if len(parts) == 2 { + raw = parts[1] + } + + params := strings.Split(raw, " ") + for _, p := range params { + s := strings.SplitN(p, "=", 2) + + var value string + if len(s) == 2 { + value = s[1] + } + + c[s[0]] = append(c[s[0]], value) + } +} + +func (c Capabilities) String() string { + var o string + for key, values := range c { + if len(values) == 0 { + o += key + " " + } + + for _, value := range values { + o += fmt.Sprintf("%s=%s ", key, value) + } + } + + return o[:len(o)-1] +} + // Supports returns true if capability is preent func (r Capabilities) Supports(capability string) bool { _, ok := r[capability] @@ -81,14 +115,10 @@ func (r Capabilities) SymbolicReference(sym string) string { return "" } -type RemoteHead struct { - Id internal.Hash - Name string -} - type GitUploadPackInfo struct { Capabilities Capabilities - Refs map[string]*RemoteHead + Head string + Refs map[string]internal.Hash } func NewGitUploadPackInfo(d *pktline.Decoder) (*GitUploadPackInfo, error) { @@ -111,14 +141,15 @@ func (r *GitUploadPackInfo) read(d *pktline.Decoder) error { } isEmpty := true - r.Refs = map[string]*RemoteHead{} + r.Refs = map[string]internal.Hash{} for _, line := range lines { if !r.isValidLine(line) { continue } if r.Capabilities == nil { - r.Capabilities = parseCapabilities(line) + r.Capabilities = Capabilities{} + r.Capabilities.Decode(line) continue } @@ -142,17 +173,31 @@ func (r *GitUploadPackInfo) isValidLine(line string) bool { } func (r *GitUploadPackInfo) readLine(line string) { - rh := r.getRemoteHead(line) - r.Refs[rh.Name] = rh -} - -func (r *GitUploadPackInfo) getRemoteHead(line string) *RemoteHead { parts := strings.Split(strings.Trim(line, " \n"), " ") if len(parts) != 2 { - return nil + return } - return &RemoteHead{internal.NewHash(parts[0]), parts[1]} + r.Refs[parts[1]] = internal.NewHash(parts[0]) +} + +func (r *GitUploadPackInfo) String() string { + return string(r.Bytes()) +} + +func (r *GitUploadPackInfo) Bytes() []byte { + e := pktline.NewEncoder() + e.AddLine("# service=git-upload-pack") + e.AddFlush() + e.AddLine(fmt.Sprintf("%s HEAD%s", r.Refs[r.Head], r.Capabilities.String())) + + for name, id := range r.Refs { + e.AddLine(fmt.Sprintf("%s %s", id, name)) + } + + e.AddFlush() + b, _ := ioutil.ReadAll(e.Reader()) + return b } type GitUploadPackRequest struct { diff --git a/clients/common/common_test.go b/clients/common/common_test.go index b397ac9..ab2de7c 100644 --- a/clients/common/common_test.go +++ b/clients/common/common_test.go @@ -49,8 +49,7 @@ func (s *SuiteCommon) TestGitUploadPackInfo(c *C) { ref := info.Capabilities.SymbolicReference("HEAD") c.Assert(ref, Equals, "refs/heads/master") - c.Assert(info.Refs[ref].Id.String(), Equals, "6ecf0ef2c2dffb796033e5a02219af86ec6584e5") - c.Assert(info.Refs[ref].Name, Equals, "refs/heads/master") + c.Assert(info.Refs[ref].String(), Equals, "6ecf0ef2c2dffb796033e5a02219af86ec6584e5") } func (s *SuiteCommon) TestGitUploadPackInfoEmpty(c *C) { @@ -59,6 +58,42 @@ func (s *SuiteCommon) TestGitUploadPackInfoEmpty(c *C) { c.Assert(err, ErrorMatches, "permanent.*empty.*") } +func (s *SuiteCommon) TestCapabilitiesDecode(c *C) { + cap := Capabilities{} + cap.Decode("symref=foo symref=qux thin-pack") + + c.Assert(cap, HasLen, 2) + c.Assert(cap["symref"], DeepEquals, []string{"foo", "qux"}) + c.Assert(cap["thin-pack"], DeepEquals, []string{""}) +} + +func (s *SuiteCommon) TestCapabilitiesString(c *C) { + cap := Capabilities{ + "symref": []string{"foo", "qux"}, + } + + c.Assert(cap.String(), Equals, "symref=foo symref=qux") +} + +func (s *SuiteCommon) TestGitUploadPackEncode(c *C) { + info := &GitUploadPackInfo{} + info.Capabilities = map[string][]string{ + "symref": []string{"HEAD:refs/heads/master"}, + } + + info.Head = "refs/heads/master" + info.Refs = map[string]internal.Hash{ + "refs/heads/master": internal.NewHash("6ecf0ef2c2dffb796033e5a02219af86ec6584e5"), + } + + c.Assert(info.String(), Equals, + "001e# service=git-upload-pack\n"+ + "0000004f6ecf0ef2c2dffb796033e5a02219af86ec6584e5 HEADsymref=HEAD:refs/heads/master\n"+ + "003f6ecf0ef2c2dffb796033e5a02219af86ec6584e5 refs/heads/master\n"+ + "0000", + ) +} + func (s *SuiteCommon) TestGitUploadPackRequest(c *C) { r := &GitUploadPackRequest{ Want: []internal.Hash{ -- cgit