From dd6f08950e36694d9757adc84ed6805620d0c032 Mon Sep 17 00:00:00 2001
From: James Moger <james.moger@gitblit.com>
Date: Wed, 20 Jul 2011 21:06:17 -0400
Subject: [PATCH] Fixed rename and delete repository (issue 10)

---
 src/com/gitblit/GitBlit.java |   41 ++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 40 insertions(+), 1 deletions(-)

diff --git a/src/com/gitblit/GitBlit.java b/src/com/gitblit/GitBlit.java
index e570e7b..c54fbe1 100644
--- a/src/com/gitblit/GitBlit.java
+++ b/src/com/gitblit/GitBlit.java
@@ -17,6 +17,7 @@
 
 import java.io.File;
 import java.io.IOException;
+import java.lang.reflect.Field;
 import java.text.MessageFormat;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -24,6 +25,7 @@
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
+import java.util.concurrent.atomic.AtomicInteger;
 
 import javax.servlet.ServletContextEvent;
 import javax.servlet.ServletContextListener;
@@ -141,7 +143,7 @@
 	public static char getChar(String key, char defaultValue) {
 		return self().settings.getChar(key, defaultValue);
 	}
-	
+
 	/**
 	 * Returns the string value for the specified key. If the key does not exist
 	 * or the value for the key can not be interpreted as a string, the
@@ -478,6 +480,41 @@
 	}
 
 	/**
+	 * Ensure that a cached repository is completely closed and its resources
+	 * are properly released.
+	 * 
+	 * @param repositoryName
+	 */
+	private void closeRepository(String repositoryName) {
+		Repository repository = getRepository(repositoryName);
+		// assume 2 uses in case reflection fails
+		int uses = 2;
+		try {
+			// The FileResolver caches repositories which is very useful
+			// for performance until you want to delete a repository.
+			// I have to use reflection to call close() the correct
+			// number of times to ensure that the object and ref databases
+			// are properly closed before I can delete the repository from
+			// the filesystem.
+			Field useCnt = Repository.class.getDeclaredField("useCnt");
+			useCnt.setAccessible(true);
+			uses = ((AtomicInteger) useCnt.get(repository)).get();
+		} catch (Exception e) {
+			logger.warn(MessageFormat
+					.format("Failed to reflectively determine use count for repository {0}",
+							repositoryName), e);
+		}
+		if (uses > 0) {
+			logger.info(MessageFormat
+					.format("{0}.useCnt={1}, calling close() {2} time(s) to close object and ref databases",
+							repositoryName, uses, uses));
+			for (int i = 0; i < uses; i++) {
+				repository.close();
+			}
+		}
+	}
+
+	/**
 	 * Returns the gitblit string vlaue for the specified key. If key is not
 	 * set, returns defaultValue.
 	 * 
@@ -540,6 +577,7 @@
 		} else {
 			// rename repository
 			if (!repositoryName.equalsIgnoreCase(repository.name)) {
+				closeRepository(repositoryName);
 				File folder = new File(repositoriesFolder, repositoryName);
 				File destFolder = new File(repositoriesFolder, repository.name);
 				if (destFolder.exists()) {
@@ -615,6 +653,7 @@
 	 */
 	public boolean deleteRepository(String repositoryName) {
 		try {
+			closeRepository(repositoryName);
 			File folder = new File(repositoriesFolder, repositoryName);
 			if (folder.exists() && folder.isDirectory()) {
 				FileUtils.delete(folder, FileUtils.RECURSIVE | FileUtils.RETRY);

--
Gitblit v1.9.1