| 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):
|
|
|