in go/pkg/client/tree.go [513:581]
func (c *Client) ComputeOutputsToUpload(execRoot, workingDir string, paths []string, cache filemetadata.Cache, sb command.SymlinkBehaviorType) (map[digest.Digest]*uploadinfo.Entry, *repb.ActionResult, error) {
outs := make(map[digest.Digest]*uploadinfo.Entry)
resPb := &repb.ActionResult{}
for _, path := range paths {
absPath := filepath.Join(execRoot, workingDir, path)
if _, err := getRelPath(execRoot, absPath); err != nil {
return nil, nil, err
}
meta := cache.Get(absPath)
if meta.Err != nil {
if e, ok := meta.Err.(*filemetadata.FileError); ok && e.IsNotFound {
continue // Ignore missing outputs.
}
return nil, nil, meta.Err
}
normPath, err := filepath.Rel(filepath.Join(execRoot, workingDir), absPath)
if err != nil {
return nil, nil, err
}
if !meta.IsDirectory {
// A regular file.
ue := uploadinfo.EntryFromFile(meta.Digest, absPath)
outs[meta.Digest] = ue
resPb.OutputFiles = append(resPb.OutputFiles, &repb.OutputFile{Path: normPath, Digest: meta.Digest.ToProto(), IsExecutable: meta.IsExecutable})
continue
}
// A directory.
fs := make(map[string]*fileSysNode)
if e := loadFiles(absPath, "", "", nil, []string{"."}, fs, cache, treeSymlinkOpts(c.TreeSymlinkOpts, sb)); e != nil {
return nil, nil, e
}
ft, err := buildTree(fs)
if err != nil {
return nil, nil, err
}
treePb := &repb.Tree{}
rootDir, childDirs, files, err := packageDirectories(ft)
if err != nil {
return nil, nil, err
}
ue, err := uploadinfo.EntryFromProto(rootDir)
if err != nil {
return nil, nil, err
}
outs[ue.Digest] = ue
treePb.Root = rootDir
for _, c := range childDirs {
treePb.Children = append(treePb.Children, c)
}
ue, err = uploadinfo.EntryFromProto(treePb)
if err != nil {
return nil, nil, err
}
outs[ue.Digest] = ue
for _, ue := range files {
outs[ue.Digest] = ue
}
resPb.OutputDirectories = append(resPb.OutputDirectories, &repb.OutputDirectory{Path: normPath, TreeDigest: ue.Digest.ToProto()})
// Upload the child directories individually as well
ueRoot, _ := uploadinfo.EntryFromProto(treePb.Root)
outs[ueRoot.Digest] = ueRoot
for _, child := range treePb.Children {
ueChild, _ := uploadinfo.EntryFromProto(child)
outs[ueChild.Digest] = ueChild
}
}
return outs, resPb, nil
}