Chromium Code Reviews| Index: go/src/infra/libs/git/object.go |
| diff --git a/go/src/infra/libs/git/object.go b/go/src/infra/libs/git/object.go |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..acb7f6b813a22ceda58d7193d45f3c4402b72d8c |
| --- /dev/null |
| +++ b/go/src/infra/libs/git/object.go |
| @@ -0,0 +1,89 @@ |
| +package git |
| + |
| +import "crypto/sha1" |
| +import "encoding/hex" |
| +import "fmt" |
| + |
| +// The empty ObjectID (all zeros) |
| +var NoID = ObjectID{} |
| + |
| +// MakeObjectIDForData hashes |data| as the git type |typ| (blob, commit, tree), |
| +// and returns an ObjectID for it. |
| +func MakeObjectIDForData(typ string, data []byte) ObjectID { |
| + h := sha1.New() |
| + h.Write([]byte(fmt.Sprintf("%s %d\x00", typ, len(data)))) |
| + h.Write(data) |
| + return MakeObjectIDRaw(h.Sum(nil)) |
| +} |
| + |
| +// MakeObjectIDRaw treats |raw| as a 20-byte Id. panic()'s if len(raw) is not 20 |
| +func MakeObjectIDRaw(raw []byte) (ret ObjectID) { |
| + if len(raw) != 20 { |
| + panic("MakeObjectIdRaw() must be invoked with a 20 byte string") |
| + } |
| + copy(ret.raw[:], raw) |
|
M-A Ruel
2014/10/18 00:47:06
Why not ret.raw = raw?
iannucci
2014/10/20 21:11:57
because I can't trust that the caller won't modify
|
| + return |
| +} |
| + |
| +// MakeObjectID decodes the 40-byte |hexval| into an ObjectID. panic()'s if |
| +// len(hexval) is not 40, or if it is not valid hexadecimal. |
| +func MakeObjectID(hexval string) ObjectID { |
| + if len(hexval) != 40 { |
| + panic("MakeObjectID() must be invoked with a 40 byte hex string") |
| + } |
| + raw, err := hex.DecodeString(hexval) |
| + if err != nil { |
| + panic(err) |
| + } |
| + return MakeObjectIDRaw(raw) |
| +} |
| + |
| +func (o ObjectID) String() string { |
| + if o != NoID { |
| + return hex.EncodeToString(o.raw[:]) |
|
M-A Ruel
2014/10/18 00:47:06
Why raw[:]?
iannucci
2014/10/20 21:11:57
Because raw is a [20]byte and not a []byte.
|
| + } |
| + return "<NoID>" |
| +} |
| + |
| +// RawString returns a git hash-object compatible (binary) representation |
| +// of the ObjectID (e.g. suitable for inclusion in a tree object output) |
| +func (o ObjectID) RawString() string { |
| + return string(o.raw[:]) |
| +} |
| + |
| +// EmptyObject is a placeholder Object which is not Internable, but can be |
| +// used to create a Complete() Tree. It can be of type "commit" or "blob". |
| +// It is never Complete(). |
| +type EmptyObject struct { |
| + id ObjectID |
| + typ string |
| +} |
| + |
| +func (o EmptyObject) ID() ObjectID { return o.id } |
| +func (o EmptyObject) Type() string { return o.typ } |
| +func (o EmptyObject) Complete() bool { return false } |
| +func (o EmptyObject) String() string { |
| + return fmt.Sprintf("EmptyObject(%s, %s)", o.ID(), o.Type()) |
| +} |
| + |
| +// NewEmptyObject returns an Object of type |typ| with no data. For "tree" types, |
| +// this returns an empty Tree (which is mutable). All other types are an |
| +// EmptyObject. |
| +func NewEmptyObject(typ string, id ObjectID) Object { |
| + switch typ { |
| + case "blob", "commit": |
| + return EmptyObject{id, typ} |
| + case "tree": |
| + return NewEmptyTree(id, 0) |
| + default: |
| + panic("unknown type " + typ) |
| + } |
| +} |
| + |
| +// NewEmptyChild returns a Child containing an EmptyObject of id. |
| +func NewEmptyChild(mode Mode, id ObjectID) *Child { |
| + return &Child{ |
| + NewEmptyObject(mode.Type(), id), |
| + mode, |
| + } |
| +} |