def main(args): unix_ts = max(ZIP_EPOCH, args.timestamp) ts = parse_date(unix_ts) default_mode = None if args.mode: default_mode = int(args.mode, 8) with zipfile.ZipFile(args.output, 'w') as zip_file: for f in args.files or []: (src_path, dst_path) = SplitNameValuePairAtSeparator(f, '=') dst_path = _combine_paths(args.directory, dst_path) entry_info = zipfile.ZipInfo(filename=dst_path, date_time=ts) if default_mode: entry_info.external_attr = default_mode << 16 entry_info.compress_type = zipfile.ZIP_DEFLATED # the zipfile library doesn't support adding a file by path with write() # and specifying a ZipInfo at the same time. with open(src_path, 'rb') as src: data = src.read() zip_file.writestr(entry_info, data)
def main(args): unix_ts = max(ZIP_EPOCH, args.timestamp) ts = parse_date(unix_ts) with ZipFile(args.output, 'w') as zip: for f in args.files or []: (src_path, dst_path) = SplitNameValuePairAtSeparator(f, '=') dst_path = _combine_paths(args.directory, dst_path) entry_info = ZipInfo(filename=dst_path, date_time=ts) entry_info.external_attr = (os.stat(src_path).st_mode & 0o777) << 16 # give full access to included file entry_info.compress_type = ZIP_DEFLATED # the zipfile library doesn't support adding a file by path with write() # and specifying a ZipInfo at the same time. with open(src_path, 'rb') as src: data = src.read() zip.writestr(entry_info, data)
def main(): parser = argparse.ArgumentParser( description='Helper for building tar packages', fromfile_prefix_chars='@') parser.add_argument('--output', required=True, help='The output file, mandatory.') parser.add_argument('--file', action='append', help='A file to add to the layer.') parser.add_argument('--manifest', help='JSON manifest of contents to add to the layer.') parser.add_argument('--mode', help='Force the mode on the added files (in octal).') parser.add_argument( '--mtime', help='Set mtime on tar file entries. May be an integer or the' ' value "portable", to get the value 2000-01-01, which is' ' is usable with non *nix OSes.') parser.add_argument('--empty_file', action='append', help='An empty file to add to the layer.') parser.add_argument('--empty_dir', action='append', help='An empty dir to add to the layer.') parser.add_argument('--empty_root_dir', action='append', help='An empty dir to add to the layer.') parser.add_argument('--tar', action='append', help='A tar file to add to the layer') parser.add_argument('--deb', action='append', help='A debian package to add to the layer') parser.add_argument( '--link', action='append', help= 'Add a symlink a inside the layer pointing to b if a:b is specified') # TODO(aiuto): Add back in the validation # flags.register_validator( # 'link', # lambda l: all(value.find(':') > 0 for value in l), # message='--link value should contains a : separator') parser.add_argument( '--directory', help='Directory in which to store the file inside the layer') parser.add_argument('--compression', help='Compression (`gz` or `bz2`), default is none.') parser.add_argument( '--modes', action='append', help='Specific mode to apply to specific file (from the file argument),' ' e.g., path/to/file=0455.') parser.add_argument('--owners', action='append', help='Specify the numeric owners of individual files, ' 'e.g. path/to/file=0.0.') parser.add_argument('--owner', default='0.0', help='Specify the numeric default owner of all files,' ' e.g., 0.0') parser.add_argument( '--owner_name', help='Specify the owner name of all files, e.g. root.root.') parser.add_argument( '--owner_names', action='append', help='Specify the owner names of individual files, e.g. ' 'path/to/file=root.root.') parser.add_argument('--root_directory', default='./', help='Default root directory is named "."') options = parser.parse_args() # Parse modes arguments default_mode = None if options.mode: # Convert from octal default_mode = int(options.mode, 8) mode_map = {} if options.modes: for filemode in options.modes: (f, mode) = SplitNameValuePairAtSeparator(filemode, '=') if f[0] == '/': f = f[1:] mode_map[f] = int(mode, 8) default_ownername = ('', '') if options.owner_name: default_ownername = options.owner_name.split('.', 1) names_map = {} if options.owner_names: for file_owner in options.owner_names: (f, owner) = SplitNameValuePairAtSeparator(file_owner, '=') (user, group) = owner.split('.', 1) if f[0] == '/': f = f[1:] names_map[f] = (user, group) default_ids = options.owner.split('.', 1) default_ids = (int(default_ids[0]), int(default_ids[1])) ids_map = {} if options.owners: for file_owner in options.owners: (f, owner) = SplitNameValuePairAtSeparator(file_owner, '=') (user, group) = owner.split('.', 1) if f[0] == '/': f = f[1:] ids_map[f] = (int(user), int(group)) # Add objects to the tar file with TarFile(options.output, GetFlagValue(options.directory), options.compression, options.root_directory, options.mtime) as output: def file_attributes(filename): if filename.startswith('/'): filename = filename[1:] return { 'mode': mode_map.get(filename, default_mode), 'ids': ids_map.get(filename, default_ids), 'names': names_map.get(filename, default_ownername), } if options.manifest: with open(options.manifest, 'r') as manifest_fp: manifest = json.load(manifest_fp) for f in manifest.get('files', []): output.add_file(f['src'], f['dst'], **file_attributes(f['dst'])) for f in manifest.get('empty_files', []): output.add_empty_file(f, **file_attributes(f)) for d in manifest.get('empty_dirs', []): output.add_empty_dir(d, **file_attributes(d)) for d in manifest.get('empty_root_dirs', []): output.add_empty_root_dir(d, **file_attributes(d)) for f in manifest.get('symlinks', []): output.add_link(f['linkname'], f['target']) for tar in manifest.get('tars', []): output.add_tar(tar) for deb in manifest.get('debs', []): output.add_deb(deb) for f in options.file or []: (inf, tof) = SplitNameValuePairAtSeparator(f, '=') output.add_file(inf, tof, **file_attributes(tof)) for f in options.empty_file or []: output.add_empty_file(f, **file_attributes(f)) for f in options.empty_dir or []: output.add_empty_dir(f, **file_attributes(f)) for f in options.empty_root_dir or []: output.add_empty_root_dir(f, **file_attributes(f)) for tar in options.tar or []: output.add_tar(tar) for deb in options.deb or []: output.add_deb(deb) for link in options.link or []: l = SplitNameValuePairAtSeparator(link, ':') output.add_link(l[0], l[1])