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