chore: deprecate apply-patches in favour of git-{import,export}-patches (#15300)
This commit is contained in:
parent
4185efa08f
commit
335e9f68b7
123 changed files with 4368 additions and 4780 deletions
|
@ -1,177 +1,27 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
from lib import git
|
||||
|
||||
SOURCE_ROOT = os.path.abspath(os.path.dirname(
|
||||
os.path.dirname(os.path.dirname(__file__))))
|
||||
VENDOR_DIR = os.path.join(SOURCE_ROOT, 'vendor')
|
||||
PYYAML_LIB_DIR = os.path.join(VENDOR_DIR, 'pyyaml', 'lib')
|
||||
sys.path.append(PYYAML_LIB_DIR)
|
||||
import yaml #pylint: disable=wrong-import-position,wrong-import-order
|
||||
|
||||
class Patch:
|
||||
def __init__(self, file_path, repo_path, paths_prefix=None,
|
||||
author='Anonymous <anonymous@electronjs.org>', description=None):
|
||||
self.author = author
|
||||
self.description = description
|
||||
self.file_path = file_path
|
||||
self.paths_prefix = paths_prefix
|
||||
self.repo_path = repo_path
|
||||
|
||||
def apply(self, reverse=False, commit=False, index=False):
|
||||
# Add the change to index only if we're going to commit it later.
|
||||
add_to_index = index or commit
|
||||
patch_applied = git.apply_patch(self.repo_path, self.file_path,
|
||||
directory=self.paths_prefix,
|
||||
index=add_to_index, reverse=reverse)
|
||||
|
||||
if not patch_applied:
|
||||
return False
|
||||
|
||||
if commit:
|
||||
message = self.__get_commit_message(reverse)
|
||||
patch_committed = git.commit(self.repo_path, author=self.author,
|
||||
message=message)
|
||||
return patch_committed
|
||||
|
||||
return True
|
||||
|
||||
def __get_commit_message(self, reverse):
|
||||
message = self.description
|
||||
|
||||
if message is None:
|
||||
message = os.path.basename(self.file_path)
|
||||
|
||||
if reverse:
|
||||
message = 'Revert: ' + message
|
||||
|
||||
return message
|
||||
|
||||
def reverse(self):
|
||||
return self.apply(reverse=True)
|
||||
|
||||
def get_file_path(self):
|
||||
return self.file_path
|
||||
|
||||
|
||||
class PatchesList:
|
||||
"""A list of patches for a specific git repo."""
|
||||
|
||||
def __init__(self, repo_path, patches):
|
||||
# TODO(alexeykuzmin): Make sure that all patches have the same repo_path.
|
||||
self.repo_path = repo_path
|
||||
self.patches = patches
|
||||
|
||||
def __len__(self):
|
||||
return len(self.patches)
|
||||
|
||||
def apply(self, reverse=False, stop_on_error=True, commit=False):
|
||||
all_patches_applied = True
|
||||
failed_patches = []
|
||||
|
||||
for patch in self.patches:
|
||||
# Even if `commit` is True we're not going to commit
|
||||
# individual patches, it takes too much time in the Chromium repo.
|
||||
# Applying all commits takes about 10 minutes (!) on a fast dev machine.
|
||||
# Instead of it we are going only to add all changes to the index
|
||||
# and commit them all at once later.
|
||||
applied_successfully = patch.apply(reverse=reverse, index=commit,
|
||||
commit=False)
|
||||
|
||||
if not applied_successfully:
|
||||
all_patches_applied = False
|
||||
failed_patches.append(patch)
|
||||
|
||||
should_stop_now = not applied_successfully and stop_on_error
|
||||
if should_stop_now:
|
||||
break
|
||||
|
||||
if commit and not all_patches_applied:
|
||||
git.reset(self.repo_path)
|
||||
|
||||
if commit and all_patches_applied:
|
||||
author = 'Electron Build Process <build@electronjs.org>'
|
||||
message = 'Apply Electron patches'
|
||||
git.commit(self.repo_path, author=author, message=message)
|
||||
|
||||
return (all_patches_applied, failed_patches)
|
||||
|
||||
def reverse(self, stop_on_error=True, commit=False):
|
||||
return self.apply(reverse=True, stop_on_error=stop_on_error, commit=commit)
|
||||
def read_patch(patch_dir, patch_filename):
|
||||
"""Read a patch from |patch_dir/filename| and amend the commit message with
|
||||
metadata about the patch file it came from."""
|
||||
ret = []
|
||||
with open(os.path.join(patch_dir, patch_filename)) as f:
|
||||
for l in f.readlines():
|
||||
if l.startswith('diff -'):
|
||||
ret.append('Patch-Filename: {}\n'.format(patch_filename))
|
||||
ret.append(l)
|
||||
return ''.join(ret)
|
||||
|
||||
|
||||
class PatchesConfig:
|
||||
@staticmethod
|
||||
def from_directory(dir_path, project_root, config_name='.patches.yaml'):
|
||||
config_path = os.path.join(dir_path, config_name)
|
||||
return PatchesConfig(config_path, project_root)
|
||||
def patch_from_dir(patch_dir):
|
||||
"""Read a directory of patches into a format suitable for passing to
|
||||
'git am'"""
|
||||
with open(os.path.join(patch_dir, ".patches")) as f:
|
||||
patch_list = [l.rstrip('\n') for l in f.readlines()]
|
||||
|
||||
def __init__(self, config_path, project_root):
|
||||
self.path = config_path
|
||||
self.patches_list = None
|
||||
self.project_root = project_root
|
||||
|
||||
def __parse(self):
|
||||
contents = None
|
||||
|
||||
if os.path.isfile(self.path):
|
||||
with open(self.path, 'r') as stream:
|
||||
try:
|
||||
contents = yaml.load(stream)
|
||||
except yaml.YAMLError as e:
|
||||
print(e)
|
||||
|
||||
return contents
|
||||
|
||||
def __create_patch(self, raw_data, base_directory, repo_path, paths_prefix):
|
||||
author = raw_data['author']
|
||||
if author is None: # Shouldn't actually happen.
|
||||
author = 'Anonymous <anonymous@electronjs.org>'
|
||||
|
||||
relative_file_path = raw_data['file']
|
||||
absolute_file_path = os.path.join(base_directory, relative_file_path)
|
||||
|
||||
# Use a patch file path as a commit summary
|
||||
# and optional description as a commit body.
|
||||
description = relative_file_path
|
||||
if raw_data['description'] is not None:
|
||||
description += '\n\n' + raw_data['description']
|
||||
|
||||
return Patch(absolute_file_path, repo_path, paths_prefix=paths_prefix,
|
||||
author=author, description=description)
|
||||
|
||||
def __create_patches_list(self):
|
||||
config_contents = self.__parse()
|
||||
if config_contents is None:
|
||||
return None
|
||||
|
||||
relative_repo_path = os.path.normpath(config_contents['repo'])
|
||||
absolute_repo_path = os.path.join(self.project_root, relative_repo_path)
|
||||
|
||||
# If the 'repo' path is not really a git repository,
|
||||
# then use that path as a prefix for patched files.
|
||||
paths_prefix = None
|
||||
if not git.is_repo_root(absolute_repo_path):
|
||||
assert(git.is_repo_root(self.project_root))
|
||||
absolute_repo_path = self.project_root
|
||||
paths_prefix = relative_repo_path
|
||||
|
||||
patches_data = config_contents['patches']
|
||||
base_directory = os.path.abspath(os.path.dirname(self.path))
|
||||
|
||||
patches = [self.__create_patch(data, base_directory, absolute_repo_path,
|
||||
paths_prefix) for data in patches_data]
|
||||
patches_list = PatchesList(repo_path=absolute_repo_path, patches=patches)
|
||||
return patches_list
|
||||
|
||||
def get_patches_list(self):
|
||||
if self.patches_list is not None:
|
||||
return self.patches_list
|
||||
|
||||
patches_list = self.__create_patches_list()
|
||||
self.patches_list = patches_list
|
||||
|
||||
return patches_list
|
||||
return ''.join([
|
||||
read_patch(patch_dir, patch_filename)
|
||||
for patch_filename in patch_list
|
||||
])
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue