diff options
-rw-r--r-- | bug/bug.go | 2 | ||||
-rw-r--r-- | identity/identity.go | 2 | ||||
-rw-r--r-- | misc/random_bugs/create_random_bugs.go | 3 | ||||
-rw-r--r-- | repository/git.go | 4 | ||||
-rw-r--r-- | repository/mock_repo.go | 48 | ||||
-rw-r--r-- | repository/repo.go | 18 | ||||
-rw-r--r-- | repository/repo_testing.go | 130 |
7 files changed, 180 insertions, 27 deletions
@@ -138,7 +138,7 @@ func readBug(repo repository.ClockedRepo, ref string) (*Bug, error) { // Load each OperationPack for _, hash := range hashes { - entries, err := repo.ListEntries(hash) + entries, err := repo.ReadTree(hash) if err != nil { return nil, errors.Wrap(err, "can't list git tree entries") } diff --git a/identity/identity.go b/identity/identity.go index c1bca4d6..d6504c52 100644 --- a/identity/identity.go +++ b/identity/identity.go @@ -118,7 +118,7 @@ func read(repo repository.Repo, ref string) (*Identity, error) { } for _, hash := range hashes { - entries, err := repo.ListEntries(hash) + entries, err := repo.ReadTree(hash) if err != nil { return nil, errors.Wrap(err, "can't list git tree entries") } diff --git a/misc/random_bugs/create_random_bugs.go b/misc/random_bugs/create_random_bugs.go index b5c19e63..7ac18db4 100644 --- a/misc/random_bugs/create_random_bugs.go +++ b/misc/random_bugs/create_random_bugs.go @@ -5,10 +5,11 @@ import ( "strings" "time" + "github.com/icrowley/fake" + "github.com/MichaelMure/git-bug/bug" "github.com/MichaelMure/git-bug/identity" "github.com/MichaelMure/git-bug/repository" - "github.com/icrowley/fake" ) type opsGenerator func(bug.Interface, identity.Interface, int64) diff --git a/repository/git.go b/repository/git.go index e4cb57e6..83037307 100644 --- a/repository/git.go +++ b/repository/git.go @@ -337,8 +337,8 @@ func (repo *GitRepo) ListCommits(ref string) ([]git.Hash, error) { } -// ListEntries will return the list of entries in a Git tree -func (repo *GitRepo) ListEntries(hash git.Hash) ([]TreeEntry, error) { +// ReadTree will return the list of entries in a Git tree +func (repo *GitRepo) ReadTree(hash git.Hash) ([]TreeEntry, error) { stdout, err := repo.runGitCommand("ls-tree", string(hash)) if err != nil { diff --git a/repository/mock_repo.go b/repository/mock_repo.go index 04d9355e..cf572d87 100644 --- a/repository/mock_repo.go +++ b/repository/mock_repo.go @@ -3,6 +3,7 @@ package repository import ( "crypto/sha1" "fmt" + "strings" "github.com/MichaelMure/git-bug/util/git" "github.com/MichaelMure/git-bug/util/lamport" @@ -151,12 +152,12 @@ func (r *mockRepoForTest) CopyRef(source string, dest string) error { } func (r *mockRepoForTest) ListRefs(refspec string) ([]string, error) { - keys := make([]string, len(r.refs)) + var keys []string - i := 0 for k := range r.refs { - keys[i] = k - i++ + if strings.HasPrefix(k, refspec) { + keys = append(keys, k) + } } return keys, nil @@ -181,7 +182,7 @@ func (r *mockRepoForTest) ListCommits(ref string) ([]git.Hash, error) { return hashes, nil } -func (r *mockRepoForTest) ListEntries(hash git.Hash) ([]TreeEntry, error) { +func (r *mockRepoForTest) ReadTree(hash git.Hash) ([]TreeEntry, error) { var data string data, ok := r.trees[hash] @@ -205,11 +206,44 @@ func (r *mockRepoForTest) ListEntries(hash git.Hash) ([]TreeEntry, error) { } func (r *mockRepoForTest) FindCommonAncestor(hash1 git.Hash, hash2 git.Hash) (git.Hash, error) { - panic("implement me") + ancestor1 := []git.Hash{hash1} + + for hash1 != "" { + c, ok := r.commits[hash1] + if !ok { + return "", fmt.Errorf("unknown commit %v", hash1) + } + ancestor1 = append(ancestor1, c.parent) + hash1 = c.parent + } + + for { + for _, ancestor := range ancestor1 { + if ancestor == hash2 { + return ancestor, nil + } + } + + c, ok := r.commits[hash2] + if !ok { + return "", fmt.Errorf("unknown commit %v", hash1) + } + + if c.parent == "" { + return "", fmt.Errorf("no ancestor found") + } + + hash2 = c.parent + } } func (r *mockRepoForTest) GetTreeHash(commit git.Hash) (git.Hash, error) { - panic("implement me") + c, ok := r.commits[commit] + if !ok { + return "", fmt.Errorf("unknown commit") + } + + return c.treeHash, nil } func (r *mockRepoForTest) GetOrCreateClock(name string) (lamport.Clock, error) { diff --git a/repository/repo.go b/repository/repo.go index 561fc1c5..13bcca4f 100644 --- a/repository/repo.go +++ b/repository/repo.go @@ -66,12 +66,21 @@ type Repo interface { // StoreTree will store a mapping key-->Hash as a Git tree StoreTree(mapping []TreeEntry) (git.Hash, error) + // ReadTree will return the list of entries in a Git tree + ReadTree(hash git.Hash) ([]TreeEntry, error) + // StoreCommit will store a Git commit with the given Git tree StoreCommit(treeHash git.Hash) (git.Hash, error) // StoreCommit will store a Git commit with the given Git tree StoreCommitWithParent(treeHash git.Hash, parent git.Hash) (git.Hash, error) + // GetTreeHash return the git tree hash referenced in a commit + GetTreeHash(commit git.Hash) (git.Hash, error) + + // FindCommonAncestor will return the last common ancestor of two chain of commit + FindCommonAncestor(hash1 git.Hash, hash2 git.Hash) (git.Hash, error) + // UpdateRef will create or update a Git reference UpdateRef(ref string, hash git.Hash) error @@ -86,15 +95,6 @@ type Repo interface { // ListCommits will return the list of tree hashes of a ref, in chronological order ListCommits(ref string) ([]git.Hash, error) - - // ListEntries will return the list of entries in a Git tree - ListEntries(hash git.Hash) ([]TreeEntry, error) - - // FindCommonAncestor will return the last common ancestor of two chain of commit - FindCommonAncestor(hash1 git.Hash, hash2 git.Hash) (git.Hash, error) - - // GetTreeHash return the git tree hash referenced in a commit - GetTreeHash(commit git.Hash) (git.Hash, error) } // ClockedRepo is a Repo that also has Lamport clocks diff --git a/repository/repo_testing.go b/repository/repo_testing.go index 43bbaf14..01d69572 100644 --- a/repository/repo_testing.go +++ b/repository/repo_testing.go @@ -2,12 +2,15 @@ package repository import ( "log" + "math/rand" "os" "strings" "testing" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/MichaelMure/git-bug/util/git" ) func CleanupTestRepos(repos ...Repo) { @@ -46,19 +49,125 @@ type RepoCleaner func(repos ...Repo) // Test suite for a Repo implementation func RepoTest(t *testing.T, creator RepoCreator, cleaner RepoCleaner) { - t.Run("Read/Write data", func(t *testing.T) { + t.Run("Blob-Tree-Commit-Ref", func(t *testing.T) { repo := creator(false) defer cleaner(repo) - data := []byte("hello") + // Blob + + data := randomData() + + blobHash1, err := repo.StoreData(data) + require.NoError(t, err) + assert.True(t, blobHash1.IsValid()) + + blob1Read, err := repo.ReadData(blobHash1) + require.NoError(t, err) + assert.Equal(t, data, blob1Read) + + // Tree + + blobHash2, err := repo.StoreData(randomData()) + require.NoError(t, err) + blobHash3, err := repo.StoreData(randomData()) + require.NoError(t, err) + + tree1 := []TreeEntry{ + { + ObjectType: Blob, + Hash: blobHash1, + Name: "blob1", + }, + { + ObjectType: Blob, + Hash: blobHash2, + Name: "blob2", + }, + } + + treeHash1, err := repo.StoreTree(tree1) + require.NoError(t, err) + assert.True(t, treeHash1.IsValid()) + + tree1Read, err := repo.ReadTree(treeHash1) + require.NoError(t, err) + assert.ElementsMatch(t, tree1, tree1Read) + + tree2 := []TreeEntry{ + { + ObjectType: Tree, + Hash: treeHash1, + Name: "tree1", + }, + { + ObjectType: Blob, + Hash: blobHash3, + Name: "blob3", + }, + } + + treeHash2, err := repo.StoreTree(tree2) + require.NoError(t, err) + assert.True(t, treeHash2.IsValid()) + + tree2Read, err := repo.ReadTree(treeHash2) + require.NoError(t, err) + assert.ElementsMatch(t, tree2, tree2Read) + + // Commit + + commit1, err := repo.StoreCommit(treeHash1) + require.NoError(t, err) + assert.True(t, commit1.IsValid()) + + treeHash1Read, err := repo.GetTreeHash(commit1) + require.NoError(t, err) + assert.Equal(t, treeHash1, treeHash1Read) + + commit2, err := repo.StoreCommitWithParent(treeHash2, commit1) + require.NoError(t, err) + assert.True(t, commit2.IsValid()) + + treeHash2Read, err := repo.GetTreeHash(commit2) + require.NoError(t, err) + assert.Equal(t, treeHash2, treeHash2Read) + + // Ref + + exist1, err := repo.RefExist("refs/bugs/ref1") + require.NoError(t, err) + assert.False(t, exist1) + + err = repo.UpdateRef("refs/bugs/ref1", commit2) + require.NoError(t, err) + + exist1, err = repo.RefExist("refs/bugs/ref1") + require.NoError(t, err) + assert.True(t, exist1) - h, err := repo.StoreData(data) + ls, err := repo.ListRefs("refs/bugs") require.NoError(t, err) - assert.NotEmpty(t, h) + assert.Equal(t, []string{"refs/bugs/ref1"}, ls) - read, err := repo.ReadData(h) + err = repo.CopyRef("refs/bugs/ref1", "refs/bugs/ref2") require.NoError(t, err) - assert.Equal(t, data, read) + + ls, err = repo.ListRefs("refs/bugs") + require.NoError(t, err) + assert.Equal(t, []string{"refs/bugs/ref1", "refs/bugs/ref2"}, ls) + + commits, err := repo.ListCommits("refs/bugs/ref2") + require.NoError(t, err) + assert.Equal(t, []git.Hash{commit1, commit2}, commits) + + // Graph + + commit3, err := repo.StoreCommitWithParent(treeHash1, commit1) + require.NoError(t, err) + + ancestorHash, err := repo.FindCommonAncestor(commit2, commit3) + require.NoError(t, err) + assert.Equal(t, commit1, ancestorHash) }) t.Run("Local config", func(t *testing.T) { @@ -68,3 +177,12 @@ func RepoTest(t *testing.T, creator RepoCreator, cleaner RepoCleaner) { testConfig(t, repo.LocalConfig()) }) } + +func randomData() []byte { + var letterRunes = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" + b := make([]byte, 32) + for i := range b { + b[i] = letterRunes[rand.Intn(len(letterRunes))] + } + return b +} |