merge_from_chromium.py revision 72724a6d44b1f9ebc7e122045a72f3502185844d
182c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)#!/usr/bin/python
29df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)#
39df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)# Copyright (C) 2012 The Android Open Source Project
49df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)#
59df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)# Licensed under the Apache License, Version 2.0 (the "License");
69df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)# you may not use this file except in compliance with the License.
79df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)# You may obtain a copy of the License at
89df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)#
99df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)#      http://www.apache.org/licenses/LICENSE-2.0
109df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)#
119df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)# Unless required by applicable law or agreed to in writing, software
129df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)# distributed under the License is distributed on an "AS IS" BASIS,
139df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
149df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)# See the License for the specific language governing permissions and
159df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)# limitations under the License.
169df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)
1782c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)"""Merge Chromium into the Android tree."""
189df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)
192efbabe43f012ff9c06c78fc19fae49421a4d356Torne (Richard Coles)import contextlib
205d65b76f6747f51bb623d00205aca85581ad4d91Torne (Richard Coles)import logging
216a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)import optparse
226a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)import os
236a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)import re
246a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)import sys
252efbabe43f012ff9c06c78fc19fae49421a4d356Torne (Richard Coles)import urllib2
261c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)
271c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)import merge_common
286a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)
296a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)
309df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)# We need to import this *after* merging from upstream to get the latest
319df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)# version. Set it to none here to catch uses before it's imported.
329df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)webview_licenses = None
339df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)
349df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)
351c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)AUTOGEN_MESSAGE = 'This commit was generated by merge_from_chromium.py.'
369df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)
379df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)
389df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)def _ReadGitFile(git_url, git_branch, sha1, path):
399df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)  """Reads a file from a remote git project at a specific revision.
4082c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)
419df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)  Args:
429df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)    git_url: The URL of the git server.
4382c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)    git_branch: The branch to fetch.
449df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)    sha1: The SHA1 at which to read.
459df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)    path: The relative path of the file to read.
469df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)  Returns:
479df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)    The contents of the specified file.
489df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)  """
499df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)  # We fetch the branch to a temporary head so that we don't download the same
509df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)  # commits multiple times.
511c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)  merge_common.GetCommandStdout(['git', 'fetch', '-f', git_url,
521c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)                                 git_branch + ':cached_upstream'])
5382c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)  return merge_common.GetCommandStdout(['git', 'show', '%s:%s' % (sha1, path)])
549df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)
559df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)
56bc79ddac4a295ce4616fbbc574f9c53702f1e02cTorne (Richard Coles)def _ParseDEPS(git_url, git_branch, sha1):
579df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)  """Parses the .DEPS.git file from Chromium and returns its contents.
5882c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)
596a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)  Args:
609df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)    git_url: The URL of the git server.
619df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)    git_branch: The branch to read.
629df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)    sha1: The SHA1 at which to read.
636a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)  Returns:
646a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)    A dictionary of the contents of .DEPS.git at the specified revision
656a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)  """
666a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)
676a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)  class FromImpl(object):
686a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)    """Used to implement the From syntax."""
696a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)
706a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)    def __init__(self, module_name):
716a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)      self.module_name = module_name
726a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)
736a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)    def __str__(self):
746a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)      return 'From("%s")' % self.module_name
756a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)
766a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)  class _VarImpl(object):
776a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)    def __init__(self, custom_vars, local_scope):
786a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)      self._custom_vars = custom_vars
796a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)      self._local_scope = local_scope
806a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)
816a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)    def Lookup(self, var_name):
826a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)      """Implements the Var syntax."""
836a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)      if var_name in self._custom_vars:
846a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)        return self._custom_vars[var_name]
856a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)      elif var_name in self._local_scope.get('vars', {}):
866a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)        return self._local_scope['vars'][var_name]
876a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)      raise Exception('Var is not defined: %s' % var_name)
886a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)
896a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)  tmp_locals = {}
906a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)  var = _VarImpl({}, tmp_locals)
916a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)  tmp_globals = {'From': FromImpl, 'Var': var.Lookup, 'deps_os': {}}
92bc79ddac4a295ce4616fbbc574f9c53702f1e02cTorne (Richard Coles)  deps_content = _ReadGitFile(git_url, git_branch, sha1, '.DEPS.git')
936a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)  exec(deps_content) in tmp_globals, tmp_locals
946a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)  return tmp_locals
956a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)
966a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)
976a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)def _GetThirdPartyProjectMergeInfo(third_party_projects, deps_vars):
9882c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)  """Gets the git URL and SHA1 for each project based on .DEPS.git.
9982c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)
1006a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)  Args:
1019df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)    third_party_projects: The list of projects to consider.
1029df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)    deps_vars: The dictionary of dependencies from .DEPS.git.
1036a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)  Returns:
1046a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)    A dictionary from project to git URL and SHA1 - 'path: (url, sha1)'
10582c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)  Raises:
106862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)    TemporaryMergeError: if a project to be merged is not found in .DEPS.git.
1076a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)  """
1086a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)  deps_fallback_order = [
1096a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)      deps_vars['deps'],
1106a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)      deps_vars['deps_os']['unix'],
1116a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)      deps_vars['deps_os']['android'],
1126a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)  ]
1136a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)  result = {}
1146a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)  for path in third_party_projects:
1156a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)    for deps in deps_fallback_order:
1166a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)      url_plus_sha1 = deps.get(os.path.join('src', path))
1176a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)      if url_plus_sha1:
1186a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)        break
1196a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)    else:
120862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)      raise merge_common.TemporaryMergeError(
12182c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)          'Could not find .DEPS.git entry for project %s. This probably '
12282c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)          'means that the project list in merge_from_chromium.py needs to be '
12382c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)          'updated.' % path)
1246a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)    match = re.match('(.*?)@(.*)', url_plus_sha1)
1256a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)    url = match.group(1)
1266a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)    sha1 = match.group(2)
1275d65b76f6747f51bb623d00205aca85581ad4d91Torne (Richard Coles)    logging.debug('  Got URL %s and SHA1 %s for project %s', url, sha1, path)
1286a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)    result[path] = {'url': url, 'sha1': sha1}
1296a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)  return result
1306a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)
1316a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)
13214ac2c8d49fa1f5f12e6a80af93f1c50312d80a8Torne (Richard Coles)def _MergeProjects(git_url, git_branch, svn_revision, root_sha1, unattended):
13382c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)  """Merges each required Chromium project into the Android repository.
13482c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)
13582c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)  .DEPS.git is consulted to determine which revision each project must be merged
13682c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)  at. Only a whitelist of required projects are merged.
13782c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)
1386a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)  Args:
13982c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)    git_url: The URL of the Chromium repository to merge from.
14082c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)    git_branch: The branch in the Chromium repository to merge from.
14182c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)    svn_revision: The SVN revision in the Chromium repository to merge from.
14282c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)    root_sha1: The git hash corresponding to svn_revision.
14314ac2c8d49fa1f5f12e6a80af93f1c50312d80a8Torne (Richard Coles)    unattended: Run in unattended mode.
14482c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)  Raises:
145862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)    TemporaryMergeError: If incompatibly licensed code is left after pruning.
1466a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)  """
1476a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)  # The logic for this step lives here, in the Android tree, as it makes no
1486a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)  # sense for a Chromium tree to know about this merge.
1496a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)
15014ac2c8d49fa1f5f12e6a80af93f1c50312d80a8Torne (Richard Coles)  if unattended:
15114ac2c8d49fa1f5f12e6a80af93f1c50312d80a8Torne (Richard Coles)    branch_create_flag = '-B'
15214ac2c8d49fa1f5f12e6a80af93f1c50312d80a8Torne (Richard Coles)  else:
15314ac2c8d49fa1f5f12e6a80af93f1c50312d80a8Torne (Richard Coles)    branch_create_flag = '-b'
154862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)  branch_name = 'merge-from-chromium-%s' % svn_revision
15514ac2c8d49fa1f5f12e6a80af93f1c50312d80a8Torne (Richard Coles)
1565d65b76f6747f51bb623d00205aca85581ad4d91Torne (Richard Coles)  logging.debug('Parsing DEPS ...')
157bc79ddac4a295ce4616fbbc574f9c53702f1e02cTorne (Richard Coles)  deps_vars = _ParseDEPS(git_url, git_branch, root_sha1)
1586a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)
1591c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)  merge_info = _GetThirdPartyProjectMergeInfo(merge_common.THIRD_PARTY_PROJECTS,
1601c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)                                              deps_vars)
1616a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)
1626a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)  for path in merge_info:
1636a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)    url = merge_info[path]['url']
1646a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)    sha1 = merge_info[path]['sha1']
1651c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)    dest_dir = os.path.join(merge_common.REPOSITORY_ROOT, path)
1661c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)    merge_common.GetCommandStdout(['git', 'checkout',
167862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)                                   branch_create_flag, branch_name,
1681c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)                                   '-t', 'goog/master-chromium'], cwd=dest_dir)
1695d65b76f6747f51bb623d00205aca85581ad4d91Torne (Richard Coles)    logging.debug('Fetching project %s at %s ...', path, sha1)
1701c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)    merge_common.GetCommandStdout(['git', 'fetch', url], cwd=dest_dir)
1711c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)    if merge_common.GetCommandStdout(['git', 'rev-list', '-1', 'HEAD..' + sha1],
1721c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)                                     cwd=dest_dir):
1735d65b76f6747f51bb623d00205aca85581ad4d91Torne (Richard Coles)      logging.debug('Merging project %s at %s ...', path, sha1)
1746a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)      # Merge conflicts make git merge return 1, so ignore errors
1751c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)      merge_common.GetCommandStdout(['git', 'merge', '--no-commit', sha1],
1761c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)                                    cwd=dest_dir, ignore_errors=True)
1771c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)      merge_common.CheckNoConflictsAndCommitMerge(
1789df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)          'Merge %s from %s at %s\n\n%s' % (path, url, sha1, AUTOGEN_MESSAGE),
17914ac2c8d49fa1f5f12e6a80af93f1c50312d80a8Torne (Richard Coles)          cwd=dest_dir, unattended=unattended)
1806a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)    else:
1815d65b76f6747f51bb623d00205aca85581ad4d91Torne (Richard Coles)      logging.debug('No new commits to merge in project %s', path)
1826a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)
1836a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)  # Handle root repository separately.
18414ac2c8d49fa1f5f12e6a80af93f1c50312d80a8Torne (Richard Coles)  merge_common.GetCommandStdout(['git', 'checkout',
185862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)                                 branch_create_flag, branch_name,
1861c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)                                 '-t', 'goog/master-chromium'])
1875d65b76f6747f51bb623d00205aca85581ad4d91Torne (Richard Coles)  logging.debug('Fetching Chromium at %s ...', root_sha1)
1881c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)  merge_common.GetCommandStdout(['git', 'fetch', git_url, git_branch])
1895d65b76f6747f51bb623d00205aca85581ad4d91Torne (Richard Coles)  logging.debug('Merging Chromium at %s ...', root_sha1)
1906a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)  # Merge conflicts make git merge return 1, so ignore errors
1911c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)  merge_common.GetCommandStdout(['git', 'merge', '--no-commit', root_sha1],
1921c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)                                ignore_errors=True)
1931c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)  merge_common.CheckNoConflictsAndCommitMerge(
194bc79ddac4a295ce4616fbbc574f9c53702f1e02cTorne (Richard Coles)      'Merge Chromium from %s branch %s at r%s (%s)\n\n%s'
19514ac2c8d49fa1f5f12e6a80af93f1c50312d80a8Torne (Richard Coles)      % (git_url, git_branch, svn_revision, root_sha1, AUTOGEN_MESSAGE),
19614ac2c8d49fa1f5f12e6a80af93f1c50312d80a8Torne (Richard Coles)      unattended=unattended)
1976a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)
1985d65b76f6747f51bb623d00205aca85581ad4d91Torne (Richard Coles)  logging.debug('Getting directories to exclude ...')
1999df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)
2009df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)  # We import this now that we have merged the latest version.
2019df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)  # It imports to a global in order that it can be used to generate NOTICE
202c7fa5294b03fbc8ccab655d87faaa6d6d704018eTorne (Richard Coles)  # later. We also disable writing bytecode to keep the source tree clean.
2031c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)  sys.path.append(os.path.join(merge_common.REPOSITORY_ROOT, 'android_webview',
2041c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)                               'tools'))
205c7fa5294b03fbc8ccab655d87faaa6d6d704018eTorne (Richard Coles)  sys.dont_write_bytecode = True
2069df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)  global webview_licenses
2079df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)  import webview_licenses
208cadf645507c329e0f5d7fbb67d9311cfa26ac638Torne (Richard Coles)  import known_issues
2099df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)
210cadf645507c329e0f5d7fbb67d9311cfa26ac638Torne (Richard Coles)  for path, exclude_list in known_issues.KNOWN_INCOMPATIBLE.iteritems():
2115d65b76f6747f51bb623d00205aca85581ad4d91Torne (Richard Coles)    logging.debug('  %s', '\n  '.join(os.path.join(path, x) for x in
2125d65b76f6747f51bb623d00205aca85581ad4d91Torne (Richard Coles)                                      exclude_list))
2131c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)    dest_dir = os.path.join(merge_common.REPOSITORY_ROOT, path)
2141c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)    merge_common.GetCommandStdout(['git', 'rm', '-rf', '--ignore-unmatch'] +
2151c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)                                  exclude_list, cwd=dest_dir)
2163c67328c9fd2fd48405af3950e59893bfdf1287bTorne (Richard Coles)    if _ModifiedFilesInIndex(dest_dir):
2171c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)      merge_common.GetCommandStdout(['git', 'commit', '-m',
2181c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)                                     'Exclude incompatible directories'],
2191c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)                                    cwd=dest_dir)
2203c67328c9fd2fd48405af3950e59893bfdf1287bTorne (Richard Coles)
2219df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)  directories_left_over = webview_licenses.GetIncompatibleDirectories()
2229df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)  if directories_left_over:
223862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)    raise merge_common.TemporaryMergeError(
224862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)        'Incompatibly licensed directories remain: ' +
225862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)        '\n'.join(directories_left_over))
2266a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)
2276a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)
228862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)def _GenerateMakefiles(svn_revision, unattended):
22982c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)  """Run gyp to generate the Android build system makefiles.
2306a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)
23182c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)  Args:
23282c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)    svn_revision: The SVN revision to mention in generated commit messages.
233862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)    unattended: Run in unattended mode.
23482c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)  """
2359df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)  # TODO(torne): The .tmp files are generated by
2366a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)  # third_party/WebKit/Source/WebCore/WebCore.gyp/WebCore.gyp into the source
2376a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)  # tree. We should avoid this, or at least use a more specific name to avoid
2386a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)  # accidentally removing or adding other files.
2391c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)  for path in merge_common.ALL_PROJECTS:
2401c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)    dest_dir = os.path.join(merge_common.REPOSITORY_ROOT, path)
2411c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)    merge_common.GetCommandStdout(['git', 'rm', '--ignore-unmatch',
2425568eda06be15d573395eaba779d62c09f6f96f1Torne (Richard Coles)                                   'GypAndroid.*.mk', '*.target.*.mk',
2435568eda06be15d573395eaba779d62c09f6f96f1Torne (Richard Coles)                                   '*.host.*.mk', '*.tmp'], cwd=dest_dir)
2441c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)
245862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)  try:
246862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)    merge_common.GetCommandStdout(['android_webview/tools/gyp_webview'])
2472735b74c930c17d39cb6510c0c2c0a43df1d181aTorne (Richard Coles)  except merge_common.MergeError as e:
248862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)    if not unattended:
249862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)      raise
250862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)    else:
251862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)      for path in merge_common.ALL_PROJECTS:
252862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)        merge_common.GetCommandStdout(
253862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)            ['git', 'reset', '--hard'],
254862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)            cwd=os.path.join(merge_common.REPOSITORY_ROOT, path))
2552735b74c930c17d39cb6510c0c2c0a43df1d181aTorne (Richard Coles)      raise merge_common.TemporaryMergeError('Makefile generation failed: ' +
25672724a6d44b1f9ebc7e122045a72f3502185844dTorne (Richard Coles)                                             str(e))
2571c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)
2581c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)  for path in merge_common.ALL_PROJECTS:
2591c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)    dest_dir = os.path.join(merge_common.REPOSITORY_ROOT, path)
2609df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)    # git add doesn't have an --ignore-unmatch so we have to do this instead:
2615568eda06be15d573395eaba779d62c09f6f96f1Torne (Richard Coles)    merge_common.GetCommandStdout(['git', 'add', '-f', 'GypAndroid.*.mk'],
2621c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)                                  ignore_errors=True, cwd=dest_dir)
2635568eda06be15d573395eaba779d62c09f6f96f1Torne (Richard Coles)    merge_common.GetCommandStdout(['git', 'add', '-f', '*.target.*.mk'],
2641c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)                                  ignore_errors=True, cwd=dest_dir)
2655568eda06be15d573395eaba779d62c09f6f96f1Torne (Richard Coles)    merge_common.GetCommandStdout(['git', 'add', '-f', '*.host.*.mk'],
2661c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)                                  ignore_errors=True, cwd=dest_dir)
2671c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)    merge_common.GetCommandStdout(['git', 'add', '-f', '*.tmp'],
2681c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)                                  ignore_errors=True, cwd=dest_dir)
2699df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)    # Only try to commit the makefiles if something has actually changed.
2709df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)    if _ModifiedFilesInIndex(dest_dir):
27182c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)      merge_common.GetCommandStdout(
27282c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)          ['git', 'commit', '-m',
27382c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)           'Update makefiles after merge of Chromium at r%s\n\n%s' %
27482c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)           (svn_revision, AUTOGEN_MESSAGE)], cwd=dest_dir)
2756a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)
2769df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)
2771c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)def _ModifiedFilesInIndex(cwd=merge_common.REPOSITORY_ROOT):
27882c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)  """Returns true if git's index contains any changes."""
2791c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)  status = merge_common.GetCommandStdout(['git', 'status', '--porcelain'],
2801c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)                                         cwd=cwd)
28182c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)  return re.search(r'^[MADRC]', status, flags=re.MULTILINE) is not None
2826a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)
2836a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)
2846a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)def _GenerateNoticeFile(svn_revision):
28582c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)  """Generates and commits a NOTICE file containing code licenses.
28682c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)
28782c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)  This covers all third-party code (from Android's perspective) that lives in
28882c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)  the Chromium tree.
28982c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)
2906a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)  Args:
29182c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)    svn_revision: The SVN revision for the main Chromium repository.
2926a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)  """
2935d65b76f6747f51bb623d00205aca85581ad4d91Torne (Richard Coles)  logging.debug('Regenerating NOTICE file ...')
2946a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)
2959df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)  contents = webview_licenses.GenerateNoticeFile()
2966a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)
2971c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)  with open(os.path.join(merge_common.REPOSITORY_ROOT, 'NOTICE'), 'w') as f:
2986a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)    f.write(contents)
2991c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)  merge_common.GetCommandStdout(['git', 'add', 'NOTICE'])
3006a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)  # Only try to commit the NOTICE update if the file has actually changed.
3016a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)  if _ModifiedFilesInIndex():
3021c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)    merge_common.GetCommandStdout([
3036a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)        'git', 'commit', '-m',
3046a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)        'Update NOTICE file after merge of Chromium at r%s\n\n%s'
3056a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)        % (svn_revision, AUTOGEN_MESSAGE)])
3066a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)
3076a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)
308e9d946910fc23e839e0ba89df0a59cdcd1aac8ddTorne (Richard Coles)def _GenerateLastChange(svn_revision):
30982c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)  """Write a build/util/LASTCHANGE file containing the current revision.
31082c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)
31182c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)  The revision number is compiled into the binary at build time from this file.
31282c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)
313e9d946910fc23e839e0ba89df0a59cdcd1aac8ddTorne (Richard Coles)  Args:
31482c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)    svn_revision: The SVN revision for the main Chromium repository.
315e9d946910fc23e839e0ba89df0a59cdcd1aac8ddTorne (Richard Coles)  """
3165d65b76f6747f51bb623d00205aca85581ad4d91Torne (Richard Coles)  logging.debug('Updating LASTCHANGE ...')
3171c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)  with open(os.path.join(merge_common.REPOSITORY_ROOT, 'build/util/LASTCHANGE'),
3181c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)            'w') as f:
31982c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)    f.write('LASTCHANGE=%s\n' % svn_revision)
3201c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)  merge_common.GetCommandStdout(['git', 'add', '-f', 'build/util/LASTCHANGE'])
321e9d946910fc23e839e0ba89df0a59cdcd1aac8ddTorne (Richard Coles)  if _ModifiedFilesInIndex():
3221c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)    merge_common.GetCommandStdout([
323e9d946910fc23e839e0ba89df0a59cdcd1aac8ddTorne (Richard Coles)        'git', 'commit', '-m',
324e9d946910fc23e839e0ba89df0a59cdcd1aac8ddTorne (Richard Coles)        'Update LASTCHANGE file after merge of Chromium at r%s\n\n%s'
325e9d946910fc23e839e0ba89df0a59cdcd1aac8ddTorne (Richard Coles)        % (svn_revision, AUTOGEN_MESSAGE)])
326e9d946910fc23e839e0ba89df0a59cdcd1aac8ddTorne (Richard Coles)
327e9d946910fc23e839e0ba89df0a59cdcd1aac8ddTorne (Richard Coles)
328862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)def GetLKGR():
329862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)  """Fetch the last known good release from Chromium's dashboard.
330862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)
331862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)  Returns:
332862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)    The last known good SVN revision.
333862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)  """
334862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)  with contextlib.closing(
335862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)      urllib2.urlopen('https://chromium-status.appspot.com/lkgr')) as lkgr:
336862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)    return int(lkgr.read())
337862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)
338862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)
339bc79ddac4a295ce4616fbbc574f9c53702f1e02cTorne (Richard Coles)def _GetSVNRevisionAndSHA1(git_url, git_branch, svn_revision):
3405d65b76f6747f51bb623d00205aca85581ad4d91Torne (Richard Coles)  logging.debug('Getting SVN revision and SHA1 ...')
3411c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)  merge_common.GetCommandStdout(['git', 'fetch', '-f', git_url,
3421c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)                                 git_branch + ':cached_upstream'])
3439536a5e5660bc0745d1f5f2f6a6468fa53ffa639Bo Liu  if svn_revision == 'HEAD':
3449536a5e5660bc0745d1f5f2f6a6468fa53ffa639Bo Liu    # Just use the latest commit.
3459536a5e5660bc0745d1f5f2f6a6468fa53ffa639Bo Liu    commit = merge_common.GetCommandStdout([
3469536a5e5660bc0745d1f5f2f6a6468fa53ffa639Bo Liu        'git', 'log', '-n1', '--grep=git-svn-id:', '--format=%H%n%b',
3479536a5e5660bc0745d1f5f2f6a6468fa53ffa639Bo Liu        'cached_upstream'])
3489536a5e5660bc0745d1f5f2f6a6468fa53ffa639Bo Liu    sha1 = commit.split()[0]
3499536a5e5660bc0745d1f5f2f6a6468fa53ffa639Bo Liu    svn_revision = re.search(r'^git-svn-id: .*@([0-9]+)', commit,
3509536a5e5660bc0745d1f5f2f6a6468fa53ffa639Bo Liu                             flags=re.MULTILINE).group(1)
3519536a5e5660bc0745d1f5f2f6a6468fa53ffa639Bo Liu    return (svn_revision, sha1)
3529536a5e5660bc0745d1f5f2f6a6468fa53ffa639Bo Liu
3532efbabe43f012ff9c06c78fc19fae49421a4d356Torne (Richard Coles)  if svn_revision is None:
3542efbabe43f012ff9c06c78fc19fae49421a4d356Torne (Richard Coles)    # Fetch LKGR from upstream.
355862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)    svn_revision = GetLKGR()
3562efbabe43f012ff9c06c78fc19fae49421a4d356Torne (Richard Coles)  output = merge_common.GetCommandStdout([
3572efbabe43f012ff9c06c78fc19fae49421a4d356Torne (Richard Coles)      'git', 'log', '--grep=git-svn-id: .*@%s' % svn_revision,
3582efbabe43f012ff9c06c78fc19fae49421a4d356Torne (Richard Coles)      '--format=%H', 'cached_upstream'])
3592efbabe43f012ff9c06c78fc19fae49421a4d356Torne (Richard Coles)  if not output:
360862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)    raise merge_common.TemporaryMergeError('Revision %s not found in git repo.'
361862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)                                           % svn_revision)
3622efbabe43f012ff9c06c78fc19fae49421a4d356Torne (Richard Coles)  # The log grep will sometimes match reverts/reapplies of commits. We take the
3632efbabe43f012ff9c06c78fc19fae49421a4d356Torne (Richard Coles)  # oldest (last) match because the first time it appears in history is
3642efbabe43f012ff9c06c78fc19fae49421a4d356Torne (Richard Coles)  # overwhelmingly likely to be the correct commit.
3652efbabe43f012ff9c06c78fc19fae49421a4d356Torne (Richard Coles)  sha1 = output.split()[-1]
3666a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)  return (svn_revision, sha1)
3676a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)
3686a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)
3692efbabe43f012ff9c06c78fc19fae49421a4d356Torne (Richard Coles)def Snapshot(svn_revision, unattended):
37082c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)  """Takes a snapshot of the Chromium tree and merges it into Android.
37182c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)
37282c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)  Android makefiles and a top-level NOTICE file are generated and committed
37382c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)  after the merge.
37482c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)
3756a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)  Args:
37682c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)    svn_revision: The SVN revision in the Chromium repository to merge from.
37714ac2c8d49fa1f5f12e6a80af93f1c50312d80a8Torne (Richard Coles)    unattended: Run in unattended mode.
3786a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)
37982c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)  Returns:
38082c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)    True if new commits were merged; False if no new commits were present.
38182c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)  """
382b4b2d8eafdf00e50598aa9305317bd691bd471adTorne (Richard Coles)  git_url = 'http://chromium.googlesource.com/chromium/src.git'
383b4b2d8eafdf00e50598aa9305317bd691bd471adTorne (Richard Coles)  git_branch = 'git-svn'
384bc79ddac4a295ce4616fbbc574f9c53702f1e02cTorne (Richard Coles)  (svn_revision, root_sha1) = _GetSVNRevisionAndSHA1(git_url, git_branch,
385bc79ddac4a295ce4616fbbc574f9c53702f1e02cTorne (Richard Coles)                                                     svn_revision)
3861c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)  if not merge_common.GetCommandStdout(['git', 'rev-list', '-1',
3871c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)                                        'HEAD..' + root_sha1]):
3885d65b76f6747f51bb623d00205aca85581ad4d91Torne (Richard Coles)    logging.info('No new commits to merge from %s branch %s at r%s (%s)',
3895d65b76f6747f51bb623d00205aca85581ad4d91Torne (Richard Coles)                 git_url, git_branch, svn_revision, root_sha1)
39082c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)    return False
3916a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)
3925d65b76f6747f51bb623d00205aca85581ad4d91Torne (Richard Coles)  logging.info('Snapshotting Chromium from %s branch %s at r%s (%s)',
3935d65b76f6747f51bb623d00205aca85581ad4d91Torne (Richard Coles)               git_url, git_branch, svn_revision, root_sha1)
3946a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)
3956a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)  # 1. Merge, accounting for excluded directories
39614ac2c8d49fa1f5f12e6a80af93f1c50312d80a8Torne (Richard Coles)  _MergeProjects(git_url, git_branch, svn_revision, root_sha1, unattended)
3976a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)
3989df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)  # 2. Generate Android NOTICE file
3996a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)  _GenerateNoticeFile(svn_revision)
4006a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)
401e9d946910fc23e839e0ba89df0a59cdcd1aac8ddTorne (Richard Coles)  # 3. Generate LASTCHANGE file
402e9d946910fc23e839e0ba89df0a59cdcd1aac8ddTorne (Richard Coles)  _GenerateLastChange(svn_revision)
403e9d946910fc23e839e0ba89df0a59cdcd1aac8ddTorne (Richard Coles)
404e9d946910fc23e839e0ba89df0a59cdcd1aac8ddTorne (Richard Coles)  # 4. Generate Android makefiles
405862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)  _GenerateMakefiles(svn_revision, unattended)
4069df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)
4071896d5d734a45c412f47fe58816665d374617d3bTorne (Richard Coles)  return True
4081896d5d734a45c412f47fe58816665d374617d3bTorne (Richard Coles)
4096a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)
410862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)def Push(svn_revision):
411bda7cff5dd92725ba000fe95d9434f81a7af486eTorne (Richard Coles)  """Push the finished snapshot to the Android repository."""
412862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)  merge_common.PushToServer('merge-from-chromium-%s' % svn_revision,
413862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)                            'master-chromium', 'master-chromium-merge')
414bda7cff5dd92725ba000fe95d9434f81a7af486eTorne (Richard Coles)
415bda7cff5dd92725ba000fe95d9434f81a7af486eTorne (Richard Coles)
4166a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)def main():
4176a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)  parser = optparse.OptionParser(usage='%prog [options]')
4186a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)  parser.epilog = ('Takes a snapshot of the Chromium tree at the specified '
4196a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)                   'Chromium SVN revision and merges it into this repository. '
4206a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)                   'Paths marked as excluded for license reasons are removed '
4216a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)                   'as part of the merge. Also generates Android makefiles and '
4226a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)                   'generates a top-level NOTICE file suitable for use in the '
4236a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)                   'Android build.')
4246a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)  parser.add_option(
4256a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)      '', '--svn_revision',
4266a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)      default=None,
4276a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)      help=('Merge to the specified chromium SVN revision, rather than using '
4289536a5e5660bc0745d1f5f2f6a6468fa53ffa639Bo Liu            'the current LKGR. Can also pass HEAD to merge from tip of tree.'))
4291896d5d734a45c412f47fe58816665d374617d3bTorne (Richard Coles)  parser.add_option(
43014ac2c8d49fa1f5f12e6a80af93f1c50312d80a8Torne (Richard Coles)      '', '--push',
43114ac2c8d49fa1f5f12e6a80af93f1c50312d80a8Torne (Richard Coles)      default=False, action='store_true',
43214ac2c8d49fa1f5f12e6a80af93f1c50312d80a8Torne (Richard Coles)      help=('Push the result of a previous merge to the server.'))
43314ac2c8d49fa1f5f12e6a80af93f1c50312d80a8Torne (Richard Coles)  parser.add_option(
43414ac2c8d49fa1f5f12e6a80af93f1c50312d80a8Torne (Richard Coles)      '', '--unattended',
4351896d5d734a45c412f47fe58816665d374617d3bTorne (Richard Coles)      default=False, action='store_true',
43614ac2c8d49fa1f5f12e6a80af93f1c50312d80a8Torne (Richard Coles)      help=('Run in unattended mode.'))
4376a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)  (options, args) = parser.parse_args()
4386a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)  if args:
4396a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)    parser.print_help()
4406a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)    return 1
4416a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)
4426a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)  if 'ANDROID_BUILD_TOP' not in os.environ:
4436a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)    print >>sys.stderr, 'You need to run the Android envsetup.sh and lunch.'
4446a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)    return 1
4456a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)
4465d65b76f6747f51bb623d00205aca85581ad4d91Torne (Richard Coles)  logging.basicConfig(format='%(message)s', level=logging.DEBUG,
4475d65b76f6747f51bb623d00205aca85581ad4d91Torne (Richard Coles)                      stream=sys.stdout)
4485d65b76f6747f51bb623d00205aca85581ad4d91Torne (Richard Coles)
44914ac2c8d49fa1f5f12e6a80af93f1c50312d80a8Torne (Richard Coles)  if options.push:
450862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)    if options.svn_revision is None:
451862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)      print >>sys.stderr, 'You need to pass the SVN revision to push.'
452862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)      return 1
453862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)    else:
454862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)      Push(options.svn_revision)
45514ac2c8d49fa1f5f12e6a80af93f1c50312d80a8Torne (Richard Coles)  else:
4562efbabe43f012ff9c06c78fc19fae49421a4d356Torne (Richard Coles)    Snapshot(options.svn_revision, options.unattended)
45714ac2c8d49fa1f5f12e6a80af93f1c50312d80a8Torne (Richard Coles)
4586a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)  return 0
4596a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)
4606a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)if __name__ == '__main__':
4616a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)  sys.exit(main())
462