package hudson.plugins.git.extensions.impl;

import hudson.Extension;
import hudson.model.TaskListener;
import hudson.plugins.git.GitException;
import hudson.plugins.git.GitSCM;
import hudson.plugins.git.extensions.GitSCMExtension;
import hudson.plugins.git.extensions.GitSCMExtensionDescriptor;
import java.io.IOException;
import java.util.Objects;

import org.jenkinsci.plugins.gitclient.FetchCommand;
import org.jenkinsci.plugins.gitclient.GitClient;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.DataBoundSetter;

/**
 * git-clean before the checkout.
 *
 * @author David S Wang
 */
public class CleanBeforeCheckout extends GitSCMExtension {
    private boolean deleteUntrackedNestedRepositories;

    @DataBoundConstructor
    public CleanBeforeCheckout() {
    }

    public boolean isDeleteUntrackedNestedRepositories() {
        return deleteUntrackedNestedRepositories;
    }

    @DataBoundSetter
    public void setDeleteUntrackedNestedRepositories(boolean deleteUntrackedNestedRepositories) {
        this.deleteUntrackedNestedRepositories = deleteUntrackedNestedRepositories;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    @Deprecated
    public void decorateFetchCommand(GitSCM scm, GitClient git, TaskListener listener, FetchCommand cmd) throws IOException, InterruptedException, GitException {
        listener.getLogger().println("Cleaning workspace");
        git.clean(deleteUntrackedNestedRepositories);
        // TODO: revisit how to hand off to SubmoduleOption
        for (GitSCMExtension ext : scm.getExtensions()) {
            ext.onClean(scm, git);
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        CleanBeforeCheckout that = (CleanBeforeCheckout) o;
        return deleteUntrackedNestedRepositories == that.deleteUntrackedNestedRepositories;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public int hashCode() {
        return Objects.hash(deleteUntrackedNestedRepositories);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public String toString() {
        return "CleanBeforeCheckout{" +
                "deleteUntrackedNestedRepositories=" + deleteUntrackedNestedRepositories +
                '}';
    }

    @Extension
    public static class DescriptorImpl extends GitSCMExtensionDescriptor {

        /**
         * {@inheritDoc}
         */
        @Override
        public String getDisplayName() {
            return "Clean before checkout";
        }
    }
}

@@ -55,32 +55,57 @@
 dson.Extension;%0A
+import hudson.model.Run;%0A
 import hudson.mo
@@ -369,16 +369,69 @@
 jects;%0A%0A
+import org.jenkinsci.plugins.gitclient.CloneCommand;%0A
 import o
@@ -1702,32 +1702,532 @@
        %7D%0A    %7D%0A%0A
+    @Override%0A    public void decorateCloneCommand(GitSCM scm, Run%3C?, ?%3E build, GitClient git, TaskListener listener,%0A                                     CloneCommand cmd) throws IOException, InterruptedException %7B%0A        listener.getLogger().println(%22Cleaning workspace%22);%0A        git.clean(deleteUntrackedNestedRepositories);%0A        // TODO: revisit how to hand off to SubmoduleOption%0A        for (GitSCMExtension ext : scm.getExtensions()) %7B%0A            ext.onClean(scm, git);%0A        %7D%0A    %7D%0A%0A
     /**%0A     * %7B

Enable CleanBeforeCheckout to be decorated in the CloneCommand The concern of removing the second fetch call is a possible repository data loss or misconfiguration in terms of the extra behaviors applied during checkout.