entity: add support for storing files

Michael Muré created

Change summary

entity/dag/common_test.go         |  6 +-
entity/dag/operation_pack_test.go | 71 +++++++++++++++++++++++++++++---
repository/tree_entry.go          | 10 ++++
3 files changed, 76 insertions(+), 11 deletions(-)

Detailed changes

entity/dag/common_test.go 🔗

@@ -21,9 +21,9 @@ import (
 type op1 struct {
 	author identity.Interface
 
-	OperationType int    `json:"type"`
-	Field1        string `json:"field_1"`
-	Files         []repository.Hash
+	OperationType int               `json:"type"`
+	Field1        string            `json:"field_1"`
+	Files         []repository.Hash `json:"files"`
 }
 
 func newOp1(author identity.Interface, field1 string, files ...repository.Hash) *op1 {

entity/dag/operation_pack_test.go 🔗

@@ -7,21 +7,16 @@ import (
 	"github.com/stretchr/testify/require"
 
 	"github.com/MichaelMure/git-bug/identity"
+	"github.com/MichaelMure/git-bug/repository"
 )
 
 func TestOperationPackReadWrite(t *testing.T) {
 	repo, id1, _, resolver, def := makeTestContext()
 
-	blobHash1, err := repo.StoreData(randomData())
-	require.NoError(t, err)
-
-	blobHash2, err := repo.StoreData(randomData())
-	require.NoError(t, err)
-
 	opp := &operationPack{
 		Author: id1,
 		Operations: []Operation{
-			newOp1(id1, "foo", blobHash1, blobHash2),
+			newOp1(id1, "foo"),
 			newOp2(id1, "bar"),
 		},
 		CreateTime: 123,
@@ -43,7 +38,7 @@ func TestOperationPackReadWrite(t *testing.T) {
 	opp3 := &operationPack{
 		Author: id1,
 		Operations: []Operation{
-			newOp1(id1, "foo", blobHash1, blobHash2),
+			newOp1(id1, "foo"),
 			newOp2(id1, "bar"),
 		},
 		CreateTime: 123,
@@ -94,6 +89,66 @@ func TestOperationPackSignedReadWrite(t *testing.T) {
 	require.Equal(t, opp.Id(), opp3.Id())
 }
 
+func TestOperationPackFiles(t *testing.T) {
+	repo, id1, _, resolver, def := makeTestContext()
+
+	blobHash1, err := repo.StoreData(randomData())
+	require.NoError(t, err)
+
+	blobHash2, err := repo.StoreData(randomData())
+	require.NoError(t, err)
+
+	opp := &operationPack{
+		Author: id1,
+		Operations: []Operation{
+			newOp1(id1, "foo", blobHash1, blobHash2),
+			newOp1(id1, "foo", blobHash2),
+		},
+		CreateTime: 123,
+		EditTime:   456,
+	}
+
+	commitHash, err := opp.Write(def, repo)
+	require.NoError(t, err)
+
+	commit, err := repo.ReadCommit(commitHash)
+	require.NoError(t, err)
+
+	opp2, err := readOperationPack(def, repo, resolver, commit)
+	require.NoError(t, err)
+
+	require.Equal(t, opp, opp2)
+
+	require.ElementsMatch(t, opp2.Operations[0].(OperationWithFiles).GetFiles(), []repository.Hash{
+		blobHash1,
+		blobHash2,
+	})
+	require.ElementsMatch(t, opp2.Operations[1].(OperationWithFiles).GetFiles(), []repository.Hash{
+		blobHash2,
+	})
+
+	tree, err := repo.ReadTree(commit.TreeHash)
+	require.NoError(t, err)
+
+	extraTreeHash, ok := repository.SearchTreeEntry(tree, extraEntryName)
+	require.True(t, ok)
+
+	extraTree, err := repo.ReadTree(extraTreeHash.Hash)
+	require.NoError(t, err)
+	require.ElementsMatch(t, extraTree, []repository.TreeEntry{
+		{
+			ObjectType: repository.Blob,
+			Hash:       blobHash1,
+			Name:       "file0",
+		},
+		{
+			ObjectType: repository.Blob,
+			Hash:       blobHash2,
+			Name:       "file1",
+		},
+	})
+}
+
 func randomData() []byte {
 	var letterRunes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
 	b := make([]byte, 32)

repository/tree_entry.go 🔗

@@ -100,3 +100,13 @@ func readTreeEntries(s string) ([]TreeEntry, error) {
 
 	return casted, nil
 }
+
+// SearchTreeEntry search a TreeEntry by name from an array
+func SearchTreeEntry(entries []TreeEntry, name string) (TreeEntry, bool) {
+	for _, entry := range entries {
+		if entry.Name == name {
+			return entry, true
+		}
+	}
+	return TreeEntry{}, false
+}