186 lines
5.9 KiB
Java
186 lines
5.9 KiB
Java
package me.brianlong.git;
|
|
|
|
import java.io.File;
|
|
import java.io.IOException;
|
|
import java.util.Map.Entry;
|
|
import java.util.UUID;
|
|
|
|
import org.eclipse.jgit.api.CloneCommand;
|
|
import org.eclipse.jgit.api.Git;
|
|
import org.eclipse.jgit.api.errors.GitAPIException;
|
|
import org.eclipse.jgit.api.errors.InvalidRemoteException;
|
|
import org.eclipse.jgit.api.errors.RefNotFoundException;
|
|
import org.eclipse.jgit.util.FileUtils;
|
|
import org.slf4j.Logger;
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
public class LocalRepositoryCache {
|
|
|
|
private static final LocalRepositoryCache INSTANCE = new LocalRepositoryCache();
|
|
|
|
public static LocalRepositoryCache getInstance() {
|
|
return INSTANCE;
|
|
}
|
|
|
|
private final Logger logger = LoggerFactory.getLogger(LocalRepositoryCache.class);
|
|
|
|
private final LRUExpiringHashMap<String, Git> cachedGits = new LRUExpiringHashMap<String, Git>(30);
|
|
// private final Map<String, String> gitIdsToUrls = new HashMap<String, String>();
|
|
private final File cacheDirectory = new File(System.getProperty("java.io.tmpdir"), "git");
|
|
|
|
private LocalRepositoryCache() {
|
|
this.cacheDirectory.mkdir();
|
|
this.cachedGits.addListener(new RepositoryCacheMapListener());
|
|
}
|
|
|
|
@Override
|
|
protected void finalize() throws Throwable {
|
|
try {
|
|
this.destroy();
|
|
} finally {
|
|
super.finalize();
|
|
}
|
|
}
|
|
|
|
private void destroy() {
|
|
if (this.logger.isDebugEnabled())
|
|
this.logger.debug("clearing local repo cache");
|
|
this.clear();
|
|
}
|
|
|
|
public synchronized ExtendedGit acquire(String url) throws GitAPIException, InvalidRemoteException, RefNotFoundException {
|
|
return this.acquire(url, null, null);
|
|
}
|
|
|
|
public synchronized ExtendedGit acquire(String url, GitCredentials creds) throws GitAPIException, InvalidRemoteException, RefNotFoundException {
|
|
return this.acquire(url, creds, null);
|
|
}
|
|
|
|
public synchronized ExtendedGit acquire(String url, String branch) throws GitAPIException, InvalidRemoteException, RefNotFoundException {
|
|
return this.acquire(url, null, branch);
|
|
}
|
|
|
|
public synchronized ExtendedGit acquire(String url, GitCredentials creds, String branch) throws GitAPIException, InvalidRemoteException, RefNotFoundException {
|
|
if (this.logger.isTraceEnabled())
|
|
this.logger.trace("acquire('" + url + "', " + creds + ", '" + branch + "')");
|
|
|
|
// Git git = this.cachedGits.remove(url);
|
|
// if (git == null) {
|
|
if (this.logger.isDebugEnabled())
|
|
this.logger.debug("creating temporary Git directory");
|
|
File gitRepoDirectory = new File(this.cacheDirectory, UUID.randomUUID().toString() + ".git");
|
|
|
|
CloneCommand clone = new CloneCommand()
|
|
.setURI(url)
|
|
.setDirectory(gitRepoDirectory);
|
|
if (branch != null)
|
|
clone.setBranch(branch);
|
|
|
|
if (this.logger.isDebugEnabled())
|
|
this.logger.debug("cloning Git repository: " + url);
|
|
ExtendedGit git = creds != null ? new CredentialedGit(clone, creds) : new ExtendedGit(clone);
|
|
if (this.logger.isInfoEnabled())
|
|
this.logger.info("Cloned Git Repository");
|
|
return git;
|
|
// git = creds != null ? new CredentialedGit(clone, creds) : new CachedGit(clone);
|
|
// this.gitIdsToUrls.put(git.getRepository().getIdentifier(), url);
|
|
// } else {
|
|
// if (branch != null) {
|
|
// if (this.logger.isDebugEnabled())
|
|
// this.logger.debug("switching Git branches: " + branch);
|
|
// git.checkout().setName(branch).call();
|
|
// }
|
|
//
|
|
// if (this.logger.isDebugEnabled())
|
|
// this.logger.debug("updating Git branch: " + branch);
|
|
// git.pull().call();
|
|
// }
|
|
}
|
|
|
|
public synchronized void release(Git git) {
|
|
if (this.logger.isTraceEnabled())
|
|
this.logger.trace("release('" + git.getRepository().getIdentifier() + "')");
|
|
|
|
// String url = this.gitIdsToUrls.get(git.getRepository().getIdentifier());
|
|
// this.cachedGits.put(url, git);
|
|
this.expunge(git);
|
|
}
|
|
|
|
public synchronized void clear() {
|
|
if (this.logger.isTraceEnabled())
|
|
this.logger.trace("clear()");
|
|
|
|
// this.cachedGits.clear();
|
|
}
|
|
|
|
private void expunge(Git git) {
|
|
// gitIdsToUrls.remove(git.getRepository().getIdentifier());
|
|
|
|
File gitDir = git.getRepository().getDirectory();
|
|
File workingTreeDir = git.getRepository().getWorkTree();
|
|
git.getRepository().close();
|
|
|
|
try {
|
|
if (this.logger.isDebugEnabled())
|
|
this.logger.debug("deleting: " + gitDir);
|
|
FileUtils.delete(gitDir, FileUtils.RECURSIVE);
|
|
} catch (IOException ie) {
|
|
this.logger.warn("Failed to delete a git directory: " + gitDir);
|
|
if (this.logger.isDebugEnabled())
|
|
this.logger.debug(ie.getMessage(), ie);
|
|
gitDir.deleteOnExit();
|
|
}
|
|
|
|
try {
|
|
if (this.logger.isDebugEnabled())
|
|
this.logger.debug("deleting: " + workingTreeDir);
|
|
FileUtils.delete(workingTreeDir, FileUtils.RECURSIVE);
|
|
} catch (IOException ie) {
|
|
this.logger.warn("Failed to delete a git directory: " + workingTreeDir);
|
|
if (this.logger.isDebugEnabled())
|
|
this.logger.debug(ie.getMessage(), ie);
|
|
workingTreeDir.deleteOnExit();
|
|
}
|
|
|
|
if (this.logger.isInfoEnabled())
|
|
this.logger.info("Deleted Git Repository");
|
|
}
|
|
|
|
|
|
|
|
private class RepositoryCacheMapListener implements ExpiringMapListener<String, Git> {
|
|
|
|
private final Logger logger = LoggerFactory.getLogger(LocalRepositoryCache.class);
|
|
|
|
@Override
|
|
public void accessed(Entry<String, Git> entry) {
|
|
}
|
|
|
|
@Override
|
|
public void added(Entry<String, Git> entry) {
|
|
// a clean one or one returned after being previously removed
|
|
}
|
|
|
|
@Override
|
|
public void expired(Entry<String, Git> entry) {
|
|
if (this.logger.isTraceEnabled())
|
|
this.logger.trace("expired('" + entry.getKey() + "', '" + entry.getValue().getRepository().getIdentifier() + "')");
|
|
expunge(entry.getValue());
|
|
}
|
|
|
|
@Override
|
|
public void removed(Entry<String, Git> entry) {
|
|
// expected to be removed only temporarily...for use elsewhere; do not close
|
|
}
|
|
|
|
@Override
|
|
public void cleared(Entry<String, Git> entry) {
|
|
if (this.logger.isTraceEnabled())
|
|
this.logger.trace("cleared('" + entry.getKey() + "', '" + entry.getValue().getRepository().getIdentifier() + "')");
|
|
expunge(entry.getValue());
|
|
}
|
|
|
|
}
|
|
|
|
}
|