From 54637e73135c25e089a265a00106337de6ce0987 Mon Sep 17 00:00:00 2001 From: Domas Monkus Date: Tue, 3 Nov 2020 11:19:36 +0200 Subject: [PATCH] Synchronization tool file history tests modified to set up a temporary git repo (#138) --- build/sync/plan/checks.go | 3 +- build/sync/plan/checks_test.go | 98 ++++++++++++++--------- build/sync/plan/git/file_history.go | 2 +- build/sync/plan/git/file_history_test.go | 62 ++++++++++++-- build/sync/plan/git/testdata/testfile.txt | 1 - go.sum | 2 + 6 files changed, 122 insertions(+), 46 deletions(-) delete mode 100644 build/sync/plan/git/testdata/testfile.txt diff --git a/build/sync/plan/checks.go b/build/sync/plan/checks.go index 1eabfbb..a65a255 100644 --- a/build/sync/plan/checks.go +++ b/build/sync/plan/checks.go @@ -133,8 +133,7 @@ func (f FileUnalteredChecker) Check(path string, setup Setup) error { } else { return fmt.Errorf("failed to get stat for %q: %v", trgPath, err) } - } - if srcInfo.IsDir() { + } else if srcInfo.IsDir() { return fmt.Errorf("%q is a directory in source repository", path) } diff --git a/build/sync/plan/checks_test.go b/build/sync/plan/checks_test.go index 6ea9600..3814400 100644 --- a/build/sync/plan/checks_test.go +++ b/build/sync/plan/checks_test.go @@ -7,8 +7,10 @@ import ( "path" "path/filepath" "testing" + "time" git "github.com/go-git/go-git/v5" + "github.com/go-git/go-git/v5/plumbing/object" "github.com/stretchr/testify/assert" "github.com/mattermost/mattermost-plugin-starter-template/build/sync/plan" @@ -48,7 +50,13 @@ func TestRepoIsCleanChecker(t *testing.T) { func TestPathExistsChecker(t *testing.T) { assert := assert.New(t) - wd, err := os.Getwd() + // Set up a working directory. + wd, err := ioutil.TempDir("", "repo") + assert.Nil(err) + defer os.RemoveAll(wd) + err = os.Mkdir(filepath.Join(wd, "t"), 0755) + assert.Nil(err) + err = ioutil.WriteFile(filepath.Join(wd, "t", "test"), []byte("lorem ipsum"), 0644) assert.Nil(err) checker := plan.PathExistsChecker{} @@ -61,30 +69,60 @@ func TestPathExistsChecker(t *testing.T) { } // Check with existing directory. - assert.Nil(checker.Check("testdata", ctx)) + assert.Nil(checker.Check("t", ctx)) // Check with existing file. - assert.Nil(checker.Check("testdata/a", ctx)) + assert.Nil(checker.Check("t/test", ctx)) err = checker.Check("nosuchpath", ctx) assert.NotNil(err) assert.True(plan.IsCheckFail(err)) } +func tempGitRepo(assert *assert.Assertions) (string, *git.Repository, func()) { + // Setup repository. + wd, err := ioutil.TempDir("", "repo") + assert.Nil(err) + + // Initialize a repository. + repo, err := git.PlainInit(wd, false) + assert.Nil(err) + w, err := repo.Worktree() + assert.Nil(err) + // Create repository files. + err = ioutil.WriteFile(filepath.Join(wd, "test"), + []byte("lorem ipsum"), 0644) + assert.Nil(err) + sig := &object.Signature{ + Name: "test", + Email: "test@example.com", + When: time.Now(), + } + _, err = w.Commit("initial commit", &git.CommitOptions{Author: sig}) + assert.Nil(err) + pathA := "a.txt" + err = ioutil.WriteFile(filepath.Join(wd, pathA), + []byte("lorem ipsum"), 0644) + assert.Nil(err) + _, err = w.Add(pathA) + assert.Nil(err) + _, err = w.Commit("add files", &git.CommitOptions{Author: sig}) + assert.Nil(err) + + return wd, repo, func() { os.RemoveAll(wd) } + +} + func TestUnalteredCheckerSameFile(t *testing.T) { assert := assert.New(t) - // Path to the root of the repo. - wd, err := filepath.Abs("../../../") - assert.Nil(err) - - gitRepo, err := git.PlainOpen(wd) - assert.Nil(err) + wd, repo, cleanup := tempGitRepo(assert) + defer cleanup() ctx := plan.Setup{ Source: plan.RepoSetup{ Path: wd, - Git: gitRepo, + Git: repo, }, Target: plan.RepoSetup{ Path: wd, @@ -96,25 +134,21 @@ func TestUnalteredCheckerSameFile(t *testing.T) { checker.Params.TargetRepo = plan.TargetRepo // Check with the same file - check should succeed - hashPath := "build/sync/plan/testdata/a" - err = checker.Check(hashPath, ctx) + hashPath := "a.txt" + err := checker.Check(hashPath, ctx) assert.Nil(err) } func TestUnalteredCheckerDifferentContents(t *testing.T) { assert := assert.New(t) - // Path to the root of the repo. - wd, err := filepath.Abs("../../../") - assert.Nil(err) - - gitRepo, err := git.PlainOpen(wd) - assert.Nil(err) + wd, repo, cleanup := tempGitRepo(assert) + defer cleanup() ctx := plan.Setup{ Source: plan.RepoSetup{ Path: wd, - Git: gitRepo, + Git: repo, }, Target: plan.RepoSetup{ Path: wd, @@ -126,25 +160,18 @@ func TestUnalteredCheckerDifferentContents(t *testing.T) { checker.Params.TargetRepo = plan.TargetRepo // Create a file with the same suffix path, but different contents. - hashPath := "build/sync/plan/testdata/a" tmpDir, err := ioutil.TempDir("", "test") assert.Nil(err) defer os.RemoveAll(tmpDir) - fullPath := filepath.Join(tmpDir, "build/sync/plan/testdata") - err = os.MkdirAll(fullPath, 0777) + err = ioutil.WriteFile(filepath.Join(tmpDir, "a.txt"), + []byte("not lorem ipsum"), 0644) assert.Nil(err) - file, err := os.OpenFile(filepath.Join(fullPath, "a"), os.O_CREATE|os.O_WRONLY, 0755) - assert.Nil(err) - _, err = file.WriteString("this file has different contents") - assert.Nil(err) - assert.Nil(file.Close()) // Set the plugin path to the temporary directory. ctx.Target.Path = tmpDir - - err = checker.Check(hashPath, ctx) + err = checker.Check("a.txt", ctx) assert.True(plan.IsCheckFail(err)) - assert.EqualError(err, fmt.Sprintf("file %q has been altered", filepath.Join(tmpDir, hashPath))) + assert.EqualError(err, fmt.Sprintf("file %q has been altered", filepath.Join(tmpDir, "a.txt"))) } @@ -153,13 +180,10 @@ func TestUnalteredCheckerDifferentContents(t *testing.T) { // the checker should pass. func TestUnalteredCheckerNonExistant(t *testing.T) { assert := assert.New(t) - hashPath := "build/sync/plan/testdata/a" + hashPath := "a.txt" - // Path to the root of the repo. - wd, err := filepath.Abs("../../../") - assert.Nil(err) - gitRepo, err := git.PlainOpen(wd) - assert.Nil(err) + wd, repo, cleanup := tempGitRepo(assert) + defer cleanup() // Temporary repo. tmpDir, err := ioutil.TempDir("", "test") @@ -172,7 +196,7 @@ func TestUnalteredCheckerNonExistant(t *testing.T) { ctx := plan.Setup{ Source: plan.RepoSetup{ Path: wd, - Git: gitRepo, + Git: repo, }, Target: plan.RepoSetup{ Path: tmpDir, diff --git a/build/sync/plan/git/file_history.go b/build/sync/plan/git/file_history.go index a047613..db7a237 100644 --- a/build/sync/plan/git/file_history.go +++ b/build/sync/plan/git/file_history.go @@ -22,6 +22,7 @@ var ErrNotFound = fmt.Errorf("not found") func FileHistory(path string, repo *git.Repository) ([]string, error) { logOpts := git.LogOptions{ FileName: &path, + All: true, } commits, err := repo.Log(&logOpts) if errors.Is(err, plumbing.ErrReferenceNotFound) { @@ -31,7 +32,6 @@ func FileHistory(path string, repo *git.Repository) ([]string, error) { return nil, fmt.Errorf("failed to get commits for path %q: %v", path, err) } defer commits.Close() - hashHistory := []string{} cerr := commits.ForEach(func(c *object.Commit) error { root, err := repo.TreeObject(c.TreeHash) diff --git a/build/sync/plan/git/file_history_test.go b/build/sync/plan/git/file_history_test.go index 6fcaa97..6d82dec 100644 --- a/build/sync/plan/git/file_history_test.go +++ b/build/sync/plan/git/file_history_test.go @@ -1,28 +1,80 @@ package git_test import ( + "io/ioutil" + "os" + "path/filepath" "testing" + "time" git "github.com/go-git/go-git/v5" + "github.com/go-git/go-git/v5/plumbing/object" "github.com/stretchr/testify/assert" gitutil "github.com/mattermost/mattermost-plugin-starter-template/build/sync/plan/git" ) +var fileContents = []byte("abcdefg") + func TestFileHistory(t *testing.T) { assert := assert.New(t) - repo, err := git.PlainOpenWithOptions("./", &git.PlainOpenOptions{ - DetectDotGit: true, + dir, err := ioutil.TempDir("", "repo") + assert.Nil(err) + defer os.RemoveAll(dir) + + // Initialize a repository. + repo, err := git.PlainInit(dir, false) + assert.Nil(err) + w, err := repo.Worktree() + assert.Nil(err) + // Create repository files. + err = ioutil.WriteFile(filepath.Join(dir, "test"), fileContents, 0644) + assert.Nil(err) + _, err = w.Add("test") + assert.Nil(err) + sig := &object.Signature{ + Name: "test", + Email: "test@example.com", + When: time.Now(), + } + _, err = w.Commit("initial commit", &git.CommitOptions{Author: sig}) + assert.Nil(err) + pathA := "a.txt" + err = ioutil.WriteFile(filepath.Join(dir, pathA), fileContents, 0644) + assert.Nil(err) + pathB := "b.txt" + err = ioutil.WriteFile(filepath.Join(dir, pathB), fileContents, 0644) + assert.Nil(err) + _, err = w.Add(pathA) + assert.Nil(err) + _, err = w.Add(pathB) + assert.Nil(err) + _, err = w.Commit("add files", &git.CommitOptions{Author: sig}) + assert.Nil(err) + // Delete one of the files. + _, err = w.Remove(pathB) + assert.Nil(err) + _, err = w.Commit("remove file b.txt", &git.CommitOptions{ + Author: sig, + All: true, }) assert.Nil(err) - sums, err := gitutil.FileHistory("build/sync/plan/git/testdata/testfile.txt", repo) + repo, err = git.PlainOpen(dir) assert.Nil(err) - assert.Contains(sums, "ba7192052d7cf77c55d3b7bf40b350b8431b208b") + + // Call file history on an existing file. + sums, err := gitutil.FileHistory("a.txt", repo) + assert.Nil(err) + assert.Equal([]string{"2fb5e13419fc89246865e7a324f476ec624e8740"}, sums) // Calling with a non-existent file returns error. - sums, err = gitutil.FileHistory("build/sync/plan/git/testdata/nosuch_testfile.txt", repo) + sums, err = gitutil.FileHistory(filepath.Join(dir, "nosuch_testfile.txt"), repo) assert.Equal(gitutil.ErrNotFound, err) assert.Nil(sums) + + // Calling with a non-existent file that was in git history returns no error. + _, err = gitutil.FileHistory(pathB, repo) + assert.Nil(err) } diff --git a/build/sync/plan/git/testdata/testfile.txt b/build/sync/plan/git/testdata/testfile.txt deleted file mode 100644 index 039983d..0000000 --- a/build/sync/plan/git/testdata/testfile.txt +++ /dev/null @@ -1 +0,0 @@ -This file is used to test file history tracking. \ No newline at end of file diff --git a/go.sum b/go.sum index 67fbf64..f3681c5 100644 --- a/go.sum +++ b/go.sum @@ -477,6 +477,7 @@ github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqn github.com/rcrowley/go-metrics v0.0.0-20190826022208-cac0b30c2563/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/remyoudompheng/bigfft v0.0.0-20190728182440-6a916e37a237/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= +github.com/rogpeppe/go-internal v1.3.0 h1:RR9dF3JtopPvtkroDZuVD7qquD0bnHlKSqaQhgwt8yk= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/rudderlabs/analytics-go v3.2.1+incompatible/go.mod h1:LF8/ty9kUX4PTY3l5c97K3nZZaX5Hwsvt+NBaRL/f30= @@ -826,6 +827,7 @@ gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogR gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/errgo.v2 v2.1.0 h1:0vLT13EuvQ0hNvakwLuFZ/jYrLp5F3kcWHXdRggjCE8= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=