diff --git a/pom.xml b/pom.xml index 4fc919e..7f45d9d 100644 --- a/pom.xml +++ b/pom.xml @@ -1,77 +1,89 @@ -<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> - <modelVersion>4.0.0</modelVersion> - <groupId>me.brianlong</groupId> - <artifactId>github-api</artifactId> - <packaging>jar</packaging> - <version>1.0-SNAPSHOT</version> - - <name>GitHub API & Utilities</name> - - <properties> - <maven.compiler.source>1.8</maven.compiler.source> - <maven.compiler.target>1.8</maven.compiler.target> - <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> - </properties> - - <dependencies> - <dependency> - <groupId>org.eclipse.jgit</groupId> - <artifactId>org.eclipse.jgit</artifactId> - <version>5.9.0.202009080501-r</version> - </dependency> - <dependency> - <groupId>org.eclipse.jgit</groupId> - <artifactId>org.eclipse.jgit.ssh.jsch</artifactId> - <version>5.9.0.202009080501-r</version> - </dependency> - <dependency> - <groupId>org.apache.httpcomponents</groupId> - <artifactId>httpclient</artifactId> - <version>4.5.12</version> - </dependency> - <dependency> - <groupId>com.fasterxml.jackson.jaxrs</groupId> - <artifactId>jackson-jaxrs-json-provider</artifactId> - <version>2.11.0</version> - </dependency> - <dependency> - <groupId>com.fasterxml.jackson.datatype</groupId> - <artifactId>jackson-datatype-jsr310</artifactId> - <version>2.11.0</version> - </dependency> - <dependency> - <groupId>junit</groupId> - <artifactId>junit</artifactId> - <version>4.13</version> - <scope>test</scope> - </dependency> - <dependency> - <groupId>org.apache.logging.log4j</groupId> - <artifactId>log4j-slf4j-impl</artifactId> - <version>2.13.2</version> - <scope>test</scope> - </dependency> - </dependencies> - - <build> - <plugins> - <plugin> - <groupId>org.apache.maven.plugins</groupId> - <artifactId>maven-surefire-plugin</artifactId> - <executions> - <execution> - <id>unit-tests</id> - <phase>test</phase> - <goals><goal>test</goal></goals> - <configuration> - <excludes> - <exclude>**/*IT.class</exclude> - </excludes> - </configuration> - </execution> - </executions> - </plugin> - </plugins> - </build> +<project xmlns="http://maven.apache.org/POM/4.0.0" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + <groupId>me.brianlong</groupId> + <artifactId>github-api</artifactId> + <packaging>jar</packaging> + <version>1.0-SNAPSHOT</version> + + <name>GitHub API & Utilities</name> + + <properties> + <maven.compiler.source>1.8</maven.compiler.source> + <maven.compiler.target>1.8</maven.compiler.target> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + </properties> + + <dependencies> + <dependency> + <groupId>org.eclipse.jgit</groupId> + <artifactId>org.eclipse.jgit</artifactId> + <version>5.9.0.202009080501-r</version> + </dependency> + <dependency> + <groupId>org.eclipse.jgit</groupId> + <artifactId>org.eclipse.jgit.ssh.jsch</artifactId> + <version>5.9.0.202009080501-r</version> + </dependency> + <dependency> + <groupId>org.apache.httpcomponents</groupId> + <artifactId>httpclient</artifactId> + <version>4.5.12</version> + </dependency> + <dependency> + <groupId>com.fasterxml.jackson.jaxrs</groupId> + <artifactId>jackson-jaxrs-json-provider</artifactId> + <version>2.11.0</version> + </dependency> + <dependency> + <groupId>com.fasterxml.jackson.datatype</groupId> + <artifactId>jackson-datatype-jsr310</artifactId> + <version>2.11.0</version> + </dependency> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>4.13</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.apache.logging.log4j</groupId> + <artifactId>log4j-slf4j-impl</artifactId> + <version>2.13.2</version> + <scope>test</scope> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-surefire-plugin</artifactId> + <configuration> + <excludes> + <exclude>**/*IT.class</exclude> + </excludes> + </configuration> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-failsafe-plugin</artifactId> + <executions> + <execution> + <id>integration-tests</id> + <phase>integration-test</phase> + <goals> + <goal>integration-test</goal> + </goals> + <configuration> + <includes> + <include>**/*IT.class</include> + </includes> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> </project> diff --git a/src/main/java/me/brianlong/git/LRUExpiringHashMap.java b/src/main/java/me/brianlong/git/LRUExpiringHashMap.java index 6064626..08f4211 100644 --- a/src/main/java/me/brianlong/git/LRUExpiringHashMap.java +++ b/src/main/java/me/brianlong/git/LRUExpiringHashMap.java @@ -9,8 +9,13 @@ import java.util.List; import java.util.Map; import java.util.Set; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + // TODO need to implement the actual expiration schedule public class LRUExpiringHashMap<K extends Serializable, V> implements ListeningMap<K, V> { + + private final Logger logger = LoggerFactory.getLogger(LRUExpiringHashMap.class); private final Map<ExpiringHashKey, V> map; private final List<MapListener<K, V>> listeners = new LinkedList<MapListener<K, V>>(); @@ -28,6 +33,8 @@ public class LRUExpiringHashMap<K extends Serializable, V> implements ListeningM @Override public void addListener(MapListener<K, V> listener) { + if (this.logger.isDebugEnabled()) + this.logger.debug("adding listener"); this.listeners.add(listener); } @@ -140,6 +147,9 @@ public class LRUExpiringHashMap<K extends Serializable, V> implements ListeningM } public void expire(K key) { + if (this.logger.isDebugEnabled()) + this.logger.debug("expiring key from map: " + key); + if (!this.map.containsKey(key)) return; diff --git a/src/main/java/me/brianlong/git/LocalRepositoryCache.java b/src/main/java/me/brianlong/git/LocalRepositoryCache.java index 1ccce39..63bdab4 100644 --- a/src/main/java/me/brianlong/git/LocalRepositoryCache.java +++ b/src/main/java/me/brianlong/git/LocalRepositoryCache.java @@ -2,8 +2,6 @@ package me.brianlong.git; import java.io.File; import java.io.IOException; -import java.util.HashMap; -import java.util.Map; import java.util.Map.Entry; import java.util.UUID; @@ -27,7 +25,7 @@ public class LocalRepositoryCache { 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 Map<String, String> gitIdsToUrls = new HashMap<String, String>(); private final File cacheDirectory = new File(System.getProperty("java.io.tmpdir"), "git"); private LocalRepositoryCache() { @@ -45,8 +43,8 @@ public class LocalRepositoryCache { } private void destroy() { - if (this.logger.isInfoEnabled()) - this.logger.info("destroy()"); + if (this.logger.isDebugEnabled()) + this.logger.debug("clearing local repo cache"); this.clear(); } @@ -63,8 +61,13 @@ public class LocalRepositoryCache { } public synchronized Git acquire(String url, GitCredentials creds, String branch) throws GitAPIException, InvalidRemoteException, RefNotFoundException { - Git git = this.cachedGits.remove(url); - if (git == null) { + 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() @@ -72,29 +75,76 @@ public class LocalRepositoryCache { .setDirectory(gitRepoDirectory); if (branch != null) clone.setBranch(branch); - git = creds != null ? new CredentialedGit(clone, creds) : new CachedGit(clone); - this.gitIdsToUrls.put(git.getRepository().getIdentifier(), url); - } else { - if (branch != null) - git.checkout().setName(branch).call(); - git.pull().call(); - } - - return git; + + if (this.logger.isDebugEnabled()) + this.logger.debug("cloning Git repository: " + url); + return creds != null ? new CredentialedGit(clone, creds) : new CachedGit(clone); +// 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) { - String sshUrl = this.gitIdsToUrls.get(git.getRepository().getIdentifier()); - this.cachedGits.put(sshUrl, 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() { - this.cachedGits.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(); + } } private class RepositoryCacheMapListener implements ExpiringMapListener<String, Git> { + + private final Logger logger = LoggerFactory.getLogger(LocalRepositoryCache.class); @Override public void accessed(Entry<String, Git> entry) { @@ -107,7 +157,9 @@ public class LocalRepositoryCache { @Override public void expired(Entry<String, Git> entry) { - this.expunge(entry.getValue()); + if (this.logger.isTraceEnabled()) + this.logger.trace("expired('" + entry.getKey() + "', '" + entry.getValue().getRepository().getIdentifier() + "')"); + expunge(entry.getValue()); } @Override @@ -117,33 +169,9 @@ public class LocalRepositoryCache { @Override public void cleared(Entry<String, Git> entry) { - this.expunge(entry.getValue()); - } - - private void expunge(Git git) { - gitIdsToUrls.remove(git.getRepository().getIdentifier()); - - File gitDir = git.getRepository().getDirectory(); - File workingTreeDir = git.getRepository().getWorkTree(); - git.getRepository().close(); - - try { - FileUtils.delete(gitDir, FileUtils.RECURSIVE); - } catch (IOException ie) { - logger.warn("Failed to delete a git directory: " + gitDir); - if (logger.isDebugEnabled()) - logger.debug(ie.getMessage(), ie); - gitDir.deleteOnExit(); - } - - try { - FileUtils.delete(workingTreeDir, FileUtils.RECURSIVE); - } catch (IOException ie) { - logger.warn("Failed to delete a git directory: " + workingTreeDir); - if (logger.isDebugEnabled()) - logger.debug(ie.getMessage(), ie); - workingTreeDir.deleteOnExit(); - } + if (this.logger.isTraceEnabled()) + this.logger.trace("cleared('" + entry.getKey() + "', '" + entry.getValue().getRepository().getIdentifier() + "')"); + expunge(entry.getValue()); } } diff --git a/src/test/java/me/brianlong/git/CommandUnitTest.java b/src/test/java/me/brianlong/git/CommandUnitTest.java index 1d09b46..fc48d7b 100644 --- a/src/test/java/me/brianlong/git/CommandUnitTest.java +++ b/src/test/java/me/brianlong/git/CommandUnitTest.java @@ -3,12 +3,14 @@ package me.brianlong.git; import java.io.File; import java.io.IOException; import java.util.List; +import java.util.UUID; import org.eclipse.jgit.api.CloneCommand; import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.ListBranchCommand.ListMode; import org.eclipse.jgit.api.errors.GitAPIException; import org.eclipse.jgit.lib.Ref; +import org.eclipse.jgit.util.FileUtils; import org.junit.AfterClass; import org.junit.Assert; import org.junit.BeforeClass; @@ -23,8 +25,7 @@ public class CommandUnitTest { @BeforeClass public static void init() throws GitAPIException, IOException { - tmpdir = new File(System.getProperty("java.io.tmpdir"), "git.tmp"); - tmpdir.mkdirs(); + tmpdir = new File(System.getProperty("java.io.tmpdir"), "git-" + UUID.randomUUID().toString() + ".tmp"); git = new CloneCommand() .setURI("git@github.com:bmlong137/env-docker-adbp.git") @@ -34,11 +35,10 @@ public class CommandUnitTest { } @AfterClass - public static void cleanup() { - git.getRepository().close(); + public static void cleanup() throws IOException { git.close(); - tmpdir.deleteOnExit(); + FileUtils.delete(tmpdir, FileUtils.RECURSIVE); } @Test diff --git a/src/test/resources/log4j2.xml b/src/test/resources/log4j2.xml index 9ee57d9..7a59c70 100644 --- a/src/test/resources/log4j2.xml +++ b/src/test/resources/log4j2.xml @@ -12,7 +12,7 @@ <Logger name="org.apache.http" level="trace" additivity="false"> <AppenderRef ref="STDOUT" /> </Logger> - <Root level="trace"> + <Root level="info"> <AppenderRef ref="STDOUT"/> </Root> </Loggers>