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