Jakob Borg 10 лет назад
Родитель
Сommit
7d766bf7c7

+ 2 - 2
Godeps/Godeps.json

@@ -19,7 +19,7 @@
 		},
 		{
 			"ImportPath": "github.com/calmh/xdr",
-			"Rev": "03e63d0b968219dd006b17c337f8a6581332f1ab"
+			"Rev": "bccf335c34c01760bdc89f98c952fcda696e27d2"
 		},
 		{
 			"ImportPath": "github.com/juju/ratelimit",
@@ -31,7 +31,7 @@
 		},
 		{
 			"ImportPath": "github.com/syncthing/protocol",
-			"Rev": "d2ec40bb67846f34d3c1e59714351127a2e869e9"
+			"Rev": "f9132cae85dcda1caba2f4ba78996d348b00ac6c"
 		},
 		{
 			"ImportPath": "github.com/syndtr/goleveldb/leveldb",

+ 12 - 14
Godeps/_workspace/src/github.com/calmh/xdr/cmd/genxdr/main.go

@@ -52,7 +52,7 @@ import (
 var encodeTpl = template.Must(template.New("encoder").Parse(`
 func (o {{.TypeName}}) EncodeXDR(w io.Writer) (int, error) {
 	var xw = xdr.NewWriter(w)
-	return o.encodeXDR(xw)
+	return o.EncodeXDRInto(xw)
 }//+n
 
 func (o {{.TypeName}}) MarshalXDR() ([]byte, error) {
@@ -70,11 +70,11 @@ func (o {{.TypeName}}) MustMarshalXDR() []byte {
 func (o {{.TypeName}}) AppendXDR(bs []byte) ([]byte, error) {
 	var aw = xdr.AppendWriter(bs)
 	var xw = xdr.NewWriter(&aw)
-	_, err := o.encodeXDR(xw)
+	_, err := o.EncodeXDRInto(xw)
 	return []byte(aw), err
 }//+n
 
-func (o {{.TypeName}}) encodeXDR(xw *xdr.Writer) (int, error) {
+func (o {{.TypeName}}) EncodeXDRInto(xw *xdr.Writer) (int, error) {
 	{{range $fieldInfo := .Fields}}
 		{{if not $fieldInfo.IsSlice}}
 			{{if ne $fieldInfo.Convert ""}}
@@ -87,7 +87,7 @@ func (o {{.TypeName}}) encodeXDR(xw *xdr.Writer) (int, error) {
 				{{end}}
 				xw.Write{{$fieldInfo.Encoder}}(o.{{$fieldInfo.Name}})
 			{{else}}
-				_, err := o.{{$fieldInfo.Name}}.encodeXDR(xw)
+				_, err := o.{{$fieldInfo.Name}}.EncodeXDRInto(xw)
 				if err != nil {
 					return xw.Tot(), err
 				}
@@ -105,7 +105,7 @@ func (o {{.TypeName}}) encodeXDR(xw *xdr.Writer) (int, error) {
 			{{else if $fieldInfo.IsBasic}}
 				xw.Write{{$fieldInfo.Encoder}}(o.{{$fieldInfo.Name}}[i])
 			{{else}}
-				_, err := o.{{$fieldInfo.Name}}[i].encodeXDR(xw)
+				_, err := o.{{$fieldInfo.Name}}[i].EncodeXDRInto(xw)
 				if err != nil {
 					return xw.Tot(), err
 				}
@@ -118,16 +118,16 @@ func (o {{.TypeName}}) encodeXDR(xw *xdr.Writer) (int, error) {
 
 func (o *{{.TypeName}}) DecodeXDR(r io.Reader) error {
 	xr := xdr.NewReader(r)
-	return o.decodeXDR(xr)
+	return o.DecodeXDRFrom(xr)
 }//+n
 
 func (o *{{.TypeName}}) UnmarshalXDR(bs []byte) error {
 	var br = bytes.NewReader(bs)
 	var xr = xdr.NewReader(br)
-	return o.decodeXDR(xr)
+	return o.DecodeXDRFrom(xr)
 }//+n
 
-func (o *{{.TypeName}}) decodeXDR(xr *xdr.Reader) error {
+func (o *{{.TypeName}}) DecodeXDRFrom(xr *xdr.Reader) error {
 	{{range $fieldInfo := .Fields}}
 		{{if not $fieldInfo.IsSlice}}
 			{{if ne $fieldInfo.Convert ""}}
@@ -139,7 +139,7 @@ func (o *{{.TypeName}}) decodeXDR(xr *xdr.Reader) error {
 					o.{{$fieldInfo.Name}} = xr.Read{{$fieldInfo.Encoder}}()
 				{{end}}
 			{{else}}
-				(&o.{{$fieldInfo.Name}}).decodeXDR(xr)
+				(&o.{{$fieldInfo.Name}}).DecodeXDRFrom(xr)
 			{{end}}
 		{{else}}
 			_{{$fieldInfo.Name}}Size := int(xr.ReadUint32())
@@ -155,7 +155,7 @@ func (o *{{.TypeName}}) decodeXDR(xr *xdr.Reader) error {
 				{{else if $fieldInfo.IsBasic}}
 					o.{{$fieldInfo.Name}}[i] = xr.Read{{$fieldInfo.Encoder}}()
 				{{else}}
-					(&o.{{$fieldInfo.Name}}[i]).decodeXDR(xr)
+					(&o.{{$fieldInfo.Name}}[i]).DecodeXDRFrom(xr)
 				{{end}}
 			}
 		{{end}}
@@ -257,7 +257,6 @@ func handleStruct(t *ast.StructType) []fieldInfo {
 			} else {
 				f = fieldInfo{
 					Name:      fn,
-					IsBasic:   false,
 					IsSlice:   true,
 					FieldType: tn,
 					Max:       max,
@@ -317,10 +316,9 @@ func generateDiagram(output io.Writer, s structInfo) {
 
 	for _, f := range fs {
 		tn := f.FieldType
-		sl := f.IsSlice
 		name := uncamelize(f.Name)
 
-		if sl {
+		if f.IsSlice {
 			fmt.Fprintf(output, "| %s |\n", center("Number of "+name, 61))
 			fmt.Fprintln(output, line)
 		}
@@ -347,7 +345,7 @@ func generateDiagram(output io.Writer, s structInfo) {
 			fmt.Fprintf(output, "/ %61s /\n", "")
 			fmt.Fprintln(output, line)
 		default:
-			if sl {
+			if f.IsSlice {
 				tn = "Zero or more " + tn + " Structures"
 				fmt.Fprintf(output, "/ %s /\n", center("", 61))
 				fmt.Fprintf(output, "\\ %s \\\n", center(tn, 61))

+ 6 - 0
Godeps/_workspace/src/github.com/syncthing/protocol/deviceid.go

@@ -6,6 +6,7 @@ import (
 	"bytes"
 	"crypto/sha256"
 	"encoding/base32"
+	"encoding/binary"
 	"errors"
 	"fmt"
 	"regexp"
@@ -67,6 +68,11 @@ func (n DeviceID) Equals(other DeviceID) bool {
 	return bytes.Compare(n[:], other[:]) == 0
 }
 
+// Short returns an integer representing bits 0-63 of the device ID.
+func (n DeviceID) Short() uint64 {
+	return binary.BigEndian.Uint64(n[:])
+}
+
 func (n *DeviceID) MarshalText() ([]byte, error) {
 	return []byte(n.String()), nil
 }

+ 2 - 2
Godeps/_workspace/src/github.com/syncthing/protocol/message.go

@@ -17,13 +17,13 @@ type FileInfo struct {
 	Name         string // max:8192
 	Flags        uint32
 	Modified     int64
-	Version      int64
+	Version      Vector
 	LocalVersion int64
 	Blocks       []BlockInfo
 }
 
 func (f FileInfo) String() string {
-	return fmt.Sprintf("File{Name:%q, Flags:0%o, Modified:%d, Version:%d, Size:%d, Blocks:%v}",
+	return fmt.Sprintf("File{Name:%q, Flags:0%o, Modified:%d, Version:%v, Size:%d, Blocks:%v}",
 		f.Name, f.Flags, f.Modified, f.Version, f.Size(), f.Blocks)
 }
 

+ 93 - 90
Godeps/_workspace/src/github.com/syncthing/protocol/message_xdr.go

@@ -51,7 +51,7 @@ struct IndexMessage {
 
 func (o IndexMessage) EncodeXDR(w io.Writer) (int, error) {
 	var xw = xdr.NewWriter(w)
-	return o.encodeXDR(xw)
+	return o.EncodeXDRInto(xw)
 }
 
 func (o IndexMessage) MarshalXDR() ([]byte, error) {
@@ -69,15 +69,15 @@ func (o IndexMessage) MustMarshalXDR() []byte {
 func (o IndexMessage) AppendXDR(bs []byte) ([]byte, error) {
 	var aw = xdr.AppendWriter(bs)
 	var xw = xdr.NewWriter(&aw)
-	_, err := o.encodeXDR(xw)
+	_, err := o.EncodeXDRInto(xw)
 	return []byte(aw), err
 }
 
-func (o IndexMessage) encodeXDR(xw *xdr.Writer) (int, error) {
+func (o IndexMessage) EncodeXDRInto(xw *xdr.Writer) (int, error) {
 	xw.WriteString(o.Folder)
 	xw.WriteUint32(uint32(len(o.Files)))
 	for i := range o.Files {
-		_, err := o.Files[i].encodeXDR(xw)
+		_, err := o.Files[i].EncodeXDRInto(xw)
 		if err != nil {
 			return xw.Tot(), err
 		}
@@ -88,7 +88,7 @@ func (o IndexMessage) encodeXDR(xw *xdr.Writer) (int, error) {
 	}
 	xw.WriteUint32(uint32(len(o.Options)))
 	for i := range o.Options {
-		_, err := o.Options[i].encodeXDR(xw)
+		_, err := o.Options[i].EncodeXDRInto(xw)
 		if err != nil {
 			return xw.Tot(), err
 		}
@@ -98,21 +98,21 @@ func (o IndexMessage) encodeXDR(xw *xdr.Writer) (int, error) {
 
 func (o *IndexMessage) DecodeXDR(r io.Reader) error {
 	xr := xdr.NewReader(r)
-	return o.decodeXDR(xr)
+	return o.DecodeXDRFrom(xr)
 }
 
 func (o *IndexMessage) UnmarshalXDR(bs []byte) error {
 	var br = bytes.NewReader(bs)
 	var xr = xdr.NewReader(br)
-	return o.decodeXDR(xr)
+	return o.DecodeXDRFrom(xr)
 }
 
-func (o *IndexMessage) decodeXDR(xr *xdr.Reader) error {
+func (o *IndexMessage) DecodeXDRFrom(xr *xdr.Reader) error {
 	o.Folder = xr.ReadString()
 	_FilesSize := int(xr.ReadUint32())
 	o.Files = make([]FileInfo, _FilesSize)
 	for i := range o.Files {
-		(&o.Files[i]).decodeXDR(xr)
+		(&o.Files[i]).DecodeXDRFrom(xr)
 	}
 	o.Flags = xr.ReadUint32()
 	_OptionsSize := int(xr.ReadUint32())
@@ -121,7 +121,7 @@ func (o *IndexMessage) decodeXDR(xr *xdr.Reader) error {
 	}
 	o.Options = make([]Option, _OptionsSize)
 	for i := range o.Options {
-		(&o.Options[i]).decodeXDR(xr)
+		(&o.Options[i]).DecodeXDRFrom(xr)
 	}
 	return xr.Error()
 }
@@ -145,9 +145,9 @@ FileInfo Structure:
 +                      Modified (64 bits)                       +
 |                                                               |
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-|                                                               |
-+                       Version (64 bits)                       +
-|                                                               |
+/                                                               /
+\                       Vector Structure                        \
+/                                                               /
 +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
 |                                                               |
 +                    Local Version (64 bits)                    +
@@ -165,7 +165,7 @@ struct FileInfo {
 	string Name<8192>;
 	unsigned int Flags;
 	hyper Modified;
-	hyper Version;
+	Vector Version;
 	hyper LocalVersion;
 	BlockInfo Blocks<>;
 }
@@ -174,7 +174,7 @@ struct FileInfo {
 
 func (o FileInfo) EncodeXDR(w io.Writer) (int, error) {
 	var xw = xdr.NewWriter(w)
-	return o.encodeXDR(xw)
+	return o.EncodeXDRInto(xw)
 }
 
 func (o FileInfo) MarshalXDR() ([]byte, error) {
@@ -192,22 +192,25 @@ func (o FileInfo) MustMarshalXDR() []byte {
 func (o FileInfo) AppendXDR(bs []byte) ([]byte, error) {
 	var aw = xdr.AppendWriter(bs)
 	var xw = xdr.NewWriter(&aw)
-	_, err := o.encodeXDR(xw)
+	_, err := o.EncodeXDRInto(xw)
 	return []byte(aw), err
 }
 
-func (o FileInfo) encodeXDR(xw *xdr.Writer) (int, error) {
+func (o FileInfo) EncodeXDRInto(xw *xdr.Writer) (int, error) {
 	if l := len(o.Name); l > 8192 {
 		return xw.Tot(), xdr.ElementSizeExceeded("Name", l, 8192)
 	}
 	xw.WriteString(o.Name)
 	xw.WriteUint32(o.Flags)
 	xw.WriteUint64(uint64(o.Modified))
-	xw.WriteUint64(uint64(o.Version))
+	_, err := o.Version.EncodeXDRInto(xw)
+	if err != nil {
+		return xw.Tot(), err
+	}
 	xw.WriteUint64(uint64(o.LocalVersion))
 	xw.WriteUint32(uint32(len(o.Blocks)))
 	for i := range o.Blocks {
-		_, err := o.Blocks[i].encodeXDR(xw)
+		_, err := o.Blocks[i].EncodeXDRInto(xw)
 		if err != nil {
 			return xw.Tot(), err
 		}
@@ -217,25 +220,25 @@ func (o FileInfo) encodeXDR(xw *xdr.Writer) (int, error) {
 
 func (o *FileInfo) DecodeXDR(r io.Reader) error {
 	xr := xdr.NewReader(r)
-	return o.decodeXDR(xr)
+	return o.DecodeXDRFrom(xr)
 }
 
 func (o *FileInfo) UnmarshalXDR(bs []byte) error {
 	var br = bytes.NewReader(bs)
 	var xr = xdr.NewReader(br)
-	return o.decodeXDR(xr)
+	return o.DecodeXDRFrom(xr)
 }
 
-func (o *FileInfo) decodeXDR(xr *xdr.Reader) error {
+func (o *FileInfo) DecodeXDRFrom(xr *xdr.Reader) error {
 	o.Name = xr.ReadStringMax(8192)
 	o.Flags = xr.ReadUint32()
 	o.Modified = int64(xr.ReadUint64())
-	o.Version = int64(xr.ReadUint64())
+	(&o.Version).DecodeXDRFrom(xr)
 	o.LocalVersion = int64(xr.ReadUint64())
 	_BlocksSize := int(xr.ReadUint32())
 	o.Blocks = make([]BlockInfo, _BlocksSize)
 	for i := range o.Blocks {
-		(&o.Blocks[i]).decodeXDR(xr)
+		(&o.Blocks[i]).DecodeXDRFrom(xr)
 	}
 	return xr.Error()
 }
@@ -266,7 +269,7 @@ struct BlockInfo {
 
 func (o BlockInfo) EncodeXDR(w io.Writer) (int, error) {
 	var xw = xdr.NewWriter(w)
-	return o.encodeXDR(xw)
+	return o.EncodeXDRInto(xw)
 }
 
 func (o BlockInfo) MarshalXDR() ([]byte, error) {
@@ -284,11 +287,11 @@ func (o BlockInfo) MustMarshalXDR() []byte {
 func (o BlockInfo) AppendXDR(bs []byte) ([]byte, error) {
 	var aw = xdr.AppendWriter(bs)
 	var xw = xdr.NewWriter(&aw)
-	_, err := o.encodeXDR(xw)
+	_, err := o.EncodeXDRInto(xw)
 	return []byte(aw), err
 }
 
-func (o BlockInfo) encodeXDR(xw *xdr.Writer) (int, error) {
+func (o BlockInfo) EncodeXDRInto(xw *xdr.Writer) (int, error) {
 	xw.WriteUint32(uint32(o.Size))
 	if l := len(o.Hash); l > 64 {
 		return xw.Tot(), xdr.ElementSizeExceeded("Hash", l, 64)
@@ -299,16 +302,16 @@ func (o BlockInfo) encodeXDR(xw *xdr.Writer) (int, error) {
 
 func (o *BlockInfo) DecodeXDR(r io.Reader) error {
 	xr := xdr.NewReader(r)
-	return o.decodeXDR(xr)
+	return o.DecodeXDRFrom(xr)
 }
 
 func (o *BlockInfo) UnmarshalXDR(bs []byte) error {
 	var br = bytes.NewReader(bs)
 	var xr = xdr.NewReader(br)
-	return o.decodeXDR(xr)
+	return o.DecodeXDRFrom(xr)
 }
 
-func (o *BlockInfo) decodeXDR(xr *xdr.Reader) error {
+func (o *BlockInfo) DecodeXDRFrom(xr *xdr.Reader) error {
 	o.Size = int32(xr.ReadUint32())
 	o.Hash = xr.ReadBytesMax(64)
 	return xr.Error()
@@ -369,7 +372,7 @@ struct RequestMessage {
 
 func (o RequestMessage) EncodeXDR(w io.Writer) (int, error) {
 	var xw = xdr.NewWriter(w)
-	return o.encodeXDR(xw)
+	return o.EncodeXDRInto(xw)
 }
 
 func (o RequestMessage) MarshalXDR() ([]byte, error) {
@@ -387,11 +390,11 @@ func (o RequestMessage) MustMarshalXDR() []byte {
 func (o RequestMessage) AppendXDR(bs []byte) ([]byte, error) {
 	var aw = xdr.AppendWriter(bs)
 	var xw = xdr.NewWriter(&aw)
-	_, err := o.encodeXDR(xw)
+	_, err := o.EncodeXDRInto(xw)
 	return []byte(aw), err
 }
 
-func (o RequestMessage) encodeXDR(xw *xdr.Writer) (int, error) {
+func (o RequestMessage) EncodeXDRInto(xw *xdr.Writer) (int, error) {
 	if l := len(o.Folder); l > 64 {
 		return xw.Tot(), xdr.ElementSizeExceeded("Folder", l, 64)
 	}
@@ -412,7 +415,7 @@ func (o RequestMessage) encodeXDR(xw *xdr.Writer) (int, error) {
 	}
 	xw.WriteUint32(uint32(len(o.Options)))
 	for i := range o.Options {
-		_, err := o.Options[i].encodeXDR(xw)
+		_, err := o.Options[i].EncodeXDRInto(xw)
 		if err != nil {
 			return xw.Tot(), err
 		}
@@ -422,16 +425,16 @@ func (o RequestMessage) encodeXDR(xw *xdr.Writer) (int, error) {
 
 func (o *RequestMessage) DecodeXDR(r io.Reader) error {
 	xr := xdr.NewReader(r)
-	return o.decodeXDR(xr)
+	return o.DecodeXDRFrom(xr)
 }
 
 func (o *RequestMessage) UnmarshalXDR(bs []byte) error {
 	var br = bytes.NewReader(bs)
 	var xr = xdr.NewReader(br)
-	return o.decodeXDR(xr)
+	return o.DecodeXDRFrom(xr)
 }
 
-func (o *RequestMessage) decodeXDR(xr *xdr.Reader) error {
+func (o *RequestMessage) DecodeXDRFrom(xr *xdr.Reader) error {
 	o.Folder = xr.ReadStringMax(64)
 	o.Name = xr.ReadStringMax(8192)
 	o.Offset = int64(xr.ReadUint64())
@@ -444,7 +447,7 @@ func (o *RequestMessage) decodeXDR(xr *xdr.Reader) error {
 	}
 	o.Options = make([]Option, _OptionsSize)
 	for i := range o.Options {
-		(&o.Options[i]).decodeXDR(xr)
+		(&o.Options[i]).DecodeXDRFrom(xr)
 	}
 	return xr.Error()
 }
@@ -475,7 +478,7 @@ struct ResponseMessage {
 
 func (o ResponseMessage) EncodeXDR(w io.Writer) (int, error) {
 	var xw = xdr.NewWriter(w)
-	return o.encodeXDR(xw)
+	return o.EncodeXDRInto(xw)
 }
 
 func (o ResponseMessage) MarshalXDR() ([]byte, error) {
@@ -493,11 +496,11 @@ func (o ResponseMessage) MustMarshalXDR() []byte {
 func (o ResponseMessage) AppendXDR(bs []byte) ([]byte, error) {
 	var aw = xdr.AppendWriter(bs)
 	var xw = xdr.NewWriter(&aw)
-	_, err := o.encodeXDR(xw)
+	_, err := o.EncodeXDRInto(xw)
 	return []byte(aw), err
 }
 
-func (o ResponseMessage) encodeXDR(xw *xdr.Writer) (int, error) {
+func (o ResponseMessage) EncodeXDRInto(xw *xdr.Writer) (int, error) {
 	xw.WriteBytes(o.Data)
 	xw.WriteUint32(uint32(o.Error))
 	return xw.Tot(), xw.Error()
@@ -505,16 +508,16 @@ func (o ResponseMessage) encodeXDR(xw *xdr.Writer) (int, error) {
 
 func (o *ResponseMessage) DecodeXDR(r io.Reader) error {
 	xr := xdr.NewReader(r)
-	return o.decodeXDR(xr)
+	return o.DecodeXDRFrom(xr)
 }
 
 func (o *ResponseMessage) UnmarshalXDR(bs []byte) error {
 	var br = bytes.NewReader(bs)
 	var xr = xdr.NewReader(br)
-	return o.decodeXDR(xr)
+	return o.DecodeXDRFrom(xr)
 }
 
-func (o *ResponseMessage) decodeXDR(xr *xdr.Reader) error {
+func (o *ResponseMessage) DecodeXDRFrom(xr *xdr.Reader) error {
 	o.Data = xr.ReadBytes()
 	o.Error = int32(xr.ReadUint32())
 	return xr.Error()
@@ -564,7 +567,7 @@ struct ClusterConfigMessage {
 
 func (o ClusterConfigMessage) EncodeXDR(w io.Writer) (int, error) {
 	var xw = xdr.NewWriter(w)
-	return o.encodeXDR(xw)
+	return o.EncodeXDRInto(xw)
 }
 
 func (o ClusterConfigMessage) MarshalXDR() ([]byte, error) {
@@ -582,11 +585,11 @@ func (o ClusterConfigMessage) MustMarshalXDR() []byte {
 func (o ClusterConfigMessage) AppendXDR(bs []byte) ([]byte, error) {
 	var aw = xdr.AppendWriter(bs)
 	var xw = xdr.NewWriter(&aw)
-	_, err := o.encodeXDR(xw)
+	_, err := o.EncodeXDRInto(xw)
 	return []byte(aw), err
 }
 
-func (o ClusterConfigMessage) encodeXDR(xw *xdr.Writer) (int, error) {
+func (o ClusterConfigMessage) EncodeXDRInto(xw *xdr.Writer) (int, error) {
 	if l := len(o.ClientName); l > 64 {
 		return xw.Tot(), xdr.ElementSizeExceeded("ClientName", l, 64)
 	}
@@ -597,7 +600,7 @@ func (o ClusterConfigMessage) encodeXDR(xw *xdr.Writer) (int, error) {
 	xw.WriteString(o.ClientVersion)
 	xw.WriteUint32(uint32(len(o.Folders)))
 	for i := range o.Folders {
-		_, err := o.Folders[i].encodeXDR(xw)
+		_, err := o.Folders[i].EncodeXDRInto(xw)
 		if err != nil {
 			return xw.Tot(), err
 		}
@@ -607,7 +610,7 @@ func (o ClusterConfigMessage) encodeXDR(xw *xdr.Writer) (int, error) {
 	}
 	xw.WriteUint32(uint32(len(o.Options)))
 	for i := range o.Options {
-		_, err := o.Options[i].encodeXDR(xw)
+		_, err := o.Options[i].EncodeXDRInto(xw)
 		if err != nil {
 			return xw.Tot(), err
 		}
@@ -617,22 +620,22 @@ func (o ClusterConfigMessage) encodeXDR(xw *xdr.Writer) (int, error) {
 
 func (o *ClusterConfigMessage) DecodeXDR(r io.Reader) error {
 	xr := xdr.NewReader(r)
-	return o.decodeXDR(xr)
+	return o.DecodeXDRFrom(xr)
 }
 
 func (o *ClusterConfigMessage) UnmarshalXDR(bs []byte) error {
 	var br = bytes.NewReader(bs)
 	var xr = xdr.NewReader(br)
-	return o.decodeXDR(xr)
+	return o.DecodeXDRFrom(xr)
 }
 
-func (o *ClusterConfigMessage) decodeXDR(xr *xdr.Reader) error {
+func (o *ClusterConfigMessage) DecodeXDRFrom(xr *xdr.Reader) error {
 	o.ClientName = xr.ReadStringMax(64)
 	o.ClientVersion = xr.ReadStringMax(64)
 	_FoldersSize := int(xr.ReadUint32())
 	o.Folders = make([]Folder, _FoldersSize)
 	for i := range o.Folders {
-		(&o.Folders[i]).decodeXDR(xr)
+		(&o.Folders[i]).DecodeXDRFrom(xr)
 	}
 	_OptionsSize := int(xr.ReadUint32())
 	if _OptionsSize > 64 {
@@ -640,7 +643,7 @@ func (o *ClusterConfigMessage) decodeXDR(xr *xdr.Reader) error {
 	}
 	o.Options = make([]Option, _OptionsSize)
 	for i := range o.Options {
-		(&o.Options[i]).decodeXDR(xr)
+		(&o.Options[i]).DecodeXDRFrom(xr)
 	}
 	return xr.Error()
 }
@@ -685,7 +688,7 @@ struct Folder {
 
 func (o Folder) EncodeXDR(w io.Writer) (int, error) {
 	var xw = xdr.NewWriter(w)
-	return o.encodeXDR(xw)
+	return o.EncodeXDRInto(xw)
 }
 
 func (o Folder) MarshalXDR() ([]byte, error) {
@@ -703,18 +706,18 @@ func (o Folder) MustMarshalXDR() []byte {
 func (o Folder) AppendXDR(bs []byte) ([]byte, error) {
 	var aw = xdr.AppendWriter(bs)
 	var xw = xdr.NewWriter(&aw)
-	_, err := o.encodeXDR(xw)
+	_, err := o.EncodeXDRInto(xw)
 	return []byte(aw), err
 }
 
-func (o Folder) encodeXDR(xw *xdr.Writer) (int, error) {
+func (o Folder) EncodeXDRInto(xw *xdr.Writer) (int, error) {
 	if l := len(o.ID); l > 64 {
 		return xw.Tot(), xdr.ElementSizeExceeded("ID", l, 64)
 	}
 	xw.WriteString(o.ID)
 	xw.WriteUint32(uint32(len(o.Devices)))
 	for i := range o.Devices {
-		_, err := o.Devices[i].encodeXDR(xw)
+		_, err := o.Devices[i].EncodeXDRInto(xw)
 		if err != nil {
 			return xw.Tot(), err
 		}
@@ -725,7 +728,7 @@ func (o Folder) encodeXDR(xw *xdr.Writer) (int, error) {
 	}
 	xw.WriteUint32(uint32(len(o.Options)))
 	for i := range o.Options {
-		_, err := o.Options[i].encodeXDR(xw)
+		_, err := o.Options[i].EncodeXDRInto(xw)
 		if err != nil {
 			return xw.Tot(), err
 		}
@@ -735,21 +738,21 @@ func (o Folder) encodeXDR(xw *xdr.Writer) (int, error) {
 
 func (o *Folder) DecodeXDR(r io.Reader) error {
 	xr := xdr.NewReader(r)
-	return o.decodeXDR(xr)
+	return o.DecodeXDRFrom(xr)
 }
 
 func (o *Folder) UnmarshalXDR(bs []byte) error {
 	var br = bytes.NewReader(bs)
 	var xr = xdr.NewReader(br)
-	return o.decodeXDR(xr)
+	return o.DecodeXDRFrom(xr)
 }
 
-func (o *Folder) decodeXDR(xr *xdr.Reader) error {
+func (o *Folder) DecodeXDRFrom(xr *xdr.Reader) error {
 	o.ID = xr.ReadStringMax(64)
 	_DevicesSize := int(xr.ReadUint32())
 	o.Devices = make([]Device, _DevicesSize)
 	for i := range o.Devices {
-		(&o.Devices[i]).decodeXDR(xr)
+		(&o.Devices[i]).DecodeXDRFrom(xr)
 	}
 	o.Flags = xr.ReadUint32()
 	_OptionsSize := int(xr.ReadUint32())
@@ -758,7 +761,7 @@ func (o *Folder) decodeXDR(xr *xdr.Reader) error {
 	}
 	o.Options = make([]Option, _OptionsSize)
 	for i := range o.Options {
-		(&o.Options[i]).decodeXDR(xr)
+		(&o.Options[i]).DecodeXDRFrom(xr)
 	}
 	return xr.Error()
 }
@@ -801,7 +804,7 @@ struct Device {
 
 func (o Device) EncodeXDR(w io.Writer) (int, error) {
 	var xw = xdr.NewWriter(w)
-	return o.encodeXDR(xw)
+	return o.EncodeXDRInto(xw)
 }
 
 func (o Device) MarshalXDR() ([]byte, error) {
@@ -819,11 +822,11 @@ func (o Device) MustMarshalXDR() []byte {
 func (o Device) AppendXDR(bs []byte) ([]byte, error) {
 	var aw = xdr.AppendWriter(bs)
 	var xw = xdr.NewWriter(&aw)
-	_, err := o.encodeXDR(xw)
+	_, err := o.EncodeXDRInto(xw)
 	return []byte(aw), err
 }
 
-func (o Device) encodeXDR(xw *xdr.Writer) (int, error) {
+func (o Device) EncodeXDRInto(xw *xdr.Writer) (int, error) {
 	if l := len(o.ID); l > 32 {
 		return xw.Tot(), xdr.ElementSizeExceeded("ID", l, 32)
 	}
@@ -835,7 +838,7 @@ func (o Device) encodeXDR(xw *xdr.Writer) (int, error) {
 	}
 	xw.WriteUint32(uint32(len(o.Options)))
 	for i := range o.Options {
-		_, err := o.Options[i].encodeXDR(xw)
+		_, err := o.Options[i].EncodeXDRInto(xw)
 		if err != nil {
 			return xw.Tot(), err
 		}
@@ -845,16 +848,16 @@ func (o Device) encodeXDR(xw *xdr.Writer) (int, error) {
 
 func (o *Device) DecodeXDR(r io.Reader) error {
 	xr := xdr.NewReader(r)
-	return o.decodeXDR(xr)
+	return o.DecodeXDRFrom(xr)
 }
 
 func (o *Device) UnmarshalXDR(bs []byte) error {
 	var br = bytes.NewReader(bs)
 	var xr = xdr.NewReader(br)
-	return o.decodeXDR(xr)
+	return o.DecodeXDRFrom(xr)
 }
 
-func (o *Device) decodeXDR(xr *xdr.Reader) error {
+func (o *Device) DecodeXDRFrom(xr *xdr.Reader) error {
 	o.ID = xr.ReadBytesMax(32)
 	o.MaxLocalVersion = int64(xr.ReadUint64())
 	o.Flags = xr.ReadUint32()
@@ -864,7 +867,7 @@ func (o *Device) decodeXDR(xr *xdr.Reader) error {
 	}
 	o.Options = make([]Option, _OptionsSize)
 	for i := range o.Options {
-		(&o.Options[i]).decodeXDR(xr)
+		(&o.Options[i]).DecodeXDRFrom(xr)
 	}
 	return xr.Error()
 }
@@ -899,7 +902,7 @@ struct Option {
 
 func (o Option) EncodeXDR(w io.Writer) (int, error) {
 	var xw = xdr.NewWriter(w)
-	return o.encodeXDR(xw)
+	return o.EncodeXDRInto(xw)
 }
 
 func (o Option) MarshalXDR() ([]byte, error) {
@@ -917,11 +920,11 @@ func (o Option) MustMarshalXDR() []byte {
 func (o Option) AppendXDR(bs []byte) ([]byte, error) {
 	var aw = xdr.AppendWriter(bs)
 	var xw = xdr.NewWriter(&aw)
-	_, err := o.encodeXDR(xw)
+	_, err := o.EncodeXDRInto(xw)
 	return []byte(aw), err
 }
 
-func (o Option) encodeXDR(xw *xdr.Writer) (int, error) {
+func (o Option) EncodeXDRInto(xw *xdr.Writer) (int, error) {
 	if l := len(o.Key); l > 64 {
 		return xw.Tot(), xdr.ElementSizeExceeded("Key", l, 64)
 	}
@@ -935,16 +938,16 @@ func (o Option) encodeXDR(xw *xdr.Writer) (int, error) {
 
 func (o *Option) DecodeXDR(r io.Reader) error {
 	xr := xdr.NewReader(r)
-	return o.decodeXDR(xr)
+	return o.DecodeXDRFrom(xr)
 }
 
 func (o *Option) UnmarshalXDR(bs []byte) error {
 	var br = bytes.NewReader(bs)
 	var xr = xdr.NewReader(br)
-	return o.decodeXDR(xr)
+	return o.DecodeXDRFrom(xr)
 }
 
-func (o *Option) decodeXDR(xr *xdr.Reader) error {
+func (o *Option) DecodeXDRFrom(xr *xdr.Reader) error {
 	o.Key = xr.ReadStringMax(64)
 	o.Value = xr.ReadStringMax(1024)
 	return xr.Error()
@@ -976,7 +979,7 @@ struct CloseMessage {
 
 func (o CloseMessage) EncodeXDR(w io.Writer) (int, error) {
 	var xw = xdr.NewWriter(w)
-	return o.encodeXDR(xw)
+	return o.EncodeXDRInto(xw)
 }
 
 func (o CloseMessage) MarshalXDR() ([]byte, error) {
@@ -994,11 +997,11 @@ func (o CloseMessage) MustMarshalXDR() []byte {
 func (o CloseMessage) AppendXDR(bs []byte) ([]byte, error) {
 	var aw = xdr.AppendWriter(bs)
 	var xw = xdr.NewWriter(&aw)
-	_, err := o.encodeXDR(xw)
+	_, err := o.EncodeXDRInto(xw)
 	return []byte(aw), err
 }
 
-func (o CloseMessage) encodeXDR(xw *xdr.Writer) (int, error) {
+func (o CloseMessage) EncodeXDRInto(xw *xdr.Writer) (int, error) {
 	if l := len(o.Reason); l > 1024 {
 		return xw.Tot(), xdr.ElementSizeExceeded("Reason", l, 1024)
 	}
@@ -1009,16 +1012,16 @@ func (o CloseMessage) encodeXDR(xw *xdr.Writer) (int, error) {
 
 func (o *CloseMessage) DecodeXDR(r io.Reader) error {
 	xr := xdr.NewReader(r)
-	return o.decodeXDR(xr)
+	return o.DecodeXDRFrom(xr)
 }
 
 func (o *CloseMessage) UnmarshalXDR(bs []byte) error {
 	var br = bytes.NewReader(bs)
 	var xr = xdr.NewReader(br)
-	return o.decodeXDR(xr)
+	return o.DecodeXDRFrom(xr)
 }
 
-func (o *CloseMessage) decodeXDR(xr *xdr.Reader) error {
+func (o *CloseMessage) DecodeXDRFrom(xr *xdr.Reader) error {
 	o.Reason = xr.ReadStringMax(1024)
 	o.Code = int32(xr.ReadUint32())
 	return xr.Error()
@@ -1040,7 +1043,7 @@ struct EmptyMessage {
 
 func (o EmptyMessage) EncodeXDR(w io.Writer) (int, error) {
 	var xw = xdr.NewWriter(w)
-	return o.encodeXDR(xw)
+	return o.EncodeXDRInto(xw)
 }
 
 func (o EmptyMessage) MarshalXDR() ([]byte, error) {
@@ -1058,25 +1061,25 @@ func (o EmptyMessage) MustMarshalXDR() []byte {
 func (o EmptyMessage) AppendXDR(bs []byte) ([]byte, error) {
 	var aw = xdr.AppendWriter(bs)
 	var xw = xdr.NewWriter(&aw)
-	_, err := o.encodeXDR(xw)
+	_, err := o.EncodeXDRInto(xw)
 	return []byte(aw), err
 }
 
-func (o EmptyMessage) encodeXDR(xw *xdr.Writer) (int, error) {
+func (o EmptyMessage) EncodeXDRInto(xw *xdr.Writer) (int, error) {
 	return xw.Tot(), xw.Error()
 }
 
 func (o *EmptyMessage) DecodeXDR(r io.Reader) error {
 	xr := xdr.NewReader(r)
-	return o.decodeXDR(xr)
+	return o.DecodeXDRFrom(xr)
 }
 
 func (o *EmptyMessage) UnmarshalXDR(bs []byte) error {
 	var br = bytes.NewReader(bs)
 	var xr = xdr.NewReader(br)
-	return o.decodeXDR(xr)
+	return o.DecodeXDRFrom(xr)
 }
 
-func (o *EmptyMessage) decodeXDR(xr *xdr.Reader) error {
+func (o *EmptyMessage) DecodeXDRFrom(xr *xdr.Reader) error {
 	return xr.Error()
 }

+ 105 - 0
Godeps/_workspace/src/github.com/syncthing/protocol/vector.go

@@ -0,0 +1,105 @@
+// Copyright (C) 2015 The Protocol Authors.
+
+package protocol
+
+// The Vector type represents a version vector. The zero value is a usable
+// version vector. The vector has slice semantics and some operations on it
+// are "append-like" in that they may return the same vector modified, or a
+// new allocated Vector with the modified contents.
+type Vector []Counter
+
+// Counter represents a single counter in the version vector.
+type Counter struct {
+	ID    uint64
+	Value uint64
+}
+
+// Update returns a Vector with the index for the specific ID incremented by
+// one. If it is possible, the vector v is updated and returned. If it is not,
+// a copy will be created, updated and returned.
+func (v Vector) Update(ID uint64) Vector {
+	for i := range v {
+		if v[i].ID == ID {
+			// Update an existing index
+			v[i].Value++
+			return v
+		} else if v[i].ID > ID {
+			// Insert a new index
+			nv := make(Vector, len(v)+1)
+			copy(nv, v[:i])
+			nv[i].ID = ID
+			nv[i].Value = 1
+			copy(nv[i+1:], v[i:])
+			return nv
+		}
+	}
+	// Append a new new index
+	return append(v, Counter{ID, 1})
+}
+
+// Merge returns the vector containing the maximum indexes from a and b. If it
+// is possible, the vector a is updated and returned. If it is not, a copy
+// will be created, updated and returned.
+func (a Vector) Merge(b Vector) Vector {
+	var ai, bi int
+	for bi < len(b) {
+		if ai == len(a) {
+			// We've reach the end of a, all that remains are appends
+			return append(a, b[bi:]...)
+		}
+
+		if a[ai].ID > b[bi].ID {
+			// The index from b should be inserted here
+			n := make(Vector, len(a)+1)
+			copy(n, a[:ai])
+			n[ai] = b[bi]
+			copy(n[ai+1:], a[ai:])
+			a = n
+		}
+
+		if a[ai].ID == b[bi].ID {
+			if v := b[bi].Value; v > a[ai].Value {
+				a[ai].Value = v
+			}
+		}
+
+		if bi < len(b) && a[ai].ID == b[bi].ID {
+			bi++
+		}
+		ai++
+	}
+
+	return a
+}
+
+// Copy returns an identical vector that is not shared with v.
+func (v Vector) Copy() Vector {
+	nv := make(Vector, len(v))
+	copy(nv, v)
+	return nv
+}
+
+// Equal returns true when the two vectors are equivalent.
+func (a Vector) Equal(b Vector) bool {
+	return a.Compare(b) == Equal
+}
+
+// LesserEqual returns true when the two vectors are equivalent or a is Lesser
+// than b.
+func (a Vector) LesserEqual(b Vector) bool {
+	comp := a.Compare(b)
+	return comp == Lesser || comp == Equal
+}
+
+// LesserEqual returns true when the two vectors are equivalent or a is Greater
+// than b.
+func (a Vector) GreaterEqual(b Vector) bool {
+	comp := a.Compare(b)
+	return comp == Greater || comp == Equal
+}
+
+// Concurrent returns true when the two vectors are concrurrent.
+func (a Vector) Concurrent(b Vector) bool {
+	comp := a.Compare(b)
+	return comp == ConcurrentGreater || comp == ConcurrentLesser
+}

+ 89 - 0
Godeps/_workspace/src/github.com/syncthing/protocol/vector_compare.go

@@ -0,0 +1,89 @@
+// Copyright (C) 2015 The Protocol Authors.
+
+package protocol
+
+// Ordering represents the relationship between two Vectors.
+type Ordering int
+
+const (
+	Equal Ordering = iota
+	Greater
+	Lesser
+	ConcurrentLesser
+	ConcurrentGreater
+)
+
+// There's really no such thing as "concurrent lesser" and "concurrent
+// greater" in version vectors, just "concurrent". But it's useful to be able
+// to get a strict ordering between versions for stable sorts and so on, so we
+// return both variants. The convenience method Concurrent() can be used to
+// check for either case.
+
+// Compare returns the Ordering that describes a's relation to b.
+func (a Vector) Compare(b Vector) Ordering {
+	var ai, bi int     // index into a and b
+	var av, bv Counter // value at current index
+
+	result := Equal
+
+	for ai < len(a) || bi < len(b) {
+		var aMissing, bMissing bool
+
+		if ai < len(a) {
+			av = a[ai]
+		} else {
+			av = Counter{}
+			aMissing = true
+		}
+
+		if bi < len(b) {
+			bv = b[bi]
+		} else {
+			bv = Counter{}
+			bMissing = true
+		}
+
+		switch {
+		case av.ID == bv.ID:
+			// We have a counter value for each side
+			if av.Value > bv.Value {
+				if result == Lesser {
+					return ConcurrentLesser
+				}
+				result = Greater
+			} else if av.Value < bv.Value {
+				if result == Greater {
+					return ConcurrentGreater
+				}
+				result = Lesser
+			}
+
+		case !aMissing && av.ID < bv.ID || bMissing:
+			// Value is missing on the b side
+			if av.Value > 0 {
+				if result == Lesser {
+					return ConcurrentLesser
+				}
+				result = Greater
+			}
+
+		case !bMissing && bv.ID < av.ID || aMissing:
+			// Value is missing on the a side
+			if bv.Value > 0 {
+				if result == Greater {
+					return ConcurrentGreater
+				}
+				result = Lesser
+			}
+		}
+
+		if ai < len(a) && (av.ID <= bv.ID || bMissing) {
+			ai++
+		}
+		if bi < len(b) && (bv.ID <= av.ID || aMissing) {
+			bi++
+		}
+	}
+
+	return result
+}

+ 249 - 0
Godeps/_workspace/src/github.com/syncthing/protocol/vector_compare_test.go

@@ -0,0 +1,249 @@
+// Copyright (C) 2015 The Protocol Authors.
+
+package protocol
+
+import (
+	"math"
+	"testing"
+)
+
+func TestCompare(t *testing.T) {
+	testcases := []struct {
+		a, b Vector
+		r    Ordering
+	}{
+		// Empty vectors are identical
+		{Vector{}, Vector{}, Equal},
+		{Vector{}, nil, Equal},
+		{nil, Vector{}, Equal},
+		{nil, Vector{Counter{42, 0}}, Equal},
+		{Vector{}, Vector{Counter{42, 0}}, Equal},
+		{Vector{Counter{42, 0}}, nil, Equal},
+		{Vector{Counter{42, 0}}, Vector{}, Equal},
+
+		// Zero is the implied value for a missing Counter
+		{
+			Vector{Counter{42, 0}},
+			Vector{Counter{77, 0}},
+			Equal,
+		},
+
+		// Equal vectors are equal
+		{
+			Vector{Counter{42, 33}},
+			Vector{Counter{42, 33}},
+			Equal,
+		},
+		{
+			Vector{Counter{42, 33}, Counter{77, 24}},
+			Vector{Counter{42, 33}, Counter{77, 24}},
+			Equal,
+		},
+
+		// These a-vectors are all greater than the b-vector
+		{
+			Vector{Counter{42, 1}},
+			nil,
+			Greater,
+		},
+		{
+			Vector{Counter{42, 1}},
+			Vector{},
+			Greater,
+		},
+		{
+			Vector{Counter{0, 1}},
+			Vector{Counter{0, 0}},
+			Greater,
+		},
+		{
+			Vector{Counter{42, 1}},
+			Vector{Counter{42, 0}},
+			Greater,
+		},
+		{
+			Vector{Counter{math.MaxUint64, 1}},
+			Vector{Counter{math.MaxUint64, 0}},
+			Greater,
+		},
+		{
+			Vector{Counter{0, math.MaxUint64}},
+			Vector{Counter{0, 0}},
+			Greater,
+		},
+		{
+			Vector{Counter{42, math.MaxUint64}},
+			Vector{Counter{42, 0}},
+			Greater,
+		},
+		{
+			Vector{Counter{math.MaxUint64, math.MaxUint64}},
+			Vector{Counter{math.MaxUint64, 0}},
+			Greater,
+		},
+		{
+			Vector{Counter{0, math.MaxUint64}},
+			Vector{Counter{0, math.MaxUint64 - 1}},
+			Greater,
+		},
+		{
+			Vector{Counter{42, math.MaxUint64}},
+			Vector{Counter{42, math.MaxUint64 - 1}},
+			Greater,
+		},
+		{
+			Vector{Counter{math.MaxUint64, math.MaxUint64}},
+			Vector{Counter{math.MaxUint64, math.MaxUint64 - 1}},
+			Greater,
+		},
+		{
+			Vector{Counter{42, 2}},
+			Vector{Counter{42, 1}},
+			Greater,
+		},
+		{
+			Vector{Counter{22, 22}, Counter{42, 2}},
+			Vector{Counter{22, 22}, Counter{42, 1}},
+			Greater,
+		},
+		{
+			Vector{Counter{42, 2}, Counter{77, 3}},
+			Vector{Counter{42, 1}, Counter{77, 3}},
+			Greater,
+		},
+		{
+			Vector{Counter{22, 22}, Counter{42, 2}, Counter{77, 3}},
+			Vector{Counter{22, 22}, Counter{42, 1}, Counter{77, 3}},
+			Greater,
+		},
+		{
+			Vector{Counter{22, 23}, Counter{42, 2}, Counter{77, 4}},
+			Vector{Counter{22, 22}, Counter{42, 1}, Counter{77, 3}},
+			Greater,
+		},
+
+		// These a-vectors are all lesser than the b-vector
+		{nil, Vector{Counter{42, 1}}, Lesser},
+		{Vector{}, Vector{Counter{42, 1}}, Lesser},
+		{
+			Vector{Counter{42, 0}},
+			Vector{Counter{42, 1}},
+			Lesser,
+		},
+		{
+			Vector{Counter{42, 1}},
+			Vector{Counter{42, 2}},
+			Lesser,
+		},
+		{
+			Vector{Counter{22, 22}, Counter{42, 1}},
+			Vector{Counter{22, 22}, Counter{42, 2}},
+			Lesser,
+		},
+		{
+			Vector{Counter{42, 1}, Counter{77, 3}},
+			Vector{Counter{42, 2}, Counter{77, 3}},
+			Lesser,
+		},
+		{
+			Vector{Counter{22, 22}, Counter{42, 1}, Counter{77, 3}},
+			Vector{Counter{22, 22}, Counter{42, 2}, Counter{77, 3}},
+			Lesser,
+		},
+		{
+			Vector{Counter{22, 22}, Counter{42, 1}, Counter{77, 3}},
+			Vector{Counter{22, 23}, Counter{42, 2}, Counter{77, 4}},
+			Lesser,
+		},
+
+		// These are all in conflict
+		{
+			Vector{Counter{42, 2}},
+			Vector{Counter{43, 1}},
+			ConcurrentGreater,
+		},
+		{
+			Vector{Counter{43, 1}},
+			Vector{Counter{42, 2}},
+			ConcurrentLesser,
+		},
+		{
+			Vector{Counter{22, 23}, Counter{42, 1}},
+			Vector{Counter{22, 22}, Counter{42, 2}},
+			ConcurrentGreater,
+		},
+		{
+			Vector{Counter{22, 21}, Counter{42, 2}},
+			Vector{Counter{22, 22}, Counter{42, 1}},
+			ConcurrentLesser,
+		},
+		{
+			Vector{Counter{22, 21}, Counter{42, 2}, Counter{43, 1}},
+			Vector{Counter{20, 1}, Counter{22, 22}, Counter{42, 1}},
+			ConcurrentLesser,
+		},
+	}
+
+	for i, tc := range testcases {
+		// Test real Compare
+		if r := tc.a.Compare(tc.b); r != tc.r {
+			t.Errorf("%d: %+v.Compare(%+v) == %v (expected %v)", i, tc.a, tc.b, r, tc.r)
+		}
+
+		// Test convenience functions
+		switch tc.r {
+		case Greater:
+			if tc.a.Equal(tc.b) {
+				t.Errorf("%+v == %+v", tc.a, tc.b)
+			}
+			if tc.a.Concurrent(tc.b) {
+				t.Errorf("%+v concurrent %+v", tc.a, tc.b)
+			}
+			if !tc.a.GreaterEqual(tc.b) {
+				t.Errorf("%+v not >= %+v", tc.a, tc.b)
+			}
+			if tc.a.LesserEqual(tc.b) {
+				t.Errorf("%+v <= %+v", tc.a, tc.b)
+			}
+		case Lesser:
+			if tc.a.Concurrent(tc.b) {
+				t.Errorf("%+v concurrent %+v", tc.a, tc.b)
+			}
+			if tc.a.Equal(tc.b) {
+				t.Errorf("%+v == %+v", tc.a, tc.b)
+			}
+			if tc.a.GreaterEqual(tc.b) {
+				t.Errorf("%+v >= %+v", tc.a, tc.b)
+			}
+			if !tc.a.LesserEqual(tc.b) {
+				t.Errorf("%+v not <= %+v", tc.a, tc.b)
+			}
+		case Equal:
+			if tc.a.Concurrent(tc.b) {
+				t.Errorf("%+v concurrent %+v", tc.a, tc.b)
+			}
+			if !tc.a.Equal(tc.b) {
+				t.Errorf("%+v not == %+v", tc.a, tc.b)
+			}
+			if !tc.a.GreaterEqual(tc.b) {
+				t.Errorf("%+v not <= %+v", tc.a, tc.b)
+			}
+			if !tc.a.LesserEqual(tc.b) {
+				t.Errorf("%+v not <= %+v", tc.a, tc.b)
+			}
+		case ConcurrentLesser, ConcurrentGreater:
+			if !tc.a.Concurrent(tc.b) {
+				t.Errorf("%+v not concurrent %+v", tc.a, tc.b)
+			}
+			if tc.a.Equal(tc.b) {
+				t.Errorf("%+v == %+v", tc.a, tc.b)
+			}
+			if tc.a.GreaterEqual(tc.b) {
+				t.Errorf("%+v >= %+v", tc.a, tc.b)
+			}
+			if tc.a.LesserEqual(tc.b) {
+				t.Errorf("%+v <= %+v", tc.a, tc.b)
+			}
+		}
+	}
+}

+ 122 - 0
Godeps/_workspace/src/github.com/syncthing/protocol/vector_test.go

@@ -0,0 +1,122 @@
+// Copyright (C) 2015 The Protocol Authors.
+
+package protocol
+
+import "testing"
+
+func TestUpdate(t *testing.T) {
+	var v Vector
+
+	// Append
+
+	v = v.Update(42)
+	expected := Vector{Counter{42, 1}}
+
+	if v.Compare(expected) != Equal {
+		t.Errorf("Update error, %+v != %+v", v, expected)
+	}
+
+	// Insert at front
+
+	v = v.Update(36)
+	expected = Vector{Counter{36, 1}, Counter{42, 1}}
+
+	if v.Compare(expected) != Equal {
+		t.Errorf("Update error, %+v != %+v", v, expected)
+	}
+
+	// Insert in moddle
+
+	v = v.Update(37)
+	expected = Vector{Counter{36, 1}, Counter{37, 1}, Counter{42, 1}}
+
+	if v.Compare(expected) != Equal {
+		t.Errorf("Update error, %+v != %+v", v, expected)
+	}
+
+	// Update existing
+
+	v = v.Update(37)
+	expected = Vector{Counter{36, 1}, Counter{37, 2}, Counter{42, 1}}
+
+	if v.Compare(expected) != Equal {
+		t.Errorf("Update error, %+v != %+v", v, expected)
+	}
+}
+
+func TestCopy(t *testing.T) {
+	v0 := Vector{Counter{42, 1}}
+	v1 := v0.Copy()
+	v1.Update(42)
+	if v0.Compare(v1) != Lesser {
+		t.Errorf("Copy error, %+v should be ancestor of %+v", v0, v1)
+	}
+}
+
+func TestMerge(t *testing.T) {
+	testcases := []struct {
+		a, b, m Vector
+	}{
+		// No-ops
+		{
+			Vector{},
+			Vector{},
+			Vector{},
+		},
+		{
+			Vector{Counter{22, 1}, Counter{42, 1}},
+			Vector{Counter{22, 1}, Counter{42, 1}},
+			Vector{Counter{22, 1}, Counter{42, 1}},
+		},
+
+		// Appends
+		{
+			Vector{},
+			Vector{Counter{22, 1}, Counter{42, 1}},
+			Vector{Counter{22, 1}, Counter{42, 1}},
+		},
+		{
+			Vector{Counter{22, 1}},
+			Vector{Counter{42, 1}},
+			Vector{Counter{22, 1}, Counter{42, 1}},
+		},
+		{
+			Vector{Counter{22, 1}},
+			Vector{Counter{22, 1}, Counter{42, 1}},
+			Vector{Counter{22, 1}, Counter{42, 1}},
+		},
+
+		// Insert
+		{
+			Vector{Counter{22, 1}, Counter{42, 1}},
+			Vector{Counter{22, 1}, Counter{23, 2}, Counter{42, 1}},
+			Vector{Counter{22, 1}, Counter{23, 2}, Counter{42, 1}},
+		},
+		{
+			Vector{Counter{42, 1}},
+			Vector{Counter{22, 1}},
+			Vector{Counter{22, 1}, Counter{42, 1}},
+		},
+
+		// Update
+		{
+			Vector{Counter{22, 1}, Counter{42, 2}},
+			Vector{Counter{22, 2}, Counter{42, 1}},
+			Vector{Counter{22, 2}, Counter{42, 2}},
+		},
+
+		// All of the above
+		{
+			Vector{Counter{10, 1}, Counter{20, 2}, Counter{30, 1}},
+			Vector{Counter{5, 1}, Counter{10, 2}, Counter{15, 1}, Counter{20, 1}, Counter{25, 1}, Counter{35, 1}},
+			Vector{Counter{5, 1}, Counter{10, 2}, Counter{15, 1}, Counter{20, 2}, Counter{25, 1}, Counter{30, 1}, Counter{35, 1}},
+		},
+	}
+
+	for i, tc := range testcases {
+		if m := tc.a.Merge(tc.b); m.Compare(tc.m) != Equal {
+			t.Errorf("%d: %+v.Merge(%+v) == %+v (expected %+v)", i, tc.a, tc.b, m, tc.m)
+		}
+	}
+
+}

+ 38 - 0
Godeps/_workspace/src/github.com/syncthing/protocol/vector_xdr.go

@@ -0,0 +1,38 @@
+// Copyright (C) 2015 The Protocol Authors.
+
+package protocol
+
+// This stuff is hacked up manually because genxdr doesn't support 'type
+// Vector []Counter' declarations and it was tricky when I tried to add it...
+
+type xdrWriter interface {
+	WriteUint32(uint32) (int, error)
+	WriteUint64(uint64) (int, error)
+}
+type xdrReader interface {
+	ReadUint32() uint32
+	ReadUint64() uint64
+}
+
+// EncodeXDRInto encodes the vector as an XDR object into the given XDR
+// encoder.
+func (v Vector) EncodeXDRInto(w xdrWriter) (int, error) {
+	w.WriteUint32(uint32(len(v)))
+	for i := range v {
+		w.WriteUint64(v[i].ID)
+		w.WriteUint64(v[i].Value)
+	}
+	return 4 + 16*len(v), nil
+}
+
+// DecodeXDRFrom decodes the XDR objects from the given reader into itself.
+func (v *Vector) DecodeXDRFrom(r xdrReader) error {
+	l := int(r.ReadUint32())
+	n := make(Vector, l)
+	for i := range n {
+		n[i].ID = r.ReadUint64()
+		n[i].Value = r.ReadUint64()
+	}
+	*v = n
+	return nil
+}