1*c8dee2aaSAndroid Build Coastguard Worker#!/usr/bin/env python 2*c8dee2aaSAndroid Build Coastguard Worker# 3*c8dee2aaSAndroid Build Coastguard Worker# Copyright 2016 Google Inc. 4*c8dee2aaSAndroid Build Coastguard Worker# 5*c8dee2aaSAndroid Build Coastguard Worker# Use of this source code is governed by a BSD-style license that can be 6*c8dee2aaSAndroid Build Coastguard Worker# found in the LICENSE file. 7*c8dee2aaSAndroid Build Coastguard Worker 8*c8dee2aaSAndroid Build Coastguard Worker 9*c8dee2aaSAndroid Build Coastguard Worker"""Utilities for zipping and unzipping files.""" 10*c8dee2aaSAndroid Build Coastguard Worker 11*c8dee2aaSAndroid Build Coastguard Worker 12*c8dee2aaSAndroid Build Coastguard Workerfrom __future__ import print_function 13*c8dee2aaSAndroid Build Coastguard Workerimport fnmatch 14*c8dee2aaSAndroid Build Coastguard Workerimport ntpath 15*c8dee2aaSAndroid Build Coastguard Workerimport os 16*c8dee2aaSAndroid Build Coastguard Workerimport posixpath 17*c8dee2aaSAndroid Build Coastguard Workerimport zipfile 18*c8dee2aaSAndroid Build Coastguard Worker 19*c8dee2aaSAndroid Build Coastguard Worker 20*c8dee2aaSAndroid Build Coastguard Workerdef filtered(names, to_skip): 21*c8dee2aaSAndroid Build Coastguard Worker """Filter the list of file or directory names.""" 22*c8dee2aaSAndroid Build Coastguard Worker rv = names[:] 23*c8dee2aaSAndroid Build Coastguard Worker for pattern in to_skip: 24*c8dee2aaSAndroid Build Coastguard Worker rv = [n for n in rv if not fnmatch.fnmatch(n, pattern)] 25*c8dee2aaSAndroid Build Coastguard Worker return rv 26*c8dee2aaSAndroid Build Coastguard Worker 27*c8dee2aaSAndroid Build Coastguard Worker 28*c8dee2aaSAndroid Build Coastguard Workerdef zip(target_dir, zip_file, to_skip=None): # pylint: disable=W0622 29*c8dee2aaSAndroid Build Coastguard Worker """Zip the given directory, write to the given zip file.""" 30*c8dee2aaSAndroid Build Coastguard Worker if not os.path.isdir(target_dir): 31*c8dee2aaSAndroid Build Coastguard Worker raise IOError('%s does not exist!' % target_dir) 32*c8dee2aaSAndroid Build Coastguard Worker to_skip = to_skip or [] 33*c8dee2aaSAndroid Build Coastguard Worker with zipfile.ZipFile(zip_file, 'w', zipfile.ZIP_DEFLATED, True) as z: 34*c8dee2aaSAndroid Build Coastguard Worker for r, d, f in os.walk(target_dir, topdown=True): 35*c8dee2aaSAndroid Build Coastguard Worker d[:] = filtered(d, to_skip) 36*c8dee2aaSAndroid Build Coastguard Worker for filename in filtered(f, to_skip): 37*c8dee2aaSAndroid Build Coastguard Worker filepath = os.path.join(r, filename) 38*c8dee2aaSAndroid Build Coastguard Worker zi = zipfile.ZipInfo(filepath) 39*c8dee2aaSAndroid Build Coastguard Worker zi.filename = os.path.relpath(filepath, target_dir) 40*c8dee2aaSAndroid Build Coastguard Worker if os.name == 'nt': 41*c8dee2aaSAndroid Build Coastguard Worker # Dumb path separator replacement for Windows. 42*c8dee2aaSAndroid Build Coastguard Worker zi.filename = zi.filename.replace(ntpath.sep, posixpath.sep) 43*c8dee2aaSAndroid Build Coastguard Worker try: 44*c8dee2aaSAndroid Build Coastguard Worker perms = os.stat(filepath).st_mode 45*c8dee2aaSAndroid Build Coastguard Worker except OSError: 46*c8dee2aaSAndroid Build Coastguard Worker if os.path.islink(filepath): 47*c8dee2aaSAndroid Build Coastguard Worker print('Skipping symlink %s' % filepath) 48*c8dee2aaSAndroid Build Coastguard Worker continue 49*c8dee2aaSAndroid Build Coastguard Worker else: 50*c8dee2aaSAndroid Build Coastguard Worker raise 51*c8dee2aaSAndroid Build Coastguard Worker zi.external_attr = perms << 16 52*c8dee2aaSAndroid Build Coastguard Worker zi.compress_type = zipfile.ZIP_DEFLATED 53*c8dee2aaSAndroid Build Coastguard Worker with open(filepath, 'rb') as f: 54*c8dee2aaSAndroid Build Coastguard Worker content = f.read() 55*c8dee2aaSAndroid Build Coastguard Worker z.writestr(zi, content) 56*c8dee2aaSAndroid Build Coastguard Worker for dirname in d: 57*c8dee2aaSAndroid Build Coastguard Worker dirpath = os.path.join(r, dirname) 58*c8dee2aaSAndroid Build Coastguard Worker z.write(dirpath, os.path.relpath(dirpath, target_dir)) 59*c8dee2aaSAndroid Build Coastguard Worker 60*c8dee2aaSAndroid Build Coastguard Worker 61*c8dee2aaSAndroid Build Coastguard Workerdef unzip(zip_file, target_dir): 62*c8dee2aaSAndroid Build Coastguard Worker """Unzip the given zip file into the target dir.""" 63*c8dee2aaSAndroid Build Coastguard Worker if not os.path.isdir(target_dir): 64*c8dee2aaSAndroid Build Coastguard Worker os.makedirs(target_dir) 65*c8dee2aaSAndroid Build Coastguard Worker with zipfile.ZipFile(zip_file, 'r', zipfile.ZIP_DEFLATED, True) as z: 66*c8dee2aaSAndroid Build Coastguard Worker for zi in z.infolist(): 67*c8dee2aaSAndroid Build Coastguard Worker dst_subpath = zi.filename 68*c8dee2aaSAndroid Build Coastguard Worker if os.name == 'nt': 69*c8dee2aaSAndroid Build Coastguard Worker # Dumb path separator replacement for Windows. 70*c8dee2aaSAndroid Build Coastguard Worker dst_subpath = dst_subpath.replace(posixpath.sep, ntpath.sep) 71*c8dee2aaSAndroid Build Coastguard Worker dst_path = os.path.join(target_dir, dst_subpath) 72*c8dee2aaSAndroid Build Coastguard Worker if dst_path.endswith(os.path.sep): 73*c8dee2aaSAndroid Build Coastguard Worker os.mkdir(dst_path) 74*c8dee2aaSAndroid Build Coastguard Worker else: 75*c8dee2aaSAndroid Build Coastguard Worker with open(dst_path, 'wb') as f: 76*c8dee2aaSAndroid Build Coastguard Worker f.write(z.read(zi)) 77*c8dee2aaSAndroid Build Coastguard Worker perms = zi.external_attr >> 16 78*c8dee2aaSAndroid Build Coastguard Worker os.chmod(dst_path, perms) 79