|
1 # |
|
2 # Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 # All rights reserved. |
|
4 # This component and the accompanying materials are made available |
|
5 # under the terms of "Eclipse Public License v1.0" |
|
6 # which accompanies this distribution, and is available |
|
7 # at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 # |
|
9 # Initial Contributors: |
|
10 # Nokia Corporation - initial contribution. |
|
11 # |
|
12 # Contributors: |
|
13 # |
|
14 # Description: |
|
15 # |
|
16 |
|
17 import os, re, zipfile |
|
18 |
|
19 SVN_IGNORE_PATTERN = r'(.*/|.*\\|^)\.svn(/.*|\\.*|$)' |
|
20 |
|
21 def zip_dir(source_dir, target_file, ignore_patterns=[]): |
|
22 """ |
|
23 Archive the contents of a directory into a zip file. |
|
24 """ |
|
25 if not os.path.isdir(source_dir): |
|
26 raise RuntimeError("'%s' does not exist or is not a directory" % dir) |
|
27 |
|
28 target_dir = os.path.dirname(target_file) |
|
29 if target_dir != '' and not os.path.exists(target_dir): |
|
30 os.makedirs(target_dir) |
|
31 |
|
32 def is_ignored(entry_name): |
|
33 for pat in ignore_patterns: |
|
34 if re.match(pat, entry_name) != None: |
|
35 return True |
|
36 return False |
|
37 |
|
38 zf = zipfile.ZipFile(target_file, 'w', compression=zipfile.ZIP_DEFLATED) |
|
39 try: |
|
40 source_dir = os.path.abspath(source_dir).replace('\\', '/') |
|
41 if not source_dir.endswith('/'): source_dir += '/' |
|
42 |
|
43 empty_dirs = [] |
|
44 for root, dirs, files in os.walk(source_dir): |
|
45 # Construct the ZIP entry name of the current directory |
|
46 root_dir_zip_name = root.replace('\\', '/')[len(source_dir):] + '/' |
|
47 |
|
48 if is_ignored(root_dir_zip_name): |
|
49 continue |
|
50 |
|
51 # Create a dictionary of the files that should be written to the |
|
52 # ZIP file |
|
53 filtered_files = {} |
|
54 for fname in files: |
|
55 if root_dir_zip_name == '/': zip_name = fname |
|
56 else: zip_name = root_dir_zip_name + fname |
|
57 if not is_ignored(zip_name): |
|
58 filtered_files[zip_name] = os.path.join(root, fname) |
|
59 |
|
60 # If the current directory is a sub-directory of an empty directory candidate, |
|
61 # remove the base directory from the sub-directory candidates |
|
62 empty_dirs = filter(lambda n: not root_dir_zip_name.startswith(n), empty_dirs) |
|
63 |
|
64 if len(filtered_files) == 0: |
|
65 # If there are no files, the directory is possibly an empty directory |
|
66 # (though it can still contain sub-directories that contain something) |
|
67 empty_dirs.append(root_dir_zip_name) |
|
68 else: |
|
69 for zip_name, path in filtered_files.iteritems(): |
|
70 zf.write(path, zip_name, zipfile.ZIP_DEFLATED) |
|
71 |
|
72 # Write empty directories |
|
73 for zip_name in empty_dirs: |
|
74 zf.writestr(zip_name, '') |
|
75 finally: |
|
76 zf.close() |