aboutsummaryrefslogtreecommitdiffstats
path: root/formats/packp/capabilities.go
diff options
context:
space:
mode:
authorAlberto Cortés <alcortesm@gmail.com>2016-10-26 17:56:26 +0200
committerMáximo Cuadros <mcuadros@gmail.com>2016-10-26 15:56:26 +0000
commit73fa9ef25a8af9c8337a4cf34a67cfe208f1a7c5 (patch)
tree66886d9b47e373b748c1bceafe1885e6f47868dd /formats/packp/capabilities.go
parentf3ab3a6c73015b5ae9b2a4756dc646e1211cedb9 (diff)
downloadgo-git-73fa9ef25a8af9c8337a4cf34a67cfe208f1a7c5.tar.gz
Use advrefs in gituploadpackinfo (#92)
* add advrefs encoder and parser * modify advrefs encoder to resemble json encoder * turn advrefs parser into a decoder * clean code * improve documentation * improve documentation * clean code * upgrade to new pktline.Add and add Flush const to easy integration * gometalinter * Use packp/advrefs for GitUploadPackInfo parsing - GitUploadPackInfo now uses packp/advrefs instead of parsing the message by itself. - Capabilities has been moved from clients/common to packp to avoid a circular import. - Cleaning of advrefs_test code. - Add support for prefix encoding and decoding in advrefs. * clean advrefs test code * clean advrefs test code * clean advrefs test code * gometalinter * add pktline encoder * change pktline.EncodeFlush to pktline.Flush * make scanner tests use the encoder instead of Pktlines * check errors on flush and clean constants * ubstitute the PktLines type with a pktline.Encoder * use pktline.Encoder in all go-git * add example of pktline.Encodef() * add package overview * documentation * support symbolic links other than HEAD * simplify decoding of shallows * packp: fix mcuadros comments - all abbreviates removed (by visual inspection, some may remain) - all empty maps are initialized using make - simplify readRef with a switch - make decodeShallow malformed error more verbose - add pktline.Encoder.encodeLine - remove infamous panic in checkPayloadLength by refactoring out the whole function
Diffstat (limited to 'formats/packp/capabilities.go')
-rw-r--r--formats/packp/capabilities.go136
1 files changed, 136 insertions, 0 deletions
diff --git a/formats/packp/capabilities.go b/formats/packp/capabilities.go
new file mode 100644
index 0000000..d77c2fa
--- /dev/null
+++ b/formats/packp/capabilities.go
@@ -0,0 +1,136 @@
+package packp
+
+import (
+ "fmt"
+ "sort"
+ "strings"
+)
+
+// Capabilities contains all the server capabilities
+// https://github.com/git/git/blob/master/Documentation/technical/protocol-capabilities.txt
+type Capabilities struct {
+ m map[string]*Capability
+ o []string
+}
+
+// Capability represents a server capability
+type Capability struct {
+ Name string
+ Values []string
+}
+
+// NewCapabilities returns a new Capabilities struct
+func NewCapabilities() *Capabilities {
+ return &Capabilities{
+ m: make(map[string]*Capability),
+ }
+}
+
+func (c *Capabilities) IsEmpty() bool {
+ return len(c.o) == 0
+}
+
+// Decode decodes a string
+func (c *Capabilities) Decode(raw string) {
+ params := strings.Split(raw, " ")
+ for _, p := range params {
+ s := strings.SplitN(p, "=", 2)
+
+ var value string
+ if len(s) == 2 {
+ value = s[1]
+ }
+
+ c.Add(s[0], value)
+ }
+}
+
+// Get returns the values for a capability
+func (c *Capabilities) Get(capability string) *Capability {
+ return c.m[capability]
+}
+
+// Set sets a capability removing the values
+func (c *Capabilities) Set(capability string, values ...string) {
+ if _, ok := c.m[capability]; ok {
+ delete(c.m, capability)
+ }
+
+ c.Add(capability, values...)
+}
+
+// Add adds a capability, values are optional
+func (c *Capabilities) Add(capability string, values ...string) {
+ if !c.Supports(capability) {
+ c.m[capability] = &Capability{Name: capability}
+ c.o = append(c.o, capability)
+ }
+
+ if len(values) == 0 {
+ return
+ }
+
+ c.m[capability].Values = append(c.m[capability].Values, values...)
+}
+
+// Supports returns true if capability is present
+func (c *Capabilities) Supports(capability string) bool {
+ _, ok := c.m[capability]
+ return ok
+}
+
+// SymbolicReference returns the reference for a given symbolic reference
+func (c *Capabilities) SymbolicReference(sym string) string {
+ if !c.Supports("symref") {
+ return ""
+ }
+
+ for _, symref := range c.Get("symref").Values {
+ parts := strings.Split(symref, ":")
+ if len(parts) != 2 {
+ continue
+ }
+
+ if parts[0] == sym {
+ return parts[1]
+ }
+ }
+
+ return ""
+}
+
+// Sorts capabilities in increasing order of their name
+func (c *Capabilities) Sort() {
+ sort.Strings(c.o)
+}
+
+func (c *Capabilities) String() string {
+ if len(c.o) == 0 {
+ return ""
+ }
+
+ var o string
+ for _, key := range c.o {
+ cap := c.m[key]
+
+ added := false
+ for _, value := range cap.Values {
+ if value == "" {
+ continue
+ }
+
+ added = true
+ o += fmt.Sprintf("%s=%s ", key, value)
+ }
+
+ if len(cap.Values) == 0 || !added {
+ o += key + " "
+ }
+ }
+
+ if len(o) == 0 {
+ return o
+ }
+
+ return o[:len(o)-1]
+}