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..822a16aaf20b28c2af41ecd0fddb358eaa2347b9 |
| --- /dev/null |
| +++ b/go/src/infra/libs/git/object.go |
| @@ -0,0 +1,147 @@ |
| +// Copyright 2014 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| +package git |
| + |
| +import ( |
| + "crypto/sha1" |
| + "encoding/hex" |
| + "fmt" |
| +) |
| + |
| +type ObjectType uint8 |
|
M-A Ruel
2014/10/21 00:55:54
If it's exported, it's worth documenting. :)
|
| + |
| +const ( |
| + UnknownType ObjectType = iota |
| + CommitType |
| + BlobType |
| + TreeType |
|
M-A Ruel
2014/10/21 00:55:54
Y U NO TAG? Even if you explicitly do not support
iannucci
2016/05/23 21:53:42
Omission, though "tag" doesn't show up in tree obj
|
| +) |
| + |
| +func (o ObjectType) String() string { |
| + switch o { |
| + case CommitType: |
| + return "commit" |
| + case BlobType: |
| + return "blob" |
| + case TreeType: |
| + return "tree" |
| + default: |
| + return "UNKNOWN" |
|
Vadim Sh.
2014/10/21 15:26:59
panic too?
|
| + } |
| +} |
| + |
| +func MakeObjectType(s string) ObjectType { |
| + switch s { |
| + case "commit": |
| + return CommitType |
| + case "blob": |
| + return BlobType |
| + case "tree": |
| + return TreeType |
| + default: |
| + panic(fmt.Errorf("unknown object type %s", s)) |
| + } |
| +} |
| + |
| +// Object is the barest essence of a git object. It has a Type, and Id, and it |
| +// can tell you if this instance is 'complete' (does it contain all the data |
| +// necessary to re-create ID()?). |
| +// |
| +// If Complete() is true, you can down-cast this to: |
| +// *Tree, *Blob, *Commit |
| +// |
| +// If Complete() is false, you can down-cast this to: |
| +// *Tree, EmptyObject |
| +// |
| +// Note that Tree's are never EmptyObject's. |
|
agable
2014/10/21 17:01:35
nit: apostrophes
|
| +type Object interface { |
| + ID() ObjectID |
| + |
| + Type() ObjectType |
| + |
| + // Returns True iff RawString will produce a string which, when hashed, |
| + // matches ID() |
| + Complete() bool |
| +} |
| + |
| +// ObjectID is a 20-byte git-sha for any Object type. |
| +type ObjectID struct { |
|
M-A Ruel
2014/10/21 00:55:54
It's fine and shorter to use
type ObjectID [20] b
agable
2014/10/21 17:01:35
Was going to say the same thing. Not sure why this
iannucci
2016/05/23 21:53:42
Modifiable, and I can't have a type alias whose 'r
|
| + raw [20]byte |
| +} |
| + |
| +// 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 ObjectType, 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) |
| + return |
|
Vadim Sh.
2014/10/21 15:26:59
is this 'return' required here?
|
| +} |
| + |
| +// 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") |
|
M-A Ruel
2014/10/21 00:55:54
In general, packages should not panic. It's really
Vadim Sh.
2014/10/21 15:26:59
IMHO, panic is like assert. If caller doesn't full
|
| + } |
| + 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[:]) |
| + } |
| + 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 ObjectType |
| +} |
| + |
| +func (o EmptyObject) ID() ObjectID { return o.id } |
| +func (o EmptyObject) Type() ObjectType { 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 ObjectType, id ObjectID) Object { |
| + switch typ { |
| + case BlobType, CommitType: |
| + return EmptyObject{id, typ} |
| + case TreeType: |
| + return NewEmptyTree(id, 0) |
| + default: |
| + panic("unknown type " + typ.String()) |
| + } |
| +} |