Commit a076eb59 authored by Brian Long's avatar Brian Long
Browse files

supporting cache the persists across runs (faster development)

parent 77820bb2
Loading
Loading
Loading
Loading
+8 −5
Original line number Diff line number Diff line
@@ -32,8 +32,8 @@ import org.slf4j.LoggerFactory;

public class ExtendedGit extends CachedGit {

	private static final Pattern gitUrlPattern = Pattern.compile("(((ssh|http(s)?)://([^@]+@)?([^:/]+)(:[0-9]+)?/)|git@([^:]+):)([\\w\\.@\\:/\\-~]+)(\\.git)");
	private final Logger logger = LoggerFactory.getLogger(ExtendedGit.class);
	private final Pattern gitUrlPattern = Pattern.compile("(((ssh|http(s)?)://([^@]+@)?([^:/]+)(:[0-9]+)?/)|git@([^:]+):)([\\w\\.@\\:/\\-~]+)(\\.git)");
	
	public ExtendedGit(Git git) {
		super(git.getRepository());
@@ -51,10 +51,13 @@ public class ExtendedGit extends CachedGit {
		String gitUrl = this.getFirstRemoteUrl();
		if (this.logger.isDebugEnabled())
			this.logger.debug("Remote URL: " + gitUrl);
		return getRepositoryFullyQualifiedName(gitUrl);
	}
	
		Matcher matcher = this.gitUrlPattern.matcher(gitUrl);
	public static String getRepositoryFullyQualifiedName(String gitUrl) throws URISyntaxException {
		Matcher matcher = gitUrlPattern.matcher(gitUrl);
		if (!matcher.find())
			throw new URISyntaxException(gitUrl, "The Git URL does not match the expected regular expression: " + this.gitUrlPattern.toString());
			throw new URISyntaxException(gitUrl, "The Git URL does not match the expected regular expression: " + gitUrlPattern.toString());
		return matcher.group(9);
	}
	
+37 −6
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@ 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.api.errors.TransportException;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.transport.CredentialsProvider;
import org.eclipse.jgit.util.FileUtils;
import org.slf4j.Logger;
@@ -36,13 +37,24 @@ public class LocalRepositoryCache {
	private final LRUExpiringHashMap<String, CachedGit> cachedGits = new LRUExpiringHashMap<>(30);
	private final Map<String, Semaphore> gitUrlSemaphores = new HashMap<>();
	final File cacheDirectory = new File(System.getProperty("java.io.tmpdir"), "git");
	private final int simultaneousProcessesPerGitRepo = 1;
	private int simultaneousThreadsPerGitRepo = 1;
	
	private LocalRepositoryCache() {
		this.cacheDirectory.mkdir();
		this.cachedGits.addListener(new RepositoryCacheMapListener<CachedGit>());
	}
	
	/**
	 * This is helpful for the tweaking performance based on the environment of
	 * execution.  A value of 1 disables concurrency which results in the
	 * persistence of Git Repositories between executions and disables cache
	 * expiration.  This is great for development, testing, and command line
	 * usage.  It is not recommended with web service frontends.
	 */
	public void setSimultaneousThreadsPerGitRepository(int threads) {
		this.simultaneousThreadsPerGitRepo = threads;
	}
	
	@Override
	protected void finalize() throws Throwable {
		try {
@@ -91,17 +103,32 @@ public class LocalRepositoryCache {
    	synchronized (this) {
	    	semaphore = this.gitUrlSemaphores.get(url);
	    	if (semaphore == null)
	    		this.gitUrlSemaphores.put(url, semaphore = new Semaphore(this.simultaneousProcessesPerGitRepo));
	    		this.gitUrlSemaphores.put(url, semaphore = new Semaphore(this.simultaneousThreadsPerGitRepo));
    	}
    	
    	File gitRepoDirectory = null;
    	
    	semaphore.acquire();
    	try {
			CachedGit git = this.cachedGits.remove(url);
			if (git == null) {
				File gitRepoDirectory = new File(this.cacheDirectory, UUID.randomUUID().toString() + ".git");
				String directoryBaseName;
				if (this.simultaneousThreadsPerGitRepo == 1)
					directoryBaseName = ExtendedGit.getRepositoryFullyQualifiedName(url).replace('/', '_');
				else directoryBaseName = UUID.randomUUID().toString();
				
				gitRepoDirectory = new File(this.cacheDirectory, directoryBaseName + ".git");
		    	if (this.logger.isDebugEnabled())
		    		this.logger.debug("Git directory cache for clone: " + gitRepoDirectory);
				
		    	if (gitRepoDirectory.exists()) {
			    	if (this.logger.isInfoEnabled())
			    		this.logger.info("Git Repository already exists; reusing: " + gitRepoDirectory);
		    		git = creds != null ? new CredentialedGit(Git.open(gitRepoDirectory), creds) : new ExtendedGit(Git.open(gitRepoDirectory));
		    	}
			}
			
			if (git == null) {
				CloneCommand clone = new CloneCommand()
		    			.setURI(url)
		    			.setDirectory(gitRepoDirectory);
@@ -115,14 +142,18 @@ public class LocalRepositoryCache {
		    		this.logger.info("Cloned Git Repository: " + ((ExtendedGit)git).getRepositoryFullyQualifiedName());
			} else {
		    	if (this.logger.isDebugEnabled())
		    		this.logger.debug("reseting Git");
		    		this.logger.debug("resetting Git");
				git.reset().setMode(ResetType.HARD).call();
				
				if (branch != null) {
				if (branch != null && !branch.equals(git.getRepository().getBranch())) {
			    	if (this.logger.isDebugEnabled())
			    		this.logger.debug("switching Git branches: " + branch);
			    	if (git.getRepository().exactRef(Constants.R_HEADS + branch) == null) {
			    		git.checkout().setName(branch).setStartPoint("origin/" + branch).setCreateBranch(true).call();
			    	} else {
			    		git.checkout().setName(branch).call();
			    	}
				}
	
		    	if (this.logger.isDebugEnabled())
		    		this.logger.debug("updating Git branch: " + git.getRepository().getBranch());