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