in go/pkg/client/cas.go [1263:1328]
func (c *Client) downloadOutputs(ctx context.Context, outs map[string]*TreeOutput, outDir string, cache filemetadata.Cache) (*MovedBytesMetadata, error) {
var symlinks, copies []*TreeOutput
downloads := make(map[digest.Digest]*TreeOutput)
fullStats := &MovedBytesMetadata{}
for _, out := range outs {
path := filepath.Join(outDir, out.Path)
if out.IsEmptyDirectory {
if err := os.MkdirAll(path, c.DirMode); err != nil {
return fullStats, err
}
continue
}
if err := os.MkdirAll(filepath.Dir(path), c.DirMode); err != nil {
return fullStats, err
}
// We create the symbolic links after all regular downloads are finished, because dangling
// links will not work.
if out.SymlinkTarget != "" {
symlinks = append(symlinks, out)
continue
}
if _, ok := downloads[out.Digest]; ok {
copies = append(copies, out)
// All copies are effectivelly cached
fullStats.Requested += out.Digest.Size
fullStats.Cached += out.Digest.Size
} else {
downloads[out.Digest] = out
}
}
stats, err := c.DownloadFiles(ctx, outDir, downloads)
fullStats.addFrom(stats)
if err != nil {
return fullStats, err
}
for _, output := range downloads {
path := output.Path
md := &filemetadata.Metadata{
Digest: output.Digest,
IsExecutable: output.IsExecutable,
}
if err := cache.Update(path, md); err != nil {
return fullStats, err
}
}
for _, out := range copies {
perm := c.RegularMode
if out.IsExecutable {
perm = c.ExecutableMode
}
src := downloads[out.Digest]
if src.IsEmptyDirectory {
return fullStats, fmt.Errorf("unexpected empty directory: %s", src.Path)
}
if err := copyFile(outDir, outDir, src.Path, out.Path, perm); err != nil {
return fullStats, err
}
}
for _, out := range symlinks {
if err := os.Symlink(out.SymlinkTarget, filepath.Join(outDir, out.Path)); err != nil {
return fullStats, err
}
}
return fullStats, nil
}