Skip to content

Commit 5a80a04

Browse files
refactor: filecollector into new package (#2174)
* refactor: filecollector into new package * Add test for symlinks * add test fix bug of GetContainerArchive * add test data
1 parent 4ca35d2 commit 5a80a04

File tree

6 files changed

+160
-35
lines changed

6 files changed

+160
-35
lines changed

pkg/container/docker_run.go

+5-4
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import (
3535
"golang.org/x/term"
3636

3737
"github.com/nektos/act/pkg/common"
38+
"github.com/nektos/act/pkg/filecollector"
3839
)
3940

4041
// NewContainer creates a reference to a container
@@ -735,20 +736,20 @@ func (cr *containerReference) copyDir(dstPath string, srcPath string, useGitIgno
735736
ignorer = gitignore.NewMatcher(ps)
736737
}
737738

738-
fc := &fileCollector{
739-
Fs: &defaultFs{},
739+
fc := &filecollector.FileCollector{
740+
Fs: &filecollector.DefaultFs{},
740741
Ignorer: ignorer,
741742
SrcPath: srcPath,
742743
SrcPrefix: srcPrefix,
743-
Handler: &tarCollector{
744+
Handler: &filecollector.TarCollector{
744745
TarWriter: tw,
745746
UID: cr.UID,
746747
GID: cr.GID,
747748
DstDir: dstPath[1:],
748749
},
749750
}
750751

751-
err = filepath.Walk(srcPath, fc.collectFiles(ctx, []string{}))
752+
err = filepath.Walk(srcPath, fc.CollectFiles(ctx, []string{}))
752753
if err != nil {
753754
return err
754755
}

pkg/container/host_environment.go

+11-10
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"golang.org/x/term"
2222

2323
"github.com/nektos/act/pkg/common"
24+
"github.com/nektos/act/pkg/filecollector"
2425
"github.com/nektos/act/pkg/lookpath"
2526
)
2627

@@ -65,7 +66,7 @@ func (e *HostEnvironment) CopyTarStream(ctx context.Context, destPath string, ta
6566
return err
6667
}
6768
tr := tar.NewReader(tarStream)
68-
cp := &copyCollector{
69+
cp := &filecollector.CopyCollector{
6970
DstDir: destPath,
7071
}
7172
for {
@@ -104,16 +105,16 @@ func (e *HostEnvironment) CopyDir(destPath string, srcPath string, useGitIgnore
104105

105106
ignorer = gitignore.NewMatcher(ps)
106107
}
107-
fc := &fileCollector{
108-
Fs: &defaultFs{},
108+
fc := &filecollector.FileCollector{
109+
Fs: &filecollector.DefaultFs{},
109110
Ignorer: ignorer,
110111
SrcPath: srcPath,
111112
SrcPrefix: srcPrefix,
112-
Handler: &copyCollector{
113+
Handler: &filecollector.CopyCollector{
113114
DstDir: destPath,
114115
},
115116
}
116-
return filepath.Walk(srcPath, fc.collectFiles(ctx, []string{}))
117+
return filepath.Walk(srcPath, fc.CollectFiles(ctx, []string{}))
117118
}
118119
}
119120

@@ -126,21 +127,21 @@ func (e *HostEnvironment) GetContainerArchive(ctx context.Context, srcPath strin
126127
if err != nil {
127128
return nil, err
128129
}
129-
tc := &tarCollector{
130+
tc := &filecollector.TarCollector{
130131
TarWriter: tw,
131132
}
132133
if fi.IsDir() {
133-
srcPrefix := filepath.Dir(srcPath)
134+
srcPrefix := srcPath
134135
if !strings.HasSuffix(srcPrefix, string(filepath.Separator)) {
135136
srcPrefix += string(filepath.Separator)
136137
}
137-
fc := &fileCollector{
138-
Fs: &defaultFs{},
138+
fc := &filecollector.FileCollector{
139+
Fs: &filecollector.DefaultFs{},
139140
SrcPath: srcPath,
140141
SrcPrefix: srcPrefix,
141142
Handler: tc,
142143
}
143-
err = filepath.Walk(srcPath, fc.collectFiles(ctx, []string{}))
144+
err = filepath.Walk(srcPath, fc.CollectFiles(ctx, []string{}))
144145
if err != nil {
145146
return nil, err
146147
}
+67
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,71 @@
11
package container
22

3+
import (
4+
"archive/tar"
5+
"context"
6+
"io"
7+
"os"
8+
"path"
9+
"path/filepath"
10+
"testing"
11+
12+
"github.com/stretchr/testify/assert"
13+
)
14+
315
// Type assert HostEnvironment implements ExecutionsEnvironment
416
var _ ExecutionsEnvironment = &HostEnvironment{}
17+
18+
func TestCopyDir(t *testing.T) {
19+
dir, err := os.MkdirTemp("", "test-host-env-*")
20+
assert.NoError(t, err)
21+
defer os.RemoveAll(dir)
22+
ctx := context.Background()
23+
e := &HostEnvironment{
24+
Path: filepath.Join(dir, "path"),
25+
TmpDir: filepath.Join(dir, "tmp"),
26+
ToolCache: filepath.Join(dir, "tool_cache"),
27+
ActPath: filepath.Join(dir, "act_path"),
28+
StdOut: os.Stdout,
29+
Workdir: path.Join("testdata", "scratch"),
30+
}
31+
_ = os.MkdirAll(e.Path, 0700)
32+
_ = os.MkdirAll(e.TmpDir, 0700)
33+
_ = os.MkdirAll(e.ToolCache, 0700)
34+
_ = os.MkdirAll(e.ActPath, 0700)
35+
err = e.CopyDir(e.Workdir, e.Path, true)(ctx)
36+
assert.NoError(t, err)
37+
}
38+
39+
func TestGetContainerArchive(t *testing.T) {
40+
dir, err := os.MkdirTemp("", "test-host-env-*")
41+
assert.NoError(t, err)
42+
defer os.RemoveAll(dir)
43+
ctx := context.Background()
44+
e := &HostEnvironment{
45+
Path: filepath.Join(dir, "path"),
46+
TmpDir: filepath.Join(dir, "tmp"),
47+
ToolCache: filepath.Join(dir, "tool_cache"),
48+
ActPath: filepath.Join(dir, "act_path"),
49+
StdOut: os.Stdout,
50+
Workdir: path.Join("testdata", "scratch"),
51+
}
52+
_ = os.MkdirAll(e.Path, 0700)
53+
_ = os.MkdirAll(e.TmpDir, 0700)
54+
_ = os.MkdirAll(e.ToolCache, 0700)
55+
_ = os.MkdirAll(e.ActPath, 0700)
56+
expectedContent := []byte("sdde/7sh")
57+
err = os.WriteFile(filepath.Join(e.Path, "action.yml"), expectedContent, 0600)
58+
assert.NoError(t, err)
59+
archive, err := e.GetContainerArchive(ctx, e.Path)
60+
assert.NoError(t, err)
61+
defer archive.Close()
62+
reader := tar.NewReader(archive)
63+
h, err := reader.Next()
64+
assert.NoError(t, err)
65+
assert.Equal(t, "action.yml", h.Name)
66+
content, err := io.ReadAll(reader)
67+
assert.NoError(t, err)
68+
assert.Equal(t, expectedContent, content)
69+
_, err = reader.Next()
70+
assert.ErrorIs(t, err, io.EOF)
71+
}
+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
testfile

pkg/container/file_collector.go pkg/filecollector/file_collector.go

+17-17
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package container
1+
package filecollector
22

33
import (
44
"archive/tar"
@@ -17,18 +17,18 @@ import (
1717
"github.com/go-git/go-git/v5/plumbing/format/index"
1818
)
1919

20-
type fileCollectorHandler interface {
20+
type Handler interface {
2121
WriteFile(path string, fi fs.FileInfo, linkName string, f io.Reader) error
2222
}
2323

24-
type tarCollector struct {
24+
type TarCollector struct {
2525
TarWriter *tar.Writer
2626
UID int
2727
GID int
2828
DstDir string
2929
}
3030

31-
func (tc tarCollector) WriteFile(fpath string, fi fs.FileInfo, linkName string, f io.Reader) error {
31+
func (tc TarCollector) WriteFile(fpath string, fi fs.FileInfo, linkName string, f io.Reader) error {
3232
// create a new dir/file header
3333
header, err := tar.FileInfoHeader(fi, linkName)
3434
if err != nil {
@@ -59,11 +59,11 @@ func (tc tarCollector) WriteFile(fpath string, fi fs.FileInfo, linkName string,
5959
return nil
6060
}
6161

62-
type copyCollector struct {
62+
type CopyCollector struct {
6363
DstDir string
6464
}
6565

66-
func (cc *copyCollector) WriteFile(fpath string, fi fs.FileInfo, linkName string, f io.Reader) error {
66+
func (cc *CopyCollector) WriteFile(fpath string, fi fs.FileInfo, linkName string, f io.Reader) error {
6767
fdestpath := filepath.Join(cc.DstDir, fpath)
6868
if err := os.MkdirAll(filepath.Dir(fdestpath), 0o777); err != nil {
6969
return err
@@ -82,29 +82,29 @@ func (cc *copyCollector) WriteFile(fpath string, fi fs.FileInfo, linkName string
8282
return nil
8383
}
8484

85-
type fileCollector struct {
85+
type FileCollector struct {
8686
Ignorer gitignore.Matcher
8787
SrcPath string
8888
SrcPrefix string
89-
Fs fileCollectorFs
90-
Handler fileCollectorHandler
89+
Fs Fs
90+
Handler Handler
9191
}
9292

93-
type fileCollectorFs interface {
93+
type Fs interface {
9494
Walk(root string, fn filepath.WalkFunc) error
9595
OpenGitIndex(path string) (*index.Index, error)
9696
Open(path string) (io.ReadCloser, error)
9797
Readlink(path string) (string, error)
9898
}
9999

100-
type defaultFs struct {
100+
type DefaultFs struct {
101101
}
102102

103-
func (*defaultFs) Walk(root string, fn filepath.WalkFunc) error {
103+
func (*DefaultFs) Walk(root string, fn filepath.WalkFunc) error {
104104
return filepath.Walk(root, fn)
105105
}
106106

107-
func (*defaultFs) OpenGitIndex(path string) (*index.Index, error) {
107+
func (*DefaultFs) OpenGitIndex(path string) (*index.Index, error) {
108108
r, err := git.PlainOpen(path)
109109
if err != nil {
110110
return nil, err
@@ -116,16 +116,16 @@ func (*defaultFs) OpenGitIndex(path string) (*index.Index, error) {
116116
return i, nil
117117
}
118118

119-
func (*defaultFs) Open(path string) (io.ReadCloser, error) {
119+
func (*DefaultFs) Open(path string) (io.ReadCloser, error) {
120120
return os.Open(path)
121121
}
122122

123-
func (*defaultFs) Readlink(path string) (string, error) {
123+
func (*DefaultFs) Readlink(path string) (string, error) {
124124
return os.Readlink(path)
125125
}
126126

127127
//nolint:gocyclo
128-
func (fc *fileCollector) collectFiles(ctx context.Context, submodulePath []string) filepath.WalkFunc {
128+
func (fc *FileCollector) CollectFiles(ctx context.Context, submodulePath []string) filepath.WalkFunc {
129129
i, _ := fc.Fs.OpenGitIndex(path.Join(fc.SrcPath, path.Join(submodulePath...)))
130130
return func(file string, fi os.FileInfo, err error) error {
131131
if err != nil {
@@ -166,7 +166,7 @@ func (fc *fileCollector) collectFiles(ctx context.Context, submodulePath []strin
166166
}
167167
}
168168
if err == nil && entry.Mode == filemode.Submodule {
169-
err = fc.Fs.Walk(file, fc.collectFiles(ctx, split))
169+
err = fc.Fs.Walk(file, fc.CollectFiles(ctx, split))
170170
if err != nil {
171171
return err
172172
}

pkg/container/file_collector_test.go pkg/filecollector/file_collector_test.go

+59-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package container
1+
package filecollector
22

33
import (
44
"archive/tar"
@@ -95,16 +95,16 @@ func TestIgnoredTrackedfile(t *testing.T) {
9595
tw := tar.NewWriter(tmpTar)
9696
ps, _ := gitignore.ReadPatterns(worktree, []string{})
9797
ignorer := gitignore.NewMatcher(ps)
98-
fc := &fileCollector{
98+
fc := &FileCollector{
9999
Fs: &memoryFs{Filesystem: fs},
100100
Ignorer: ignorer,
101101
SrcPath: "mygitrepo",
102102
SrcPrefix: "mygitrepo" + string(filepath.Separator),
103-
Handler: &tarCollector{
103+
Handler: &TarCollector{
104104
TarWriter: tw,
105105
},
106106
}
107-
err := fc.Fs.Walk("mygitrepo", fc.collectFiles(context.Background(), []string{}))
107+
err := fc.Fs.Walk("mygitrepo", fc.CollectFiles(context.Background(), []string{}))
108108
assert.NoError(t, err, "successfully collect files")
109109
tw.Close()
110110
_, _ = tmpTar.Seek(0, io.SeekStart)
@@ -115,3 +115,58 @@ func TestIgnoredTrackedfile(t *testing.T) {
115115
_, err = tr.Next()
116116
assert.ErrorIs(t, err, io.EOF, "tar must only contain one element")
117117
}
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+
}

0 commit comments

Comments
 (0)