Interface PluginCommandBuilderFactory
SCM
, allows the ScmService
to provide an ScmCommandBuilder
that
can be used to build custom commands for advanced functionality. SCMs which do not support a command builder should
not implement this interface and should return null
from Scm.getCommandBuilderFactory()
.
SCMs implementing this interface are required to provide a free-form ScmCommandBuilder
. They are also
encouraged to provide a type-safe builder API on top of that, to simplify creating custom commands correctly
and safely. For plugins which provide a type-safe builder, it is encouraged for them to use a sub-interface which
extends this one. For example:
//A type-safe builder for MyScm's diff command
public interface DiffCommandBuilder extends CommandBuilderSupport<DiffCommandBuilder> {
//A fluent API for constructing a diff command, exposing builder-style methods for setting
//only parameters that are supported as valid arguments on the SCM's diff command
}
//Adds methods for retrieving type-safe builders, in addition to the normal free-form builder methods
public interface MyScmCommandBuilder extends ScmCommandBuilder<MyScmCommandBuilder> {
//A type-safe builder for performing diffs
DiffCommandBuilder diff();
//Other custom builders for other commands supported by the SCM
}
//Overrides the builder(Repository) method using a covariant return type to return a builder supporting both
//type-safe and free-form commands, instead of ScmCommandBuilder
public interface MyScmCommandBuilderFactory extends PluginCommandBuilderFactory {
@Nonnull
@Override
MyScmCommandBuilder builder(@Nullable Repository repository);
}
Notice that the type-safe builder extends from CommandBuilderSupport
, not CommandBuilder
. It
is encouraged that plugins which expose a type-safe builder API do not mix their type-safe API with their free-form
API, as doing so effectively defeats the purpose of providing a type-safe API and will make it more difficult for the
implementor to pass correct arguments. When a consumer is using the MyScmCommandBuilder
, they may choose to
construct a diff command entirely using free-form arguments, or they may create a DiffCommandBuilder
and
leverage its API to produce one with known-correct arguments.
The SCM plugin would then expose the class implementing their custom MyScmCommandBuilderFactory
using a
component
directive:
<!-- Note: This should be in the SCM provider's atlassian-plugin.xml -->
<component key="myScmCommandBuilderFactory"
class="com.example.DefaultMyScmCommandBuilderFactory"
public="true">
<interface>com.example.MyScmCommandBuilderFactory</interface>
</component>
The public="true"
allows other plugins to import the component. This approach allows other plugin developers
to import the SCM plugin's type-safe builder API with a component-import
directive:
<!-- Note: This should be in the SCM consumer's atlassian-plugin.xml -->
<component-import key="myScmCommandBuilderFactory"
interface="com.example.MyScmCommandBuilderFactory"/>
Note: The system never uses the ScmCommandBuilder
to perform SCM operations. SCM plugins are encouraged to
provide a command builder to allow other plugins to leverage SCM features not exposed by ScmCommandFactory
and ScmPullRequestCommandFactory
-
Method Summary
Modifier and TypeMethodDescriptioncom.atlassian.bitbucket.scm.ScmCommandBuilder<?>
builder
(com.atlassian.bitbucket.repository.Repository repository) Creates aScmCommandBuilder
which can be used to construct free-form commands to interact directly with the underlying SCM implementation and perform custom functions on repositories.
-
Method Details
-
builder
@Nonnull com.atlassian.bitbucket.scm.ScmCommandBuilder<?> builder(@Nonnull com.atlassian.bitbucket.repository.Repository repository) Creates aScmCommandBuilder
which can be used to construct free-form commands to interact directly with the underlying SCM implementation and perform custom functions on repositories.Command builders are provided as a very powerful extension point for plugin developers, allowing them to create new functionality that uses commands the application does not, or uses them in different ways. However, plugin developers should be aware that:
- The system may support multiple versions of an SCM, and those versions may support different commands and/or arguments, and even the "same" command may produce different output between versions
- In a free-form builder, the command and arguments are not checked until the command is run; the system does not, and cannot, validate that the arguments are correct in advance
- Above all, the system cannot verify the safety of commands being executed; plugin developers must apply due diligence to ensure the operations they perform do not damage the repository
If a
Repository
is provided, the createdScmCommandBuilder
will use the repository's directory as its initial working directory. However, for commands that create repositories, such asgit init
, the provided repository may benull
. In such cases, the builder will use the default working directory. Note that, after the builder has been created, it is possible to change the working directory on the instance, before commands are constructed.At a minimum, all
ScmCommandBuilderFactory
implementations are required to provide a free-form builder. They are encouraged to provide a type-safe builder as well, by using a covariant return on their implementation of this method to return a derived builder supporting both free-form and type-safe techniques. How to do this is described in the class-level documentation.Note: Per the contract of the
ScmCommandBuilder
API, the returned builder is not thread-safe. If multiple threads require use of a builder, each thread should always create its own builder.- Parameters:
repository
- the repository whose directory should be the initial working directory, ornull
, if no repository exists, to use the default working directory- Returns:
- a new command builder
-