From 2a18bb304caea46f9fb6fd5e1d37a13f53dc19e4 Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Thu, 10 May 2012 13:32:16 -0700 Subject: [PATCH] Support gitdir: refs in BaseRepositoryBuilder.findGitDir This allows findGitDir to be used for repositories containing a .git file with a gitdir: ref to the repository's directory such as submodule repositories that point to a folder under the parent repository's .git/modules folder Change-Id: I2f1ec7215a2208aa90511c065cadc7e816522f62 Signed-off-by: Chris Aniszczyk --- .../file/FileRepositoryBuilderTest.java | 57 +++++++++++++++++++ .../jgit/lib/BaseRepositoryBuilder.java | 57 +++++++++++-------- 2 files changed, 89 insertions(+), 25 deletions(-) diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/FileRepositoryBuilderTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/FileRepositoryBuilderTest.java index aed48aa5f..b6377482d 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/FileRepositoryBuilderTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/storage/file/FileRepositoryBuilderTest.java @@ -45,13 +45,16 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.io.File; +import java.io.FileWriter; import java.io.IOException; import org.eclipse.jgit.junit.LocalDiskRepositoryTestCase; import org.eclipse.jgit.lib.ConfigConstants; +import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.util.FileUtils; import org.junit.Test; @@ -108,4 +111,58 @@ public void unknownRepositoryFormatVersion() throws Exception { assertNotNull(e.getMessage()); } } + + @Test + public void absoluteGitDirRef() throws Exception { + FileRepository repo1 = createWorkRepository(); + File dir = createTempDirectory("dir"); + File dotGit = new File(dir, Constants.DOT_GIT); + new FileWriter(dotGit).append( + "gitdir: " + repo1.getDirectory().getAbsolutePath()).close(); + FileRepositoryBuilder builder = new FileRepositoryBuilder(); + + builder.setWorkTree(dir); + builder.setMustExist(true); + FileRepository repo2 = builder.build(); + + assertEquals(repo1.getDirectory(), repo2.getDirectory()); + assertEquals(dir, repo2.getWorkTree()); + } + + @Test + public void relativeGitDirRef() throws Exception { + FileRepository repo1 = createWorkRepository(); + File dir = new File(repo1.getWorkTree(), "dir"); + assertTrue(dir.mkdir()); + File dotGit = new File(dir, Constants.DOT_GIT); + new FileWriter(dotGit).append("gitdir: ../" + Constants.DOT_GIT) + .close(); + + FileRepositoryBuilder builder = new FileRepositoryBuilder(); + builder.setWorkTree(dir); + builder.setMustExist(true); + FileRepository repo2 = builder.build(); + + assertEquals(repo1.getDirectory(), repo2.getDirectory()); + assertEquals(dir, repo2.getWorkTree()); + } + + @Test + public void scanWithGitDirRef() throws Exception { + FileRepository repo1 = createWorkRepository(); + File dir = createTempDirectory("dir"); + File dotGit = new File(dir, Constants.DOT_GIT); + new FileWriter(dotGit).append( + "gitdir: " + repo1.getDirectory().getAbsolutePath()).close(); + FileRepositoryBuilder builder = new FileRepositoryBuilder(); + + builder.setWorkTree(dir); + builder.findGitDir(dir); + assertEquals(repo1.getDirectory(), builder.getGitDir()); + builder.setMustExist(true); + FileRepository repo2 = builder.build(); + + assertEquals(repo1.getDirectory(), repo2.getDirectory()); + assertEquals(dir, repo2.getWorkTree()); + } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/lib/BaseRepositoryBuilder.java b/org.eclipse.jgit/src/org/eclipse/jgit/lib/BaseRepositoryBuilder.java index 17e06039b..f80c80360 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/lib/BaseRepositoryBuilder.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/lib/BaseRepositoryBuilder.java @@ -100,6 +100,29 @@ private static boolean isSymRef(byte[] ref) { && ref[7] == ' '; } + private static File getSymRef(File workTree, File dotGit) + throws IOException { + byte[] content = IO.readFully(dotGit); + if (!isSymRef(content)) + throw new IOException(MessageFormat.format( + JGitText.get().invalidGitdirRef, dotGit.getAbsolutePath())); + + int pathStart = 8; + int lineEnd = RawParseUtils.nextLF(content, pathStart); + if (content[lineEnd - 1] == '\n') + lineEnd--; + if (lineEnd == pathStart) + throw new IOException(MessageFormat.format( + JGitText.get().invalidGitdirRef, dotGit.getAbsolutePath())); + + String gitdirPath = RawParseUtils.decode(content, pathStart, lineEnd); + File gitdirFile = new File(gitdirPath); + if (gitdirFile.isAbsolute()) + return gitdirFile; + else + return new File(workTree, gitdirPath).getCanonicalFile(); + } + private FS fs; private File gitDir; @@ -491,7 +514,13 @@ public B findGitDir(File current) { if (FileKey.isGitRepository(dir, tryFS)) { setGitDir(dir); break; - } + } else if (dir.isFile()) + try { + setGitDir(getSymRef(current, dir)); + break; + } catch (IOException ignored) { + // Continue searching if gitdir ref isn't found + } current = current.getParentFile(); if (current != null && ceilingDirectories != null @@ -567,30 +596,8 @@ protected void setupGitDir() throws IOException { File dotGit = new File(getWorkTree(), DOT_GIT); if (!dotGit.isFile()) setGitDir(dotGit); - else { - byte[] content = IO.readFully(dotGit); - if (!isSymRef(content)) - throw new IOException(MessageFormat.format( - JGitText.get().invalidGitdirRef, - dotGit.getAbsolutePath())); - int pathStart = 8; - int lineEnd = RawParseUtils.nextLF(content, pathStart); - if (content[lineEnd - 1] == '\n') - lineEnd--; - if (lineEnd == pathStart) - throw new IOException(MessageFormat.format( - JGitText.get().invalidGitdirRef, - dotGit.getAbsolutePath())); - - String gitdirPath = RawParseUtils.decode(content, pathStart, - lineEnd); - File gitdirFile = new File(gitdirPath); - if (gitdirFile.isAbsolute()) - setGitDir(gitdirFile); - else - setGitDir(new File(getWorkTree(), gitdirPath) - .getCanonicalFile()); - } + else + setGitDir(getSymRef(getWorkTree(), dotGit)); } }