diff --git a/README.adoc b/README.adoc index 9fe260dc41..0cf8f4749a 100644 --- a/README.adoc +++ b/README.adoc @@ -136,6 +136,17 @@ checkout scmGit( userRemoteConfigs: [[url: 'https://github.com/jenkinsci/ws-cleanup-plugin']]) ---- +[source,groovy] +---- +checkout resolveScm( + source: gitSource( + credentialsId: 'git-cred', + traits: [cloneOption(cloneOption(depth: 1, shallow: true)), gitBranchDiscovery()] + remote: 'https://github.com/jenkinsci/ws-cleanup-plugin'), + targets: ['main', 'master'] +) +---- + ==== Checkout with a narrow refspec Checkout from the workspace cleanup plugin source repository using https without credentials, the `master` branch, and with a refspec specific to the master branch. diff --git a/src/main/java/jenkins/plugins/git/AbstractGitSCMSource.java b/src/main/java/jenkins/plugins/git/AbstractGitSCMSource.java index 1504297965..2e310a0640 100644 --- a/src/main/java/jenkins/plugins/git/AbstractGitSCMSource.java +++ b/src/main/java/jenkins/plugins/git/AbstractGitSCMSource.java @@ -404,6 +404,7 @@ private , R extends GitSCMSourceRequest> fetch.tags(context.wantTags()); } fetch = fetch.prune(prune); + fetch = fetch.shallow(context.wantShallow()).depth(context.depth()); URIish remoteURI = null; try { diff --git a/src/main/java/jenkins/plugins/git/GitSCMSourceContext.java b/src/main/java/jenkins/plugins/git/GitSCMSourceContext.java index df04fdd288..4fa12dd0a0 100644 --- a/src/main/java/jenkins/plugins/git/GitSCMSourceContext.java +++ b/src/main/java/jenkins/plugins/git/GitSCMSourceContext.java @@ -94,6 +94,14 @@ public class GitSCMSourceContext, R extends */ @NonNull private String remoteName = AbstractGitSCMSource.DEFAULT_REMOTE_NAME; + /** + * Perform shallow clone + */ + private boolean shallow; + /** + * Shallow clone depth + */ + private Integer depth; /** * Constructor. @@ -192,6 +200,25 @@ public final String remoteName() { return remoteName; } + /** + * Returns {@code true} if a limited number of commits will be retrieved when cloning with a GitSCMSource. + * A GitSCMSource is most commonly used when defining a multibranch Pipeline. + * + * @return {@code true} if a limited number of commits will be retrieved + */ + public final boolean wantShallow() { + return shallow; + } + + /** + * Returns shallow clone depth + * + * @return shallow clone depth + */ + public final Integer depth() { + return depth; + } + /** * Adds a requirement for branch details to any {@link GitSCMSourceRequest} for this context. * @@ -358,6 +385,34 @@ public final List asRefSpecs() { return result; } + /** + * Limit the number of commits that will be retrieved when the multibranch Pipeline is cloned. + * When shallow clone is enabled, a single commit will be retrieved instead of retrieving all commits. + * If more commits are needed, set the depth to a larger value. + * + * @param shallow {@code true} to perform shallow clone + * @return {@code this} for method chaining. + */ + @SuppressWarnings("unchecked") + @NonNull + public final C shallow(boolean shallow) { + this.shallow = shallow; + return (C) this; + } + + /** + * Configures shallow clone depth + * + * @param depth upper limit to the number of commits included in the repository clone + * @return {@code this} for method chaining. + */ + @SuppressWarnings("unchecked") + @NonNull + public final C depth(Integer depth) { + this.depth = depth; + return (C) this; + } + /** * {@inheritDoc} */ diff --git a/src/main/java/jenkins/plugins/git/traits/CloneOptionTrait.java b/src/main/java/jenkins/plugins/git/traits/CloneOptionTrait.java index 68a1d3a4ec..679b98da58 100644 --- a/src/main/java/jenkins/plugins/git/traits/CloneOptionTrait.java +++ b/src/main/java/jenkins/plugins/git/traits/CloneOptionTrait.java @@ -27,6 +27,8 @@ import hudson.Extension; import hudson.plugins.git.extensions.impl.CloneOption; +import jenkins.plugins.git.GitSCMSourceContext; +import jenkins.scm.api.trait.SCMSourceContext; import jenkins.scm.api.trait.SCMSourceTrait; import org.jenkinsci.Symbol; import org.kohsuke.stapler.DataBoundConstructor; @@ -47,6 +49,14 @@ public CloneOptionTrait(CloneOption extension) { super(extension); } + @Override + protected void decorateContext(SCMSourceContext context) { + if (context instanceof GitSCMSourceContext gitContext) { + CloneOption extension = getExtension(); + gitContext.shallow(extension.isShallow()).depth(extension.getDepth()); + } + } + /** * Our {@link hudson.model.Descriptor} */ diff --git a/src/test/java/jenkins/plugins/git/traits/CloneOptionTraitTest.java b/src/test/java/jenkins/plugins/git/traits/CloneOptionTraitTest.java new file mode 100644 index 0000000000..7da43ebd89 --- /dev/null +++ b/src/test/java/jenkins/plugins/git/traits/CloneOptionTraitTest.java @@ -0,0 +1,42 @@ +package jenkins.plugins.git.traits; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.Test; + +import hudson.plugins.git.extensions.impl.CloneOption; +import jenkins.plugins.git.GitSCMSourceContext; + +class CloneOptionTraitTest { + + @Test + void testShallowDisabledByDefault() { + GitSCMSourceContext context = new GitSCMSourceContext<>(null, null); + assertFalse(context.wantShallow()); + assertNull(context.depth()); + } + + @Test + void testDecorateWithDefaultCloneOption() { + GitSCMSourceContext context = new GitSCMSourceContext<>(null, null); + CloneOption cloneOption = new CloneOption(false, null, null); + CloneOptionTrait cloneOptionTrait = new CloneOptionTrait(cloneOption); + cloneOptionTrait.decorateContext(context); + assertFalse(context.wantShallow()); + assertNull(context.depth()); + } + + @Test + void testDecorateCloneOptionWithShallow() { + GitSCMSourceContext context = new GitSCMSourceContext<>(null, null); + CloneOption cloneOption = new CloneOption(true, null, null); + cloneOption.setDepth(10); + CloneOptionTrait cloneOptionTrait = new CloneOptionTrait(cloneOption); + cloneOptionTrait.decorateContext(context); + assertTrue(context.wantShallow()); + assertEquals(context.depth(), 10); + } +} \ No newline at end of file