Class SCM
- java.lang.Object
-
- hudson.scm.SCM
-
- All Implemented Interfaces:
ExtensionPoint
,Describable<SCM>
- Direct Known Subclasses:
NullSCM
@ExportedBean public abstract class SCM extends Object implements Describable<SCM>, ExtensionPoint
Captures the configuration information in it.To register a custom
SCM
implementation from a plugin, putExtension
on yourSCMDescriptor
.Use the "project-changes" view to render change list to be displayed at the project level. The default implementation simply aggregates change lists from builds, but your SCM can provide different views. The view gets the "builds" variable which is a list of builds that are selected for the display.
If you are interested in writing a subclass in a plugin, also take a look at "Writing an SCM plugin" wiki article.
- Author:
- Kohsuke Kawaguchi
-
-
Nested Class Summary
-
Nested classes/interfaces inherited from interface hudson.ExtensionPoint
ExtensionPoint.LegacyInstancesAreScopedToHudson
-
-
Field Summary
Fields Modifier and Type Field Description static PermissionGroup
PERMISSIONS
static Permission
TAG
Permission to create new tags.
-
Constructor Summary
Constructors Constructor Description SCM()
-
Method Summary
All Methods Static Methods Instance Methods Abstract Methods Concrete Methods Deprecated Methods Modifier and Type Method Description SCMRevisionState
_calcRevisionsFromBuild(AbstractBuild<?,?> build, Launcher launcher, TaskListener listener)
Deprecated.static List<SCMDescriptor<?>>
_for(AbstractProject project)
Deprecated.static List<SCMDescriptor<?>>
_for(Job project)
Determines which kinds of SCMs are applicable to a given project.static DescriptorExtensionList<SCM,SCMDescriptor<?>>
all()
Returns all the registeredSCMDescriptor
s.void
buildEnvironment(Run<?,?> build, Map<String,String> env)
Adds environmental variables for the builds to the given map.void
buildEnvVars(AbstractBuild<?,?> build, Map<String,String> env)
Deprecated.in favor ofbuildEnvironment(Run, Map)
.SCMRevisionState
calcRevisionsFromBuild(AbstractBuild<?,?> build, Launcher launcher, TaskListener listener)
Deprecated.SCMRevisionState
calcRevisionsFromBuild(Run<?,?> build, FilePath workspace, Launcher launcher, TaskListener listener)
Calculates theSCMRevisionState
that represents the state of the workspace of the given build.boolean
checkout(AbstractBuild<?,?> build, Launcher launcher, FilePath workspace, BuildListener listener, File changelogFile)
Deprecated.void
checkout(Run<?,?> build, Launcher launcher, FilePath workspace, TaskListener listener, File changelogFile, SCMRevisionState baseline)
Obtains a fresh workspace of the module(s) into the specified directory of the specified machine.protected PollingResult
compareRemoteRevisionWith(AbstractProject<?,?> project, Launcher launcher, FilePath workspace, TaskListener listener, SCMRevisionState baseline)
Deprecated.PollingResult
compareRemoteRevisionWith(Job<?,?> project, Launcher launcher, FilePath workspace, TaskListener listener, SCMRevisionState baseline)
Compares the current state of the remote repository against the given baselineSCMRevisionState
.abstract ChangeLogParser
createChangeLogParser()
The returned object will be used to parsechangelog.xml
.protected boolean
createEmptyChangeLog(File changelogFile, BuildListener listener, String rootTag)
Deprecated.protected void
createEmptyChangeLog(File changelogFile, TaskListener listener, String rootTag)
Api
getApi()
ExposeSCM
to the remote API.RepositoryBrowser<?>
getBrowser()
Returns theRepositoryBrowser
for files controlled by thisSCM
.SCMDescriptor<?>
getDescriptor()
Gets the descriptor for this instance.RepositoryBrowser<?>
getEffectiveBrowser()
Returns the applicableRepositoryBrowser
for files controlled by thisSCM
.String
getKey()
Should create a key by which this SCM configuration might be distinguished from others in the same project.FilePath
getModuleRoot(FilePath workspace)
Deprecated.since 1.382 Use/overridegetModuleRoot(FilePath, AbstractBuild)
instead.FilePath
getModuleRoot(FilePath workspace, AbstractBuild build)
Gets the top directory of the checked out module.FilePath[]
getModuleRoots(FilePath workspace)
Deprecated.as of 1.382.FilePath[]
getModuleRoots(FilePath workspace, AbstractBuild build)
Gets the top directories of all the checked out modules.String
getType()
Type of this SCM.RepositoryBrowser<?>
guessBrowser()
Try to guess how a repository browser should be configured, based on URLs and the like.protected String
nullify(String s)
PollingResult
poll(AbstractProject<?,?> project, Launcher launcher, FilePath workspace, TaskListener listener, SCMRevisionState baseline)
Convenience method for the caller to handle the backward compatibility between pre 1.345 SCMs.boolean
pollChanges(AbstractProject<?,?> project, Launcher launcher, FilePath workspace, TaskListener listener)
Deprecated.as of 1.345 OverridecalcRevisionsFromBuild(AbstractBuild, Launcher, TaskListener)
andcompareRemoteRevisionWith(AbstractProject, Launcher, FilePath, TaskListener, SCMRevisionState)
for implementation.void
postCheckout(AbstractBuild<?,?> build, Launcher launcher, FilePath workspace, BuildListener listener)
Deprecated.void
postCheckout(Run<?,?> build, Launcher launcher, FilePath workspace, TaskListener listener)
Get a chance to do operations after the workspace i checked out and the changelog is written.boolean
processWorkspaceBeforeDeletion(AbstractProject<?,?> project, FilePath workspace, Node node)
Deprecated.boolean
processWorkspaceBeforeDeletion(Job<?,?> project, FilePath workspace, Node node)
Called before a workspace is deleted on the given node, to provide SCM an opportunity to perform clean up.boolean
requiresWorkspaceForPolling()
Returns true if this SCM requires a checked out workspace for doing polling.boolean
supportsPolling()
Returns true if this SCM supportspoling
.
-
-
-
Field Detail
-
PERMISSIONS
public static final PermissionGroup PERMISSIONS
-
TAG
public static final Permission TAG
Permission to create new tags.- Since:
- 1.171
-
-
Method Detail
-
getBrowser
@CheckForNull public RepositoryBrowser<?> getBrowser()
Returns theRepositoryBrowser
for files controlled by thisSCM
.- Returns:
- null to indicate that there's no explicitly configured browser for this SCM instance.
- See Also:
getEffectiveBrowser()
-
getType
@Exported public String getType()
Type of this SCM. Exposed so that the client of the remote API can tell what SCM this is.
-
getEffectiveBrowser
@Exported(name="browser") @CheckForNull public final RepositoryBrowser<?> getEffectiveBrowser()
Returns the applicableRepositoryBrowser
for files controlled by thisSCM
.- See Also:
guessBrowser()
-
supportsPolling
public boolean supportsPolling()
Returns true if this SCM supportspoling
.- Since:
- 1.105
-
requiresWorkspaceForPolling
public boolean requiresWorkspaceForPolling()
Returns true if this SCM requires a checked out workspace for doing polling.This flag affects the behavior of Hudson when a job lost its workspace (typically due to a agent outage.) If this method returns true and polling is configured, then that would usually trigger a new build.
This flag also affects the mutual exclusion control between builds and polling. If this methods returns false, polling will continue asynchronously even when a build is in progress, but otherwise the polling activity is blocked if a build is currently using a workspace.
The default implementation returns true.
See issue JENKINS-1348 for more discussion of this feature.
- Since:
- 1.196
-
processWorkspaceBeforeDeletion
public boolean processWorkspaceBeforeDeletion(@NonNull Job<?,?> project, @NonNull FilePath workspace, @NonNull Node node) throws IOException, InterruptedException
Called before a workspace is deleted on the given node, to provide SCM an opportunity to perform clean up.Hudson periodically scans through all the agents and removes old workspaces that are deemed unnecessary. This behavior is implemented in
WorkspaceCleanupThread
, and it is necessary to control the disk consumption on agents. If we don't do this, in a long run, all the agents will have workspaces for all the projects, which will be prohibitive in big Hudson.However, some SCM implementations require that the server be made aware of deletion of the local workspace, and this method provides an opportunity for SCMs to perform such a clean-up act.
This call back is invoked after Hudson determines that a workspace is unnecessary, but before the actual recursive directory deletion happens.
Note that this method does not guarantee that such a clean up will happen. For example, agents can be taken offline by being physically removed from the network, and in such a case there's no opportunity to perform this clean up.
This method is also invoked when the project is deleted.
- Parameters:
project
- The project that owns thisSCM
. This is always the same object for a particular instance ofSCM
. Just passed in here so thatSCM
itself doesn't have to remember the value.workspace
- The workspace which is about to be deleted. This can be a remote file path.node
- The node that hosts the workspace. SCM can use this information to determine the course of action.- Returns:
- true if
SCM
is OK to let Hudson proceed with deleting the workspace. False to veto the workspace deletion. - Throws:
IOException
InterruptedException
- Since:
- 1.568
-
processWorkspaceBeforeDeletion
@Deprecated public boolean processWorkspaceBeforeDeletion(AbstractProject<?,?> project, FilePath workspace, Node node) throws IOException, InterruptedException
Deprecated.- Throws:
IOException
InterruptedException
-
pollChanges
@Deprecated public boolean pollChanges(AbstractProject<?,?> project, Launcher launcher, FilePath workspace, TaskListener listener) throws IOException, InterruptedException
Deprecated.as of 1.345 OverridecalcRevisionsFromBuild(AbstractBuild, Launcher, TaskListener)
andcompareRemoteRevisionWith(AbstractProject, Launcher, FilePath, TaskListener, SCMRevisionState)
for implementation. The implementation is now separated in two pieces, one that computes the revision of the current workspace, and the other that computes the revision of the remote repository. Callpoll(AbstractProject, Launcher, FilePath, TaskListener, SCMRevisionState)
for use instead.Checks if there has been any changes to this module in the repository. TODO: we need to figure out a better way to communicate an error back, so that we won't keep retrying the same node (for example an agent might be down.)If the SCM doesn't implement polling, have the
supportsPolling()
method return false.- Parameters:
project
- The project to check for updateslauncher
- Abstraction of the machine where the polling will take place. If SCM declares that the polling doesn't require a workspace, this parameter is null.workspace
- The workspace directory that contains baseline files. If SCM declares that the polling doesn't require a workspace, this parameter is null.listener
- Logs during the polling should be sent here.- Returns:
- true if the change is detected.
- Throws:
InterruptedException
- interruption is usually caused by the user aborting the computation. this exception should be simply propagated all the way up.IOException
- See Also:
supportsPolling()
-
calcRevisionsFromBuild
@CheckForNull public SCMRevisionState calcRevisionsFromBuild(@NonNull Run<?,?> build, @Nullable FilePath workspace, @Nullable Launcher launcher, @NonNull TaskListener listener) throws IOException, InterruptedException
Calculates theSCMRevisionState
that represents the state of the workspace of the given build.The returned object is then fed into the
compareRemoteRevisionWith(AbstractProject, Launcher, FilePath, TaskListener, SCMRevisionState)
method as the baselineSCMRevisionState
to determine if the build is necessary.This method is called after source code is checked out for the given build (that is, after
checkout(Run, Launcher, FilePath, TaskListener, File, SCMRevisionState)
has finished successfully.)The obtained object is added to the build as an
Action
for later retrieval. As an optimization,SCM
implementation can choose to computeSCMRevisionState
and add it as an action during check out, in which case this method will not called.- Parameters:
build
- The calculatedSCMRevisionState
is for the files checked out in this build. IfrequiresWorkspaceForPolling()
returns true, Hudson makes sure that the workspace of this build is available and accessible by the callee.workspace
- the location of the checkout; normally not null, since this will normally be called immediately after checkout, though could be null if data is being loaded from a very old version of Jenkins and the SCM declares that it does not require a workspace for pollinglauncher
- Abstraction of the machine where the polling will take place. Nullness matches that ofworkspace
.listener
- Logs during the polling should be sent here.- Throws:
InterruptedException
- interruption is usually caused by the user aborting the computation. this exception should be simply propagated all the way up.IOException
- Since:
- 1.568
-
calcRevisionsFromBuild
@Deprecated public SCMRevisionState calcRevisionsFromBuild(AbstractBuild<?,?> build, Launcher launcher, TaskListener listener) throws IOException, InterruptedException
Deprecated.- Throws:
IOException
InterruptedException
-
_calcRevisionsFromBuild
@Deprecated public SCMRevisionState _calcRevisionsFromBuild(AbstractBuild<?,?> build, Launcher launcher, TaskListener listener) throws IOException, InterruptedException
Deprecated.- Throws:
IOException
InterruptedException
-
compareRemoteRevisionWith
public PollingResult compareRemoteRevisionWith(@NonNull Job<?,?> project, @Nullable Launcher launcher, @Nullable FilePath workspace, @NonNull TaskListener listener, @NonNull SCMRevisionState baseline) throws IOException, InterruptedException
Compares the current state of the remote repository against the given baselineSCMRevisionState
.Conceptually, the act of polling is to take two states of the repository and to compare them to see if there's any difference. In practice, however, comparing two arbitrary repository states is an expensive operation, so in this abstraction, we chose to mix (1) the act of building up a repository state and (2) the act of comparing it with the earlier state, so that SCM implementations can implement this more easily.
Multiple invocations of this method may happen over time to make sure that the remote repository is "quiet" before Hudson schedules a new build.
- Parameters:
project
- The project to check for updateslauncher
- Abstraction of the machine where the polling will take place. If SCM declares that the polling doesn't require a workspace, this parameter is null.workspace
- The workspace directory that contains baseline files. If SCM declares that the polling doesn't require a workspace, this parameter is null.listener
- Logs during the polling should be sent here.baseline
- The baseline of the comparison. This object is the return value from earliercompareRemoteRevisionWith(AbstractProject, Launcher, FilePath, TaskListener, SCMRevisionState)
orcalcRevisionsFromBuild(AbstractBuild, Launcher, TaskListener)
.- Returns:
- This method returns multiple values that are bundled together into the
PollingResult
value type.PollingResult.baseline
should be the value of the baseline parameter,PollingResult.remote
is the current state of the remote repository (this object only needs to be understandable to the future invocations of this method), andPollingResult.change
that indicates the degree of changes found during the comparison. - Throws:
InterruptedException
- interruption is usually caused by the user aborting the computation. this exception should be simply propagated all the way up.IOException
- Since:
- 1.568
-
compareRemoteRevisionWith
@Deprecated protected PollingResult compareRemoteRevisionWith(AbstractProject<?,?> project, Launcher launcher, FilePath workspace, TaskListener listener, SCMRevisionState baseline) throws IOException, InterruptedException
Deprecated.- Throws:
IOException
InterruptedException
-
poll
public final PollingResult poll(AbstractProject<?,?> project, Launcher launcher, FilePath workspace, TaskListener listener, SCMRevisionState baseline) throws IOException, InterruptedException
Convenience method for the caller to handle the backward compatibility between pre 1.345 SCMs.- Throws:
IOException
InterruptedException
-
getKey
@NonNull public String getKey()
Should create a key by which this SCM configuration might be distinguished from others in the same project. Should be invariable across builds but otherwise as distinctive as possible.Could include information such as the relative paths used in
getModuleRoots(FilePath, AbstractBuild)
, and/or configured repository URLs and branch names, and/or labels set for this purpose by the user.The result may be used for various purposes, but it may be long and/or include URL-unsafe characters, so to use in a URL path component you may need to first wrap it in
Util.getDigestOf(String)
or otherwise encode it.- Returns:
- by default, just
getType()
- Since:
- 1.568
-
checkout
public void checkout(@NonNull Run<?,?> build, @NonNull Launcher launcher, @NonNull FilePath workspace, @NonNull TaskListener listener, @CheckForNull File changelogFile, @CheckForNull SCMRevisionState baseline) throws IOException, InterruptedException
Obtains a fresh workspace of the module(s) into the specified directory of the specified machine.The "update" operation can be performed instead of a fresh checkout if feasible.
This operation should also capture the information necessary to tag the workspace later.
- Parameters:
launcher
- Abstracts away the machine that the files will be checked out.workspace
- a directory to check out the source code. May contain left-over from the previous build.changelogFile
- Upon a successful return, this file should capture the changelog. When there's no change, this file should contain an empty entry. SeecreateEmptyChangeLog(File, TaskListener, String)
. May be null, in which case no changelog was requested.baseline
- version from the previous build to use for changelog creation, if requested and available- Throws:
InterruptedException
- interruption is usually caused by the user aborting the build. this exception will cause the build to be aborted.AbortException
- in case of a routine failureIOException
- Since:
- 1.568
-
checkout
@Deprecated public boolean checkout(AbstractBuild<?,?> build, Launcher launcher, FilePath workspace, BuildListener listener, @NonNull File changelogFile) throws IOException, InterruptedException
Deprecated.- Throws:
IOException
InterruptedException
-
postCheckout
public void postCheckout(@NonNull Run<?,?> build, @NonNull Launcher launcher, @NonNull FilePath workspace, @NonNull TaskListener listener) throws IOException, InterruptedException
Get a chance to do operations after the workspace i checked out and the changelog is written.- Throws:
IOException
InterruptedException
- Since:
- 1.568
-
postCheckout
@Deprecated public void postCheckout(AbstractBuild<?,?> build, Launcher launcher, FilePath workspace, BuildListener listener) throws IOException, InterruptedException
Deprecated.- Throws:
IOException
InterruptedException
-
buildEnvironment
public void buildEnvironment(@NonNull Run<?,?> build, @NonNull Map<String,String> env)
Adds environmental variables for the builds to the given map.This can be used to propagate information from SCM to builds (for example, SVN revision number.)
This method is invoked whenever someone does
AbstractBuild.getEnvironment(TaskListener)
, viabuildEnvVars(AbstractBuild, Map)
, which can be before/after your checkout method is invoked. So if you are going to provide information about check out (like SVN revision number that was checked out), be prepared for the possibility that the check out hasn't happened yet.- Since:
- 2.60
-
buildEnvVars
@Deprecated public void buildEnvVars(AbstractBuild<?,?> build, Map<String,String> env)
Deprecated.in favor ofbuildEnvironment(Run, Map)
.
-
getModuleRoot
public FilePath getModuleRoot(FilePath workspace, AbstractBuild build)
Gets the top directory of the checked out module.Often SCMs have to create a directory inside a workspace, which creates directory layout like this:
workspace <- workspace root +- xyz <- directory checked out by SCM +- CVS +- build.xml <- user file
Many builders, like Ant or Maven, works off the specific user file at the top of the checked out module (in the above case, that would be
xyz/build.xml
), yet the builder doesn't know the "xyz" part; that comes from SCM.Collaboration between
Builder
andSCM
allows Hudson to find build.xml without asking the user to enter "xyz" again.This method is for this purpose. It takes the workspace root as a parameter, and expected to return the directory that was checked out from SCM.
If this SCM is configured to create a directory, try to return that directory so that builders can work seamlessly.
If SCM doesn't need to create any directory inside workspace, or in any other tricky cases, it should revert to the default implementation, which is to just return the parameter.
- Parameters:
workspace
- The workspace root directory.build
- The build for which the module root is desired. This parameter is null when existing legacy code calls deprecatedgetModuleRoot(FilePath)
. Handle this situation gracefully if your can, but otherwise you can just fail with an exception, too.- Since:
- 1.382
-
getModuleRoot
@Deprecated public FilePath getModuleRoot(FilePath workspace)
Deprecated.since 1.382 Use/overridegetModuleRoot(FilePath, AbstractBuild)
instead.
-
getModuleRoots
public FilePath[] getModuleRoots(FilePath workspace, AbstractBuild build)
Gets the top directories of all the checked out modules.Some SCMs support checking out multiple modules inside a workspace, which creates directory layout like this:
This method takes the workspace root as a parameter, and is expected to return all the module roots that were checked out from SCM.workspace <- workspace root +- xyz <- directory checked out by SCM +- .svn +- build.xml <- user file +- abc <- second module from different SCM root +- .svn +- build.xml <- user file
For normal SCMs, the array will be of length
1
and it's contents will be identical to callinggetModuleRoot(FilePath, AbstractBuild)
.- Parameters:
workspace
- The workspace root directorybuild
- The build for which the module roots are desired. This parameter is null when existing legacy code calls deprecatedgetModuleRoot(FilePath)
. Handle this situation gracefully if your can, but otherwise you can just fail with an exception, too.- Returns:
- An array of all module roots.
- Since:
- 1.382
-
getModuleRoots
@Deprecated public FilePath[] getModuleRoots(FilePath workspace)
Deprecated.as of 1.382. Use/derive fromgetModuleRoots(FilePath, AbstractBuild)
instead.
-
createChangeLogParser
public abstract ChangeLogParser createChangeLogParser()
The returned object will be used to parsechangelog.xml
.
-
getDescriptor
public SCMDescriptor<?> getDescriptor()
Description copied from interface:Describable
Gets the descriptor for this instance.Descriptor
is a singleton for every concreteDescribable
implementation, so ifa.getClass() == b.getClass()
then by defaulta.getDescriptor() == b.getDescriptor()
as well. (In rare cases a single implementation class may be used for instances with distinct descriptors.)- Specified by:
getDescriptor
in interfaceDescribable<SCM>
-
createEmptyChangeLog
@Deprecated protected final boolean createEmptyChangeLog(File changelogFile, BuildListener listener, String rootTag)
Deprecated.
-
createEmptyChangeLog
protected final void createEmptyChangeLog(@NonNull File changelogFile, @NonNull TaskListener listener, @NonNull String rootTag) throws IOException
- Throws:
IOException
- Since:
- 1.568
-
all
public static DescriptorExtensionList<SCM,SCMDescriptor<?>> all()
Returns all the registeredSCMDescriptor
s.
-
_for
public static List<SCMDescriptor<?>> _for(@CheckForNull Job project)
Determines which kinds of SCMs are applicable to a given project.- Parameters:
project
- a project on which we might be configuring SCM, or null if unknown- Returns:
- all descriptors which
SCMDescriptor.isApplicable(Job)
to it, also filtered byTopLevelItemDescriptor.isApplicable(hudson.model.Descriptor)
; or simplyall()
if there is no project - Since:
- 1.568
-
_for
@Deprecated public static List<SCMDescriptor<?>> _for(AbstractProject project)
Deprecated.
-
guessBrowser
@CheckForNull public RepositoryBrowser<?> guessBrowser()
Try to guess how a repository browser should be configured, based on URLs and the like. Used whengetBrowser()
has not been explicitly configured.- Returns:
- a reasonable default value for
getEffectiveBrowser()
, or null - Since:
- 1.568
-
-