153 lines
6.1 KiB
Python
Executable File
153 lines
6.1 KiB
Python
Executable File
#!/usr/bin/env python
|
|
# Copyright (C) 2017 Apple Inc. All rights reserved.
|
|
#
|
|
# Redistribution and use in source and binary forms, with or without
|
|
# modification, are permitted provided that the following conditions
|
|
# are met:
|
|
# 1. Redistributions of source code must retain the above copyright
|
|
# notice, this list of conditions and the following disclaimer.
|
|
# 2. Redistributions in binary form must reproduce the above copyright
|
|
# notice, this list of conditions and the following disclaimer in the
|
|
# documentation and/or other materials provided with the distribution.
|
|
#
|
|
# THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND
|
|
# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
# WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
# DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR
|
|
# ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
# A webkitpy import needs to go first for autoinstaller to work with subsequent imports.
|
|
import webkitpy
|
|
|
|
import os
|
|
import six
|
|
import sys
|
|
|
|
REBASE_DICTIONARY = {
|
|
'WebKit2/': 'WebKit/',
|
|
'WebKit/': 'WebKitLegacy/'
|
|
}
|
|
class RebaseStatus:
|
|
DO_NOT_NEED = 0
|
|
MAYBE_NEED = 1
|
|
NEED = 2
|
|
ALREADY = 3
|
|
|
|
|
|
def append_source(path):
|
|
return os.path.join('Source', path)
|
|
|
|
|
|
def is_editable_line(line):
|
|
editable_prefixes = ('Index: ', '--- ', '+++ ', 'diff --git ')
|
|
return any(map(line.startswith, editable_prefixes))
|
|
|
|
|
|
def needs_rebase(line):
|
|
if not is_editable_line(line):
|
|
return RebaseStatus.DO_NOT_NEED
|
|
|
|
for current_name, rebased_name in six.iteritems(REBASE_DICTIONARY):
|
|
# Check if we've already rebased. We need to check if the rebased_name is already in the REBASE_DICTIONARY,
|
|
# in this case, we don't know if we've already been rebased.
|
|
if append_source(rebased_name) in line and rebased_name not in REBASE_DICTIONARY:
|
|
return RebaseStatus.ALREADY
|
|
|
|
# Check if we need to rebase. We need to check if the current name is one of the potential rebase names.
|
|
# In this case, we don't know if we need the rebase.
|
|
if append_source(current_name) in line and current_name not in REBASE_DICTIONARY.values():
|
|
return RebaseStatus.NEED
|
|
|
|
# Check if we might need a rebase
|
|
for current_name, rebased_name in six.iteritems(REBASE_DICTIONARY):
|
|
if append_source(current_name) in line:
|
|
return RebaseStatus.MAYBE_NEED
|
|
|
|
return RebaseStatus.DO_NOT_NEED
|
|
|
|
|
|
def rebase_line(line):
|
|
if not is_editable_line(line):
|
|
for current_name, rebased_name in six.iteritems(REBASE_DICTIONARY):
|
|
if current_name in line:
|
|
sys.stderr.write('Found an instance of {} in the patch. Did you mean to replace it with {}?\n'.format(current_name, rebased_name))
|
|
return line
|
|
for current_name, rebased_name in six.iteritems(REBASE_DICTIONARY):
|
|
if append_source(current_name) in line:
|
|
return line.replace(append_source(current_name), append_source(rebased_name))
|
|
return line
|
|
|
|
|
|
def rebase(patch_content, output_file, patch_name):
|
|
rebase_status = RebaseStatus.DO_NOT_NEED
|
|
for line in patch_content:
|
|
line_status = needs_rebase(line)
|
|
if (rebase_status == RebaseStatus.NEED and line_status == RebaseStatus.ALREADY) or (rebase_status == RebaseStatus.ALREADY and line_status == RebaseStatus.NEED):
|
|
sys.stderr.write('{} is a partially rebased patch\n'.format(patch_name))
|
|
return -1
|
|
rebase_status = max(rebase_status, line_status)
|
|
|
|
if rebase_status == RebaseStatus.MAYBE_NEED and output_file == sys.stdout:
|
|
sys.stderr.write('Cannot determine if path from {} has already been rebased, rebasing anyways\n'.format(patch_name))
|
|
elif rebase_status == RebaseStatus.MAYBE_NEED:
|
|
rebase_status = RebaseStatus.MAYBE_NEED
|
|
sys.stdout.write('{} may have already been rebased, are you sure you want to rebase it Y/n?\n'.format(patch_name))
|
|
line = sys.stdin.readline().rstrip().upper()
|
|
if line == 'Y' or line == 'YES':
|
|
rebase_status = RebaseStatus.NEED
|
|
|
|
if rebase_status == RebaseStatus.ALREADY or rebase_status == RebaseStatus.MAYBE_NEED:
|
|
# Output the provided patch if no re-base is required
|
|
for line in patch_content:
|
|
output_file.write(line)
|
|
return 0
|
|
|
|
if rebase_status == RebaseStatus.MAYBE_NEED:
|
|
sys.stderr.write('Cannot determine if path from {} has already been rebased, rebasing anyways\n'.format(patch_name))
|
|
|
|
for line in patch_content:
|
|
output_file.write(rebase_line(line))
|
|
|
|
return 0
|
|
|
|
|
|
def parse_arguments():
|
|
files_to_rebase = []
|
|
if len(sys.argv) == 1:
|
|
sys.stderr.write('Reading patch from stdin\n')
|
|
return []
|
|
elif sys.argv[1] == '-h' or sys.argv[1] == 'help':
|
|
print('rebase-patch-after-webkit-move usage:')
|
|
print('\trebase-patch-after-webkit-move -h, help')
|
|
print('\t\tPrint this message')
|
|
print('\trebase-patch-after-webkit-move <path to patch>')
|
|
print('\t\tReplace the patch at the provided path with a rebased patch')
|
|
print('\trebase-patch-after-webkit-move')
|
|
print('\t\tTreat stdin as the patch to be rebased')
|
|
exit(0)
|
|
|
|
for path in sys.argv[1:]:
|
|
if not os.path.isfile(path):
|
|
sys.stderr.write('{} does not exist, cannot rebase patch\n'.format(path))
|
|
exit(1)
|
|
files_to_rebase.append(path)
|
|
|
|
return files_to_rebase
|
|
|
|
|
|
if __name__ == '__main__':
|
|
files_to_rebase = parse_arguments()
|
|
|
|
status = 0
|
|
for path in files_to_rebase:
|
|
if rebase(open(path, 'r').readlines(), open(path, 'w'), path) != 0:
|
|
status = 1
|
|
if not files_to_rebase:
|
|
status = rebase(sys.stdin.readlines(), sys.stdout, 'STDIN')
|
|
exit(status)
|