Index: build/android/gyp/util/build_utils.py |
diff --git a/build/android/gyp/util/build_utils.py b/build/android/gyp/util/build_utils.py |
index b12c56252dc8dca0a95d447e888598c56efbed93..81041ef2f9bf6843e0e00dbbc779db05a34ff5c6 100644 |
--- a/build/android/gyp/util/build_utils.py |
+++ b/build/android/gyp/util/build_utils.py |
@@ -25,6 +25,7 @@ COLORAMA_ROOT = os.path.join(CHROMIUM_SRC, |
# aapt should ignore OWNERS files in addition the default ignore pattern. |
AAPT_IGNORE_PATTERN = ('!OWNERS:!.svn:!.git:!.ds_store:!*.scc:.*:<dir>_*:' + |
'!CVS:!thumbs.db:!picasa.ini:!*~:!*.d.stamp') |
+HERMETIC_TIMESTAMP = (2001, 1, 1, 0, 0, 0) |
@contextlib.contextmanager |
@@ -218,21 +219,38 @@ def ExtractAll(zip_path, path=None, no_clobber=True, pattern=None): |
z.extractall(path=path) |
-def DoZip(inputs, output, base_dir): |
+def DoZip(inputs, output, base_dir=None): |
+ """Creates a zip file from a list of files. |
+ |
+ Args: |
+ inputs: A list of paths to zip, or a list of (zip_path, fs_path) tuples. |
+ output: Destination .zip file. |
+ base_dir: Prefix to strip from inputs. |
+ """ |
+ input_tuples = [] |
+ for tup in inputs: |
+ if isinstance(tup, basestring): |
+ tup = (os.path.relpath(tup, base_dir), tup) |
+ input_tuples.append(tup) |
+ |
+ # Sort by zip path to ensure stable zip ordering. |
+ input_tuples.sort(key=lambda tup: tup[0]) |
with zipfile.ZipFile(output, 'w') as outfile: |
- for f in inputs: |
- CheckZipPath(os.path.relpath(f, base_dir)) |
- outfile.write(f, os.path.relpath(f, base_dir)) |
+ for zip_path, fs_path in input_tuples: |
+ CheckZipPath(zip_path) |
+ zipinfo = zipfile.ZipInfo(filename=zip_path, date_time=HERMETIC_TIMESTAMP) |
+ with file(fs_path) as f: |
+ contents = f.read() |
+ outfile.writestr(zipinfo, contents) |
def ZipDir(output, base_dir): |
- with zipfile.ZipFile(output, 'w') as outfile: |
- for root, _, files in os.walk(base_dir): |
- for f in files: |
- path = os.path.join(root, f) |
- archive_path = os.path.relpath(path, base_dir) |
- CheckZipPath(archive_path) |
- outfile.write(path, archive_path) |
+ """Creates a zip file from a directory.""" |
+ inputs = [] |
+ for root, _, files in os.walk(base_dir): |
+ for f in files: |
+ inputs.append(os.path.join(root, f)) |
+ DoZip(inputs, output, base_dir) |
def MatchesGlob(path, filters): |
@@ -240,16 +258,21 @@ def MatchesGlob(path, filters): |
return filters and any(fnmatch.fnmatch(path, f) for f in filters) |
-def MergeZips(output, inputs, exclude_patterns=None): |
+def MergeZips(output, inputs, exclude_patterns=None, path_transform=None): |
+ path_transform = path_transform or (lambda p, z: p) |
added_names = set() |
with zipfile.ZipFile(output, 'w') as out_zip: |
for in_file in inputs: |
with zipfile.ZipFile(in_file, 'r') as in_zip: |
for name in in_zip.namelist(): |
- if not (name in added_names or MatchesGlob(name, exclude_patterns)): |
- out_zip.writestr(name, in_zip.read(name)) |
- added_names.add(name) |
+ dst_name = path_transform(name, in_file) |
+ already_added = dst_name in added_names |
+ if not already_added and not MatchesGlob(dst_name, exclude_patterns): |
+ zipinfo = zipfile.ZipInfo(filename=dst_name, |
+ date_time=HERMETIC_TIMESTAMP) |
+ out_zip.writestr(zipinfo, in_zip.read(name)) |
+ added_names.add(dst_name) |
def PrintWarning(message): |