aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMáximo Cuadros <mcuadros@gmail.com>2015-10-31 00:40:50 +0100
committerMáximo Cuadros <mcuadros@gmail.com>2015-10-31 00:40:50 +0100
commitfe1fc1aa7dca3e0f6e54ab17f0acfa45f269e58c (patch)
tree71af4726ece2d944eedd7b568ec1d7e68fbc5f25
parentfcbb68e3658a7929fe4f7e306fa8e9b602ff48f3 (diff)
downloadgo-git-fe1fc1aa7dca3e0f6e54ab17f0acfa45f269e58c.tar.gz
clients: Capabilities parsing improvement and GitUploadPackInfo encoding
-rw-r--r--clients/common/common.go75
-rw-r--r--clients/common/common_test.go39
-rw-r--r--common_test.go5
-rw-r--r--remote.go7
4 files changed, 105 insertions, 21 deletions
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{
diff --git a/common_test.go b/common_test.go
index 446bc16..612afd1 100644
--- a/common_test.go
+++ b/common_test.go
@@ -28,9 +28,8 @@ func (s *MockGitUploadPackService) Info() (*common.GitUploadPackInfo, error) {
return &common.GitUploadPackInfo{
Capabilities: common.Capabilities(values),
- Refs: map[string]*common.RemoteHead{
- "refs/heads/master": &common.RemoteHead{Id: hash},
- },
+ Head: "refs/heads/master",
+ Refs: map[string]internal.Hash{"refs/heads/master": hash},
}, nil
}
diff --git a/remote.go b/remote.go
index 7d21710..1c74ce0 100644
--- a/remote.go
+++ b/remote.go
@@ -77,5 +77,10 @@ func (r *Remote) Ref(refName string) (internal.Hash, error) {
return internal.NewHash(""), fmt.Errorf("unable to find ref %q", refName)
}
- return ref.Id, nil
+ return ref, nil
+}
+
+// Refs returns the Hash pointing the given refName
+func (r *Remote) Refs() map[string]internal.Hash {
+ return r.upInfo.Refs
}