From 1aa6e081ffe319ff3ddfa246783cb65dc1c71b3b Mon Sep 17 00:00:00 2001
From: James Moger <james.moger@gitblit.com>
Date: Wed, 28 Mar 2012 17:57:35 -0400
Subject: [PATCH] Fixed symlink absolute path/canonical path mixup with JGit (issue 78)

---
 docs/04_releases.mkd                            |    6 ++++++
 tests/com/gitblit/tests/IssuesTest.java         |    5 ++---
 tests/com/gitblit/tests/LuceneExecutorTest.java |    5 +++--
 src/com/gitblit/GitServlet.java                 |    5 ++---
 src/com/gitblit/utils/FileUtils.java            |   29 +++++++++++++++++++++++++++++
 src/com/gitblit/utils/JGitUtils.java            |    4 ++--
 6 files changed, 44 insertions(+), 10 deletions(-)

diff --git a/docs/04_releases.mkd b/docs/04_releases.mkd
index 51d3a1a..322aed4 100644
--- a/docs/04_releases.mkd
+++ b/docs/04_releases.mkd
@@ -6,6 +6,12 @@
 
 #### fixes
 
+- Fixed absolute path/canonical path discrepancy between Gitblit and JGit regarding use of symlinks (issue 78)
+
+**0.9.1** *released 2012-03-27*
+
+#### fixes
+
 - Lucene folder was stored in working copy instead of in .git folder
 
 **0.9.0** *released 2012-03-27*
diff --git a/src/com/gitblit/GitServlet.java b/src/com/gitblit/GitServlet.java
index 3b60e9f..73c6eaa 100644
--- a/src/com/gitblit/GitServlet.java
+++ b/src/com/gitblit/GitServlet.java
@@ -50,6 +50,7 @@
 
 import com.gitblit.models.RepositoryModel;
 import com.gitblit.models.UserModel;
+import com.gitblit.utils.FileUtils;
 import com.gitblit.utils.HttpUtils;
 import com.gitblit.utils.StringUtils;
 
@@ -207,9 +208,7 @@
 		 */
 		protected RepositoryModel getRepositoryModel(ReceivePack rp) {
 			Repository repository = rp.getRepository();
-			String rootPath = GitBlit.getRepositoriesFolder().getAbsolutePath();
-			String repositoryName = StringUtils.getRelativePath(rootPath, repository.getDirectory()
-					.getAbsolutePath());
+			String repositoryName = FileUtils.getRelativePath(GitBlit.getRepositoriesFolder(), repository.getDirectory());
 			RepositoryModel model = GitBlit.self().getRepositoryModel(repositoryName);
 			return model;
 		}
diff --git a/src/com/gitblit/utils/FileUtils.java b/src/com/gitblit/utils/FileUtils.java
index 29c9d0f..f8d35c8 100644
--- a/src/com/gitblit/utils/FileUtils.java
+++ b/src/com/gitblit/utils/FileUtils.java
@@ -149,4 +149,33 @@
 			}
 		}
 	}
+	
+	/**
+	 * Determine the relative path between two files.  Takes into account
+	 * canonical paths, if possible.
+	 * 
+	 * @param basePath
+	 * @param path
+	 * @return a relative path from basePath to path
+	 */
+	public static String getRelativePath(File basePath, File path) {
+		File exactBase = getExactFile(basePath);
+		File exactPath = getExactFile(path);
+		return StringUtils.getRelativePath(exactBase.getPath(), exactPath.getPath());
+	}
+	
+	/**
+	 * Returns the exact path for a file. This path will be the canonical path
+	 * unless an exception is thrown in which case it will be the absolute path.
+	 * 
+	 * @param path
+	 * @return the exact file
+	 */
+	public static File getExactFile(File path) {
+		try {
+			return path.getCanonicalFile();
+		} catch (IOException e) {
+			return path.getAbsoluteFile();
+		}
+	}
 }
