Index: client/isolateserver.py |
diff --git a/client/isolateserver.py b/client/isolateserver.py |
index c8feb0961a2e1e3785cf265c122b827c88771537..6d7ca1910699294b81f8fbcc678c3f0646c26134 100755 |
--- a/client/isolateserver.py |
+++ b/client/isolateserver.py |
@@ -364,6 +364,65 @@ def is_valid_file(path, size): |
return True |
+def is_cached(ifile, cache): |
+ """Determines if all the isolated file's contents are in the given LocalCache |
+ |
+ """ |
+ files = ifile.data.get(u'files', {}) |
+ for f in files.keys(): |
+ # Can't do for f, props in files.keys() otherwise we see "too many |
+ # values to unpack". |
+ props = files.get(f, None) |
+ if not props: |
+ logging.warning('Problem getting info for %s', f) |
+ return False |
+ digest = props.get('h', None) |
+ if not digest: |
+ logging.warning('Hash can\'t be empty %s', f) |
+ return False |
+ if digest not in cache: |
+ logging.info('File with digest %s is missing', digest) |
+ return False |
+ return True |
+ |
+ |
+def extract(ifile, target_dir, cache): |
+ """Extracts the isolated file's contents to target dir. |
+ |
+ It stops if any couldn't be found. |
+ """ |
+ files = ifile.data.get(u'files', {}) |
+ for f in files.keys(): |
+ # Can't do for f, props in files.keys() otherwise we see "too many |
+ # values to unpack". |
+ props = files.get(f, None) |
+ if not props: |
+ logging.warning('Problem getting info for %s', f) |
+ return False |
+ file_mode = props.get('m', None) |
+ if file_mode: |
+ # Ignore all bits apart from the user |
+ file_mode &= 0700 |
+ |
+ dstpath = os.path.join(target_dir, f) |
+ file_path.ensure_tree(os.path.dirname(dstpath)) |
+ digest = props.get('h', None) |
+ if not digest: |
+ logging.warning('Hash can\'t be empty %s', f) |
+ return False |
+ if digest not in cache: |
+ logging.info('File with digest %s is missing', digest) |
+ return False |
+ srcpath = cache.getfileobj(digest).name |
+ |
+ file_path.link_file(unicode(dstpath), unicode(srcpath), |
+ file_path.HARDLINK_WITH_FALLBACK) |
+ |
+ if file_mode is not None: |
+ fs.chmod(dstpath, file_mode) |
+ return True |
+ |
+ |
class FileItem(Item): |
"""A file to push to Storage. |
@@ -1719,14 +1778,14 @@ def fetch_isolated(isolated_hash, storage, cache, outdir, use_symlinks): |
return bundle |
-def directory_to_metadata(root, algo, blacklist): |
+def directory_to_metadata(root, algo, blacklist, collapse_symlinks): |
"""Returns the FileItem list and .isolated metadata for a directory.""" |
root = file_path.get_native_path_case(root) |
paths = isolated_format.expand_directory_and_symlink( |
root, '.' + os.path.sep, blacklist, sys.platform != 'win32') |
metadata = { |
relpath: isolated_format.file_to_metadata( |
- os.path.join(root, relpath), {}, 0, algo, False) |
+ os.path.join(root, relpath), {}, 0, algo, collapse_symlinks) |
for relpath in paths |
} |
for v in metadata.itervalues(): |
@@ -1772,7 +1831,7 @@ def archive_files_to_storage(storage, files, blacklist): |
if fs.isdir(filepath): |
# Uploading a whole directory. |
items, metadata = directory_to_metadata( |
- filepath, storage.hash_algo, blacklist) |
+ filepath, storage.hash_algo, blacklist, False) |
# Create the .isolated file. |
if not tempdir: |