Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2905)

Unified Diff: client/cmd/isolate/exp_archive.go

Issue 2958913002: isolate: pull exparchive filewalk code into its own func (Closed)
Patch Set: address review comments Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | client/cmd/isolate/exp_archive_test.go » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: client/cmd/isolate/exp_archive.go
diff --git a/client/cmd/isolate/exp_archive.go b/client/cmd/isolate/exp_archive.go
index d78eb53821d3854fcd24ba3346fa8aacab2f8db4..e10cff14a7e787b66e8cdb7e4de964d5efdb72ec 100644
--- a/client/cmd/isolate/exp_archive.go
+++ b/client/cmd/isolate/exp_archive.go
@@ -77,6 +77,77 @@ type Item struct {
Digest isolated.HexDigest
}
+// itemGroup is a list of Items, plus a count of the aggregate size.
+type itemGroup struct {
+ items []*Item
+ totalSize int64
+}
+
+func (ig *itemGroup) AddItem(item *Item) {
+ ig.items = append(ig.items, item)
+ ig.totalSize += item.Size
+}
+
+// partitioningWalker contains the state necessary to partition isolate deps by handling multiple os.WalkFunc invocations.
+type partitioningWalker struct {
+ // rootDir must be initialized before walkFn is called.
+ rootDir string
+
+ parts partitionedDeps
+}
+
+// partitionedDeps contains a list of items to be archived, partitioned into symlinks and files categorized by size.
+type partitionedDeps struct {
+ links itemGroup
+ filesToArchive itemGroup
+ indivFiles itemGroup
+}
+
+// walkFn implements filepath.WalkFunc, for use traversing a directory hierarchy to be isolated.
+// It accumulates files in pw.parts, partitioned into symlinks and files categorized by size.
+func (pw *partitioningWalker) walkFn(path string, info os.FileInfo, err error) error {
+ if err != nil {
+ return err
+ }
+ if info.IsDir() {
+ return nil
+ }
+
+ relPath, err := filepath.Rel(pw.rootDir, path)
+ if err != nil {
+ return err
+ }
+
+ item := &Item{
+ Path: path,
+ RelPath: relPath,
+ Mode: info.Mode(),
+ Size: info.Size(),
+ }
+
+ switch {
+ case item.Mode&os.ModeSymlink == os.ModeSymlink:
+ pw.parts.links.AddItem(item)
+ case item.Size < archiveThreshold:
+ pw.parts.filesToArchive.AddItem(item)
+ default:
+ pw.parts.indivFiles.AddItem(item)
+ }
+ return nil
+}
+
+// partitionDeps walks each of the deps, partioning the results into symlinks and files categorized by size.
+func partitionDeps(deps []string, rootDir string) (partitionedDeps, error) {
+ walker := partitioningWalker{rootDir: rootDir}
+ for _, dep := range deps {
+ // Try to walk dep. If dep is a file (or symlink), the inner function is called exactly once.
+ if err := filepath.Walk(filepath.Clean(dep), walker.walkFn); err != nil {
+ return partitionedDeps{}, err
+ }
+ }
+ return walker.parts, nil
+}
+
// main contains the core logic for experimental archive.
func (c *expArchiveRun) main() error {
// TODO(djd): This func is long and has a lot of internal complexity (like,
@@ -109,57 +180,22 @@ func (c *expArchiveRun) main() error {
checker := NewChecker(ctx, client)
uploader := NewUploader(ctx, client, 1)
- // Walk each of the deps, partioning the results into symlinks and files categorised by size.
- var links, archiveFiles, indivFiles []*Item
- var archiveSize, indivSize int64 // Cumulative size of archived/individual files.
- for _, dep := range deps {
- // Try to walk dep. If dep is a file (or symlink), the inner function is called exactly once.
- err := filepath.Walk(filepath.Clean(dep), func(path string, info os.FileInfo, err error) error {
- if err != nil {
- return err
- }
- if info.IsDir() {
- return nil
- }
-
- relPath, err := filepath.Rel(rootDir, path)
- if err != nil {
- return err
- }
-
- item := &Item{
- Path: path,
- RelPath: relPath,
- Mode: info.Mode(),
- Size: info.Size(),
- }
-
- switch {
- case item.Mode&os.ModeSymlink == os.ModeSymlink:
- links = append(links, item)
- case item.Size < archiveThreshold:
- archiveFiles = append(archiveFiles, item)
- archiveSize += item.Size
- default:
- indivFiles = append(indivFiles, item)
- indivSize += item.Size
- }
- return nil
- })
- if err != nil {
- return err
- }
+ parts, err := partitionDeps(deps, rootDir)
+ if err != nil {
+ return fmt.Errorf("partitioning deps: %v", err)
}
// Construct a map of the files that constitute the isolate.
files := make(map[string]isolated.File)
- log.Printf("Isolate expanded to %d files (total size %s) and %d symlinks", len(archiveFiles)+len(indivFiles), humanize.Bytes(uint64(archiveSize+indivSize)), len(links))
- log.Printf("\t%d files (%s) to be isolated individually", len(indivFiles), humanize.Bytes(uint64(indivSize)))
- log.Printf("\t%d files (%s) to be isolated in archives", len(archiveFiles), humanize.Bytes(uint64(archiveSize)))
+ numFiles := len(parts.filesToArchive.items) + len(parts.indivFiles.items)
+ filesSize := uint64(parts.filesToArchive.totalSize + parts.indivFiles.totalSize)
+ log.Printf("Isolate expanded to %d files (total size %s) and %d symlinks", numFiles, humanize.Bytes(filesSize), len(parts.links.items))
+ log.Printf("\t%d files (%s) to be isolated individually", len(parts.indivFiles.items), humanize.Bytes(uint64(parts.indivFiles.totalSize)))
+ log.Printf("\t%d files (%s) to be isolated in archives", len(parts.filesToArchive.items), humanize.Bytes(uint64(parts.filesToArchive.totalSize)))
// Handle the symlinks.
- for _, item := range links {
+ for _, item := range parts.links.items {
l, err := os.Readlink(item.Path)
if err != nil {
return fmt.Errorf("unable to resolve symlink for %q: %v", item.Path, err)
@@ -168,7 +204,7 @@ func (c *expArchiveRun) main() error {
}
// Handle the small to-be-archived files.
- bundles := ShardItems(archiveFiles, archiveMaxSize)
+ bundles := ShardItems(parts.filesToArchive.items, archiveMaxSize)
log.Printf("\t%d TAR archives to be isolated", len(bundles))
for _, bundle := range bundles {
@@ -202,7 +238,7 @@ func (c *expArchiveRun) main() error {
}
// Handle the large individually-uploaded files.
- for _, item := range indivFiles {
+ for _, item := range parts.indivFiles.items {
d, err := hashFile(item.Path)
if err != nil {
return err
@@ -222,7 +258,8 @@ func (c *expArchiveRun) main() error {
// Marshal the isolated file into JSON, and create an Item to describe it.
isol.Files = files
- isolJSON, err := json.Marshal(isol)
+ var isolJSON []byte
+ isolJSON, err = json.Marshal(isol)
if err != nil {
return err
}
« no previous file with comments | « no previous file | client/cmd/isolate/exp_archive_test.go » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698