github.com/nektos/act@v0.2.63/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/filecollector"
    16  )
    17  
    18  type LocalRepositoryCache struct {
    19  	Parent            ActionCache
    20  	LocalRepositories map[string]string
    21  	CacheDirCache     map[string]string
    22  }
    23  
    24  func (l *LocalRepositoryCache) Fetch(ctx context.Context, cacheDir, url, ref, token string) (string, error) {
    25  	if dest, ok := l.LocalRepositories[fmt.Sprintf("%s@%s", url, ref)]; ok {
    26  		l.CacheDirCache[fmt.Sprintf("%s@%s", cacheDir, ref)] = dest
    27  		return ref, nil
    28  	}
    29  	if purl, err := goURL.Parse(url); err == nil {
    30  		if dest, ok := l.LocalRepositories[fmt.Sprintf("%s@%s", strings.TrimPrefix(purl.Path, "/"), ref)]; ok {
    31  			l.CacheDirCache[fmt.Sprintf("%s@%s", cacheDir, ref)] = dest
    32  			return ref, nil
    33  		}
    34  	}
    35  	return l.Parent.Fetch(ctx, cacheDir, url, ref, token)
    36  }
    37  
    38  func (l *LocalRepositoryCache) GetTarArchive(ctx context.Context, cacheDir, sha, includePrefix string) (io.ReadCloser, error) {
    39  	// sha is mapped to ref in fetch if there is a local override
    40  	if dest, ok := l.CacheDirCache[fmt.Sprintf("%s@%s", cacheDir, sha)]; ok {
    41  		srcPath := filepath.Join(dest, includePrefix)
    42  		buf := &bytes.Buffer{}
    43  		tw := tar.NewWriter(buf)
    44  		defer tw.Close()
    45  		srcPath = filepath.Clean(srcPath)
    46  		fi, err := os.Lstat(srcPath)
    47  		if err != nil {
    48  			return nil, err
    49  		}
    50  		tc := &filecollector.TarCollector{
    51  			TarWriter: tw,
    52  		}
    53  		if fi.IsDir() {
    54  			srcPrefix := srcPath
    55  			if !strings.HasSuffix(srcPrefix, string(filepath.Separator)) {
    56  				srcPrefix += string(filepath.Separator)
    57  			}
    58  			fc := &filecollector.FileCollector{
    59  				Fs:        &filecollector.DefaultFs{},
    60  				SrcPath:   srcPath,
    61  				SrcPrefix: srcPrefix,
    62  				Handler:   tc,
    63  			}
    64  			err = filepath.Walk(srcPath, fc.CollectFiles(ctx, []string{}))
    65  			if err != nil {
    66  				return nil, err
    67  			}
    68  		} else {
    69  			var f io.ReadCloser
    70  			var linkname string
    71  			if fi.Mode()&fs.ModeSymlink != 0 {
    72  				linkname, err = os.Readlink(srcPath)
    73  				if err != nil {
    74  					return nil, err
    75  				}
    76  			} else {
    77  				f, err = os.Open(srcPath)
    78  				if err != nil {
    79  					return nil, err
    80  				}
    81  				defer f.Close()
    82  			}
    83  			err := tc.WriteFile(fi.Name(), fi, linkname, f)
    84  			if err != nil {
    85  				return nil, err
    86  			}
    87  		}
    88  		return io.NopCloser(buf), nil
    89  	}
    90  	return l.Parent.GetTarArchive(ctx, cacheDir, sha, includePrefix)
    91  }