@ThreadSafe public interface

Scm

com.atlassian.stash.scm.Scm
Known Indirect Subclasses

Class Overview

Describes a pluggable extension point for implementing custom SCMs.

In order for an SCM to be usable by the system, it must implement:

It may also implement the following to enable additional system functionality: It may also implement the following to provide extra functionality for other plugin developers: Further details about each of these, and how to implement them correctly, is divided between method documentation and documentation on the interfaces being returned. SCM plugins are complicated to implement, so it is encouraged that developers read the documentation provided thoroughly to ensure they do not violate invariants that allow the system to use its SCMs correctly.

SCMs which support additional functionality, or have custom factory types, are encouraged to provide a sub- interface extending from this one exposing that functionality. For example:

     //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 {
         //See the documentation for PluginCommandBuilderFactory
     }

     //Overrides methods using covariant return types to return an enhanced CancelableCommands instead of
     //Command Commands
     public interface MyScmCommandFactory extends PluginCommandFactory {
         //See the documentation for PluginCommandFactory
     }

     //Overrides methods using covariant return types to return custom versions of the PluginCommandFactory,
     //PluginCommandBuilderFactory and PluginPullRequestCommandFactory interfaces
     public interface MyScm extends Scm {
         //Supports both free-form and type-safe builders
         @Nonnull
         @Override
         MyScmCommandBuilderFactory getCommandBuilderFactory();

         //Uses enhanced CancelableCommands
         @Nonnull
         @Override
         MyScmCommandFactory getCommandFactory();

         @Nonnull
         @Override
         MyScmPullRequestCommandFactory getPullRequestCommandFactory();
     }
 
Notice that the getCommandBuilderFactory() and getPullRequestCommandFactory() have had their annotations changed to @Nonnull, indicating that MyScm definitely supports both builders and pull requests. This allows other plugin developers to know the features supported by the custom SCM so they can leverage them fully.

SCM plugins are encouraged to define a separate component for their Scm implementations, but they are required to define an scm entry or the SCM will not be detected by the system. The following example illustrates both directives:

     <!-- Note: These should be in the SCM provider's atlassian-plugin.xml -->
     <component key="myScm" class="com.example.DefaultMyScm" public="true">
         <interface>com.example.MyScm</interface>
     </component>

     <scm key="scm" class="bean:myScm"/>
 
The public="true" allows other plugins to import the component. This approach allows other plugin developers to import the SCM directly and leverage its enhanced functionality with a component-import directive:
     <!-- Note: This should be in the SCM consumer's atlassian-plugin.xml -->
     <component-import key="myScm" interface="com.example.MyScm"/>
 

For SCMs which define a component for their Scm, it is strongly encouraged that they reference that component for their scm directive, as shown above. This ensures a single instance of the Scm is constructed for use by other plugins and by the system.

Note: Implementors are strongly encouraged to extend from AbstractScm. This interface will change, over time, and any class implementing it directly will be broken by such changes. Extending from the abstract class will help prevent such breakages.

Note: Implementations of this interface are required to be thread-safe. Implementations of related interfaces such as PluginCommandBuilderFactory, PluginCommandFactory and PluginPullRequestCommandFactory are not required to be thread-safe if distinct instances are returned for each call.

Warning: If a component directive is defined but the scm directive does not reference it and instead defines class="com.example.MyScm", two instances will be created. The one created with the component directive may be imported by plugins (assuming it is public; otherwise, it may never be used anywhere!) and the one created with the scm directive will be used by the system.

See Also

Summary

Public Methods
@Nullable PluginCommandBuilderFactory getCommandBuilderFactory()
Retrieves a PluginCommandBuilderFactory, used to create ScmCommandBuilder command builders for custom SCM commands.
@Nonnull PluginCommandFactory getCommandFactory()
Retrieves a PluginCommandFactory, used to create Command commands for performing standard SCM operations such as retrieving commits and viewing diffs.
@Nullable PluginCompareCommandFactory getCompareCommandFactory()
Retrieves a PluginCompareCommandFactory, used to create Command commands tailored for comparing refs.
@Nullable PluginHookHandlerFactory getHookHandlerFactory()
Retrieves a PluginHookHandlerFactory, used to create com.atlassian.stash.hook.HookHandler
@Nonnull String getId()
Retrieves a unique identifier for the SCM that is provided by the plugin.
@Nonnull String getName()
Retrieves a well-known name for the SCM that is provided by the plugin.
@Nullable PluginPullRequestCommandFactory getPullRequestCommandFactory()
Retrieves a PluginPullRequestCommandFactory, used to create Command commands tailored for use supporting pull requests.
@Nullable PluginRefCommandFactory getRefCommandFactory()
Retrieves a PluginRefCommandFactory, used to create Command commands tailored for creating branches and tags.
@Nonnull ScmStatus getStatus()
Retrieves the current status for the SCM.
boolean isEmpty(Repository repository)
Retrieves a flag indicating whether the specified Repository is empty, from the perspective of the SCM implementation.

