Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[JENKINS-42971] New API for SCMFileSystem to allow for lightweight checkout with build params #160

Merged
merged 8 commits into from
Aug 9, 2022
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 an associated build context, if any, that could be used for example to look up parameters
* @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) and override this method to delegate to it");
}

/**
* 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 behavior.
* For example, variables in the branch name can be expanded 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
MartinKosicky marked this conversation as resolved.
Show resolved Hide resolved
public SCMFileSystem build(@NonNull Item owner, @NonNull SCM scm, @CheckForNull SCMRevision rev,
@CheckForNull Run<?,?> _build)
throws IOException, InterruptedException
{
// if this is not overridden, fall back to the previous implementation
return build(owner, scm, rev);
}
}
}