Created
April 25, 2019 05:18
-
-
Save nedtwigg/a5ce9dadc160a8ec2ac48deb55b4e4c6 to your computer and use it in GitHub Desktop.
A rewrite of CleanCommand
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.io.File; | |
import java.io.IOException; | |
import java.util.Objects; | |
import java.util.TreeSet; | |
import java.util.function.Consumer; | |
import org.eclipse.jgit.api.Git; | |
import org.eclipse.jgit.api.GitCommand; | |
import org.eclipse.jgit.api.Status; | |
import org.eclipse.jgit.api.errors.GitAPIException; | |
import org.eclipse.jgit.api.errors.JGitInternalException; | |
import org.eclipse.jgit.errors.NoWorkTreeException; | |
import org.eclipse.jgit.events.WorkingTreeModifiedEvent; | |
import org.eclipse.jgit.lib.Repository; | |
import org.eclipse.jgit.submodule.SubmoduleWalk.IgnoreSubmoduleMode; | |
import org.eclipse.jgit.util.FS; | |
import org.eclipse.jgit.util.FileUtils; | |
import com.diffplug.common.base.Consumers; | |
/** | |
* Remove untracked files from the working tree | |
* | |
* @see <a | |
* href="http://www.kernel.org/pub/software/scm/git/docs/git-clean.html" | |
* >Git documentation about Clean</a> | |
*/ | |
public class CleanCommand extends GitCommand<TreeSet<String>> { | |
private boolean applyToSubmodules; | |
private boolean dryRun; | |
private boolean directories; | |
private boolean ignoreOnly; | |
private Consumer<String> perFile = Consumers.doNothing(); | |
/** | |
* Constructor for CleanCommand | |
* | |
* @param repo | |
* the {@link org.eclipse.jgit.lib.Repository} | |
*/ | |
public CleanCommand(Repository repo) { | |
super(repo); | |
} | |
/** | |
* {@inheritDoc} | |
* <p> | |
* Executes the {@code clean} command with all the options and parameters | |
* collected by the setter methods of this class. Each instance of this | |
* class should only be used for one invocation of the command (means: one | |
* call to {@link #call()}) | |
*/ | |
@Override | |
public TreeSet<String> call() throws NoWorkTreeException, GitAPIException { | |
TreeSet<String> allModified = new TreeSet<>(); | |
try (Git git = new Git(repo)) { | |
Status status = git.status() | |
.setIgnoreSubmodules(applyToSubmodules ? IgnoreSubmoduleMode.NONE : IgnoreSubmoduleMode.ALL) | |
.call(); | |
// find the | |
TreeSet<String> filesToDelete = new TreeSet<>(); | |
TreeSet<String> foldersToDelete = directories ? new TreeSet<>() : null; | |
if (ignoreOnly) { | |
FS fs = getRepository().getFS(); | |
for (String p : status.getIgnoredNotInIndex()) { | |
File f = new File(repo.getWorkTree(), p); | |
if (fs.isFile(f) || fs.isSymLink(f)) { | |
filesToDelete.add(p); | |
} else if (directories && fs.isDirectory(f)) { | |
foldersToDelete.add(p); | |
} | |
} | |
} else { | |
filesToDelete.addAll(status.getUntracked()); | |
if (directories) { | |
foldersToDelete.addAll(status.getUntrackedFolders()); | |
} | |
} | |
for (String path : filesToDelete) { | |
allModified.add(path); | |
perFile.accept(path); | |
if (!dryRun) { | |
FileUtils.delete(new File(repo.getWorkTree(), path), FileUtils.SKIP_MISSING); | |
} | |
} | |
if (directories) { | |
for (String path : foldersToDelete) { | |
String pathWithSlash = path + "/"; | |
perFile.accept(pathWithSlash); | |
allModified.add(pathWithSlash); | |
if (!dryRun) { | |
FileUtils.delete(new File(repo.getWorkTree(), path), FileUtils.RECURSIVE | FileUtils.SKIP_MISSING); | |
} | |
} | |
} | |
} catch (IOException e) { | |
throw new JGitInternalException(e.getMessage(), e); | |
} finally { | |
if (!dryRun && !allModified.isEmpty()) { | |
repo.fireEvent(new WorkingTreeModifiedEvent(null, allModified)); | |
} | |
} | |
return allModified; | |
} | |
/** | |
* If dryRun is set, the paths in question will not actually be deleted. | |
* Defaults to false. | |
* | |
* @param dryRun | |
* whether to do a dry run or not | |
* @return {@code this} | |
*/ | |
public CleanCommand setDryRun(boolean dryRun) { | |
this.dryRun = dryRun; | |
return this; | |
} | |
/** | |
* If dirs is set, in addition to files, also clean directories. | |
* Defaults to false. | |
* | |
* @param dirs | |
* whether to clean directories too, or only files. | |
* @return {@code this} | |
*/ | |
public CleanCommand setCleanDirectories(boolean dirs) { | |
directories = dirs; | |
return this; | |
} | |
/** | |
* If ignoreOnly is set, only report ignored files and folders. | |
* Otherwise, skip any files which are covered by .gitignore. | |
* Defaults to false. | |
* | |
* @param ignore | |
* whether to apply only to .gitignore or not. | |
* @return {@code this} | |
*/ | |
public CleanCommand setIgnoreOnly(boolean ignoreOnly) { | |
this.ignoreOnly = ignoreOnly; | |
return this; | |
} | |
/** | |
* Determines whether to apply command to the working copy | |
* of submodules. Defaults to false. | |
* | |
* @param applyToSubmodules | |
* whether to clean submodules or not | |
* @return {@code this} | |
*/ | |
public CleanCommand setApplyToSubmodules(boolean applyToSubmodules) { | |
this.applyToSubmodules = applyToSubmodules; | |
return this; | |
} | |
/** Called before each file is removed. */ | |
public CleanCommand beforeRemove(Consumer<String> perFile) { | |
this.perFile = Objects.requireNonNull(perFile); | |
return this; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment