func()

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
}