github.com/nektos/act@v0.2.83/pkg/runner/local_repository_cache.go (about) 1 package runner 2 3 import ( 4 "archive/tar" 5 "bytes" 6 "context" 7 "fmt" 8 "io" 9 "io/fs" 10 goURL "net/url" 11 "os" 12 "path/filepath" 13 "strings" 14 15 "github.com/nektos/act/pkg/common" 16 "github.com/nektos/act/pkg/filecollector" 17 ) 18 19 type LocalRepositoryCache struct { 20 Parent ActionCache 21 LocalRepositories map[string]string 22 CacheDirCache map[string]string 23 } 24 25 func (l *LocalRepositoryCache) Fetch(ctx context.Context, cacheDir, url, ref, token string) (string, error) { 26 logger := common.Logger(ctx) 27 logger.Debugf("LocalRepositoryCache fetch %s with ref %s", url, ref) 28 if dest, ok := l.LocalRepositories[fmt.Sprintf("%s@%s", url, ref)]; ok { 29 logger.Infof("LocalRepositoryCache matched %s with ref %s to %s", url, ref, dest) 30 l.CacheDirCache[fmt.Sprintf("%s@%s", cacheDir, ref)] = dest 31 return ref, nil 32 } 33 if purl, err := goURL.Parse(url); err == nil { 34 if dest, ok := l.LocalRepositories[fmt.Sprintf("%s@%s", strings.TrimPrefix(purl.Path, "/"), ref)]; ok { 35 logger.Infof("LocalRepositoryCache matched %s with ref %s to %s", url, ref, dest) 36 l.CacheDirCache[fmt.Sprintf("%s@%s", cacheDir, ref)] = dest 37 return ref, nil 38 } 39 } 40 logger.Infof("LocalRepositoryCache not matched %s with Ref %s", url, ref) 41 return l.Parent.Fetch(ctx, cacheDir, url, ref, token) 42 } 43 44 func (l *LocalRepositoryCache) GetTarArchive(ctx context.Context, cacheDir, sha, includePrefix string) (io.ReadCloser, error) { 45 logger := common.Logger(ctx) 46 // sha is mapped to ref in fetch if there is a local override 47 if dest, ok := l.CacheDirCache[fmt.Sprintf("%s@%s", cacheDir, sha)]; ok { 48 logger.Infof("LocalRepositoryCache read cachedir %s with ref %s and subpath '%s' from %s", cacheDir, sha, includePrefix, dest) 49 srcPath := filepath.Join(dest, includePrefix) 50 buf := &bytes.Buffer{} 51 tw := tar.NewWriter(buf) 52 defer tw.Close() 53 srcPath = filepath.Clean(srcPath) 54 fi, err := os.Lstat(srcPath) 55 if err != nil { 56 return nil, err 57 } 58 tc := &filecollector.TarCollector{ 59 TarWriter: tw, 60 } 61 if fi.IsDir() { 62 srcPrefix := srcPath 63 if !strings.HasSuffix(srcPrefix, string(filepath.Separator)) { 64 srcPrefix += string(filepath.Separator) 65 } 66 fc := &filecollector.FileCollector{ 67 Fs: &filecollector.DefaultFs{}, 68 SrcPath: srcPath, 69 SrcPrefix: srcPrefix, 70 Handler: tc, 71 } 72 err = filepath.Walk(srcPath, fc.CollectFiles(ctx, []string{})) 73 if err != nil { 74 return nil, err 75 } 76 } else { 77 var f io.ReadCloser 78 var linkname string 79 if fi.Mode()&fs.ModeSymlink != 0 { 80 linkname, err = os.Readlink(srcPath) 81 if err != nil { 82 return nil, err 83 } 84 } else { 85 f, err = os.Open(srcPath) 86 if err != nil { 87 return nil, err 88 } 89 defer f.Close() 90 } 91 err := tc.WriteFile(fi.Name(), fi, linkname, f) 92 if err != nil { 93 return nil, err 94 } 95 } 96 return io.NopCloser(buf), nil 97 } 98 logger.Infof("LocalRepositoryCache not matched cachedir %s with Ref %s and subpath '%s'", cacheDir, sha, includePrefix) 99 return l.Parent.GetTarArchive(ctx, cacheDir, sha, includePrefix) 100 }