diff --git a/src/com/gitblit/utils/JGitUtils.java b/src/com/gitblit/utils/JGitUtils.java
index f495a38..72e948c 100644
--- a/src/com/gitblit/utils/JGitUtils.java
+++ b/src/com/gitblit/utils/JGitUtils.java
@@ -301,6 +301,7 @@
 	 */
 	private static List<String> getRepositoryList(String basePath, File searchFolder,
 			boolean onlyBare, boolean searchSubfolders) {
+		File baseFile = new File(basePath);
 		List<String> list = new ArrayList<String>();
 		for (File file : searchFolder.listFiles()) {
 			if (file.isDirectory()) {
@@ -310,8 +311,7 @@
 						continue;
 					}
 					// determine repository name relative to base path
-					String repository = StringUtils.getRelativePath(basePath,
-							file.getAbsolutePath());
+					String repository = FileUtils.getRelativePath(baseFile, file);
 					list.add(repository);
 				} else if (searchSubfolders && file.canRead()) {
 					// look for repositories in subfolders
diff --git a/tests/com/gitblit/tests/IssuesTest.java b/tests/com/gitblit/tests/IssuesTest.java
index e329f66..11f9551 100644
--- a/tests/com/gitblit/tests/IssuesTest.java
+++ b/tests/com/gitblit/tests/IssuesTest.java
@@ -34,9 +34,9 @@
 import com.gitblit.models.IssueModel.Priority;
 import com.gitblit.models.IssueModel.Status;
 import com.gitblit.models.SearchResult;
+import com.gitblit.utils.FileUtils;
 import com.gitblit.utils.IssueUtils;
 import com.gitblit.utils.IssueUtils.IssueFilter;
-import com.gitblit.utils.StringUtils;
 
 /**
  * Tests the mechanics of distributed issue management on the gb-issues branch.
@@ -49,8 +49,7 @@
 	@Test
 	public void testLifecycle() throws Exception {
 		Repository repository = GitBlitSuite.getIssuesTestRepository();
-		String name = StringUtils.getRelativePath(GitBlitSuite.REPOSITORIES.getAbsolutePath(),
-				repository.getDirectory().getAbsolutePath());
+		String name = FileUtils.getRelativePath(GitBlitSuite.REPOSITORIES, repository.getDirectory());
 		
 		// create and insert an issue
 		Change c1 = newChange("testCreation() " + Long.toHexString(System.currentTimeMillis()));
diff --git a/tests/com/gitblit/tests/LuceneExecutorTest.java b/tests/com/gitblit/tests/LuceneExecutorTest.java
index d221744..ec81fd8 100644
--- a/tests/com/gitblit/tests/LuceneExecutorTest.java
+++ b/tests/com/gitblit/tests/LuceneExecutorTest.java
@@ -23,10 +23,12 @@
 import org.eclipse.jgit.lib.Repository;
 import org.junit.Test;
 
+import com.gitblit.GitBlit;
 import com.gitblit.LuceneExecutor;
 import com.gitblit.models.RefModel;
 import com.gitblit.models.RepositoryModel;
 import com.gitblit.models.SearchResult;
+import com.gitblit.utils.FileUtils;
 import com.gitblit.utils.JGitUtils;
 import com.gitblit.utils.StringUtils;
 
@@ -44,8 +46,7 @@
 	
 	private RepositoryModel newRepositoryModel(Repository repository) {		
 		RepositoryModel model = new RepositoryModel();
-		model.name = StringUtils.getRelativePath(GitBlitSuite.REPOSITORIES.getAbsolutePath(),
-				repository.getDirectory().getAbsolutePath());
+		model.name = FileUtils.getRelativePath(GitBlitSuite.REPOSITORIES, repository.getDirectory());
 		model.hasCommits = JGitUtils.hasCommits(repository);
 		
 		// index all local branches

--
Gitblit v1.9.1