Skip to content

Commit

Permalink
packfile: permit methods on nil *Index
Browse files Browse the repository at this point in the history
  • Loading branch information
zombiezen committed Jan 24, 2021
1 parent b3394f8 commit 8b99452
Show file tree
Hide file tree
Showing 2 changed files with 56 additions and 4 deletions.
26 changes: 25 additions & 1 deletion packfile/index.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ head room.
*/

// Index is an in-memory mapping of object IDs to offsets within a packfile.
// This maps 1:1 with index files produced by git-index-pack(1).
// This maps 1:1 with index files produced by git-index-pack(1). (*Index)(nil)
// is treated the same as the Index for an empty packfile.
type Index struct {
// ObjectIDs is a sorted list of object IDs in the packfile.
ObjectIDs []githash.SHA1
Expand Down Expand Up @@ -234,6 +235,9 @@ func readFull(r io.Reader, buf []byte) (int, error) {

// EncodeV2 writes idx in Git's packfile index version 2 format.
func (idx *Index) EncodeV2(w io.Writer) error {
if idx == nil {
idx = &Index{PackfileSHA1: emptyPackfileSHA1()}
}
if err := idx.validate(); err != nil {
return fmt.Errorf("write packfile index: %w", err)
}
Expand Down Expand Up @@ -299,6 +303,9 @@ func (idx *Index) EncodeV2(w io.Writer) error {
// should only be used for compatibility, since the version 1 format does not
// store PackedChecksums and do not support packfiles larger than 4 GiB.
func (idx *Index) EncodeV1(w io.Writer) error {
if idx == nil {
idx = &Index{PackfileSHA1: emptyPackfileSHA1()}
}
if err := idx.validate(); err != nil {
return fmt.Errorf("write packfile index: %w", err)
}
Expand Down Expand Up @@ -370,6 +377,17 @@ func (idx *Index) encodeFanOut(w io.Writer) error {
return nil
}

func emptyPackfileSHA1() githash.SHA1 {
buf := new(bytes.Buffer)
w := NewWriter(buf, 0)
if err := w.Close(); err != nil {
panic(err)
}
var sum githash.SHA1
copy(sum[:], buf.Bytes()[buf.Len()-githash.SHA1Size:])
return sum
}

// MarshalBinary encodes the index in Git's packfile index version 2 format.
func (idx *Index) MarshalBinary() ([]byte, error) {
buf := new(bytes.Buffer)
Expand All @@ -383,6 +401,9 @@ func (idx *Index) MarshalBinary() ([]byte, error) {
// present in the index. The result is undefined if idx.ObjectIDs is not sorted.
// This search is O(log len(idx.ObjectIDs)).
func (idx *Index) FindID(id githash.SHA1) int {
if idx == nil {
return -1
}
i := sort.Search(len(idx.ObjectIDs), func(i int) bool {
return bytes.Compare(idx.ObjectIDs[i][:], id[:]) >= 0
})
Expand All @@ -394,6 +415,9 @@ func (idx *Index) FindID(id githash.SHA1) int {

// Len returns the number of objects in the index.
func (idx *Index) Len() int {
if idx == nil {
return 0
}
return len(idx.ObjectIDs)
}

Expand Down
34 changes: 31 additions & 3 deletions packfile/index_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,13 +124,27 @@ func TestIndexEncodeV1(t *testing.T) {
}
got := new(bytes.Buffer)
if err := test.wantIndex.EncodeV1(got); err != nil {
t.Error("ReadIndex:", err)
t.Error("EncodeV1:", err)
}
if diff := cmp.Diff(want, got.Bytes()); diff != "" {
t.Errorf("index (-want +got):\n%s", diff)
}
})
}

t.Run("Nil", func(t *testing.T) {
want, err := ioutil.ReadFile(filepath.Join("testdata", "Empty.idx1"))
if err != nil {
t.Fatal(err)
}
got := new(bytes.Buffer)
if err := (*Index)(nil).EncodeV1(got); err != nil {
t.Error("EncodeV1:", err)
}
if diff := cmp.Diff(want, got.Bytes()); diff != "" {
t.Errorf("index (-want +got):\n%s", diff)
}
})
}

func TestIndexEncodeV2(t *testing.T) {
Expand All @@ -145,7 +159,7 @@ func TestIndexEncodeV2(t *testing.T) {
}
got := new(bytes.Buffer)
if err := test.wantIndex.EncodeV2(got); err != nil {
t.Error("ReadIndex:", err)
t.Error("EncodeV2:", err)
}
if diff := cmp.Diff(want, got.Bytes()); diff != "" {
t.Errorf("index (-want +got):\n%s", diff)
Expand All @@ -160,7 +174,21 @@ func TestIndexEncodeV2(t *testing.T) {
}
got := new(bytes.Buffer)
if err := bigOffsetIndex.EncodeV2(got); err != nil {
t.Error("ReadIndex:", err)
t.Error("EncodeV2:", err)
}
if diff := cmp.Diff(want, got.Bytes()); diff != "" {
t.Errorf("index (-want +got):\n%s", diff)
}
})

t.Run("Nil", func(t *testing.T) {
want, err := ioutil.ReadFile(filepath.Join("testdata", "Empty.idx2"))
if err != nil {
t.Fatal(err)
}
got := new(bytes.Buffer)
if err := (*Index)(nil).EncodeV2(got); err != nil {
t.Error("EncodeV2:", err)
}
if diff := cmp.Diff(want, got.Bytes()); diff != "" {
t.Errorf("index (-want +got):\n%s", diff)
Expand Down

0 comments on commit 8b99452

Please sign in to comment.