Interface PluginCommandBuilderFactory


public interface PluginCommandBuilderFactory
When implemented by an 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 Type
    Method
    Description
    com.atlassian.bitbucket.scm.ScmCommandBuilder<?>
    builder(com.atlassian.bitbucket.repository.Repository repository)
    Creates a ScmCommandBuilder 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 a ScmCommandBuilder 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 created ScmCommandBuilder will use the repository's directory as its initial working directory. However, for commands that create repositories, such as git init, the provided repository may be null. 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, or null, if no repository exists, to use the default working directory
      Returns:
      a new command builder