| OLD | NEW |
| 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 | 4 |
| 5 import hashlib | 5 import hashlib |
| 6 import os | 6 import os |
| 7 import sys | 7 import sys |
| 8 # when pylint runs the third_party module is the one from depot_tools | 8 # when pylint runs the third_party module is the one from depot_tools |
| 9 # pylint: disable=E0611 | 9 # pylint: disable=E0611 |
| 10 from third_party import fancy_urllib | 10 from third_party import fancy_urllib |
| 11 import urllib2 | 11 import urllib2 |
| 12 | 12 |
| 13 | 13 |
| 14 SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) | 14 SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__)) |
| 15 | 15 |
| 16 | 16 |
| 17 def UrlOpen(url): | 17 def UrlOpen(url): |
| 18 request = fancy_urllib.FancyRequest(url) | 18 request = fancy_urllib.FancyRequest(url) |
| 19 ca_certs = os.path.join(SCRIPT_DIR, 'cacerts.txt') | 19 ca_certs = os.path.join(SCRIPT_DIR, 'cacerts.txt') |
| 20 request.set_ssl_info(ca_certs=ca_certs) | 20 request.set_ssl_info(ca_certs=ca_certs) |
| 21 url_opener = urllib2.build_opener( | 21 url_opener = urllib2.build_opener( |
| 22 fancy_urllib.FancyProxyHandler(), | 22 fancy_urllib.FancyProxyHandler(), |
| 23 fancy_urllib.FancyRedirectHandler(), | 23 fancy_urllib.FancyRedirectHandler(), |
| 24 fancy_urllib.FancyHTTPSHandler()) | 24 fancy_urllib.FancyHTTPSHandler()) |
| 25 return url_opener.open(request) | 25 return url_opener.open(request) |
| 26 | 26 |
| 27 | 27 |
| 28 def MakeProgressFunction(file_size=0): | 28 def MakeProgressFunction(file_size): |
| 29 # An inner function can only read nonlocal variables, not assign them. We can | 29 # An inner function can only read nonlocal variables, not assign them. We can |
| 30 # work around this by using a list of one element. | 30 # work around this by using a list of one element. |
| 31 dots = [0] | 31 dots = [0] |
| 32 def ShowKnownProgress(progress): | 32 def ShowKnownProgress(progress): |
| 33 '''Returns a progress function based on a known file size''' | 33 '''Returns a progress function based on a known file size''' |
| 34 if progress == 0: | 34 if progress == 0: |
| 35 sys.stdout.write('|%s|\n' % ('=' * 48)) | 35 sys.stdout.write('|%s|\n' % ('=' * 48)) |
| 36 elif progress == -1: |
| 37 sys.stdout.write('\n') |
| 36 else: | 38 else: |
| 37 new_dots = progress * 50 / file_size - dots[0] | 39 new_dots = progress * 50 / file_size - dots[0] |
| 38 sys.stdout.write('.' * new_dots) | 40 sys.stdout.write('.' * new_dots) |
| 39 dots[0] += new_dots | 41 dots[0] += new_dots |
| 40 if progress == file_size: | |
| 41 sys.stdout.write('\n') | |
| 42 sys.stdout.flush() | 42 sys.stdout.flush() |
| 43 | 43 |
| 44 return ShowKnownProgress | 44 return ShowKnownProgress |
| 45 | 45 |
| 46 | 46 |
| 47 def DownloadAndComputeHash(from_stream, to_stream=None, progress_func=None): | 47 def DownloadAndComputeHash(from_stream, to_stream=None, progress_func=None): |
| 48 '''Read from from-stream and generate sha1 and size info. | 48 '''Read from from-stream and generate sha1 and size info. |
| 49 | 49 |
| 50 Args: | 50 Args: |
| 51 from_stream: An input stream that supports read. | 51 from_stream: An input stream that supports read. |
| 52 to_stream: [optional] the data is written to to_stream if it is | 52 to_stream: [optional] the data is written to to_stream if it is |
| 53 provided. | 53 provided. |
| 54 progress_func: [optional] A function used to report download progress. If | 54 progress_func: [optional] A function used to report download progress. If |
| 55 provided, progress_func is called with progress=0 at the | 55 provided, progress_func is called with progress=0 at the |
| 56 beginning of the download, periodically with progress=1 | 56 beginning of the download, periodically with progress>0 |
| 57 during the download, and progress=100 at the end. | 57 (== number of bytes read do far) during the download, and |
| 58 progress=-1 at the end or if the download was aborted. |
| 58 | 59 |
| 59 Return | 60 Return |
| 60 A tuple (sha1, size) where sha1 is a sha1-hash for the archive data and | 61 A tuple (sha1, size) where sha1 is a sha1-hash for the archive data and |
| 61 size is the size of the archive data in bytes.''' | 62 size is the size of the archive data in bytes.''' |
| 62 # Use a no-op progress function if none is specified. | 63 # Use a no-op progress function if none is specified. |
| 63 def progress_no_op(progress): | 64 def progress_no_op(progress): |
| 64 pass | 65 pass |
| 65 if not progress_func: | 66 if not progress_func: |
| 66 progress_func = progress_no_op | 67 progress_func = progress_no_op |
| 67 | 68 |
| 68 sha1_hash = hashlib.sha1() | 69 sha1_hash = hashlib.sha1() |
| 69 size = 0 | 70 size = 0 |
| 70 progress_func(progress=0) | 71 try: |
| 71 while(1): | 72 progress_func(progress=0) |
| 72 data = from_stream.read(32768) | 73 while True: |
| 73 if not data: | 74 data = from_stream.read(32768) |
| 74 break | 75 if not data: |
| 75 sha1_hash.update(data) | 76 break |
| 76 size += len(data) | 77 sha1_hash.update(data) |
| 77 if to_stream: | 78 size += len(data) |
| 78 to_stream.write(data) | 79 if to_stream: |
| 79 progress_func(size) | 80 to_stream.write(data) |
| 80 | 81 progress_func(size) |
| 81 progress_func(progress=100) | 82 finally: |
| 83 progress_func(progress=-1) |
| 82 return sha1_hash.hexdigest(), size | 84 return sha1_hash.hexdigest(), size |
| OLD | NEW |