package sk.stuba.fiit.perconik.eclipse.jgit.lib;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.NoSuchElementException;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.GitCommand;
import org.eclipse.jgit.api.LogCommand;
import org.eclipse.jgit.ignore.IgnoreNode;
import org.eclipse.jgit.ignore.IgnoreNode.MatchResult;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import sk.stuba.fiit.perconik.utilities.io.MorePaths;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.base.Throwables.propagate;
import static com.google.common.collect.Lists.newLinkedList;
/**
* Static utility methods pertaining to Git repositories.
*
* @author Pavol Zbell
* @since 1.0
*/
public final class GitRepositories {
private GitRepositories() {}
private static <T> T handle(final GitCommand<T> command) {
try {
return command.call();
} catch (Exception e) {
throw propagate(e);
}
}
private static Iterable<RevCommit> handleLogCommand(final LogCommand command) {
try {
return command.all().call();
} catch (Exception e) {
throw propagate(e);
}
}
private static RevCommit handleMostRecentCommit(final LogCommand command) {
try {
return command.setMaxCount(1).call().iterator().next();
} catch (NoSuchElementException e) {
return null;
} catch (Exception e) {
throw propagate(e);
}
}
public static String getShortBranch(final Repository repository) {
try {
return repository.getBranch();
} catch (Exception e) {
throw propagate(e);
}
}
public static String getFullBranch(final Repository repository) {
try {
return repository.getFullBranch();
} catch (Exception e) {
throw propagate(e);
}
}
public static List<Ref> getBranches(final Repository repository) {
return handle(new Git(repository).branchList());
}
public static List<Ref> getTags(final Repository repository) {
return handle(new Git(repository).tagList());
}
public static Iterable<RevCommit> getFileLog(final Repository repository, final Path path) {
return getFileLog(repository, path.toString());
}
public static Iterable<RevCommit> getFileLog(final Repository repository, final String path) {
return handleLogCommand(new Git(repository).log().addPath(path));
}
public static List<Path> getIgnoreFiles(final Repository repository, final Path path) {
Path root = repository.getDirectory().toPath().getParent().toAbsolutePath().normalize();
Path leaf = path.toAbsolutePath().normalize();
checkState(leaf.startsWith(root));
List<Path> paths = newLinkedList();
for (Path other: MorePaths.downToRoot(path)) {
if (other.equals(root)) {
break;
}
Path ignore = other.resolve(Constants.DOT_GIT_IGNORE);
if (Files.isRegularFile(ignore)) {
paths.add(ignore);
}
}
return paths;
}
public static List<Path> getIgnoreFiles(final Repository repository, final String path) {
return getIgnoreFiles(repository, Paths.get(path));
}
public static IgnoreNode getIgnoreNode(final Path path) {
IgnoreNode node = new IgnoreNode();
Path ignore = path.resolve(Constants.DOT_GIT_IGNORE);
if (Files.isRegularFile(ignore)) {
try {
node.parse(Files.newInputStream(ignore));
} catch (IOException e) {
propagate(e);
}
}
return node;
}
public static IgnoreNode getIgnoreNode(final String path) {
return getIgnoreNode(Paths.get(path));
}
public static List<IgnoreNode> getIgnoreNodes(final Repository repository, final Path path) {
List<IgnoreNode> nodes = newLinkedList();
for (Path ignore: getIgnoreFiles(repository, path)) {
nodes.add(getIgnoreNode(ignore));
}
return nodes;
}
public static List<IgnoreNode> getIgnoreNodes(final Repository repository, final String path) {
return getIgnoreNodes(repository, Paths.get(path));
}
public static RevCommit getMostRecentCommit(final Repository repository) {
return handleMostRecentCommit(new Git(repository).log());
}
public static RevCommit getMostRecentCommit(final Repository repository, final Path path) {
return getMostRecentCommit(repository, path.toString());
}
public static RevCommit getMostRecentCommit(final Repository repository, final String path) {
return handleMostRecentCommit(new Git(repository).log().addPath(path));
}
public static String getRemoteOriginUrl(final Repository repository) {
return GitConfigurations.getRemoteOriginUrl(repository.getConfig());
}
public static boolean isIgnored(final Repository repository, final Path path) {
return isIgnored(getIgnoreNodes(repository, path), path);
}
public static boolean isIgnored(final Repository repository, final String path) {
return isIgnored(repository, Paths.get(path));
}
public static boolean isIgnored(final Iterable<IgnoreNode> nodes, final Path path) {
return isIgnored(nodes, path.toString(), Files.isDirectory(path));
}
public static boolean isIgnored(final Iterable<IgnoreNode> nodes, final String path) {
return isIgnored(nodes, path, Files.isDirectory(Paths.get(path)));
}
private static boolean isIgnored(final Iterable<IgnoreNode> nodes, final String path, final boolean directory) {
for (IgnoreNode node: nodes) {
MatchResult result = node.isIgnored(path, directory);
switch (result) {
case IGNORED:
return true;
case NOT_IGNORED:
return false;
default:
continue;
}
}
return false;
}
}