github.1485827954.workers.dev/nektos/act@v0.2.63/pkg/filecollector/file_collector_test.go (about)

     1  package filecollector
     2  
     3  import (
     4  	"archive/tar"
     5  	"context"
     6  	"io"
     7  	"path/filepath"
     8  	"strings"
     9  	"testing"
    10  
    11  	"github.com/go-git/go-billy/v5"
    12  	"github.com/go-git/go-billy/v5/memfs"
    13  	git "github.com/go-git/go-git/v5"
    14  	"github.com/go-git/go-git/v5/plumbing/cache"
    15  	"github.com/go-git/go-git/v5/plumbing/format/gitignore"
    16  	"github.com/go-git/go-git/v5/plumbing/format/index"
    17  	"github.com/go-git/go-git/v5/storage/filesystem"
    18  	"github.com/stretchr/testify/assert"
    19  )
    20  
    21  type memoryFs struct {
    22  	billy.Filesystem
    23  }
    24  
    25  func (mfs *memoryFs) walk(root string, fn filepath.WalkFunc) error {
    26  	dir, err := mfs.ReadDir(root)
    27  	if err != nil {
    28  		return err
    29  	}
    30  	for i := 0; i < len(dir); i++ {
    31  		filename := filepath.Join(root, dir[i].Name())
    32  		err = fn(filename, dir[i], nil)
    33  		if dir[i].IsDir() {
    34  			if err == filepath.SkipDir {
    35  				err = nil
    36  			} else if err := mfs.walk(filename, fn); err != nil {
    37  				return err
    38  			}
    39  		}
    40  		if err != nil {
    41  			return err
    42  		}
    43  	}
    44  	return nil
    45  }
    46  
    47  func (mfs *memoryFs) Walk(root string, fn filepath.WalkFunc) error {
    48  	stat, err := mfs.Lstat(root)
    49  	if err != nil {
    50  		return err
    51  	}
    52  	err = fn(strings.Join([]string{root, "."}, string(filepath.Separator)), stat, nil)
    53  	if err != nil {
    54  		return err
    55  	}
    56  	return mfs.walk(root, fn)
    57  }
    58  
    59  func (mfs *memoryFs) OpenGitIndex(path string) (*index.Index, error) {
    60  	f, _ := mfs.Filesystem.Chroot(filepath.Join(path, ".git"))
    61  	storage := filesystem.NewStorage(f, cache.NewObjectLRUDefault())
    62  	i, err := storage.Index()
    63  	if err != nil {
    64  		return nil, err
    65  	}
    66  	return i, nil
    67  }
    68  
    69  func (mfs *memoryFs) Open(path string) (io.ReadCloser, error) {
    70  	return mfs.Filesystem.Open(path)
    71  }
    72  
    73  func (mfs *memoryFs) Readlink(path string) (string, error) {
    74  	return mfs.Filesystem.Readlink(path)
    75  }
    76  
    77  func TestIgnoredTrackedfile(t *testing.T) {
    78  	fs := memfs.New()
    79  	_ = fs.MkdirAll("mygitrepo/.git", 0o777)
    80  	dotgit, _ := fs.Chroot("mygitrepo/.git")
    81  	worktree, _ := fs.Chroot("mygitrepo")
    82  	repo, _ := git.Init(filesystem.NewStorage(dotgit, cache.NewObjectLRUDefault()), worktree)
    83  	f, _ := worktree.Create(".gitignore")
    84  	_, _ = f.Write([]byte(".*\n"))
    85  	f.Close()
    86  	// This file shouldn't be in the tar
    87  	f, _ = worktree.Create(".env")
    88  	_, _ = f.Write([]byte("test=val1\n"))
    89  	f.Close()
    90  	w, _ := repo.Worktree()
    91  	// .gitignore is in the tar after adding it to the index
    92  	_, _ = w.Add(".gitignore")
    93  
    94  	tmpTar, _ := fs.Create("temp.tar")
    95  	tw := tar.NewWriter(tmpTar)
    96  	ps, _ := gitignore.ReadPatterns(worktree, []string{})
    97  	ignorer := gitignore.NewMatcher(ps)
    98  	fc := &FileCollector{
    99  		Fs:        &memoryFs{Filesystem: fs},
   100  		Ignorer:   ignorer,
   101  		SrcPath:   "mygitrepo",
   102  		SrcPrefix: "mygitrepo" + string(filepath.Separator),
   103  		Handler: &TarCollector{
   104  			TarWriter: tw,
   105  		},
   106  	}
   107  	err := fc.Fs.Walk("mygitrepo", fc.CollectFiles(context.Background(), []string{}))
   108  	assert.NoError(t, err, "successfully collect files")
   109  	tw.Close()
   110  	_, _ = tmpTar.Seek(0, io.SeekStart)
   111  	tr := tar.NewReader(tmpTar)
   112  	h, err := tr.Next()
   113  	assert.NoError(t, err, "tar must not be empty")
   114  	assert.Equal(t, ".gitignore", h.Name)
   115  	_, err = tr.Next()
   116  	assert.ErrorIs(t, err, io.EOF, "tar must only contain one element")
   117  }
   118  
   119  func TestSymlinks(t *testing.T) {
   120  	fs := memfs.New()
   121  	_ = fs.MkdirAll("mygitrepo/.git", 0o777)
   122  	dotgit, _ := fs.Chroot("mygitrepo/.git")
   123  	worktree, _ := fs.Chroot("mygitrepo")
   124  	repo, _ := git.Init(filesystem.NewStorage(dotgit, cache.NewObjectLRUDefault()), worktree)
   125  	// This file shouldn't be in the tar
   126  	f, err := worktree.Create(".env")
   127  	assert.NoError(t, err)
   128  	_, err = f.Write([]byte("test=val1\n"))
   129  	assert.NoError(t, err)
   130  	f.Close()
   131  	err = worktree.Symlink(".env", "test.env")
   132  	assert.NoError(t, err)
   133  
   134  	w, err := repo.Worktree()
   135  	assert.NoError(t, err)
   136  
   137  	// .gitignore is in the tar after adding it to the index
   138  	_, err = w.Add(".env")
   139  	assert.NoError(t, err)
   140  	_, err = w.Add("test.env")
   141  	assert.NoError(t, err)
   142  
   143  	tmpTar, _ := fs.Create("temp.tar")
   144  	tw := tar.NewWriter(tmpTar)
   145  	ps, _ := gitignore.ReadPatterns(worktree, []string{})
   146  	ignorer := gitignore.NewMatcher(ps)
   147  	fc := &FileCollector{
   148  		Fs:        &memoryFs{Filesystem: fs},
   149  		Ignorer:   ignorer,
   150  		SrcPath:   "mygitrepo",
   151  		SrcPrefix: "mygitrepo" + string(filepath.Separator),
   152  		Handler: &TarCollector{
   153  			TarWriter: tw,
   154  		},
   155  	}
   156  	err = fc.Fs.Walk("mygitrepo", fc.CollectFiles(context.Background(), []string{}))
   157  	assert.NoError(t, err, "successfully collect files")
   158  	tw.Close()
   159  	_, _ = tmpTar.Seek(0, io.SeekStart)
   160  	tr := tar.NewReader(tmpTar)
   161  	h, err := tr.Next()
   162  	files := map[string]tar.Header{}
   163  	for err == nil {
   164  		files[h.Name] = *h
   165  		h, err = tr.Next()
   166  	}
   167  
   168  	assert.Equal(t, ".env", files[".env"].Name)
   169  	assert.Equal(t, "test.env", files["test.env"].Name)
   170  	assert.Equal(t, ".env", files["test.env"].Linkname)
   171  	assert.ErrorIs(t, err, io.EOF, "tar must be read cleanly to EOF")
   172  }