rbtools.clients.base.scmclient¶
Base class for interfacing with source code management tools.
New in version 4.0.
Classes
|
A base class for interfacing with a source code management tool. |
A commit in a commit history. |
|
A commit message from a local repository. |
|
The result of a diff operation. |
|
A revision specification parsed from command line arguments. |
- class rbtools.clients.base.scmclient.SCMClientRevisionSpec[source]¶
Bases:
TypedDict
A revision specification parsed from command line arguments.
This class helps provide type hinting to results from
BaseSCMClient.parse_revision_spec()
.The dictionary may include other arbitrary keys.
New in version 4.0.
- base: Optional[object]¶
A revision to use as the base of the resulting diff.
The value is considered an opaque value, dependent on the SCMClient.
This is required.
- Type:
- tip: Optional[object]¶
A revision to use as the tip of the resulting diff.
The value is considered an opaque value, dependent on the SCMClient.
This is required.
- Type:
- parent_base: Optional[object]¶
The revision to use as the base of a parent diff.
The value is considered an opaque value, dependent on the SCMClient.
This is optional.
- Type:
- commit_id: Optional[str]¶
The commit ID of the single commit being posted, if not using a range.
This is optional.
- Type:
- extra: Optional[Mapping[str, Any]]¶
Any extra revision state not used above.
If a SCMClient needs to provide information in addition or instead of the above, they should populate this field, rather than placing the information in the main revision dictionary. This helps ensure a stable, typed interface for all revision data.
New in version 4.0.
- __optional_keys__ = frozenset({})¶
- __orig_bases__ = (<function TypedDict>,)¶
- __required_keys__ = frozenset({'base', 'commit_id', 'extra', 'parent_base', 'tip'})¶
- __total__ = True¶
- class rbtools.clients.base.scmclient.SCMClientDiffResult[source]¶
Bases:
TypedDict
The result of a diff operation.
This class helps provide type hinting to results from
BaseSCMClient.diff()
.New in version 4.0.
- diff: Optional[bytes]¶
The contents of the diff to upload.
This should be
None
or an empty string if diff generation fails.- Type:
- base_commit_id: Optional[str]¶
The ID of the commit that the change is based on, if available.
This is necessary for some hosting services that don’t provide individual file access.
- Type:
- review_request_extra_data: Optional[Dict[str, Any]]¶
This may contain structured data. It will be sent to the server as part of a JSON Merge Patch.
This requires Review Board 3.0 or higher.
New in version 3.1.
- __optional_keys__ = frozenset({})¶
- __orig_bases__ = (<function TypedDict>,)¶
- __required_keys__ = frozenset({'base_commit_id', 'changenum', 'commit_id', 'diff', 'parent_diff', 'review_request_extra_data'})¶
- __total__ = True¶
- class rbtools.clients.base.scmclient.SCMClientCommitHistoryItem[source]¶
Bases:
TypedDict
A commit in a commit history.
This class helps provide type hinting to results from
BaseSCMClient.get_commit_history()
.New in version 4.0.
- committer_email: Optional[str]¶
The e-mail address of the person or entity who committed the change.
- Type:
- __optional_keys__ = frozenset({})¶
- __orig_bases__ = (<function TypedDict>,)¶
- __required_keys__ = frozenset({'author_date', 'author_email', 'author_name', 'commit_id', 'commit_message', 'committer_date', 'committer_email', 'committer_name', 'parent_id'})¶
- __total__ = True¶
- class rbtools.clients.base.scmclient.SCMClientCommitMessage[source]¶
Bases:
TypedDict
A commit message from a local repository.
This class helps provide type hinting to results from
BaseSCMClient.get_commit_message()
.New in version 4.0.
- summary: Optional[str]¶
The summary of a commit message.
This should generally match the first line of a commit.
- Type:
- description: Optional[str]¶
The description of a commit message.
This should generally match the remainder of the commit message after the summary, if any content remains.
- Type:
- __optional_keys__ = frozenset({})¶
- __orig_bases__ = (<function TypedDict>,)¶
- __required_keys__ = frozenset({'description', 'summary'})¶
- __total__ = True¶
- class rbtools.clients.base.scmclient.BaseSCMClient(config: Optional[Dict[str, Any]] = None, options: Optional[Namespace] = None)[source]¶
Bases:
object
A base class for interfacing with a source code management tool.
These are used for fetching repository information and generating diffs.
Callers must run
setup()
orhas_dependencies()
before calling methods on this tool.Changed in version 4.0:
Moved from
rbtools.clients
intorbtools.clients.base.scmclient
and renamed fromSCMClient
toBaseSCMClient
.A call to
setup()
orhas_dependencies()
will be required starting in RBTools 5.0.
- scmclient_id: str = ''¶
The unique ID of the client.
New in version 4.0: This will be required in RBTools 5.0.
- Type:
- server_tool_names: Optional[str] = None¶
A comma-separated list of SCMClient names on the server
New in version 3.0.
- Type:
- requires_diff_tool: Union[bool, List[str]] = False¶
Whether this tool requires a command line diff tool.
This may be a boolean or a list.
If a boolean, then this must be
False
if no command line tool is required, orTrue
if any command line tool supported by RBTools is available (in which case the SCMClient is responsible for ensuring compatibility).If a list, then this must be a list of registered diff tool IDs that are compatible.
New in version 4.0.
- supports_changesets: bool = False¶
Whether the SCM uses server-side changesets
New in version 3.0.
- Type:
- supports_diff_extra_args: bool = False¶
Whether the SCM client’s diff method takes the
extra_args
parameter.- Type:
- supports_diff_exclude_patterns: bool = False¶
Whether the SCM client supports excluding files from the diff.
- Type:
- supports_no_renames: bool = False¶
Whether the SCM client can generate diffs without renamed files.
- Type:
- supports_parent_diffs: bool = False¶
Whether the SCM client supports generating parent diffs.
New in version 3.0.
- Type:
- can_get_file_content: bool = False¶
Whether the tool can get files at specific revisions.
New in version 5.0.
- Type:
- __init__(config: Optional[Dict[str, Any]] = None, options: Optional[Namespace] = None) None [source]¶
Initialize the client.
- Parameters:
config (
dict
, optional) – The loaded user config.options (
argparse.Namespace
, optional) – The parsed command line arguments.
- config: RBToolsConfig¶
User configuration.
Any user configuration loaded via
.reviewboardrc
files. This may be empty.
- options: Optional[argparse.Namespace]¶
Command line arguments passed to this client.
This may be empty, and makes assumptions about which command line arguments are registered with a command. It’s intended for use within RBTools.
This may be
None
.- Type:
- capabilities: Optional[Capabilities]¶
Capabilities returned by the server.
This will be
None
if not set by the server.
- is_setup: bool¶
Whether the client is set up and ready for operations.
Operations may fail or crash if this is
False
.Callers must call
setup()
orhas_dependencies()
before performing operations using this client.New in version 4.0.
- Type:
- setup() None [source]¶
Set up the client.
This will perform checks to ensure the client can be used. Callers should make sure to either call this method or
has_dependencies()
before performing any other operations on this client.If checks succeed,
is_setup
will beTrue
, and operations using this client can be performed.If checks fail, an exception may be raised, and
is_setup
will beFalse
.Note that this will not check
requires_diff_tool
, as that is only required for certain operations. Checking for a compatible diff tool is the responsibility of the caller whenever working with diffs.New in version 4.0.
- Raises:
rbtools.clients.errors.SCMClientDependencyError – One or more required dependencies are missing.
- has_dependencies(expect_checked: bool = False) bool [source]¶
Return whether all dependencies for the client are available.
Either this or
setup()
must be called before any operations are performed with this client.New in version 4.0.
- Parameters:
expect_checked (
bool
, optional) –Whether the caller expects that dependency checking has already been done.
If
True
, and dependencies have not yet been checked viacheck_dependencies()
, this will raise a deprecation warning.Starting in RBTools 4.0, this will raise an exception if
check_dependencies()
hasn’t yet been called.- Returns:
True
if dependencies are all available.False
if one or more are not.- Return type:
- check_dependencies() None [source]¶
Check whether the base dependencies needed are available.
This is responsible for checking for any command line tools or Python modules required to consider this client as an option when scanning repositories or selecting a specific client.
This should not check for diff implementations or anything specific about a local filesystem. It’s merely a first-pass dependency check.
This function is normally called via
setup()
(which will re-raise any exceptions here) orhas_dependencies()
. It doesn’t need to be called manually unless attempting to re-generate the exception.Subclasses can log any failed checks in the debug log, to help with debugging missing tools. If checking against multiple possible names, they may also record information needed to locate the matching executable for future operations.
It’s recommended to use
rbtools.utils.checks.check_install()
to help with executable dependency checks.New in version 4.0.
- Raises:
rbtools.clients.errors.SCMClientDependencyError – One or more required dependencies are missing.
- is_remote_only() bool [source]¶
Return whether this repository is operating in remote-only mode.
For some SCMs and some operations, it may be possible to operate exclusively with a remote server and have no working directory.
New in version 3.0.
- Returns:
Whether this repository is operating in remote-only mode.
- Return type:
- get_local_path() Optional[str] [source]¶
Return the local path to the working tree.
This is expected to be overridden by subclasses.
New in version 3.0.
- Returns:
The filesystem path of the repository on the client system.
- Return type:
- get_repository_info() Optional[RepositoryInfo] [source]¶
Return repository information for the current working tree.
This is expected to be overridden by subclasses.
New in version 3.0.
- Returns:
The repository info structure.
- Return type:
- get_diff_tool() Optional[BaseDiffTool] [source]¶
Return a diff tool for use with this client.
This can be used by subclasses, and by callers that want to check if a compatible diff tool is available before calling
diff()
.The value is cached for the client.
New in version 4.0.
- Returns:
The diff instance, if a compatible instance is found.
This will be
None
ifrequires_diff_tool
isFalse
.- Return type:
rbtools.diffs.tools.base.BaseDiffTool
- Raises:
TypeError –
requires_diff_tool
was an unsupported type.rbtools.diffs.tools.errors.MissingDiffToolError – No compatible diff tool could be found.
- find_matching_server_repository(repositories: ListResource) Tuple[Optional[ItemResource], Optional[ItemResource]] [source]¶
Find a match for the repository on the server.
New in version 3.0.
- Parameters:
repositories (
rbtools.api.resource.ListResource
) – The fetched repositories.- Returns:
A 2-tuple of matching repository information:
- Tuple:
0 (
rbtools.api.resource.ItemResource
) – The matching repository resource, if found.If not found, this will be
None
.1 (
rbtools.api.resource.ItemResource
) – The matching repository information resource, if found.If not found, this will be
None
.
- Return type:
- get_repository_name() Optional[str] [source]¶
Return any repository name configured in the repository.
This is used as a fallback from the standard config options, for repository types that support configuring the name in repository metadata.
New in version 3.0.
- Returns:
The configured repository name, or None.
- Return type:
- check_options() None [source]¶
Verify the command line options.
This is expected to be overridden by subclasses, if they need to do specific validation of the command line.
- Raises:
rbtools.clients.errors.OptionsCheckError – The supplied command line options were incorrect. In particular, if a file has history scheduled with the commit, the user needs to explicitly choose what behavior they want.
- get_changenum(revisions: SCMClientRevisionSpec) Optional[str] [source]¶
Return the change number for the given revisions.
This is only used when the client is supposed to send a change number to the server (such as with Perforce).
- Parameters:
revisions (
dict
) – A revisions dictionary as returned byparse_revision_spec()
.- Returns:
The change number to send to the Review Board server.
- Return type:
- scan_for_server(repository_info: RepositoryInfo) Optional[str] [source]¶
Find the server path.
This will search for the server name in the .reviewboardrc config files. These are loaded with the current directory first, and searching through each parent directory, and finally $HOME/.reviewboardrc last.
- Parameters:
repository_info (
rbtools.clients.base.repository.RepositoryInfo
) – The repository information structure.- Returns:
The Review Board server URL, if available.
- Return type:
- parse_revision_spec(revisions: List[str] = []) SCMClientRevisionSpec [source]¶
Parse the given revision spec.
The ‘revisions’ argument is a list of revisions as specified by the user. Items in the list do not necessarily represent a single revision, since the user can use SCM-native syntaxes such as “r1..r2” or “r1:r2”. SCMTool-specific overrides of this method are expected to deal with such syntaxes.
- Parameters:
revisions (
list
ofstr
, optional) – A list of revisions as specified by the user. Items in the list do not necessarily represent a single revision, since the user can use SCM-native syntaxes such asr1..r2
orr1:r2
. SCMTool-specific overrides of this method are expected to deal with such syntaxes.- Returns:
A dictionary containing keys found in
SCMClientRevisionSpec
.Additional keys may be included by subclasses for their own internal use.
These will be used to generate the diffs to upload to Review Board (or print). The diff for review will include the changes in (base, tip], and the parent diff (if necessary) will include (parent, base].
If a single revision is passed in, this will return the parent of that revision for “base” and the passed-in revision for “tip”.
If zero revisions are passed in, this will return revisions relevant for the “current change”. The exact definition of what “current” means is specific to each SCMTool backend, and documented in the implementation classes.
- Return type:
- Raises:
rbtools.clients.errors.InvalidRevisionSpecError – The given revisions could not be parsed.
rbtools.clients.errors.TooManyRevisionsError – The specified revisions list contained too many revisions.
- get_tree_matches_review_request(review_request: ReviewRequestResource, *, revisions: SCMClientRevisionSpec, **kwargs) Optional[bool] [source]¶
Return whether a review request matches revisions or tree state.
This works along with review request matching in tools like rbt post to match state in a review request (such as in
extra_data
) with the state in the local tree (such as the local branch or SCM-specific identifiers other than a commit ID).Subclasses can override this to implement their own matching logic. By default, no additional logic is implemented.
New in version 3.1.
- Parameters:
review_request (
rbtools.api.resource.ReviewRequestResource
) – The review request being matched.revisions (
dict
) – A dictionary of revisions, as returned byparse_revision_spec()
.**kwargs (
dict
, unused) – Additional keyword arguments, for future expansion.
- Returns:
True
if the review request is considered an exact match.False
if the review request should be explicitly discarded as a possible match.None
if a match could not be determined based on available information.- Return type:
- diff(revisions: SCMClientRevisionSpec, *, include_files: List[str] = [], exclude_patterns: List[str] = [], no_renames: bool = False, repository_info: Optional[RepositoryInfo] = None, extra_args: List[str] = [], with_parent_diff: bool = True) SCMClientDiffResult [source]¶
Perform a diff using the given revisions.
Callers should make sure that the appropriate diff tool is installed by calling
rbtools.diffs.tools.registry.get_diff_tool()
and passingrequires_diff_tool
if it’s a list.This is expected to be overridden by subclasses, which should:
Set
requires_diff_tool
based on the client’s needs.Optionally use
options
for any client-specific diff functionality.Call
get_diff_tool()
early, if needed.
Subclasses that need to support special arguments should use
options
.Changed in version 4.0:
All arguments except
revisions
must be specified as keyword arguments.Subclasses should now use
requires_diff_tool
andget_diff_tool()
instead of manually invoking diff tools.
- Parameters:
revisions (
dict
) – A dictionary of revisions, as returned byparse_revision_spec()
.include_files (
list
ofstr
, optional) – A list of files to whitelist during the diff generation.exclude_patterns (
list
ofstr
, optional) – A list of shell-style glob patterns to blacklist during diff generation.no_renames (
bool
, optional) – Whether to avoid rename detection.repository_info (
rbtools.clients.base.repository.RepositoryInfo
, optional) – The repository info structure.extra_args (
list
, unused) – Additional arguments to be passed to the diff generation.with_parent_diff (
bool
, optional) – Whether or not to compute a parent diff.
- Returns:
A dictionary containing keys documented in
SCMClientDiffResult
.- Return type:
- get_commit_history(revisions: SCMClientRevisionSpec) Optional[List[SCMClientCommitHistoryItem]] [source]¶
Return the commit history between the given revisions.
Derived classes must override this method if they support posting with history.
- has_pending_changes() bool [source]¶
Return whether there are changes waiting to be committed.
Derived classes should override this method if they wish to support checking for pending changes.
- Returns:
True
if the working directory has been modified or if changes have been staged in the index.- Return type:
- apply_patch(patch_file: str, *, base_path: str, base_dir: str, p: Optional[str] = None, revert: bool = False) PatchResult [source]¶
Apply the patch and return a PatchResult indicating its success.
- Parameters:
patch_file (
str
) – The name of the patch file to apply.base_path (
str
) – The base path that the diff was generated in.base_dir (
str
) – The path of the current working directory relative to the root of the repository.p (
str
, optional) – The prefix level of the diff.revert (
bool
, optional) – Whether the patch should be reverted rather than applied.
- Returns:
The result of the patch operation.
- Return type:
- create_commit(*, message: str, author: PatchAuthor, run_editor: bool, files: List[str] = [], all_files: bool = False) None [source]¶
Create a commit based on the provided message and author.
Derived classes should override this method if they wish to support committing changes to their repositories.
- Parameters:
message (
str
) – The commit message to use.author (
rbtools.clients.base.patch.PatchAuthor
) – The author of the commit.run_editor (
bool
) – Whether to run the user’s editor on the commit message before committing.files (
list
ofstr
, optional) – The list of filenames to commit.all_files (
bool
, optional) – Whether to commit all changed files, ignoring thefiles
argument.
- Raises:
NotImplementedError – The client does not support creating commits.
rbtools.clients.errors.CreateCommitError – The commit message could not be created. It may have been aborted by the user.
- get_commit_message(revisions: SCMClientRevisionSpec) Optional[SCMClientCommitMessage] [source]¶
Return the commit message from the commits in the given revisions.
This pulls out the first line from the commit messages of the given revisions. That is then used as the summary.
- Parameters:
revisions (
dict
) – A dictionary as returned byparse_revision_spec()
.- Returns:
A dictionary containing keys found in
SCMClientCommitMessage
.This may be
None
, if no commit message is found.- Return type:
- delete_branch(branch_name: str, *, merged_only: bool = True) None [source]¶
Delete the specified branch.
- Parameters:
- Raises:
rbtools.clients.errors.SCMError – An error occurred while deleting the branch.
- merge(*, target: str, destination: str, message: str, author: PatchAuthor, squash: bool = False, run_editor: bool = False, close_branch: bool = True) None [source]¶
Merge the target branch with destination branch.
- Parameters:
target (
str
) – The name of the branch to merge.destination (
str
) – The name of the branch to merge into.message (
str
) – The commit message to use.author (
rbtools.clients.base.patch.PatchAuthor
) – The author of the commit.squash (
bool
, optional) – Whether to squash the commits or do a plain merge.run_editor (
bool
, optional) – Whether to run the user’s editor on the commit message before committing.close_branch (
bool
, optional) – Whether to close/delete the merged branch.
- Raises:
rbtools.clients.errors.MergeError – An error occurred while merging the branch.
- push_upstream(remote_branch: str) None [source]¶
Push the current branch to upstream.
- Parameters:
remote_branch (
str
) – The name of the branch to push to.- Raises:
rbtools.client.errors.PushError – The branch was unable to be pushed.
- get_raw_commit_message(revisions: SCMClientRevisionSpec) str [source]¶
Extract the commit messages on the commits in the given revisions.
Derived classes should override this method in order to allow callers to fetch commit messages. This is needed for description guessing.
If a derived class is unable to fetch the description,
None
should be returned.Callers that need to differentiate the summary from the description should instead use get_commit_message().
- get_current_branch() str [source]¶
Return the repository branch name of the current directory.
Derived classes should override this method if they are able to determine the current branch of the working directory.
- Returns:
A string with the name of the current branch. If the branch is unable to be determined, returns
None
.- Return type:
- supports_empty_files() bool [source]¶
Return whether the server supports added/deleted empty files.
- Returns:
True
if the Review Board server supports added or deleted empty files.- Return type:
- apply_patch_for_empty_files(patch: bytes, *, p_num: str, revert: bool = False) bool [source]¶
Return whether any empty files in the patch are applied.
- Parameters:
- Returns:
True
if there are empty files in the patch.False
if there were no empty files, or if an error occurred while applying the patch.- Return type:
- amend_commit_description(message: str, *, revisions: Optional[SCMClientRevisionSpec] = None) None [source]¶
Update a commit message to the given string.
- Parameters:
message (
str
) – The commit message to use when amending the commit.revisions (
dict
, optional) – A dictionary of revisions, as returned byparse_revision_spec()
. This provides compatibility with SCMs that allow modifications of multiple changesets at any given time, and will amend the change referenced by thetip
key.
- Raises:
rbtools.clients.errors.AmendError – The amend operation failed.
- get_file_content(*, filename: str, revision: str) bytes [source]¶
Return the contents of a file at a given revision.
This may be implemented by subclasses in order to support uploading binary files to diffs.
New in version 5.0.