summaryrefslogtreecommitdiffstats
path: root/pkg/filecollector/file_collector_test.go
diff options
context:
space:
mode:
Diffstat (limited to 'pkg/filecollector/file_collector_test.go')
-rw-r--r--pkg/filecollector/file_collector_test.go172
1 files changed, 172 insertions, 0 deletions
diff --git a/pkg/filecollector/file_collector_test.go b/pkg/filecollector/file_collector_test.go
new file mode 100644
index 0000000..60a8d4d
--- /dev/null
+++ b/pkg/filecollector/file_collector_test.go
@@ -0,0 +1,172 @@
+package filecollector
+
+import (
+ "archive/tar"
+ "context"
+ "io"
+ "path/filepath"
+ "strings"
+ "testing"
+
+ "github.com/go-git/go-billy/v5"
+ "github.com/go-git/go-billy/v5/memfs"
+ git "github.com/go-git/go-git/v5"
+ "github.com/go-git/go-git/v5/plumbing/cache"
+ "github.com/go-git/go-git/v5/plumbing/format/gitignore"
+ "github.com/go-git/go-git/v5/plumbing/format/index"
+ "github.com/go-git/go-git/v5/storage/filesystem"
+ "github.com/stretchr/testify/assert"
+)
+
+type memoryFs struct {
+ billy.Filesystem
+}
+
+func (mfs *memoryFs) walk(root string, fn filepath.WalkFunc) error {
+ dir, err := mfs.ReadDir(root)
+ if err != nil {
+ return err
+ }
+ for i := 0; i < len(dir); i++ {
+ filename := filepath.Join(root, dir[i].Name())
+ err = fn(filename, dir[i], nil)
+ if dir[i].IsDir() {
+ if err == filepath.SkipDir {
+ err = nil
+ } else if err := mfs.walk(filename, fn); err != nil {
+ return err
+ }
+ }
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+}
+
+func (mfs *memoryFs) Walk(root string, fn filepath.WalkFunc) error {
+ stat, err := mfs.Lstat(root)
+ if err != nil {
+ return err
+ }
+ err = fn(strings.Join([]string{root, "."}, string(filepath.Separator)), stat, nil)
+ if err != nil {
+ return err
+ }
+ return mfs.walk(root, fn)
+}
+
+func (mfs *memoryFs) OpenGitIndex(path string) (*index.Index, error) {
+ f, _ := mfs.Filesystem.Chroot(filepath.Join(path, ".git"))
+ storage := filesystem.NewStorage(f, cache.NewObjectLRUDefault())
+ i, err := storage.Index()
+ if err != nil {
+ return nil, err
+ }
+ return i, nil
+}
+
+func (mfs *memoryFs) Open(path string) (io.ReadCloser, error) {
+ return mfs.Filesystem.Open(path)
+}
+
+func (mfs *memoryFs) Readlink(path string) (string, error) {
+ return mfs.Filesystem.Readlink(path)
+}
+
+func TestIgnoredTrackedfile(t *testing.T) {
+ fs := memfs.New()
+ _ = fs.MkdirAll("mygitrepo/.git", 0o777)
+ dotgit, _ := fs.Chroot("mygitrepo/.git")
+ worktree, _ := fs.Chroot("mygitrepo")
+ repo, _ := git.Init(filesystem.NewStorage(dotgit, cache.NewObjectLRUDefault()), worktree)
+ f, _ := worktree.Create(".gitignore")
+ _, _ = f.Write([]byte(".*\n"))
+ f.Close()
+ // This file shouldn't be in the tar
+ f, _ = worktree.Create(".env")
+ _, _ = f.Write([]byte("test=val1\n"))
+ f.Close()
+ w, _ := repo.Worktree()
+ // .gitignore is in the tar after adding it to the index
+ _, _ = w.Add(".gitignore")
+
+ tmpTar, _ := fs.Create("temp.tar")
+ tw := tar.NewWriter(tmpTar)
+ ps, _ := gitignore.ReadPatterns(worktree, []string{})
+ ignorer := gitignore.NewMatcher(ps)
+ fc := &FileCollector{
+ Fs: &memoryFs{Filesystem: fs},
+ Ignorer: ignorer,
+ SrcPath: "mygitrepo",
+ SrcPrefix: "mygitrepo" + string(filepath.Separator),
+ Handler: &TarCollector{
+ TarWriter: tw,
+ },
+ }
+ err := fc.Fs.Walk("mygitrepo", fc.CollectFiles(context.Background(), []string{}))
+ assert.NoError(t, err, "successfully collect files")
+ tw.Close()
+ _, _ = tmpTar.Seek(0, io.SeekStart)
+ tr := tar.NewReader(tmpTar)
+ h, err := tr.Next()
+ assert.NoError(t, err, "tar must not be empty")
+ assert.Equal(t, ".gitignore", h.Name)
+ _, err = tr.Next()
+ assert.ErrorIs(t, err, io.EOF, "tar must only contain one element")
+}
+
+func TestSymlinks(t *testing.T) {
+ fs := memfs.New()
+ _ = fs.MkdirAll("mygitrepo/.git", 0o777)
+ dotgit, _ := fs.Chroot("mygitrepo/.git")
+ worktree, _ := fs.Chroot("mygitrepo")
+ repo, _ := git.Init(filesystem.NewStorage(dotgit, cache.NewObjectLRUDefault()), worktree)
+ // This file shouldn't be in the tar
+ f, err := worktree.Create(".env")
+ assert.NoError(t, err)
+ _, err = f.Write([]byte("test=val1\n"))
+ assert.NoError(t, err)
+ f.Close()
+ err = worktree.Symlink(".env", "test.env")
+ assert.NoError(t, err)
+
+ w, err := repo.Worktree()
+ assert.NoError(t, err)
+
+ // .gitignore is in the tar after adding it to the index
+ _, err = w.Add(".env")
+ assert.NoError(t, err)
+ _, err = w.Add("test.env")
+ assert.NoError(t, err)
+
+ tmpTar, _ := fs.Create("temp.tar")
+ tw := tar.NewWriter(tmpTar)
+ ps, _ := gitignore.ReadPatterns(worktree, []string{})
+ ignorer := gitignore.NewMatcher(ps)
+ fc := &FileCollector{
+ Fs: &memoryFs{Filesystem: fs},
+ Ignorer: ignorer,
+ SrcPath: "mygitrepo",
+ SrcPrefix: "mygitrepo" + string(filepath.Separator),
+ Handler: &TarCollector{
+ TarWriter: tw,
+ },
+ }
+ err = fc.Fs.Walk("mygitrepo", fc.CollectFiles(context.Background(), []string{}))
+ assert.NoError(t, err, "successfully collect files")
+ tw.Close()
+ _, _ = tmpTar.Seek(0, io.SeekStart)
+ tr := tar.NewReader(tmpTar)
+ h, err := tr.Next()
+ files := map[string]tar.Header{}
+ for err == nil {
+ files[h.Name] = *h
+ h, err = tr.Next()
+ }
+
+ assert.Equal(t, ".env", files[".env"].Name)
+ assert.Equal(t, "test.env", files["test.env"].Name)
+ assert.Equal(t, ".env", files["test.env"].Linkname)
+ assert.ErrorIs(t, err, io.EOF, "tar must be read cleanly to EOF")
+}