| OLD | NEW |
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # Copyright 2013 The LUCI Authors. All rights reserved. | 2 # Copyright 2013 The LUCI Authors. All rights reserved. |
| 3 # Use of this source code is governed under the Apache License, Version 2.0 | 3 # Use of this source code is governed under the Apache License, Version 2.0 |
| 4 # that can be found in the LICENSE file. | 4 # that can be found in the LICENSE file. |
| 5 | 5 |
| 6 """Archives a set of files or directories to an Isolate Server.""" | 6 """Archives a set of files or directories to an Isolate Server.""" |
| 7 | 7 |
| 8 __version__ = '0.6.0' | 8 __version__ = '0.7.0' |
| 9 | 9 |
| 10 import base64 | 10 import base64 |
| 11 import errno | 11 import errno |
| 12 import functools | 12 import functools |
| 13 import io | 13 import io |
| 14 import logging | 14 import logging |
| 15 import optparse | 15 import optparse |
| 16 import os | 16 import os |
| 17 import re | 17 import re |
| 18 import signal | 18 import signal |
| 19 import stat | 19 import stat |
| 20 import sys | 20 import sys |
| 21 import tarfile |
| 21 import tempfile | 22 import tempfile |
| 22 import threading | 23 import threading |
| 23 import time | 24 import time |
| 24 import types | 25 import types |
| 25 import zlib | 26 import zlib |
| 26 | 27 |
| 27 from third_party import colorama | 28 from third_party import colorama |
| 28 from third_party.depot_tools import fix_encoding | 29 from third_party.depot_tools import fix_encoding |
| 29 from third_party.depot_tools import subcommand | 30 from third_party.depot_tools import subcommand |
| 30 | 31 |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 162 if name is None: | 163 if name is None: |
| 163 return | 164 return |
| 164 | 165 |
| 165 # If the file like object was created using something like open("test.txt") | 166 # If the file like object was created using something like open("test.txt") |
| 166 # name will end up being a str (such as a function outside our control, like | 167 # name will end up being a str (such as a function outside our control, like |
| 167 # the standard library). We want all our paths to be unicode objects, so we | 168 # the standard library). We want all our paths to be unicode objects, so we |
| 168 # decode it. | 169 # decode it. |
| 169 if not isinstance(name, unicode): | 170 if not isinstance(name, unicode): |
| 170 name = name.decode(sys.getfilesystemencoding()) | 171 name = name.decode(sys.getfilesystemencoding()) |
| 171 | 172 |
| 173 # fs.exists requires an absolute path, otherwise it will fail with an |
| 174 # assertion error. |
| 175 if not os.path.isabs(name): |
| 176 return |
| 177 |
| 172 if fs.exists(name): | 178 if fs.exists(name): |
| 173 return name | 179 return name |
| 174 | 180 |
| 175 | 181 |
| 176 # TODO(tansell): Replace fileobj_copy with shutil.copyfileobj once proper file | 182 # TODO(tansell): Replace fileobj_copy with shutil.copyfileobj once proper file |
| 177 # wrappers have been created. | 183 # wrappers have been created. |
| 178 def fileobj_copy( | 184 def fileobj_copy( |
| 179 dstfileobj, srcfileobj, size=-1, | 185 dstfileobj, srcfileobj, size=-1, |
| 180 chunk_size=isolated_format.DISK_FILE_CHUNK): | 186 chunk_size=isolated_format.DISK_FILE_CHUNK): |
| 181 """Copy data from srcfileobj to dstfileobj. | 187 """Copy data from srcfileobj to dstfileobj. |
| (...skipping 1918 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2100 | 2106 |
| 2101 if filetype == 'basic': | 2107 if filetype == 'basic': |
| 2102 file_mode = props.get('m') | 2108 file_mode = props.get('m') |
| 2103 if file_mode: | 2109 if file_mode: |
| 2104 # Ignore all bits apart from the user | 2110 # Ignore all bits apart from the user |
| 2105 file_mode &= 0700 | 2111 file_mode &= 0700 |
| 2106 putfile( | 2112 putfile( |
| 2107 srcfileobj, fullpath, file_mode, | 2113 srcfileobj, fullpath, file_mode, |
| 2108 use_symlink=use_symlinks) | 2114 use_symlink=use_symlinks) |
| 2109 | 2115 |
| 2116 elif filetype == 'tar': |
| 2117 basedir = os.path.dirname(fullpath) |
| 2118 with tarfile.TarFile(fileobj=srcfileobj) as extractor: |
| 2119 for ti in extractor: |
| 2120 if not ti.isfile(): |
| 2121 logging.warning( |
| 2122 'Path(%r) is nonfile (%s), skipped', |
| 2123 ti.name, ti.type) |
| 2124 continue |
| 2125 fp = os.path.normpath(os.path.join(basedir, ti.name)) |
| 2126 if not fp.startswith(basedir): |
| 2127 logging.error( |
| 2128 'Path(%r) is outside root directory', |
| 2129 fp) |
| 2130 ifd = extractor.extractfile(ti) |
| 2131 file_path.ensure_tree(os.path.dirname(fp)) |
| 2132 putfile(ifd, fp, 0700, ti.size) |
| 2133 |
| 2110 elif filetype == 'ar': | 2134 elif filetype == 'ar': |
| 2111 basedir = os.path.dirname(fullpath) | 2135 basedir = os.path.dirname(fullpath) |
| 2112 extractor = arfile.ArFileReader(srcfileobj, fullparse=False) | 2136 extractor = arfile.ArFileReader(srcfileobj, fullparse=False) |
| 2113 for ai, ifd in extractor: | 2137 for ai, ifd in extractor: |
| 2114 fp = os.path.normpath(os.path.join(basedir, ai.name)) | 2138 fp = os.path.normpath(os.path.join(basedir, ai.name)) |
| 2139 if not fp.startswith(basedir): |
| 2140 logging.error( |
| 2141 'Path(%r) is outside root directory', |
| 2142 fp) |
| 2115 file_path.ensure_tree(os.path.dirname(fp)) | 2143 file_path.ensure_tree(os.path.dirname(fp)) |
| 2116 putfile(ifd, fp, 0700, ai.size) | 2144 putfile(ifd, fp, 0700, ai.size) |
| 2117 | 2145 |
| 2118 else: | 2146 else: |
| 2119 raise isolated_format.IsolatedError( | 2147 raise isolated_format.IsolatedError( |
| 2120 'Unknown file type %r', filetype) | 2148 'Unknown file type %r', filetype) |
| 2121 | 2149 |
| 2122 # Report progress. | 2150 # Report progress. |
| 2123 duration = time.time() - last_update | 2151 duration = time.time() - last_update |
| 2124 if duration > DELAY_BETWEEN_UPDATES_IN_SECS: | 2152 if duration > DELAY_BETWEEN_UPDATES_IN_SECS: |
| (...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2456 return dispatcher.execute(OptionParserIsolateServer(), args) | 2484 return dispatcher.execute(OptionParserIsolateServer(), args) |
| 2457 | 2485 |
| 2458 | 2486 |
| 2459 if __name__ == '__main__': | 2487 if __name__ == '__main__': |
| 2460 subprocess42.inhibit_os_error_reporting() | 2488 subprocess42.inhibit_os_error_reporting() |
| 2461 fix_encoding.fix_encoding() | 2489 fix_encoding.fix_encoding() |
| 2462 tools.disable_buffering() | 2490 tools.disable_buffering() |
| 2463 colorama.init() | 2491 colorama.init() |
| 2464 file_path.enable_symlink() | 2492 file_path.enable_symlink() |
| 2465 sys.exit(main(sys.argv[1:])) | 2493 sys.exit(main(sys.argv[1:])) |
| OLD | NEW |