Public Methods

@Nullable public PluginCommandBuilderFactory getCommandBuilderFactory ()

Retrieves a PluginCommandBuilderFactory, used to create ScmCommandBuilder command builders for custom SCM commands.

Implementation Note: This method is optional. SCMs which do not support a ScmCommandBuilder may return null.

Returns
  • a command builder factory, or null if the SCM does not support command builders
See Also

@Nonnull public PluginCommandFactory getCommandFactory ()

Retrieves a PluginCommandFactory, used to create Command commands for performing standard SCM operations such as retrieving commits and viewing diffs. The commands created by the returned factory are used to support normal system functionality; as a result, SCMs are required to provide an implementation.

Implementation Note: This method is required and may not return null.

Returns
  • a command factory, providing access to required SCM functionality

@Nullable public PluginCompareCommandFactory getCompareCommandFactory ()

Retrieves a PluginCompareCommandFactory, used to create Command commands tailored for comparing refs.

Implementation Note: This method is optional. SCMs which do not support comparing refs may return null.

Returns
  • a compare command factory, or null if the SCM does not support it
See Also

@Nullable public PluginHookHandlerFactory getHookHandlerFactory ()

Retrieves a PluginHookHandlerFactory, used to create com.atlassian.stash.hook.HookHandler

Returns
  • a hook handler factory, or null if the SCM does not support hooks
See Also

@Nonnull public String getId ()

Retrieves a unique identifier for the SCM that is provided by the plugin.

Identifiers should be unique to the SCM's type. Using the name of the SCM's binary is a good approach. For example, a plugin implementing support for git might return "git" as its identifier. This approach allows the system to detect when multiple plugins are installed which implement git support, potentially leading to unexpected behaviour from some repositories.

Implementation Note: This method is required and may not return null.

Returns
  • a unique identifier for the SCM, preferably based on its binary

@Nonnull public String getName ()

Retrieves a well-known name for the SCM that is provided by the plugin.

Most SCMs use binaries which do not match the well-known name of the SCM. For example, Subversion's binary is svn, and Mercurial's is hg. This method should return the SCM's well-known name, suitable for display in a user interface.

Implementation Note: This method is required and may not return null.

Returns
  • the SCM's well-known name

@Nullable public PluginPullRequestCommandFactory getPullRequestCommandFactory ()

Retrieves a PluginPullRequestCommandFactory, used to create Command commands tailored for use supporting pull requests. Repositories using an SCM which implements this method will have the ability to create, view and merge pull requests.

Implementation Note: This method is optional. SCMs which do not support pull requests may return null. Repositories using such SCMs will not be able to create pull requests.

Returns
  • a pull request command factory, or null if the SCM does not support pull requests
See Also

@Nullable public PluginRefCommandFactory getRefCommandFactory ()

Retrieves a PluginRefCommandFactory, used to create Command commands tailored for creating branches and tags.

Implementation Note: This method is optional. SCMs which do not support mutable refs may return null. Repositories using such SCMs will not be able create branches and tags.

See Also
  • ScmFeature#REFS

@Nonnull public ScmStatus getStatus ()

Retrieves the current status for the SCM.

Available SCMs are expected to be able to process requests. However, there may be situations in which an SCM is unavailable. For example, if the plugin relies on a binary, or common library, which is not installed on the host system, the SCM may be unavailable. When an SCM is unavailable, a message explaining the reason must be provided on the returned ScmStatus.

An SCM's status may be capable of changing over time. However, where possible, it is best for SCMs to determine their status up front. An ScmStatusChangedEvent should be raised if an SCM's status changes at runtime, but is not required. However, the system may not detect the change to the SCM's status if it does not raise an event.

Implementation Note: This method is required and may not return null.

Returns
  • the current status of the SCM
See Also

public boolean isEmpty (Repository repository)

Retrieves a flag indicating whether the specified Repository is empty, from the perspective of the SCM implementation. Potential criteria for determining whether a repository is empty include:

  • Whether it has branches
  • Whether it has tags
  • Whether it has commits
The contract for Scm.isEmpty(Repository) only mandates that a newly-created repository must be considered empty.

How to determine whether a repository is "empty" depends on the SCM, as most SCMs create housekeeping files in their repositories to allow them to manage state. As a result, the system cannot simply test for the absence of any files. Instead, it calls this method to allow the SCM to perform the test.

Implementation Note: This method is required.

Parameters
repository the repository to check
Returns
  • true if the repository is empty; otherwise, false