merge_from_chromium.py revision 09ead754abd2cfcffea54040b1c9ac98db8af834
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.'
364465da421aa5ee3d2f6a016b961c301040f0fa23Torne (Richard Coles)SRC_GIT_BRANCH = 'refs/remotes/history/upstream-master'
379df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)
389df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)
394465da421aa5ee3d2f6a016b961c301040f0fa23Torne (Richard Coles)def _ReadGitFile(sha1, path, git_url=None, git_branch=None):
404465da421aa5ee3d2f6a016b961c301040f0fa23Torne (Richard Coles)  """Reads a file from a (possibly remote) git project at a specific revision.
4182c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)
429df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)  Args:
439df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)    sha1: The SHA1 at which to read.
449df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)    path: The relative path of the file to read.
454465da421aa5ee3d2f6a016b961c301040f0fa23Torne (Richard Coles)    git_url: The URL of the git server, if reading a remote project.
464465da421aa5ee3d2f6a016b961c301040f0fa23Torne (Richard Coles)    git_branch: The branch to fetch, if reading a remote project.
479df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)  Returns:
489df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)    The contents of the specified file.
499df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)  """
504465da421aa5ee3d2f6a016b961c301040f0fa23Torne (Richard Coles)  if git_url:
514465da421aa5ee3d2f6a016b961c301040f0fa23Torne (Richard Coles)    # We fetch the branch to a temporary head so that we don't download the same
524465da421aa5ee3d2f6a016b961c301040f0fa23Torne (Richard Coles)    # commits multiple times.
534465da421aa5ee3d2f6a016b961c301040f0fa23Torne (Richard Coles)    merge_common.GetCommandStdout(['git', 'fetch', '-f', git_url,
544465da421aa5ee3d2f6a016b961c301040f0fa23Torne (Richard Coles)                                   git_branch + ':cached_upstream'])
5582c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)  return merge_common.GetCommandStdout(['git', 'show', '%s:%s' % (sha1, path)])
569df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)
579df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)
584465da421aa5ee3d2f6a016b961c301040f0fa23Torne (Richard Coles)def _ParseDEPS(sha1):
599df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)  """Parses the .DEPS.git file from Chromium and returns its contents.
6082c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)
616a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)  Args:
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': {}}
924465da421aa5ee3d2f6a016b961c301040f0fa23Torne (Richard Coles)  deps_content = _ReadGitFile(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)
1324465da421aa5ee3d2f6a016b961c301040f0fa23Torne (Richard Coles)def _MergeProjects(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_branch: The branch in the Chromium repository to merge from.
14082c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)    svn_revision: The SVN revision in the Chromium repository to merge from.
14182c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)    root_sha1: The git hash corresponding to svn_revision.
14214ac2c8d49fa1f5f12e6a80af93f1c50312d80a8Torne (Richard Coles)    unattended: Run in unattended mode.
14382c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)  Raises:
144862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)    TemporaryMergeError: If incompatibly licensed code is left after pruning.
1456a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)  """
1466a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)  # The logic for this step lives here, in the Android tree, as it makes no
1476a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)  # sense for a Chromium tree to know about this merge.
1486a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)
14914ac2c8d49fa1f5f12e6a80af93f1c50312d80a8Torne (Richard Coles)  if unattended:
15014ac2c8d49fa1f5f12e6a80af93f1c50312d80a8Torne (Richard Coles)    branch_create_flag = '-B'
15114ac2c8d49fa1f5f12e6a80af93f1c50312d80a8Torne (Richard Coles)  else:
15214ac2c8d49fa1f5f12e6a80af93f1c50312d80a8Torne (Richard Coles)    branch_create_flag = '-b'
153862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)  branch_name = 'merge-from-chromium-%s' % svn_revision
15414ac2c8d49fa1f5f12e6a80af93f1c50312d80a8Torne (Richard Coles)
1555d65b76f6747f51bb623d00205aca85581ad4d91Torne (Richard Coles)  logging.debug('Parsing DEPS ...')
1564465da421aa5ee3d2f6a016b961c301040f0fa23Torne (Richard Coles)  deps_vars = _ParseDEPS(root_sha1)
1576a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)
1581c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)  merge_info = _GetThirdPartyProjectMergeInfo(merge_common.THIRD_PARTY_PROJECTS,
1591c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)                                              deps_vars)
1606a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)
1616a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)  for path in merge_info:
1624465da421aa5ee3d2f6a016b961c301040f0fa23Torne (Richard Coles)    # webkit needs special handling as we have a local mirror
1634465da421aa5ee3d2f6a016b961c301040f0fa23Torne (Richard Coles)    local_mirrored = path == 'third_party/WebKit'
1646a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)    url = merge_info[path]['url']
1656a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)    sha1 = merge_info[path]['sha1']
1661c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)    dest_dir = os.path.join(merge_common.REPOSITORY_ROOT, path)
1674465da421aa5ee3d2f6a016b961c301040f0fa23Torne (Richard Coles)    if local_mirrored:
1684465da421aa5ee3d2f6a016b961c301040f0fa23Torne (Richard Coles)      remote = 'history'
1694465da421aa5ee3d2f6a016b961c301040f0fa23Torne (Richard Coles)    else:
1704465da421aa5ee3d2f6a016b961c301040f0fa23Torne (Richard Coles)      remote = 'goog'
1711c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)    merge_common.GetCommandStdout(['git', 'checkout',
172862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)                                   branch_create_flag, branch_name,
1734465da421aa5ee3d2f6a016b961c301040f0fa23Torne (Richard Coles)                                   '-t', remote + '/master-chromium'],
1744465da421aa5ee3d2f6a016b961c301040f0fa23Torne (Richard Coles)                                  cwd=dest_dir)
1754465da421aa5ee3d2f6a016b961c301040f0fa23Torne (Richard Coles)    if not local_mirrored:
1764465da421aa5ee3d2f6a016b961c301040f0fa23Torne (Richard Coles)      logging.debug('Fetching project %s at %s ...', path, sha1)
1774465da421aa5ee3d2f6a016b961c301040f0fa23Torne (Richard Coles)      merge_common.GetCommandStdout(['git', 'fetch', url], cwd=dest_dir)
1781c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)    if merge_common.GetCommandStdout(['git', 'rev-list', '-1', 'HEAD..' + sha1],
1791c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)                                     cwd=dest_dir):
1805d65b76f6747f51bb623d00205aca85581ad4d91Torne (Richard Coles)      logging.debug('Merging project %s at %s ...', path, sha1)
1816a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)      # Merge conflicts make git merge return 1, so ignore errors
1821c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)      merge_common.GetCommandStdout(['git', 'merge', '--no-commit', sha1],
1831c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)                                    cwd=dest_dir, ignore_errors=True)
1841c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)      merge_common.CheckNoConflictsAndCommitMerge(
1859df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)          'Merge %s from %s at %s\n\n%s' % (path, url, sha1, AUTOGEN_MESSAGE),
18614ac2c8d49fa1f5f12e6a80af93f1c50312d80a8Torne (Richard Coles)          cwd=dest_dir, unattended=unattended)
1876a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)    else:
1885d65b76f6747f51bb623d00205aca85581ad4d91Torne (Richard Coles)      logging.debug('No new commits to merge in project %s', path)
1896a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)
1906a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)  # Handle root repository separately.
19114ac2c8d49fa1f5f12e6a80af93f1c50312d80a8Torne (Richard Coles)  merge_common.GetCommandStdout(['git', 'checkout',
192862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)                                 branch_create_flag, branch_name,
1934465da421aa5ee3d2f6a016b961c301040f0fa23Torne (Richard Coles)                                 '-t', 'history/master-chromium'])
1945d65b76f6747f51bb623d00205aca85581ad4d91Torne (Richard Coles)  logging.debug('Merging Chromium at %s ...', root_sha1)
1956a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)  # Merge conflicts make git merge return 1, so ignore errors
1961c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)  merge_common.GetCommandStdout(['git', 'merge', '--no-commit', root_sha1],
1971c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)                                ignore_errors=True)
1981c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)  merge_common.CheckNoConflictsAndCommitMerge(
1994465da421aa5ee3d2f6a016b961c301040f0fa23Torne (Richard Coles)      'Merge Chromium  at r%s (%s)\n\n%s'
2004465da421aa5ee3d2f6a016b961c301040f0fa23Torne (Richard Coles)      % (svn_revision, root_sha1, AUTOGEN_MESSAGE), unattended=unattended)
2016a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)
2025d65b76f6747f51bb623d00205aca85581ad4d91Torne (Richard Coles)  logging.debug('Getting directories to exclude ...')
2039df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)
2049df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)  # We import this now that we have merged the latest version.
2059df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)  # It imports to a global in order that it can be used to generate NOTICE
206c7fa5294b03fbc8ccab655d87faaa6d6d704018eTorne (Richard Coles)  # later. We also disable writing bytecode to keep the source tree clean.
2071c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)  sys.path.append(os.path.join(merge_common.REPOSITORY_ROOT, 'android_webview',
2081c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)                               'tools'))
209c7fa5294b03fbc8ccab655d87faaa6d6d704018eTorne (Richard Coles)  sys.dont_write_bytecode = True
2109df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)  global webview_licenses
2119df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)  import webview_licenses
212cadf645507c329e0f5d7fbb67d9311cfa26ac638Torne (Richard Coles)  import known_issues
2139df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)
214cadf645507c329e0f5d7fbb67d9311cfa26ac638Torne (Richard Coles)  for path, exclude_list in known_issues.KNOWN_INCOMPATIBLE.iteritems():
2155d65b76f6747f51bb623d00205aca85581ad4d91Torne (Richard Coles)    logging.debug('  %s', '\n  '.join(os.path.join(path, x) for x in
2165d65b76f6747f51bb623d00205aca85581ad4d91Torne (Richard Coles)                                      exclude_list))
2171c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)    dest_dir = os.path.join(merge_common.REPOSITORY_ROOT, path)
2181c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)    merge_common.GetCommandStdout(['git', 'rm', '-rf', '--ignore-unmatch'] +
2191c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)                                  exclude_list, cwd=dest_dir)
2203c67328c9fd2fd48405af3950e59893bfdf1287bTorne (Richard Coles)    if _ModifiedFilesInIndex(dest_dir):
2211c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)      merge_common.GetCommandStdout(['git', 'commit', '-m',
222cb12295daa313fcefcfff1681c30f3fe935e762eTorne (Richard Coles)                                     'Exclude unwanted directories'],
2231c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)                                    cwd=dest_dir)
2243c67328c9fd2fd48405af3950e59893bfdf1287bTorne (Richard Coles)
2259df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)  directories_left_over = webview_licenses.GetIncompatibleDirectories()
2269df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)  if directories_left_over:
227862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)    raise merge_common.TemporaryMergeError(
228862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)        'Incompatibly licensed directories remain: ' +
229862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)        '\n'.join(directories_left_over))
2306a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)
2316a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)
232862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)def _GenerateMakefiles(svn_revision, unattended):
23382c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)  """Run gyp to generate the Android build system makefiles.
2346a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)
23582c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)  Args:
23682c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)    svn_revision: The SVN revision to mention in generated commit messages.
237862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)    unattended: Run in unattended mode.
23882c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)  """
2394098e8316ddaa5b20fd8f97438fd063a5468db0eTorne (Richard Coles)  logging.debug('Generating makefiles ...')
2404098e8316ddaa5b20fd8f97438fd063a5468db0eTorne (Richard Coles)
2419df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)  # TODO(torne): The .tmp files are generated by
2426a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)  # third_party/WebKit/Source/WebCore/WebCore.gyp/WebCore.gyp into the source
2436a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)  # tree. We should avoid this, or at least use a more specific name to avoid
2446a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)  # accidentally removing or adding other files.
2451c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)  for path in merge_common.ALL_PROJECTS:
2461c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)    dest_dir = os.path.join(merge_common.REPOSITORY_ROOT, path)
2471c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)    merge_common.GetCommandStdout(['git', 'rm', '--ignore-unmatch',
2485568eda06be15d573395eaba779d62c09f6f96f1Torne (Richard Coles)                                   'GypAndroid.*.mk', '*.target.*.mk',
2495568eda06be15d573395eaba779d62c09f6f96f1Torne (Richard Coles)                                   '*.host.*.mk', '*.tmp'], cwd=dest_dir)
2501c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)
251862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)  try:
252862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)    merge_common.GetCommandStdout(['android_webview/tools/gyp_webview'])
2532735b74c930c17d39cb6510c0c2c0a43df1d181aTorne (Richard Coles)  except merge_common.MergeError as e:
254862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)    if not unattended:
255862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)      raise
256862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)    else:
257862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)      for path in merge_common.ALL_PROJECTS:
258862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)        merge_common.GetCommandStdout(
259862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)            ['git', 'reset', '--hard'],
260862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)            cwd=os.path.join(merge_common.REPOSITORY_ROOT, path))
2612735b74c930c17d39cb6510c0c2c0a43df1d181aTorne (Richard Coles)      raise merge_common.TemporaryMergeError('Makefile generation failed: ' +
26272724a6d44b1f9ebc7e122045a72f3502185844dTorne (Richard Coles)                                             str(e))
2631c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)
2641c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)  for path in merge_common.ALL_PROJECTS:
2651c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)    dest_dir = os.path.join(merge_common.REPOSITORY_ROOT, path)
2669df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)    # git add doesn't have an --ignore-unmatch so we have to do this instead:
2675568eda06be15d573395eaba779d62c09f6f96f1Torne (Richard Coles)    merge_common.GetCommandStdout(['git', 'add', '-f', 'GypAndroid.*.mk'],
2681c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)                                  ignore_errors=True, cwd=dest_dir)
2695568eda06be15d573395eaba779d62c09f6f96f1Torne (Richard Coles)    merge_common.GetCommandStdout(['git', 'add', '-f', '*.target.*.mk'],
2701c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)                                  ignore_errors=True, cwd=dest_dir)
2715568eda06be15d573395eaba779d62c09f6f96f1Torne (Richard Coles)    merge_common.GetCommandStdout(['git', 'add', '-f', '*.host.*.mk'],
2721c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)                                  ignore_errors=True, cwd=dest_dir)
2731c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)    merge_common.GetCommandStdout(['git', 'add', '-f', '*.tmp'],
2741c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)                                  ignore_errors=True, cwd=dest_dir)
2759df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)    # Only try to commit the makefiles if something has actually changed.
2769df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)    if _ModifiedFilesInIndex(dest_dir):
27782c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)      merge_common.GetCommandStdout(
27882c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)          ['git', 'commit', '-m',
27982c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)           'Update makefiles after merge of Chromium at r%s\n\n%s' %
28082c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)           (svn_revision, AUTOGEN_MESSAGE)], cwd=dest_dir)
2816a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)
2829df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)
2831c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)def _ModifiedFilesInIndex(cwd=merge_common.REPOSITORY_ROOT):
28482c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)  """Returns true if git's index contains any changes."""
2851c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)  status = merge_common.GetCommandStdout(['git', 'status', '--porcelain'],
2861c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)                                         cwd=cwd)
28782c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)  return re.search(r'^[MADRC]', status, flags=re.MULTILINE) is not None
2886a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)
2896a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)
2906a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)def _GenerateNoticeFile(svn_revision):
29182c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)  """Generates and commits a NOTICE file containing code licenses.
29282c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)
29382c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)  This covers all third-party code (from Android's perspective) that lives in
29482c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)  the Chromium tree.
29582c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)
2966a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)  Args:
29782c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)    svn_revision: The SVN revision for the main Chromium repository.
2986a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)  """
2995d65b76f6747f51bb623d00205aca85581ad4d91Torne (Richard Coles)  logging.debug('Regenerating NOTICE file ...')
3006a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)
3019df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)  contents = webview_licenses.GenerateNoticeFile()
3026a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)
3031c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)  with open(os.path.join(merge_common.REPOSITORY_ROOT, 'NOTICE'), 'w') as f:
3046a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)    f.write(contents)
3051c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)  merge_common.GetCommandStdout(['git', 'add', 'NOTICE'])
3066a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)  # Only try to commit the NOTICE update if the file has actually changed.
3076a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)  if _ModifiedFilesInIndex():
3081c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)    merge_common.GetCommandStdout([
3096a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)        'git', 'commit', '-m',
3106a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)        'Update NOTICE file after merge of Chromium at r%s\n\n%s'
3116a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)        % (svn_revision, AUTOGEN_MESSAGE)])
3126a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)
3136a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)
314e9d946910fc23e839e0ba89df0a59cdcd1aac8ddTorne (Richard Coles)def _GenerateLastChange(svn_revision):
31582c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)  """Write a build/util/LASTCHANGE file containing the current revision.
31682c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)
31782c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)  The revision number is compiled into the binary at build time from this file.
31882c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)
319e9d946910fc23e839e0ba89df0a59cdcd1aac8ddTorne (Richard Coles)  Args:
32082c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)    svn_revision: The SVN revision for the main Chromium repository.
321e9d946910fc23e839e0ba89df0a59cdcd1aac8ddTorne (Richard Coles)  """
3225d65b76f6747f51bb623d00205aca85581ad4d91Torne (Richard Coles)  logging.debug('Updating LASTCHANGE ...')
3231c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)  with open(os.path.join(merge_common.REPOSITORY_ROOT, 'build/util/LASTCHANGE'),
3241c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)            'w') as f:
32582c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)    f.write('LASTCHANGE=%s\n' % svn_revision)
3261c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)  merge_common.GetCommandStdout(['git', 'add', '-f', 'build/util/LASTCHANGE'])
327e9d946910fc23e839e0ba89df0a59cdcd1aac8ddTorne (Richard Coles)  if _ModifiedFilesInIndex():
3281c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)    merge_common.GetCommandStdout([
329e9d946910fc23e839e0ba89df0a59cdcd1aac8ddTorne (Richard Coles)        'git', 'commit', '-m',
330e9d946910fc23e839e0ba89df0a59cdcd1aac8ddTorne (Richard Coles)        'Update LASTCHANGE file after merge of Chromium at r%s\n\n%s'
331e9d946910fc23e839e0ba89df0a59cdcd1aac8ddTorne (Richard Coles)        % (svn_revision, AUTOGEN_MESSAGE)])
332e9d946910fc23e839e0ba89df0a59cdcd1aac8ddTorne (Richard Coles)
333e9d946910fc23e839e0ba89df0a59cdcd1aac8ddTorne (Richard Coles)
334862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)def GetLKGR():
335862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)  """Fetch the last known good release from Chromium's dashboard.
336862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)
337862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)  Returns:
338862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)    The last known good SVN revision.
339862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)  """
340862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)  with contextlib.closing(
341862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)      urllib2.urlopen('https://chromium-status.appspot.com/lkgr')) as lkgr:
342862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)    return int(lkgr.read())
343862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)
344862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)
345a611c7e365068e2130b6de87b2b14e3b75ae1d4eBo Liudef GetHEAD():
346a611c7e365068e2130b6de87b2b14e3b75ae1d4eBo Liu  """Fetch the latest HEAD revision from the git mirror of the Chromium svn
347a611c7e365068e2130b6de87b2b14e3b75ae1d4eBo Liu  repo.
348a611c7e365068e2130b6de87b2b14e3b75ae1d4eBo Liu
349a611c7e365068e2130b6de87b2b14e3b75ae1d4eBo Liu  Returns:
350a611c7e365068e2130b6de87b2b14e3b75ae1d4eBo Liu    The latest HEAD SVN revision.
351a611c7e365068e2130b6de87b2b14e3b75ae1d4eBo Liu  """
3524465da421aa5ee3d2f6a016b961c301040f0fa23Torne (Richard Coles)  (svn_revision, root_sha1) = _GetSVNRevisionAndSHA1(SRC_GIT_BRANCH,
3534465da421aa5ee3d2f6a016b961c301040f0fa23Torne (Richard Coles)                                                     'HEAD')
354a611c7e365068e2130b6de87b2b14e3b75ae1d4eBo Liu  return int(svn_revision)
355a611c7e365068e2130b6de87b2b14e3b75ae1d4eBo Liu
356a611c7e365068e2130b6de87b2b14e3b75ae1d4eBo Liu
3573977434d5c3aafc00eaae0d2e78fa8ddd72536f3Bo Liudef _ParseSvnRevisionFromGitCommitMessage(commit_message):
3583977434d5c3aafc00eaae0d2e78fa8ddd72536f3Bo Liu  return re.search(r'^git-svn-id: .*@([0-9]+)', commit_message,
3593977434d5c3aafc00eaae0d2e78fa8ddd72536f3Bo Liu                   flags=re.MULTILINE).group(1)
3603977434d5c3aafc00eaae0d2e78fa8ddd72536f3Bo Liu
3613977434d5c3aafc00eaae0d2e78fa8ddd72536f3Bo Liu
3623977434d5c3aafc00eaae0d2e78fa8ddd72536f3Bo Liudef _GetSVNRevisionFromSha(sha1):
3633977434d5c3aafc00eaae0d2e78fa8ddd72536f3Bo Liu  commit = merge_common.GetCommandStdout([
3643977434d5c3aafc00eaae0d2e78fa8ddd72536f3Bo Liu      'git', 'show', '--format=%H%n%b', sha1])
3653977434d5c3aafc00eaae0d2e78fa8ddd72536f3Bo Liu  return _ParseSvnRevisionFromGitCommitMessage(commit)
3663977434d5c3aafc00eaae0d2e78fa8ddd72536f3Bo Liu
3673977434d5c3aafc00eaae0d2e78fa8ddd72536f3Bo Liu
3684465da421aa5ee3d2f6a016b961c301040f0fa23Torne (Richard Coles)def _GetSVNRevisionAndSHA1(git_branch, svn_revision, sha1=None):
3695d65b76f6747f51bb623d00205aca85581ad4d91Torne (Richard Coles)  logging.debug('Getting SVN revision and SHA1 ...')
3703977434d5c3aafc00eaae0d2e78fa8ddd72536f3Bo Liu
3713977434d5c3aafc00eaae0d2e78fa8ddd72536f3Bo Liu  if sha1:
3723977434d5c3aafc00eaae0d2e78fa8ddd72536f3Bo Liu    return (_GetSVNRevisionFromSha(sha1), sha1)
3733977434d5c3aafc00eaae0d2e78fa8ddd72536f3Bo Liu
3749536a5e5660bc0745d1f5f2f6a6468fa53ffa639Bo Liu  if svn_revision == 'HEAD':
3759536a5e5660bc0745d1f5f2f6a6468fa53ffa639Bo Liu    # Just use the latest commit.
3769536a5e5660bc0745d1f5f2f6a6468fa53ffa639Bo Liu    commit = merge_common.GetCommandStdout([
3779536a5e5660bc0745d1f5f2f6a6468fa53ffa639Bo Liu        'git', 'log', '-n1', '--grep=git-svn-id:', '--format=%H%n%b',
3784465da421aa5ee3d2f6a016b961c301040f0fa23Torne (Richard Coles)        git_branch])
3799536a5e5660bc0745d1f5f2f6a6468fa53ffa639Bo Liu    sha1 = commit.split()[0]
3803977434d5c3aafc00eaae0d2e78fa8ddd72536f3Bo Liu    svn_revision = _ParseSvnRevisionFromGitCommitMessage(commit)
3819536a5e5660bc0745d1f5f2f6a6468fa53ffa639Bo Liu    return (svn_revision, sha1)
3829536a5e5660bc0745d1f5f2f6a6468fa53ffa639Bo Liu
3832efbabe43f012ff9c06c78fc19fae49421a4d356Torne (Richard Coles)  if svn_revision is None:
3842efbabe43f012ff9c06c78fc19fae49421a4d356Torne (Richard Coles)    # Fetch LKGR from upstream.
385862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)    svn_revision = GetLKGR()
3862efbabe43f012ff9c06c78fc19fae49421a4d356Torne (Richard Coles)  output = merge_common.GetCommandStdout([
3872efbabe43f012ff9c06c78fc19fae49421a4d356Torne (Richard Coles)      'git', 'log', '--grep=git-svn-id: .*@%s' % svn_revision,
3884465da421aa5ee3d2f6a016b961c301040f0fa23Torne (Richard Coles)      '--format=%H', git_branch])
3892efbabe43f012ff9c06c78fc19fae49421a4d356Torne (Richard Coles)  if not output:
390862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)    raise merge_common.TemporaryMergeError('Revision %s not found in git repo.'
391862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)                                           % svn_revision)
3922efbabe43f012ff9c06c78fc19fae49421a4d356Torne (Richard Coles)  # The log grep will sometimes match reverts/reapplies of commits. We take the
3932efbabe43f012ff9c06c78fc19fae49421a4d356Torne (Richard Coles)  # oldest (last) match because the first time it appears in history is
3942efbabe43f012ff9c06c78fc19fae49421a4d356Torne (Richard Coles)  # overwhelmingly likely to be the correct commit.
3952efbabe43f012ff9c06c78fc19fae49421a4d356Torne (Richard Coles)  sha1 = output.split()[-1]
3966a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)  return (svn_revision, sha1)
3976a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)
3986a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)
3993977434d5c3aafc00eaae0d2e78fa8ddd72536f3Bo Liudef Snapshot(svn_revision, root_sha1, unattended):
40082c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)  """Takes a snapshot of the Chromium tree and merges it into Android.
40182c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)
40282c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)  Android makefiles and a top-level NOTICE file are generated and committed
40382c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)  after the merge.
40482c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)
4056a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)  Args:
40682c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)    svn_revision: The SVN revision in the Chromium repository to merge from.
4073977434d5c3aafc00eaae0d2e78fa8ddd72536f3Bo Liu    root_sha1: The sha1 in the Chromium git mirror to merge from. Only one of
4083977434d5c3aafc00eaae0d2e78fa8ddd72536f3Bo Liu               svn_revision and root_sha1 should be specified.
40914ac2c8d49fa1f5f12e6a80af93f1c50312d80a8Torne (Richard Coles)    unattended: Run in unattended mode.
4106a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)
41182c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)  Returns:
41282c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)    True if new commits were merged; False if no new commits were present.
41382c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)  """
414a611c7e365068e2130b6de87b2b14e3b75ae1d4eBo Liu  git_branch = SRC_GIT_BRANCH
4154465da421aa5ee3d2f6a016b961c301040f0fa23Torne (Richard Coles)  (svn_revision, root_sha1) = _GetSVNRevisionAndSHA1(git_branch, svn_revision,
4164465da421aa5ee3d2f6a016b961c301040f0fa23Torne (Richard Coles)                                                     root_sha1)
4171c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)  if not merge_common.GetCommandStdout(['git', 'rev-list', '-1',
4181c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)                                        'HEAD..' + root_sha1]):
4194465da421aa5ee3d2f6a016b961c301040f0fa23Torne (Richard Coles)    logging.info('No new commits to merge from %s at r%s (%s)',
4204465da421aa5ee3d2f6a016b961c301040f0fa23Torne (Richard Coles)                 git_branch, svn_revision, root_sha1)
42182c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)    return False
4226a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)
4234465da421aa5ee3d2f6a016b961c301040f0fa23Torne (Richard Coles)  logging.info('Snapshotting Chromium from %s at r%s (%s)',
4244465da421aa5ee3d2f6a016b961c301040f0fa23Torne (Richard Coles)               git_branch, svn_revision, root_sha1)
4256a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)
4266a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)  # 1. Merge, accounting for excluded directories
4274465da421aa5ee3d2f6a016b961c301040f0fa23Torne (Richard Coles)  _MergeProjects(git_branch, svn_revision, root_sha1, unattended)
4286a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)
4299df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)  # 2. Generate Android NOTICE file
4306a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)  _GenerateNoticeFile(svn_revision)
4316a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)
432e9d946910fc23e839e0ba89df0a59cdcd1aac8ddTorne (Richard Coles)  # 3. Generate LASTCHANGE file
433e9d946910fc23e839e0ba89df0a59cdcd1aac8ddTorne (Richard Coles)  _GenerateLastChange(svn_revision)
434e9d946910fc23e839e0ba89df0a59cdcd1aac8ddTorne (Richard Coles)
435e9d946910fc23e839e0ba89df0a59cdcd1aac8ddTorne (Richard Coles)  # 4. Generate Android makefiles
436862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)  _GenerateMakefiles(svn_revision, unattended)
4379df6a6c4638cfab15aa303682c15050a9509eb44Torne (Richard Coles)
4381896d5d734a45c412f47fe58816665d374617d3bTorne (Richard Coles)  return True
4391896d5d734a45c412f47fe58816665d374617d3bTorne (Richard Coles)
4406a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)
441862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)def Push(svn_revision):
442bda7cff5dd92725ba000fe95d9434f81a7af486eTorne (Richard Coles)  """Push the finished snapshot to the Android repository."""
44309ead754abd2cfcffea54040b1c9ac98db8af834Torne (Richard Coles)  src = 'merge-from-chromium-%s' % svn_revision
44409ead754abd2cfcffea54040b1c9ac98db8af834Torne (Richard Coles)  for branch in ['master-chromium-merge', 'master-chromium']:
44509ead754abd2cfcffea54040b1c9ac98db8af834Torne (Richard Coles)    logging.debug('Pushing to server (%s) ...' % branch)
44609ead754abd2cfcffea54040b1c9ac98db8af834Torne (Richard Coles)    for path in merge_common.ALL_PROJECTS:
44709ead754abd2cfcffea54040b1c9ac98db8af834Torne (Richard Coles)      if path in merge_common.PROJECTS_WITH_FLAT_HISTORY:
44809ead754abd2cfcffea54040b1c9ac98db8af834Torne (Richard Coles)        remote = 'history'
44909ead754abd2cfcffea54040b1c9ac98db8af834Torne (Richard Coles)      else:
45009ead754abd2cfcffea54040b1c9ac98db8af834Torne (Richard Coles)        remote = 'goog'
45109ead754abd2cfcffea54040b1c9ac98db8af834Torne (Richard Coles)      logging.debug('Pushing %s', path)
45209ead754abd2cfcffea54040b1c9ac98db8af834Torne (Richard Coles)      dest_dir = os.path.join(merge_common.REPOSITORY_ROOT, path)
45309ead754abd2cfcffea54040b1c9ac98db8af834Torne (Richard Coles)      GetCommandStdout(['git', 'push', '-f', remote, src + ':' + branch],
45409ead754abd2cfcffea54040b1c9ac98db8af834Torne (Richard Coles)                       cwd=dest_dir)
455bda7cff5dd92725ba000fe95d9434f81a7af486eTorne (Richard Coles)
456bda7cff5dd92725ba000fe95d9434f81a7af486eTorne (Richard Coles)
4576a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)def main():
4586a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)  parser = optparse.OptionParser(usage='%prog [options]')
4596a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)  parser.epilog = ('Takes a snapshot of the Chromium tree at the specified '
4606a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)                   'Chromium SVN revision and merges it into this repository. '
4616a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)                   'Paths marked as excluded for license reasons are removed '
4626a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)                   'as part of the merge. Also generates Android makefiles and '
4636a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)                   'generates a top-level NOTICE file suitable for use in the '
4646a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)                   'Android build.')
4656a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)  parser.add_option(
4666a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)      '', '--svn_revision',
4676a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)      default=None,
4686a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)      help=('Merge to the specified chromium SVN revision, rather than using '
4693977434d5c3aafc00eaae0d2e78fa8ddd72536f3Bo Liu            'the current LKGR. Can also pass HEAD to merge from tip of tree. '
4703977434d5c3aafc00eaae0d2e78fa8ddd72536f3Bo Liu            'Only one of svn_revision and sha1 should be specified'))
4713977434d5c3aafc00eaae0d2e78fa8ddd72536f3Bo Liu  parser.add_option(
4723977434d5c3aafc00eaae0d2e78fa8ddd72536f3Bo Liu      '', '--sha1',
4733977434d5c3aafc00eaae0d2e78fa8ddd72536f3Bo Liu      default=None,
4743977434d5c3aafc00eaae0d2e78fa8ddd72536f3Bo Liu      help=('Merge to the specified chromium sha1 revision from ' + SRC_GIT_BRANCH
4753977434d5c3aafc00eaae0d2e78fa8ddd72536f3Bo Liu            + ' branch, rather than using the current LKGR. Only one of'
4763977434d5c3aafc00eaae0d2e78fa8ddd72536f3Bo Liu             'svn_revision and sha1 should be specified.'))
4771896d5d734a45c412f47fe58816665d374617d3bTorne (Richard Coles)  parser.add_option(
47814ac2c8d49fa1f5f12e6a80af93f1c50312d80a8Torne (Richard Coles)      '', '--push',
47914ac2c8d49fa1f5f12e6a80af93f1c50312d80a8Torne (Richard Coles)      default=False, action='store_true',
4803977434d5c3aafc00eaae0d2e78fa8ddd72536f3Bo Liu      help=('Push the result of a previous merge to the server. Note '
4813977434d5c3aafc00eaae0d2e78fa8ddd72536f3Bo Liu            'svn_revision must be given.'))
48214ac2c8d49fa1f5f12e6a80af93f1c50312d80a8Torne (Richard Coles)  parser.add_option(
4839fb672be51066b51a372885377cc0eff78e1a34cTorne (Richard Coles)      '', '--get_lkgr',
4849fb672be51066b51a372885377cc0eff78e1a34cTorne (Richard Coles)      default=False, action='store_true',
4859fb672be51066b51a372885377cc0eff78e1a34cTorne (Richard Coles)      help=('Just print the current LKGR on stdout and exit.'))
4869fb672be51066b51a372885377cc0eff78e1a34cTorne (Richard Coles)  parser.add_option(
487a611c7e365068e2130b6de87b2b14e3b75ae1d4eBo Liu      '', '--get_head',
488a611c7e365068e2130b6de87b2b14e3b75ae1d4eBo Liu      default=False, action='store_true',
489a611c7e365068e2130b6de87b2b14e3b75ae1d4eBo Liu      help=('Just print the current HEAD revision on stdout and exit.'))
490a611c7e365068e2130b6de87b2b14e3b75ae1d4eBo Liu  parser.add_option(
49114ac2c8d49fa1f5f12e6a80af93f1c50312d80a8Torne (Richard Coles)      '', '--unattended',
4921896d5d734a45c412f47fe58816665d374617d3bTorne (Richard Coles)      default=False, action='store_true',
49314ac2c8d49fa1f5f12e6a80af93f1c50312d80a8Torne (Richard Coles)      help=('Run in unattended mode.'))
494d2a42d0b062f4c9bb4c3fefc80cde98350b5974eTorne (Richard Coles)  parser.add_option(
495d2a42d0b062f4c9bb4c3fefc80cde98350b5974eTorne (Richard Coles)      '', '--no_changes_exit',
496d2a42d0b062f4c9bb4c3fefc80cde98350b5974eTorne (Richard Coles)      default=0, type='int',
497d2a42d0b062f4c9bb4c3fefc80cde98350b5974eTorne (Richard Coles)      help=('Exit code to use if there are no changes to merge, for scripts.'))
4986a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)  (options, args) = parser.parse_args()
4996a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)  if args:
5006a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)    parser.print_help()
5016a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)    return 1
5026a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)
5036a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)  if 'ANDROID_BUILD_TOP' not in os.environ:
5046a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)    print >>sys.stderr, 'You need to run the Android envsetup.sh and lunch.'
5056a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)    return 1
5066a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)
5075d65b76f6747f51bb623d00205aca85581ad4d91Torne (Richard Coles)  logging.basicConfig(format='%(message)s', level=logging.DEBUG,
5085d65b76f6747f51bb623d00205aca85581ad4d91Torne (Richard Coles)                      stream=sys.stdout)
5095d65b76f6747f51bb623d00205aca85581ad4d91Torne (Richard Coles)
5109fb672be51066b51a372885377cc0eff78e1a34cTorne (Richard Coles)  if options.get_lkgr:
5119fb672be51066b51a372885377cc0eff78e1a34cTorne (Richard Coles)    print GetLKGR()
512a611c7e365068e2130b6de87b2b14e3b75ae1d4eBo Liu  elif options.get_head:
513a611c7e365068e2130b6de87b2b14e3b75ae1d4eBo Liu    logging.disable(logging.CRITICAL)  # Prevent log messages
514a611c7e365068e2130b6de87b2b14e3b75ae1d4eBo Liu    print GetHEAD()
5159fb672be51066b51a372885377cc0eff78e1a34cTorne (Richard Coles)  elif options.push:
516862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)    if options.svn_revision is None:
517862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)      print >>sys.stderr, 'You need to pass the SVN revision to push.'
518862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)      return 1
519862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)    else:
520862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)      Push(options.svn_revision)
52114ac2c8d49fa1f5f12e6a80af93f1c50312d80a8Torne (Richard Coles)  else:
5223977434d5c3aafc00eaae0d2e78fa8ddd72536f3Bo Liu    if not Snapshot(options.svn_revision, options.sha1, options.unattended):
523d2a42d0b062f4c9bb4c3fefc80cde98350b5974eTorne (Richard Coles)      return options.no_changes_exit
52414ac2c8d49fa1f5f12e6a80af93f1c50312d80a8Torne (Richard Coles)
5256a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)  return 0
5266a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)
5276a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)if __name__ == '__main__':
5286a8c82cdaffde31477cacabea89afefeded67f3eTorne (Richard Coles)  sys.exit(main())
529