blob: a6ce362d77f9058e3781355efae3059d0312f229 [file] [log] [blame]
Chris Bracken9985bc02021-07-31 11:09:12 -07001#!/usr/bin/env python3
2#
Dan Fielda05803a2019-10-10 06:56:43 -07003# Copyright 2013 The Flutter Authors. All rights reserved.
4# Use of this source code is governed by a BSD-style license that can be
5# found in the LICENSE file.
6
7import argparse
godofredoc988e8fc2022-03-02 08:26:11 -08008import json
Dan Fielda05803a2019-10-10 06:56:43 -07009import os
godofredoc59c9daf2022-03-25 23:30:02 -070010import stat
Dan Fielda05803a2019-10-10 06:56:43 -070011import sys
godofredoc8ae76c32022-08-22 08:16:46 -070012import zipfile
Dan Fielda05803a2019-10-10 06:56:43 -070013
14
15def _zip_dir(path, zip_file, prefix):
16 path = path.rstrip('/\\')
godofredoc835ba6b2022-08-19 22:30:19 -070017 for root, directories, files in os.walk(path):
18 for directory in directories:
19 if os.path.islink(os.path.join(root, directory)):
20 add_symlink(
21 zip_file,
godofredoc8ae76c32022-08-22 08:16:46 -070022 os.path.join(root, directory),
godofredoc835ba6b2022-08-19 22:30:19 -070023 os.path.join(root.replace(path, prefix), directory),
24 )
Dan Fielda05803a2019-10-10 06:56:43 -070025 for file in files:
godofredoc59c9daf2022-03-25 23:30:02 -070026 if os.path.islink(os.path.join(root, file)):
27 add_symlink(
Zachary Anderson9e0316d2022-06-03 13:00:14 -070028 zip_file, os.path.join(root, file),
godofredoc59c9daf2022-03-25 23:30:02 -070029 os.path.join(root.replace(path, prefix), file)
30 )
31 continue
Zachary Anderson9e0316d2022-06-03 13:00:14 -070032 zip_file.write(
33 os.path.join(root, file),
34 os.path.join(root.replace(path, prefix), file)
35 )
Dan Fielda05803a2019-10-10 06:56:43 -070036
37
godofredoc59c9daf2022-03-25 23:30:02 -070038def add_symlink(zip_file, source, target):
39 """Adds a symlink to a zip file.
40
41 Args:
42 zip_file: The ZipFile obj where the symlink will be added.
43 source: The full path to the symlink.
44 target: The target path for the symlink within the zip file.
45 """
Zachary Anderson9e0316d2022-06-03 13:00:14 -070046 zip_info = zipfile.ZipInfo(target)
47 zip_info.create_system = 3 # Unix like system
48 unix_st_mode = (
49 stat.S_IFLNK | stat.S_IRUSR | stat.S_IWUSR | stat.S_IXUSR | stat.S_IRGRP
50 | stat.S_IWGRP | stat.S_IXGRP | stat.S_IROTH | stat.S_IWOTH | stat.S_IXOTH
51 )
godofredoc59c9daf2022-03-25 23:30:02 -070052 zip_info.external_attr = unix_st_mode << 16
godofredoc8ae76c32022-08-22 08:16:46 -070053 zip_file.writestr(zip_info, os.readlink(source))
godofredoc59c9daf2022-03-25 23:30:02 -070054
55
Dan Fielda05803a2019-10-10 06:56:43 -070056def main(args):
57 zip_file = zipfile.ZipFile(args.output, 'w', zipfile.ZIP_DEFLATED)
godofredoc988e8fc2022-03-02 08:26:11 -080058 if args.source_file:
59 with open(args.source_file) as source_file:
60 file_dict_list = json.load(source_file)
61 for file_dict in file_dict_list:
godofredoc59c9daf2022-03-25 23:30:02 -070062 if os.path.islink(file_dict['source']):
63 add_symlink(zip_file, file_dict['source'], file_dict['destination'])
64 continue
godofredoc988e8fc2022-03-02 08:26:11 -080065 if os.path.isdir(file_dict['source']):
66 _zip_dir(file_dict['source'], zip_file, file_dict['destination'])
67 else:
68 zip_file.write(file_dict['source'], file_dict['destination'])
69 else:
70 for path, archive_name in args.input_pairs:
godofredoc59c9daf2022-03-25 23:30:02 -070071 if os.path.islink(path):
72 add_symlink(zip_file, path, archive_name)
73 continue
godofredoc988e8fc2022-03-02 08:26:11 -080074 if os.path.isdir(path):
75 _zip_dir(path, zip_file, archive_name)
76 else:
77 zip_file.write(path, archive_name)
Dan Fielda05803a2019-10-10 06:56:43 -070078 zip_file.close()
79
80
81if __name__ == '__main__':
Zachary Anderson9e0316d2022-06-03 13:00:14 -070082 parser = argparse.ArgumentParser(description='This script creates zip files.')
83 parser.add_argument(
84 '-o',
85 dest='output',
86 action='store',
87 help='The name of the output zip file.'
88 )
89 parser.add_argument(
90 '-i',
91 dest='input_pairs',
92 nargs=2,
93 action='append',
94 help='The input file and its destination location in the zip archive.'
95 )
96 parser.add_argument(
97 '-f',
98 dest='source_file',
99 action='store',
100 help='The path to the file list to zip.'
101 )
Dan Fielda05803a2019-10-10 06:56:43 -0700102 sys.exit(main(parser.parse_args()))