7f9d66ae157510adf84a0630c4238e016c4e1fce
[scm/test.git] / git / odb / blob.go
1 package odb
2
3 import (
4         "bytes"
5         "io"
6 )
7
8 // Blob represents a Git object of type "blob".
9 type Blob struct {
10         // Size is the total uncompressed size of the blob's contents.
11         Size int64
12         // Contents is a reader that yields the uncompressed blob contents. It
13         // may only be read once. It may or may not implement io.ReadSeeker.
14         Contents io.Reader
15
16         // closeFn is a function that is called to free any resources held by
17         // the Blob.  In particular, this will close a file, if the Blob is
18         // being read from a file on disk.
19         closeFn func() error
20 }
21
22 // NewBlobFromBytes returns a new *Blob that yields the data given.
23 func NewBlobFromBytes(contents []byte) *Blob {
24         return &Blob{
25                 Contents: bytes.NewReader(contents),
26                 Size:     int64(len(contents)),
27         }
28 }
29
30 // Type implements Object.ObjectType by returning the correct object type for
31 // Blobs, BlobObjectType.
32 func (b *Blob) Type() ObjectType { return BlobObjectType }
33
34 // Decode implements Object.Decode and decodes the uncompressed blob contents
35 // being read. It returns the number of bytes that it consumed off of the
36 // stream, which is always zero.
37 //
38 // If any errors are encountered while reading the blob, they will be returned.
39 func (b *Blob) Decode(r io.Reader, size int64) (n int, err error) {
40         b.Size = size
41         b.Contents = io.LimitReader(r, size)
42
43         b.closeFn = func() error {
44                 if closer, ok := r.(io.Closer); ok {
45                         return closer.Close()
46                 }
47                 return nil
48         }
49
50         return 0, nil
51 }
52
53 // Encode encodes the blob's contents to the given io.Writer, "w". If there was
54 // any error copying the blob's contents, that error will be returned.
55 //
56 // Otherwise, the number of bytes written will be returned.
57 func (b *Blob) Encode(to io.Writer) (n int, err error) {
58         nn, err := io.Copy(to, b.Contents)
59
60         return int(nn), err
61 }
62
63 // Closes closes any resources held by the open Blob, or returns nil if there
64 // were no errors.
65 func (b *Blob) Close() error {
66         if b.closeFn == nil {
67                 return nil
68         }
69         return b.closeFn()
70 }
71
72 // Equal returns whether the receiving and given blobs are equal, or in other
73 // words, whether they are represented by the same SHA-1 when saved to the
74 // object database.
75 func (b *Blob) Equal(other *Blob) bool {
76         if (b == nil) != (other == nil) {
77                 return false
78         }
79
80         if b != nil {
81                 return b.Contents == other.Contents &&
82                         b.Size == other.Size
83         }
84         return true
85 }