-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathobject.go
More file actions
167 lines (147 loc) · 2.89 KB
/
object.go
File metadata and controls
167 lines (147 loc) · 2.89 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
package git
import (
"encoding/hex"
"errors"
"fmt"
)
type ObjType int
const (
ObjNone = ObjType(iota)
ObjCommit
ObjTree
ObjBlob
ObjTag
objFutureExpansion
ObjOffsetDelta
ObjRefDelta
)
var typeFromString = map[string]ObjType{
"tree": ObjTree,
"commit": ObjCommit,
"blob": ObjBlob,
"tag": ObjTag,
}
func (t ObjType) String() string {
switch t {
case ObjCommit:
return "commit"
case ObjTree:
return "tree"
case ObjBlob:
return "blob"
case ObjTag:
return "tag"
case objFutureExpansion:
return "--"
case ObjOffsetDelta:
return "offset-delta"
case ObjRefDelta:
return "ref-delta"
default:
return fmt.Sprintf("ObjType(%d)", t)
}
}
type GitObject interface {
Name() *Ptr
Type() ObjType
Payload() ([]byte, error)
Load() (GitObject, error)
}
type Ptr struct {
hash [20]byte
}
// returns true if q is strictly less than p
func (p *Ptr) Less(q *Ptr) bool {
for i := 0; i < 20; i++ {
if q.hash[i] < p.hash[i] {
return true
}
if q.hash[i] != p.hash[i] {
return false
}
}
return false
}
func (p *Ptr) Equals(q *Ptr) bool {
for i := 0; i < 20; i++ {
if p.hash[i] != q.hash[i] {
return false
}
}
return true
}
func ParsePtr(s string) (p Ptr, ok bool) {
buf, err := hex.DecodeString(s)
if err != nil {
//fmt.Printf("Denied %s\n", err)
return
}
if len(buf) != 20 {
//fmt.Printf("len is %d\n", len(buf))
return
}
ok = true
copy(p.hash[:], buf)
return
}
func (p *Ptr) String() string {
return hex.EncodeToString(p.hash[:])
}
func objParse(hexref string) (ret Ptr, ok bool) {
z, err := hex.DecodeString(hexref)
if err != nil {
return
}
if len(z) != 20 {
return
}
copy(ret.hash[:], z)
ok = true
return
}
// what does this do exactly?
func (g *Git) ExpandRef(ref string) (*Ptr, error) {
z, err := hex.DecodeString(ref)
if err != nil {
return nil, err
}
if len(z) != 20 {
return nil, ErrInvalidRef
}
p := &Ptr{}
copy(p.hash[:], z)
return p, nil
}
var ErrInvalidRef = errors.New("invalid reference")
func (of *ObjFile) Close() error {
of.unz.Close()
return of.raw.Close()
}
func (of *ObjFile) Read(buf []byte) (int, error) {
return of.unz.Read(buf)
}
func (g *Git) verify(n *Ptr, t ObjType, data []byte) bool {
// TODO: verify hash
return true
}
// Interpret decodes the "payload" portion of a git object, given its
// type and name (hash). That is, the part that appears after the
// preamble (the preamble is the object type string, the length, and
// the NUL byte). Note that in packfiles, the type and length are
// encoded elseway, so the payload portion is all that appears.
// However, the preamble is included in the hash.
func (g *Git) Interpret(n *Ptr, t ObjType, data []byte) (GitObject, error) {
if g == nil {
panic("null")
}
switch t {
case ObjTree:
return g.loadTree(n, data)
case ObjCommit:
return g.loadCommit(n, data)
case ObjBlob:
return g.loadBlob(n, data)
default:
return nil, ErrUnknownObjectType
}
}