Removed file git history (#128)
This commit is contained in:
parent
57f7843ae1
commit
5eb33f8675
9 changed files with 171 additions and 44 deletions
|
@ -5,6 +5,8 @@ import (
|
|||
"os"
|
||||
"sort"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/mattermost/mattermost-plugin-starter-template/build/sync/plan/git"
|
||||
)
|
||||
|
||||
|
@ -99,41 +101,69 @@ func (r PathExistsChecker) Check(path string, ctx Setup) error {
|
|||
// reference will default to the source repository and repo - to the target.
|
||||
type FileUnalteredChecker struct {
|
||||
Params struct {
|
||||
ReferenceRepo RepoID `json:"compared-to"`
|
||||
Repo RepoID `json:"in"`
|
||||
SourceRepo RepoID `json:"compared-to"`
|
||||
TargetRepo RepoID `json:"in"`
|
||||
}
|
||||
}
|
||||
|
||||
// Check implements the Checker interface.
|
||||
func (f FileUnalteredChecker) Check(path string, setup Setup) error {
|
||||
setup.Logf("checking if file %q has not been altered", path)
|
||||
repo := f.Params.Repo
|
||||
repo := f.Params.TargetRepo
|
||||
if repo == "" {
|
||||
repo = TargetRepo
|
||||
}
|
||||
reference := f.Params.ReferenceRepo
|
||||
if reference == "" {
|
||||
reference = SourceRepo
|
||||
source := f.Params.SourceRepo
|
||||
if source == "" {
|
||||
source = SourceRepo
|
||||
}
|
||||
absPath := setup.PathInRepo(repo, path)
|
||||
trgPath := setup.PathInRepo(repo, path)
|
||||
srcPath := setup.PathInRepo(source, path)
|
||||
|
||||
info, err := os.Stat(absPath)
|
||||
if os.IsNotExist(err) {
|
||||
return CheckFailf("file %q has been deleted", absPath)
|
||||
}
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get stat for %q: %v", absPath, err)
|
||||
}
|
||||
if info.IsDir() {
|
||||
return fmt.Errorf("%q is a directory", absPath)
|
||||
}
|
||||
|
||||
fileHashes, err := git.FileHistory(path, setup.GetRepo(reference).Git)
|
||||
fileHashes, err := git.FileHistory(path, setup.GetRepo(source).Git)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
currentHash, err := git.GetFileHash(absPath)
|
||||
var srcDeleted bool
|
||||
srcInfo, err := os.Stat(srcPath)
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
srcDeleted = true
|
||||
} else {
|
||||
return fmt.Errorf("failed to get stat for %q: %v", trgPath, err)
|
||||
}
|
||||
}
|
||||
if srcInfo.IsDir() {
|
||||
return fmt.Errorf("%q is a directory in source repository", path)
|
||||
}
|
||||
|
||||
trgInfo, err := os.Stat(trgPath)
|
||||
if os.IsNotExist(err) {
|
||||
if srcDeleted {
|
||||
// File has been deleted in target and source repositories.
|
||||
// Consider it unaltered.
|
||||
return nil
|
||||
}
|
||||
// Check if the file was ever in git history.
|
||||
_, err := git.FileHistory(path, setup.GetRepo(repo).Git)
|
||||
if errors.Is(err, git.ErrNotFound) {
|
||||
// This is a new file being introduced to the target repo.
|
||||
// Consider it unaltered.
|
||||
return nil
|
||||
} else if err != nil {
|
||||
return err
|
||||
}
|
||||
return CheckFailf("file %q has been deleted", trgPath)
|
||||
}
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to get stat for %q: %v", trgPath, err)
|
||||
}
|
||||
if trgInfo.IsDir() {
|
||||
return fmt.Errorf("%q is a directory", trgPath)
|
||||
}
|
||||
|
||||
currentHash, err := git.GetFileHash(trgPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -143,5 +173,5 @@ func (f FileUnalteredChecker) Check(path string, setup Setup) error {
|
|||
if idx < len(fileHashes) && fileHashes[idx] == currentHash {
|
||||
return nil
|
||||
}
|
||||
return CheckFailf("file %q has been altered", absPath)
|
||||
return CheckFailf("file %q has been altered", trgPath)
|
||||
}
|
||||
|
|
|
@ -8,8 +8,8 @@ import (
|
|||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
git "github.com/go-git/go-git/v5"
|
||||
"github.com/stretchr/testify/assert"
|
||||
git "gopkg.in/src-d/go-git.v4"
|
||||
|
||||
"github.com/mattermost/mattermost-plugin-starter-template/build/sync/plan"
|
||||
)
|
||||
|
@ -71,7 +71,7 @@ func TestPathExistsChecker(t *testing.T) {
|
|||
assert.True(plan.IsCheckFail(err))
|
||||
}
|
||||
|
||||
func TestUnalteredChecker(t *testing.T) {
|
||||
func TestUnalteredCheckerSameFile(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
// Path to the root of the repo.
|
||||
|
@ -92,18 +92,44 @@ func TestUnalteredChecker(t *testing.T) {
|
|||
}
|
||||
|
||||
checker := plan.FileUnalteredChecker{}
|
||||
checker.Params.ReferenceRepo = plan.SourceRepo
|
||||
checker.Params.Repo = plan.TargetRepo
|
||||
checker.Params.SourceRepo = plan.SourceRepo
|
||||
checker.Params.TargetRepo = plan.TargetRepo
|
||||
|
||||
// Check with the same file - check should succeed
|
||||
hashPath := "build/sync/plan/testdata/a"
|
||||
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)
|
||||
|
||||
ctx := plan.Setup{
|
||||
Source: plan.RepoSetup{
|
||||
Path: wd,
|
||||
Git: gitRepo,
|
||||
},
|
||||
Target: plan.RepoSetup{
|
||||
Path: wd,
|
||||
},
|
||||
}
|
||||
|
||||
checker := plan.FileUnalteredChecker{}
|
||||
checker.Params.SourceRepo = plan.SourceRepo
|
||||
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)
|
||||
defer os.RemoveAll(tmpDir)
|
||||
fullPath := filepath.Join(tmpDir, "build/sync/plan/testdata")
|
||||
err = os.MkdirAll(fullPath, 0777)
|
||||
assert.Nil(err)
|
||||
|
@ -119,4 +145,45 @@ func TestUnalteredChecker(t *testing.T) {
|
|||
err = checker.Check(hashPath, ctx)
|
||||
assert.True(plan.IsCheckFail(err))
|
||||
assert.EqualError(err, fmt.Sprintf("file %q has been altered", filepath.Join(tmpDir, hashPath)))
|
||||
|
||||
}
|
||||
|
||||
// TestUnalteredCheckerNonExistant tests running the unaltered file checker
|
||||
// in the case where the target file does not exist. If the files has no history,
|
||||
// the checker should pass.
|
||||
func TestUnalteredCheckerNonExistant(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
hashPath := "build/sync/plan/testdata/a"
|
||||
|
||||
// Path to the root of the repo.
|
||||
wd, err := filepath.Abs("../../../")
|
||||
assert.Nil(err)
|
||||
gitRepo, err := git.PlainOpen(wd)
|
||||
assert.Nil(err)
|
||||
|
||||
// Temporary repo.
|
||||
tmpDir, err := ioutil.TempDir("", "test")
|
||||
assert.Nil(err)
|
||||
defer os.RemoveAll(tmpDir)
|
||||
|
||||
trgRepo, err := git.PlainInit(tmpDir, false)
|
||||
assert.Nil(err)
|
||||
|
||||
ctx := plan.Setup{
|
||||
Source: plan.RepoSetup{
|
||||
Path: wd,
|
||||
Git: gitRepo,
|
||||
},
|
||||
Target: plan.RepoSetup{
|
||||
Path: tmpDir,
|
||||
Git: trgRepo,
|
||||
},
|
||||
}
|
||||
|
||||
checker := plan.FileUnalteredChecker{}
|
||||
checker.Params.SourceRepo = plan.SourceRepo
|
||||
checker.Params.TargetRepo = plan.TargetRepo
|
||||
|
||||
err = checker.Check(hashPath, ctx)
|
||||
assert.Nil(err)
|
||||
}
|
||||
|
|
|
@ -8,8 +8,10 @@ import (
|
|||
"os"
|
||||
"path/filepath"
|
||||
|
||||
git "gopkg.in/src-d/go-git.v4"
|
||||
"gopkg.in/src-d/go-git.v4/plumbing/object"
|
||||
git "github.com/go-git/go-git/v5"
|
||||
"github.com/go-git/go-git/v5/plumbing"
|
||||
"github.com/go-git/go-git/v5/plumbing/object"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// ErrNotFound signifies the file was not found.
|
||||
|
@ -22,6 +24,9 @@ func FileHistory(path string, repo *git.Repository) ([]string, error) {
|
|||
FileName: &path,
|
||||
}
|
||||
commits, err := repo.Log(&logOpts)
|
||||
if errors.Is(err, plumbing.ErrReferenceNotFound) {
|
||||
return nil, ErrNotFound
|
||||
}
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get commits for path %q: %v", path, err)
|
||||
}
|
||||
|
|
|
@ -3,8 +3,8 @@ package git_test
|
|||
import (
|
||||
"testing"
|
||||
|
||||
git "github.com/go-git/go-git/v5"
|
||||
"github.com/stretchr/testify/assert"
|
||||
git "gopkg.in/src-d/go-git.v4"
|
||||
|
||||
gitutil "github.com/mattermost/mattermost-plugin-starter-template/build/sync/plan/git"
|
||||
)
|
||||
|
@ -16,6 +16,7 @@ func TestFileHistory(t *testing.T) {
|
|||
DetectDotGit: true,
|
||||
})
|
||||
assert.Nil(err)
|
||||
|
||||
sums, err := gitutil.FileHistory("build/sync/plan/git/testdata/testfile.txt", repo)
|
||||
assert.Nil(err)
|
||||
assert.Contains(sums, "ba7192052d7cf77c55d3b7bf40b350b8431b208b")
|
||||
|
@ -24,4 +25,9 @@ func TestFileHistory(t *testing.T) {
|
|||
sums, err = gitutil.FileHistory("build/sync/plan/git/testdata/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.
|
||||
sums, err = gitutil.FileHistory("build/sync/plan/git/testdata/removedfile.txt", repo)
|
||||
assert.Nil(err)
|
||||
assert.Equal([]string{"213df5d04c108c99d3ec9ffe43a53f638f0ede0b"}, sums)
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ import (
|
|||
"os"
|
||||
"path/filepath"
|
||||
|
||||
git "gopkg.in/src-d/go-git.v4"
|
||||
git "github.com/go-git/go-git/v5"
|
||||
)
|
||||
|
||||
// RepoID identifies a repository - either plugin or template.
|
||||
|
|
Reference in a new issue