11c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)# Copyright (C) 2012 The Android Open Source Project 21c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)# 31c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)# Licensed under the Apache License, Version 2.0 (the "License"); 41c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)# you may not use this file except in compliance with the License. 51c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)# You may obtain a copy of the License at 61c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)# 71c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)# http://www.apache.org/licenses/LICENSE-2.0 81c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)# 91c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)# Unless required by applicable law or agreed to in writing, software 101c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)# distributed under the License is distributed on an "AS IS" BASIS, 111c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 121c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)# See the License for the specific language governing permissions and 131c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)# limitations under the License. 141c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles) 1582c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)"""Common data/functions for the Chromium merging scripts.""" 161c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles) 175d65b76f6747f51bb623d00205aca85581ad4d91Torne (Richard Coles)import logging 181c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)import os 191c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)import re 201c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)import subprocess 211c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles) 221c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles) 231c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)REPOSITORY_ROOT = os.path.join(os.environ['ANDROID_BUILD_TOP'], 241c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles) 'external/chromium_org') 251c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles) 261c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles) 271c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)# Whitelist of projects that need to be merged to build WebView. We don't need 281c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)# the other upstream repositories used to build the actual Chrome app. 2982c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)# Different stages of the merge process need different ways of looking at the 3082c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)# list, so we construct different combinations below. 3182c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles) 3233e5c69dc781743cc2560bef57763170b61bae3fTorne (Richard Coles)THIRD_PARTY_PROJECTS_WITH_FLAT_HISTORY = [ 3333e5c69dc781743cc2560bef57763170b61bae3fTorne (Richard Coles) 'third_party/WebKit', 3433e5c69dc781743cc2560bef57763170b61bae3fTorne (Richard Coles)] 3533e5c69dc781743cc2560bef57763170b61bae3fTorne (Richard Coles) 3633e5c69dc781743cc2560bef57763170b61bae3fTorne (Richard Coles)THIRD_PARTY_PROJECTS_WITH_FULL_HISTORY = [ 371c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles) 'sdch/open-vcdiff', 381c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles) 'testing/gtest', 39c057d5bb4006c946b148106e1536a0570047e84fBo Liu 'third_party/angle_dx11', 4046e06376d64605bfae5337fbd2588537c8a1f982Torne (Richard Coles) 'third_party/eyesfree/src/android/java/src/com/googlecode/eyesfree/braille', 411c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles) 'third_party/freetype', 421c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles) 'third_party/icu', 431c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles) 'third_party/leveldatabase/src', 44fe1e1418b6c6d4d9492feb627aa2af5fadd8eb53Torne (Richard Coles) 'third_party/libjingle/source/talk', 451c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles) 'third_party/libphonenumber/src/phonenumbers', 461c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles) 'third_party/libphonenumber/src/resources', 472ad1105953c418b574ecffa8b002d41d0564e9d7Ben Murdoch 'third_party/mesa/src', 481c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles) 'third_party/openssl', 49fc21d2e7a06dcdbe43f35f1ba20d9e8770738339Ben Murdoch 'third_party/opus/src', 501c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles) 'third_party/ots', 511c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles) 'third_party/skia/include', 521c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles) 'third_party/skia/gyp', 531c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles) 'third_party/skia/src', 54cadf645507c329e0f5d7fbb67d9311cfa26ac638Torne (Richard Coles) 'third_party/smhasher/src', 55b455389686a6d4225f9270c4a2f63e03a8c0f6cdTorne (Richard Coles) 'third_party/yasm/source/patched-yasm', 561c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles) 'tools/grit', 571c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles) 'tools/gyp', 581c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles) 'v8', 591c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)] 601c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles) 6133e5c69dc781743cc2560bef57763170b61bae3fTorne (Richard Coles)PROJECTS_WITH_FLAT_HISTORY = ['.'] + THIRD_PARTY_PROJECTS_WITH_FLAT_HISTORY 6233e5c69dc781743cc2560bef57763170b61bae3fTorne (Richard Coles)PROJECTS_WITH_FULL_HISTORY = THIRD_PARTY_PROJECTS_WITH_FULL_HISTORY 6333e5c69dc781743cc2560bef57763170b61bae3fTorne (Richard Coles) 6433e5c69dc781743cc2560bef57763170b61bae3fTorne (Richard Coles)THIRD_PARTY_PROJECTS = (THIRD_PARTY_PROJECTS_WITH_FLAT_HISTORY + 6533e5c69dc781743cc2560bef57763170b61bae3fTorne (Richard Coles) THIRD_PARTY_PROJECTS_WITH_FULL_HISTORY) 6633e5c69dc781743cc2560bef57763170b61bae3fTorne (Richard Coles) 671c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)ALL_PROJECTS = ['.'] + THIRD_PARTY_PROJECTS 681c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles) 691c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles) 7033e5c69dc781743cc2560bef57763170b61bae3fTorne (Richard Coles)# Directories to be removed when flattening history. 7133e5c69dc781743cc2560bef57763170b61bae3fTorne (Richard Coles)PRUNE_WHEN_FLATTENING = { 7233e5c69dc781743cc2560bef57763170b61bae3fTorne (Richard Coles) 'third_party/WebKit': [ 7333e5c69dc781743cc2560bef57763170b61bae3fTorne (Richard Coles) 'LayoutTests', 7433e5c69dc781743cc2560bef57763170b61bae3fTorne (Richard Coles) ], 7533e5c69dc781743cc2560bef57763170b61bae3fTorne (Richard Coles)} 7633e5c69dc781743cc2560bef57763170b61bae3fTorne (Richard Coles) 7733e5c69dc781743cc2560bef57763170b61bae3fTorne (Richard Coles) 7882c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)# Only projects that have their history flattened can have directories pruned. 7933e5c69dc781743cc2560bef57763170b61bae3fTorne (Richard Coles)assert all(p in PROJECTS_WITH_FLAT_HISTORY for p in PRUNE_WHEN_FLATTENING) 8033e5c69dc781743cc2560bef57763170b61bae3fTorne (Richard Coles) 8133e5c69dc781743cc2560bef57763170b61bae3fTorne (Richard Coles) 8282c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)class MergeError(Exception): 8382c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles) """Used to signal an error that prevents the merge from being completed.""" 8482c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles) 8582c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles) 8682c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles)class CommandError(MergeError): 8782c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles) """This exception is raised when a process run by GetCommandStdout fails.""" 8882c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles) 8982c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles) def __init__(self, returncode, cmd, cwd, stdout, stderr): 9082c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles) super(CommandError, self).__init__() 9182c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles) self.returncode = returncode 9282c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles) self.cmd = cmd 9382c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles) self.cwd = cwd 9482c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles) self.stdout = stdout 9582c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles) self.stderr = stderr 9682c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles) 9782c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles) def __str__(self): 9882c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles) return ("Command '%s' returned non-zero exit status %d. cwd was '%s'.\n\n" 9982c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles) "===STDOUT===\n%s\n===STDERR===\n%s\n" % 10082c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles) (self.cmd, self.returncode, self.cwd, self.stdout, self.stderr)) 10182c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles) 10282c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles) 103862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles)class TemporaryMergeError(MergeError): 104862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles) """A merge error that can potentially be resolved by trying again later.""" 105862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles) 106862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles) 1071c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles)def GetCommandStdout(args, cwd=REPOSITORY_ROOT, ignore_errors=False): 1081c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles) """Gets stdout from runnng the specified shell command. 10982c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles) 11082c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles) Similar to subprocess.check_output() except that it can capture stdout and 11182c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles) stderr separately for better error reporting. 11282c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles) 1131c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles) Args: 11482c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles) args: The command and its arguments as an iterable. 1151c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles) cwd: The working directory to use. Defaults to REPOSITORY_ROOT. 11682c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles) ignore_errors: Ignore the command's return code and stderr. 1171c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles) Returns: 1181c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles) stdout from running the command. 11982c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles) Raises: 12082c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles) CommandError: if the command exited with a nonzero status. 1211c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles) """ 1221c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles) p = subprocess.Popen(args=args, cwd=cwd, stdout=subprocess.PIPE, 1231c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles) stderr=subprocess.PIPE) 1241c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles) stdout, stderr = p.communicate() 1251c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles) if p.returncode == 0 or ignore_errors: 1261c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles) return stdout 1271c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles) else: 12882c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles) raise CommandError(p.returncode, ' '.join(args), cwd, stdout, stderr) 1291c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles) 1301c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles) 13114ac2c8d49fa1f5f12e6a80af93f1c50312d80a8Torne (Richard Coles)def CheckNoConflictsAndCommitMerge(commit_message, unattended=False, 13214ac2c8d49fa1f5f12e6a80af93f1c50312d80a8Torne (Richard Coles) cwd=REPOSITORY_ROOT): 13382c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles) """Checks for conflicts and commits once they are resolved. 13482c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles) 13582c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles) Certain conflicts are resolved automatically; if any remain, the user is 13682c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles) prompted to resolve them. The user can specify a custom commit message. 13782c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles) 1381c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles) Args: 13982c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles) commit_message: The default commit message. 14014ac2c8d49fa1f5f12e6a80af93f1c50312d80a8Torne (Richard Coles) unattended: If running unattended, abort on conflicts. 14182c98161b9cd8e8f94e00d89b6fd56540473b3d4Torne (Richard Coles) cwd: Working directory to use. 14214ac2c8d49fa1f5f12e6a80af93f1c50312d80a8Torne (Richard Coles) Raises: 143862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles) TemporaryMergeError: If there are conflicts in unattended mode. 1441c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles) """ 1451c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles) status = GetCommandStdout(['git', 'status', '--porcelain'], cwd=cwd) 1461c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles) conflicts_deleted_by_us = re.findall(r'^(?:DD|DU) ([^\n]+)$', status, 1471c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles) flags=re.MULTILINE) 1481c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles) if conflicts_deleted_by_us: 1495d65b76f6747f51bb623d00205aca85581ad4d91Torne (Richard Coles) logging.info('Keeping ours for the following locally deleted files.\n %s', 1505d65b76f6747f51bb623d00205aca85581ad4d91Torne (Richard Coles) '\n '.join(conflicts_deleted_by_us)) 1511c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles) GetCommandStdout(['git', 'rm', '-rf', '--ignore-unmatch'] + 1521c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles) conflicts_deleted_by_us, cwd=cwd) 1531c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles) 1541c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles) # If upstream renames a file we have deleted then it will conflict, but 1551c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles) # we shouldn't just blindly delete these files as they may have been renamed 1561c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles) # into a directory we don't delete. Let them get re-added; they will get 1571c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles) # re-deleted if they are still in a directory we delete. 1581c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles) conflicts_renamed_by_them = re.findall(r'^UA ([^\n]+)$', status, 1591c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles) flags=re.MULTILINE) 1601c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles) if conflicts_renamed_by_them: 1615d65b76f6747f51bb623d00205aca85581ad4d91Torne (Richard Coles) logging.info('Adding theirs for the following locally deleted files.\n %s', 1625d65b76f6747f51bb623d00205aca85581ad4d91Torne (Richard Coles) '\n '.join(conflicts_renamed_by_them)) 1631c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles) GetCommandStdout(['git', 'add', '-f'] + conflicts_renamed_by_them, cwd=cwd) 1641c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles) 1651c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles) while True: 1661c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles) status = GetCommandStdout(['git', 'status', '--porcelain'], cwd=cwd) 1671c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles) conflicts = re.findall(r'^((DD|AU|UD|UA|DU|AA|UU) [^\n]+)$', status, 1681c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles) flags=re.MULTILINE) 1691c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles) if not conflicts: 1701c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles) break 17114ac2c8d49fa1f5f12e6a80af93f1c50312d80a8Torne (Richard Coles) if unattended: 172862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles) GetCommandStdout(['git', 'reset', '--hard'], cwd=cwd) 173862edb04ee66c65ce977d9b14b8809aad40749acTorne (Richard Coles) raise TemporaryMergeError('Cannot resolve merge conflicts.') 1741c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles) conflicts_string = '\n'.join([x[0] for x in conflicts]) 1751c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles) new_commit_message = raw_input( 1761c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles) ('The following conflicts exist and must be resolved.\n\n%s\n\nWhen ' 1771c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles) 'done, enter a commit message or press enter to use the default ' 1781c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles) '(\'%s\').\n\n') % (conflicts_string, commit_message)) 1791c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles) if new_commit_message: 1801c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles) commit_message = new_commit_message 1811c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles) 1821c263f2b522bcb9159547d14f9f57abac46967c7Torne (Richard Coles) GetCommandStdout(['git', 'commit', '-m', commit_message], cwd=cwd) 183