Skip to content
77 changes: 64 additions & 13 deletions src/main/java/jenkins/scm/api/SCMFileSystem.java
Original file line number Diff line number Diff line change
Expand Up @@ -187,15 +187,37 @@ public static SCMFileSystem of(@NonNull Item owner, @NonNull SCM scm) throws IOE
* @throws InterruptedException if the attempt to create a {@link SCMFileSystem} was interrupted.
*/
@CheckForNull
public static SCMFileSystem of(@NonNull Item owner, @NonNull SCM scm, @CheckForNull SCMRevision rev)
public static SCMFileSystem of(@NonNull Item owner, @NonNull SCM scm,@CheckForNull SCMRevision rev) throws IOException, InterruptedException {
return of(owner, scm, rev,null);
}


/**
* Given a {@link SCM} this method will try to retrieve a corresponding {@link SCMFileSystem} instance that
* reflects the content at the specified {@link SCMRevision}.
*
* @param owner the owner of the {@link SCM}
* @param scm the {@link SCM}.
* @param rev the specified {@link SCMRevision}.
* @param build the specified {@link Run}.
* @return the corresponding {@link SCMFileSystem} or {@code null} if there is none.
* @throws IOException if the attempt to create a {@link SCMFileSystem} failed due to an IO error
* (such as the remote system being unavailable)
* @throws InterruptedException if the attempt to create a {@link SCMFileSystem} was interrupted.
*/
@CheckForNull
public static SCMFileSystem of(@NonNull Item owner, @NonNull SCM scm,
@CheckForNull SCMRevision rev,
@CheckForNull Run<?,?> build)
throws IOException, InterruptedException {
Objects.requireNonNull(scm);
SCMFileSystem fallBack = null;
Throwable failure = null;
for (Builder b : ExtensionList.lookup(Builder.class)) {
if (b.supports(scm)) {
try {
SCMFileSystem inspector = b.build(owner, scm, rev);
SCMFileSystem inspector = b.build(owner, scm, rev, build);

if (inspector != null) {
if (inspector.isFixedRevision()) {
return inspector;
Expand Down Expand Up @@ -231,15 +253,15 @@ public static SCMFileSystem of(@NonNull Item owner, @NonNull SCM scm, @CheckForN

/**
* Given a {@link SCM} this method will check if there is at least one {@link SCMFileSystem} provider capable
* of being instantiated. Returning {@code true} does not mean that {@link #of(Item, SCM, SCMRevision)}
* of being instantiated. Returning {@code true} does not mean that {@link #of(Item, SCM, SCMRevision, Run)}
* will be able to instantiate a {@link SCMFileSystem} for any specific {@link SCMRevision},
* rather returning {@code false} indicates that there is absolutely no point in calling
* {@link #of(Item, SCM, SCMRevision)} as it will always return {@code null}.
* {@link #of(Item, SCM, SCMRevision, Run)} as it will always return {@code null}.
*
* @param scm the {@link SCMSource}.
* @return {@code true} if {@link SCMFileSystem#of(Item, SCM)} / {@link #of(Item, SCM, SCMRevision)} could return a
* @return {@code true} if {@link SCMFileSystem#of(Item, SCM)} / {@link #of(Item, SCM, SCMRevision, Run)} could return a
* {@link SCMFileSystem} implementation, {@code false} if {@link SCMFileSystem#of(Item, SCM)} /
* {@link #of(Item, SCM, SCMRevision)} will always return {@code null} for the supplied {@link SCM}.
* {@link #of(Item, SCM, SCMRevision, Run)} will always return {@code null} for the supplied {@link SCM}.
* @since 2.0
*/
public static boolean supports(@NonNull SCM scm) {
Expand Down Expand Up @@ -350,13 +372,13 @@ public static boolean supports(@NonNull SCMSource source) {
/**
* Given a {@link SCMDescriptor} this method will check if there is at least one {@link SCMFileSystem} provider
* capable of being instantiated from the descriptor's {@link SCMSource}. Returning {@code true} does not mean that
* {@link #of(Item, SCM, SCMRevision)} will be able to instantiate a {@link SCMFileSystem} for any specific
* {@link #of(Item, SCM, SCMRevision, Run)} will be able to instantiate a {@link SCMFileSystem} for any specific
* {@link Item} or {@link SCMRevision}, rather returning {@code false} indicates that there is absolutely no point
* in calling {@link #of(Item, SCM, SCMRevision)} as it will always return {@code null}.
* in calling {@link #of(Item, SCM, SCMRevision, Run)} as it will always return {@code null}.
*
* @param descriptor the {@link SCMDescriptor}.
* @return {@code true} if {@link #of(Item, SCM, SCMRevision)} could return a {@link SCMFileSystem} implementation,
* {@code false} if {@link #of(Item, SCM, SCMRevision)} will always return {@code null} for the supplied {@link SCM}.
* @return {@code true} if {@link #of(Item, SCM, SCMRevision, Run)} could return a {@link SCMFileSystem} implementation,
* {@code false} if {@link #of(Item, SCM, SCMRevision, Run)} will always return {@code null} for the supplied {@link SCM}.
* @since 2.3.0
*/
public static boolean supports(@NonNull SCMDescriptor descriptor) {
Expand Down Expand Up @@ -500,8 +522,11 @@ public final boolean supports(SCMSourceDescriptor descriptor) {
* @throws InterruptedException if the attempt to create a {@link SCMFileSystem} was interrupted.
*/
@CheckForNull
public abstract SCMFileSystem build(@NonNull Item owner, @NonNull SCM scm, @CheckForNull SCMRevision rev)
throws IOException, InterruptedException;
public SCMFileSystem build(@NonNull Item owner, @NonNull SCM scm, @CheckForNull SCMRevision rev)
throws IOException, InterruptedException
{
throw new AbstractMethodError("Implement build(Item, SCM, SCMRevision,Run<?,?>)");
}

/**
* Given a {@link SCMSource}, a {@link SCMHead} and a {@link SCMRevision} this method should try to build a
Expand All @@ -525,12 +550,38 @@ public SCMFileSystem build(@NonNull SCMSource source, @NonNull SCMHead head,
if (owner == null) {
throw new IOException("Cannot instantiate a SCMFileSystem from an SCM without an owner");
}
return build(owner, source.build(head, rev), rev);
return build(owner, source.build(head, rev), rev, null);
}

private boolean isEnclosedByDescribable(Descriptor<?> descriptor) {
Class<?> enclosingClass = getClass().getEnclosingClass();
return enclosingClass != null && descriptor.clazz.isAssignableFrom(enclosingClass);
}

/**
* Given a {@link SCM} this should try to build a corresponding {@link SCMFileSystem} instance that
* reflects the content at the specified {@link SCMRevision}. If the {@link SCM} is supported but not
* for a fixed revision, best effort is acceptable as the most capable {@link SCMFileSystem} will be returned
* to the caller. If the {@link Run} is provided, it can be used to alter the behaviour of buil based on the current Run
* for example, expand branch name based on current build properties, etc.
*
* @param owner the owner of the {@link SCM}
* @param scm the {@link SCM}.
* @param rev the specified {@link SCMRevision}.
* @param _build the specified {@link Run}.
* @return the corresponding {@link SCMFileSystem} or {@code null} if this builder cannot create a {@link
* SCMFileSystem} for the specified {@link SCM}.
* @throws IOException if the attempt to create a {@link SCMFileSystem} failed due to an IO error
* (such as the remote system being unavailable)
* @throws InterruptedException if the attempt to create a {@link SCMFileSystem} was interrupted.
*/
@CheckForNull
public SCMFileSystem build(@NonNull Item owner, @NonNull SCM scm, @CheckForNull SCMRevision rev,
@CheckForNull Run<?,?> _build)
throws IOException, InterruptedException
{
// if this is not overriden, fallback to the previous implementation
return build(owner,scm, rev);
}
}
}