rbtools.diffs.patcher¶
Support for applying patches to a local source tree.
New in version 5.1.
Classes
Parsed output from a patch command. |
|
|
Applies patches and optionally commits to source trees. |
Keyword arguments available when instantiating a Patcher. |
- class rbtools.diffs.patcher.ParsedPatchOutput[source]¶
Bases:
TypedDict
Parsed output from a patch command.
This is designed to collect information from parsing an unstructured patch output stream. The default
Patcher
supports pulling information from GNU Patch and Apple Patch commands, though this data can be returned from any patch tool.New in version 5.1.
- patched_files: list[str]¶
A list of filenames for files patched or attempted to be patched.
This may include files that had conflicts and coud not be fully patched.
- __closed__ = False¶
- __extra_items__ = None¶
- __mutable_keys__ = frozenset({'conflicting_files', 'fatal_error', 'has_empty_files', 'has_partial_applied_files', 'patched_files'})¶
- __optional_keys__ = frozenset({})¶
- __orig_bases__ = (<function TypedDict>,)¶
- __readonly_keys__ = frozenset({})¶
- __required_keys__ = frozenset({'conflicting_files', 'fatal_error', 'has_empty_files', 'has_partial_applied_files', 'patched_files'})¶
- __total__ = True¶
- class rbtools.diffs.patcher.PatcherKwargs[source]¶
Bases:
TypedDict
Keyword arguments available when instantiating a Patcher.
New in version 5.1.
- dest_path: NotRequired[Optional[Path]]¶
The local path where patches will be applied.
If not provided, this will patch in the current directory by default.
- repository_info: NotRequired[Optional[RepositoryInfo]]¶
Information on the current source code repository.
- __closed__ = False¶
- __extra_items__ = None¶
- __mutable_keys__ = frozenset({'dest_path', 'patches', 'repository_info', 'revert', 'squash'})¶
- __optional_keys__ = frozenset({})¶
- __orig_bases__ = (<function TypedDict>,)¶
- __readonly_keys__ = frozenset({})¶
- __required_keys__ = frozenset({'dest_path', 'patches', 'repository_info', 'revert', 'squash'})¶
- __total__ = True¶
- class rbtools.diffs.patcher.Patcher(*, patches: Sequence[Patch], dest_path: Optional[Path] = None, repository_info: Optional[RepositoryInfo] = None, revert: bool = False, squash: bool = False)[source]¶
Bases:
object
Applies patches and optionally commits to source trees.
This takes a list of patches and criteria for applying those patches and attempts to apply them to the source tree. After construction, consumers can call
patch()
to apply the patches.By default, this will apply the patches one-by-one using the patch command. Subclasses may override the patching behavior to use native SCM patching capabilities, or to apply multiple patches in one go.
Depending on the implementation, this will also allow callers to commit those patches to the repository. They must first check for
can_commit
and then callprepare_for_commit()
prior to beginning thepatch()
operation.New in version 5.1.
- can_commit: bool = False¶
Whether this patcher is capable of committing to a repository.
This can be enabled by SCM-specific patchers to enable committing after applying patches.
- can_patch_empty_files: bool = False¶
Whether empty files can be patched.
By default, empty files cannot be patched. Subclasses must set this to
True
if they are capable of applying empty patches.
- __init__(*, patches: Sequence[Patch], dest_path: Optional[Path] = None, repository_info: Optional[RepositoryInfo] = None, revert: bool = False, squash: bool = False) None [source]¶
Initialize the patcher.
- Parameters:
patches (
list
ofrbtools.diffs.patches.Patch
) – The list of patches to apply (or revert), in order.dest_path (
pathlib.Path
, optional) –The local path where patches will be applied.
If not provided, this will patch in the current directory by default.
repository (
rbtools.clients.base.repository.RepositoryInfo
) –Information on the current source code repository.
This may be needed in order to apply patches correctly to some kinds of repositories.
revert (
bool
, optional) – Whether to revert the patches.squash (
bool
, optional) – Whether to squash the patches together into one patch.
- dest_path: Path¶
The local path where patches will be applied.
- repository_info: Optional[RepositoryInfo]¶
Information on the current source code repository.
This may be needed in order to apply patches correctly to some kinds of repositories.
- applied_patch_results: list[PatchResult]¶
The list of any results from applied patches.
- prepare_for_commit(*, default_author: Optional[PatchAuthor] = None, default_message: Optional[str] = None, review_request: Optional[ReviewRequestResource] = None, run_commit_editor: bool = False) None [source]¶
Prepare the patching process to commit applied changes.
Once called, the patcher will be responsible for taking any applied changes and turning it into one or more commits.
This only works if
can_commit
isTrue
.The caller is responsible for providing either a default author and commit message, or a review request containing defaults to use. These will be used if the patch doesn’t contain that information already.
- Parameters:
default_author (
rbtools.diffs.patches.PatchAuthor
, optional) – The default author to use for commits.default_message (
str
, optional) – The default message to use for commits.review_request (
rbtools.api.resource.ReviewRequestResource
, optional) – The review request to use for a default author and message.run_commit_editor (
bool
, optional) – Whether to run the user’s editor to edit a commit message before making the commit.
- patch() Iterator[PatchResult] [source]¶
Applies the patches to the tree.
This is the primary method used to apply the patches. It will handle applying the patches, returning results, and raising exceptions on errors.
This method may only be called once.
- Yields:
rbtools.diffs.patches.PatchResult
– The result of each patch application, whether the patch applied successfully or with normal patch failures.- Raises:
rbtools.diffs.errors.ApplyPatchResult – There was an error attempting to apply a patch. This won’t be raised simply for conflicts or normal patch failures. It may be raised for errors encountered during the patching process.
- apply_patches() Iterator[PatchResult] [source]¶
Internal function to apply the patches.
This will handle applying all patches provided to the patcher.
Subclasses should override this if providing batch-patching logic. They would also be responsible for handling commits, if requested by the caller and supported by the subclass.
This must only be called internally by the patcher.
- Yields:
rbtools.diffs.patches.PatchResult
– The result of each patch application, whether the patch applied successfully or with normal patch failures.- Raises:
rbtools.diffs.errors.ApplyPatchResult – There was an error attempting to apply a patch. This won’t be raised simply for conflicts or normal patch failures. It may be raised for errors encountered during the patching process.
- apply_single_patch(*, patch: Patch, patch_num: int) PatchResult [source]¶
Internal function to apply a single patch.
This will take a single patch and apply it. It may be applied to files that already contain other modifications or have had other patches applied to it.
Subclasses that can apply patches one-by-one may override this to apply patches using SCM-specific methods.
This must only be called internally by the patcher.
- Parameters:
patch (
rbtools.diffs.patches.Patch
) – The patch to apply, opened for reading.patch_num (
int
) – The 1-based index of this patch in the full list of patches.
- Returns:
The result of the patch application, whether the patch applied successfully or with normal patch failures.
- Return type:
- Raises:
rbtools.diffs.errors.ApplyPatchResult – There was an error attempting to apply the patch. This won’t be raised simply for conflicts or normal patch failures. It may be raised for errors encountered during the patching process.
- get_default_prefix_level(*, patch: Patch) Optional[int] [source]¶
Return the default path prefix strip level for a patch.
This function determines how much of a path to strip by default, if an explicit value isn’t given.
Subclasses can override this to provide a different default.
- Parameters:
patch (
rbtools.diffs.patches.Patch
) – The path to generate a default prefix strip level for.- Returns:
The prefix strip level, or
None
if a clear one could not be determined.- Return type:
- parse_patch_output(patch_output: bytes) ParsedPatchOutput [source]¶
Parse the patch command’s output for useful information.
This will parse the standard output from a supported patch command to return information that can be used to identify patched files, partially-applied files, conflicting files, and error messages.
It’s only used if the patcher uses the default patch application logic or if it’s called explicitly.
- Parameters:
patch_output (
bytes
) – The patch output to parse.- Returns:
The parsed data found from the patch output.
- Return type:
- create_commit(*, patch_result: PatchResult, run_commit_editor: bool) None [source]¶
Internal method to create a commit based on a patch result.
Subclasses must implement this and set
can_commit
if it supports creating commits based on changes in the working tree.This must only be called internally by the patcher.
- Parameters:
patch_result (
rbtools.diffs.patches.PatchResult
) – The patch result containing the patch/patches to commit.run_commit_editor (
bool
) – Whether to run the configured commit editor to alter the commit message.
- Raises:
rbtools.diffs.errors.ApplyPatchResult – There was an error attempting to commit the patch.
- apply_patch_for_empty_files(patch: Patch) bool [source]¶
Apply an empty file patch to a file.
Normally, a patching tool can’t apply an empty patch to a file (which may be done to create a file, delete a file, or change metadata for a file). Subclasses can override this and enable
can_patch_empty_files
to opt into special logic for applying empty-file patches.The logic for applying the patch is entirely up to the subclass, and is not required for a patcher.
- Parameters:
patch (
rbtools.diffs.patches.Patch
) – The opened patch to check and possibly apply.- Returns:
True
if there are empty files in the patch that were applied.False
if there were no empty files or the files could not be applied (which will lead to an error).- Return type:
- Raises:
rbtools.diffs.errors.ApplyPatchError – There was an error while applying the patch.