Chromium Code Reviews| 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.4.8' | 8 __version__ = '0.4.8' |
| 9 | 9 |
| 10 import base64 | 10 import base64 |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 109 class Error(Exception): | 109 class Error(Exception): |
| 110 """Generic runtime error.""" | 110 """Generic runtime error.""" |
| 111 pass | 111 pass |
| 112 | 112 |
| 113 | 113 |
| 114 class Aborted(Error): | 114 class Aborted(Error): |
| 115 """Operation aborted.""" | 115 """Operation aborted.""" |
| 116 pass | 116 pass |
| 117 | 117 |
| 118 | 118 |
| 119 class AlreadyExists(Error): | |
| 120 """File already exists.""" | |
| 121 | |
| 122 | |
| 119 def file_read(path, chunk_size=isolated_format.DISK_FILE_CHUNK, offset=0): | 123 def file_read(path, chunk_size=isolated_format.DISK_FILE_CHUNK, offset=0): |
| 120 """Yields file content in chunks of |chunk_size| starting from |offset|.""" | 124 """Yields file content in chunks of |chunk_size| starting from |offset|.""" |
| 121 with fs.open(path, 'rb') as f: | 125 with fs.open(path, 'rb') as f: |
| 122 if offset: | 126 if offset: |
| 123 f.seek(offset) | 127 f.seek(offset) |
| 124 while True: | 128 while True: |
| 125 data = f.read(chunk_size) | 129 data = f.read(chunk_size) |
| 126 if not data: | 130 if not data: |
| 127 break | 131 break |
| 128 yield data | 132 yield data |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 214 def create_symlinks(base_directory, files): | 218 def create_symlinks(base_directory, files): |
| 215 """Creates any symlinks needed by the given set of files.""" | 219 """Creates any symlinks needed by the given set of files.""" |
| 216 for filepath, properties in files: | 220 for filepath, properties in files: |
| 217 if 'l' not in properties: | 221 if 'l' not in properties: |
| 218 continue | 222 continue |
| 219 if sys.platform == 'win32': | 223 if sys.platform == 'win32': |
| 220 # TODO(maruel): Create symlink via the win32 api. | 224 # TODO(maruel): Create symlink via the win32 api. |
| 221 logging.warning('Ignoring symlink %s', filepath) | 225 logging.warning('Ignoring symlink %s', filepath) |
| 222 continue | 226 continue |
| 223 outfile = os.path.join(base_directory, filepath) | 227 outfile = os.path.join(base_directory, filepath) |
| 228 if os.path.exists(outfile): | |
|
M-A Ruel
2016/06/15 17:28:27
I'm not super excited about adding another system
nodir
2016/06/15 17:53:42
Done
| |
| 229 raise AlreadyExists('File %s already exists.' % outfile) | |
| 224 # os.symlink() doesn't exist on Windows. | 230 # os.symlink() doesn't exist on Windows. |
| 225 os.symlink(properties['l'], outfile) # pylint: disable=E1101 | 231 os.symlink(properties['l'], outfile) # pylint: disable=E1101 |
| 226 | 232 |
| 227 | 233 |
| 228 def is_valid_file(path, size): | 234 def is_valid_file(path, size): |
| 229 """Determines if the given files appears valid. | 235 """Determines if the given files appears valid. |
| 230 | 236 |
| 231 Currently it just checks the file's size. | 237 Currently it just checks the file's size. |
| 232 """ | 238 """ |
| 233 if size == UNKNOWN_FILE_SIZE: | 239 if size == UNKNOWN_FILE_SIZE: |
| (...skipping 1726 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1960 last_update = time.time() | 1966 last_update = time.time() |
| 1961 with threading_utils.DeadlockDetector(DEADLOCK_TIMEOUT) as detector: | 1967 with threading_utils.DeadlockDetector(DEADLOCK_TIMEOUT) as detector: |
| 1962 while remaining: | 1968 while remaining: |
| 1963 detector.ping() | 1969 detector.ping() |
| 1964 | 1970 |
| 1965 # Wait for any item to finish fetching to cache. | 1971 # Wait for any item to finish fetching to cache. |
| 1966 digest = fetch_queue.wait(remaining) | 1972 digest = fetch_queue.wait(remaining) |
| 1967 | 1973 |
| 1968 # Link corresponding files to a fetched item in cache. | 1974 # Link corresponding files to a fetched item in cache. |
| 1969 for filepath, props in remaining.pop(digest): | 1975 for filepath, props in remaining.pop(digest): |
| 1970 cache.hardlink( | 1976 dest = os.path.join(outdir, filepath) |
| 1971 digest, os.path.join(outdir, filepath), props.get('m')) | 1977 if os.path.exists(dest): |
|
M-A Ruel
2016/06/15 17:28:27
this one is harder to skip since the actual execut
nodir
2016/06/15 17:53:42
Acknowledged.
| |
| 1978 raise AlreadyExists('File %s already exists' % dest) | |
| 1979 cache.hardlink(digest, dest, props.get('m')) | |
| 1972 | 1980 |
| 1973 # Report progress. | 1981 # Report progress. |
| 1974 duration = time.time() - last_update | 1982 duration = time.time() - last_update |
| 1975 if duration > DELAY_BETWEEN_UPDATES_IN_SECS: | 1983 if duration > DELAY_BETWEEN_UPDATES_IN_SECS: |
| 1976 msg = '%d files remaining...' % len(remaining) | 1984 msg = '%d files remaining...' % len(remaining) |
| 1977 print msg | 1985 print msg |
| 1978 logging.info(msg) | 1986 logging.info(msg) |
| 1979 last_update = time.time() | 1987 last_update = time.time() |
| 1980 | 1988 |
| 1981 # Cache could evict some items we just tried to fetch, it's a fatal error. | 1989 # Cache could evict some items we just tried to fetch, it's a fatal error. |
| (...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2298 dispatcher = subcommand.CommandDispatcher(__name__) | 2306 dispatcher = subcommand.CommandDispatcher(__name__) |
| 2299 return dispatcher.execute(OptionParserIsolateServer(), args) | 2307 return dispatcher.execute(OptionParserIsolateServer(), args) |
| 2300 | 2308 |
| 2301 | 2309 |
| 2302 if __name__ == '__main__': | 2310 if __name__ == '__main__': |
| 2303 subprocess42.inhibit_os_error_reporting() | 2311 subprocess42.inhibit_os_error_reporting() |
| 2304 fix_encoding.fix_encoding() | 2312 fix_encoding.fix_encoding() |
| 2305 tools.disable_buffering() | 2313 tools.disable_buffering() |
| 2306 colorama.init() | 2314 colorama.init() |
| 2307 sys.exit(main(sys.argv[1:])) | 2315 sys.exit(main(sys.argv[1:])) |
| OLD | NEW |