| OLD | NEW |
| (Empty) | |
| 1 #!/usr/bin/env python |
| 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. |
| 5 |
| 6 """Utilities for checking out Chrome source files from SVN. |
| 7 |
| 8 Chrome release version number is required for checkout. Version number is used |
| 9 to lookup the corresponding DEPS file from Chrome releases. DEPS file contains |
| 10 the dependencies, revision number, and other pertinent information about that |
| 11 particular build. It also specifies whether its a branch or a trunk release |
| 12 and contains a corresponding revision number. The revision number, which is |
| 13 needed to checkout files from SVN, is obtained by parsing the contents of the |
| 14 DEPS file. |
| 15 """ |
| 16 |
| 17 import httplib |
| 18 import logging |
| 19 import os |
| 20 import re |
| 21 import socket |
| 22 import subprocess |
| 23 import urllib2 |
| 24 |
| 25 _BASE_SVN_URL = 'svn://svn.chromium.org/chrome' |
| 26 _SELENIUM_URL = 'http://selenium.googlecode.com/svn/trunk/py' |
| 27 _PYFTPDLIB_URL = 'http://pyftpdlib.googlecode.com/svn/trunk' |
| 28 _CHROME_URL = 'http://src.chromium.org/viewvc/chrome/releases' |
| 29 |
| 30 |
| 31 def _SetupLogging(): |
| 32 """Sets the logging configuration.""" |
| 33 log_format = '%(asctime)s - %(levelname)s : %(message)s' |
| 34 logging.basicConfig(level=logging.DEBUG, format=log_format) |
| 35 |
| 36 |
| 37 _SetupLogging() |
| 38 |
| 39 |
| 40 def _GetContentAndReturnResponse(url): |
| 41 """Gets contents of the file at the specified url. |
| 42 |
| 43 Args: |
| 44 url: The path where the file is located. |
| 45 |
| 46 Returns: |
| 47 A string containing the file contents. |
| 48 """ |
| 49 url_opener = urllib2.urlopen(url) |
| 50 data = url_opener.read() |
| 51 url_opener.close() |
| 52 return data |
| 53 |
| 54 |
| 55 def _GetDeps(version): |
| 56 """Returns contents of DEPS file that corresponds with the version number. |
| 57 |
| 58 Args: |
| 59 version: Chrome version number (e.g., 21.0.1136.0). |
| 60 """ |
| 61 url = '%s/%s/DEPS' % (_CHROME_URL, version) |
| 62 deps = _GetContentAndReturnResponse(url) |
| 63 return deps |
| 64 |
| 65 |
| 66 def _ParseVersion(version_str): |
| 67 """Parses the version string to get the different identifiers. |
| 68 |
| 69 Args: |
| 70 version_str: Chrome release version number. |
| 71 """ |
| 72 match = re.search(r'((\d+)\.(\d+)\.(\d+)\.(\d+))', version_str) |
| 73 if match: |
| 74 version = {'version': match.group(1), |
| 75 'major': int(match.group(2)), |
| 76 'minor': int(match.group(3)), |
| 77 'build': int(match.group(4)), |
| 78 'patch': int(match.group(5))} |
| 79 return version |
| 80 raise RuntimeError('Invalid version number was specified: %r' % version_str) |
| 81 |
| 82 |
| 83 def _GetRevisionInfo(version_str, deps): |
| 84 """Gets the revision info by parsing the contents of the DEPS file. |
| 85 |
| 86 Args: |
| 87 version_str: A string representing the Chrome version number. |
| 88 deps: A string that contains the contents of corresponding DEPS file. |
| 89 |
| 90 Returns: |
| 91 A string that contains pertinent information about the Chrome version. |
| 92 """ |
| 93 version = _ParseVersion(version_str) |
| 94 # Match 'src:' followed by a line break in deps. This is where the revision |
| 95 # number is located. |
| 96 match = re.search('\'src\':[\n\r ]+\'(.*?)\'', deps) |
| 97 if match: |
| 98 # If matched, look for the revision number which follows the @ symbol. |
| 99 match = re.search(r'@(\d+)', match.group(1)) |
| 100 if match: |
| 101 version['revision'] = int(match.group(1)) |
| 102 # Parse the matching string to see if it contains a branch number. If |
| 103 # there is a branch number, it will follow the word 'branches'. |
| 104 match = re.search("""['"]src['"].*?:.*?['"]/branches/(.*?)/.*?,""", |
| 105 deps, re.DOTALL | re.IGNORECASE) |
| 106 if match: |
| 107 version['branch'] = match.group(1) |
| 108 else: |
| 109 version['branch'] = 'trunk' |
| 110 return version |
| 111 |
| 112 |
| 113 def _GetRevision(deps, rev_type): |
| 114 """Gets selenium/pyftpdlib revision number by parsing contents of DEPS file. |
| 115 |
| 116 Args: |
| 117 deps: A string that contains the contents of corresponding DEPS file. |
| 118 rev_type: Type of revision number to look up: 'selenium' or 'pyftpdlib'. |
| 119 |
| 120 Returns: |
| 121 An integer representing the revision number that was requested. |
| 122 """ |
| 123 assert rev_type == 'selenium' or rev_type == 'pyftpdlib' |
| 124 if rev_type == 'selenium': |
| 125 match = re.search(r'http://selenium\.googlecode\.com/svn/trunk/py@(\d+)', |
| 126 deps, re.DOTALL | re.IGNORECASE | re.MULTILINE) |
| 127 elif rev_type == 'pyftpdlib': |
| 128 match = re.search(r'http://pyftpdlib\.googlecode\.com/svn/trunk@(\d+)', |
| 129 deps, re.DOTALL | re.IGNORECASE | re.MULTILINE) |
| 130 if match: |
| 131 return int(match.group(1)) |
| 132 raise RuntimeError('Could not find the revision number in DEPS.') |
| 133 |
| 134 |
| 135 def _SvnCheckout(path, revision=None, dest=None): |
| 136 """Does a SVN checkout on specified source files. |
| 137 |
| 138 Args: |
| 139 path: URL that is to be checked out. |
| 140 revision: Revision number. |
| 141 dest: Destination where the data will be downloaded. |
| 142 """ |
| 143 cmd = 'svn checkout' |
| 144 if revision: |
| 145 cmd += ' --revision %d' % revision |
| 146 cmd += ' %s' % path |
| 147 if dest: |
| 148 cmd += ' %s' % dest |
| 149 logging.info(cmd) |
| 150 subprocess.check_call([cmd], shell=True) |
| 151 |
| 152 |
| 153 def _IsVersionValid(version): |
| 154 """Checks if the version number has the correct format. |
| 155 |
| 156 Args: |
| 157 version: Version number to check. |
| 158 |
| 159 Returns: |
| 160 True if 'n.n.n.n' pattern is found in version number, otherwise False. |
| 161 """ |
| 162 return isinstance(version, basestring) and re.match('\d+\.\d+\.\d+\.\d+', |
| 163 version) |
| 164 |
| 165 |
| 166 def CheckOut(version, dest): |
| 167 """Checks out all necessary source files. |
| 168 |
| 169 Args: |
| 170 version: Chrome release version number (e.g., 21.0.1136.0). |
| 171 dest: Destination where the checked out files will go. |
| 172 """ |
| 173 if not _IsVersionValid(version): |
| 174 raise RuntimeError('Invalid version number was specified: %r.' % version) |
| 175 if not os.path.isdir(dest): |
| 176 os.mkdir(dest) |
| 177 deps = _GetDeps(version) |
| 178 rev_info = _GetRevisionInfo(version, deps) |
| 179 logging.info(rev_info) |
| 180 # If it's a patch, checkout the branch. |
| 181 if rev_info['patch']: |
| 182 svn_url_base = _BASE_SVN_URL + '/branches/%s' % rev_info['branch'] |
| 183 # If not, check out the trunk. |
| 184 else: |
| 185 svn_url_base = _BASE_SVN_URL + '/trunk' |
| 186 _SvnCheckout('%s/src/chrome/test/functional' % svn_url_base, |
| 187 rev_info['revision'], os.path.join(dest, 'src', |
| 188 'chrome', 'test', |
| 189 'functional')) |
| 190 _SvnCheckout('%s/src/chrome/test/pyautolib' % svn_url_base, |
| 191 rev_info['revision'], os.path.join(dest, 'src', 'chrome', |
| 192 'test', 'pyautolib')) |
| 193 _SvnCheckout('%s/src/third_party/simplejson' % svn_url_base, |
| 194 rev_info['revision'], os.path.join(dest, 'src', 'third_party', |
| 195 'simplejson')) |
| 196 _SvnCheckout('%s/src/third_party/tlslite' % svn_url_base, |
| 197 rev_info['revision'], os.path.join(dest, 'src', 'third_party', |
| 198 'tlslite')) |
| 199 _SvnCheckout('%s/src/net/tools/testserver' % svn_url_base, |
| 200 rev_info['revision'], os.path.join(dest, 'src', 'net', 'tools', |
| 201 'testserver')) |
| 202 _SvnCheckout(_SELENIUM_URL, _GetRevision(deps, 'selenium'), |
| 203 os.path.join(dest, 'src', 'third_party', 'webdriver', 'pylib', |
| 204 'selenium')) |
| 205 _SvnCheckout(_PYFTPDLIB_URL, _GetRevision(deps, 'pyftpdlib'), |
| 206 os.path.join(dest, 'src', 'third_party', 'pyftpdlib')) |
| OLD | NEW |