1 // Copyright 2009 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
17 func gitSHA1(data
[]byte) []byte {
19 // special case: 0 length is all zeros sum
20 return make([]byte, 20)
23 fmt
.Fprintf(h
, "blob %d\x00", len(data
))
28 // BUG(rsc): The Git binary delta format is not implemented, only Git binary literals.
30 // GitBinaryLiteral represents a Git binary literal diff.
31 type GitBinaryLiteral
struct {
32 OldSHA1
[]byte // if non-empty, the SHA1 hash of the original
33 New
[]byte // the new contents
36 // Apply implements the Diff interface's Apply method.
37 func (d
*GitBinaryLiteral
) Apply(old
[]byte) ([]byte, os
.Error
) {
38 if sum
:= gitSHA1(old
); !bytes
.HasPrefix(sum
, d
.OldSHA1
) {
39 return nil, ErrPatchFailure
44 func unhex(c
byte) uint8 {
46 case '0' <= c
&& c
<= '9':
48 case 'a' <= c
&& c
<= 'f':
50 case 'A' <= c
&& c
<= 'F':
56 func getHex(s
[]byte) (data
[]byte, rest
[]byte) {
58 for n
< len(s
) && unhex(s
[n
]) != 255 {
61 n
&^= 1 // Only take an even number of hex digits.
62 data
= make([]byte, n
/2)
64 data
[i
] = unhex(s
[2*i
])<<4 |
unhex(s
[2*i
+1])
70 // ParseGitBinary parses raw as a Git binary patch.
71 func ParseGitBinary(raw
[]byte) (Diff
, os
.Error
) {
72 var oldSHA1
, newSHA1
[]byte
77 first
, raw
, _
= getLine(raw
, 1)
78 first
= bytes
.TrimSpace(first
)
79 if s
, ok
:= skip(first
, "index "); ok
{
80 oldSHA1
, s
= getHex(s
)
81 if s
, ok
= skip(s
, ".."); !ok
{
84 newSHA1
, s
= getHex(s
)
87 if _
, ok
:= skip(first
, "GIT binary patch"); ok
{
91 if n
, _
, ok
:= atoi(first
, "literal ", 10); ok
&& sawBinary
{
92 data
:= make([]byte, n
)
93 d
:= git85
.NewDecoder(bytes
.NewBuffer(raw
))
94 z
, err
:= zlib
.NewReader(d
)
99 if _
, err
= io
.ReadFull(z
, data
); err
!= nil {
101 err
= io
.ErrUnexpectedEOF
106 m
, err
:= z
.Read(buf
[0:])
107 if m
!= 0 || err
!= os
.EOF
{
108 return nil, os
.NewError("Git binary literal longer than expected")
111 if sum
:= gitSHA1(data
); !bytes
.HasPrefix(sum
, newSHA1
) {
112 return nil, os
.NewError("Git binary literal SHA1 mismatch")
114 return &GitBinaryLiteral
{oldSHA1
, data
}, nil
117 return nil, os
.NewError("unexpected Git patch header: " + string(first
))