From 543c5238ae3578f37cb9ada36b95775fa564e41d Mon Sep 17 00:00:00 2001 From: Kevin Sawicki Date: Sun, 1 Apr 2012 18:36:42 -0700 Subject: [PATCH] Recurse into cloned submodules Iterate over all successfully cloned submodules recursively and continue initializing and updating until no more are found. Bug: 375426 Change-Id: Ifb99e41e2deb0c369442bca3c0f5f072dd006816 --- .../eclipse/jgit/api/CloneCommandTest.java | 87 +++++++++++++++++++ .../org/eclipse/jgit/api/CloneCommand.java | 12 ++- 2 files changed, 97 insertions(+), 2 deletions(-) diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CloneCommandTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CloneCommandTest.java index b63a4158f..906a8966f 100644 --- a/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CloneCommandTest.java +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/api/CloneCommandTest.java @@ -69,6 +69,7 @@ import org.eclipse.jgit.storage.file.FileBasedConfig; import org.eclipse.jgit.submodule.SubmoduleStatus; import org.eclipse.jgit.submodule.SubmoduleStatusType; +import org.eclipse.jgit.submodule.SubmoduleWalk; import org.eclipse.jgit.util.SystemReader; import org.junit.Test; @@ -303,6 +304,92 @@ public void testCloneRepositoryWithSubmodules() throws Exception { assertEquals(commit, pathStatus.getIndexId()); } + @Test + public void testCloneRepositoryWithNestedSubmodules() throws Exception { + git.checkout().setName(Constants.MASTER).call(); + + // Create submodule 1 + File submodule1 = createTempDirectory("testCloneRepositoryWithNestedSubmodules1"); + Git sub1Git = Git.init().setDirectory(submodule1).call(); + assertNotNull(sub1Git); + Repository sub1 = sub1Git.getRepository(); + assertNotNull(sub1); + addRepoToClose(sub1); + + String file = "file.txt"; + String path = "sub"; + + write(new File(sub1.getWorkTree(), file), "content"); + sub1Git.add().addFilepattern(file).call(); + RevCommit commit = sub1Git.commit().setMessage("create file").call(); + assertNotNull(commit); + + // Create submodule 2 + File submodule2 = createTempDirectory("testCloneRepositoryWithNestedSubmodules2"); + Git sub2Git = Git.init().setDirectory(submodule2).call(); + assertNotNull(sub2Git); + Repository sub2 = sub2Git.getRepository(); + assertNotNull(sub2); + addRepoToClose(sub2); + + write(new File(sub2.getWorkTree(), file), "content"); + sub2Git.add().addFilepattern(file).call(); + RevCommit sub2Head = sub2Git.commit().setMessage("create file").call(); + assertNotNull(sub2Head); + + // Add submodule 2 to submodule 1 + assertNotNull(sub1Git.submoduleAdd().setPath(path) + .setURI(sub2.getDirectory().toURI().toString()).call()); + RevCommit sub1Head = sub1Git.commit().setAll(true) + .setMessage("Adding submodule").call(); + assertNotNull(sub1Head); + + // Add submodule 1 to default repository + assertNotNull(git.submoduleAdd().setPath(path) + .setURI(sub1.getDirectory().toURI().toString()).call()); + assertNotNull(git.commit().setAll(true).setMessage("Adding submodule") + .call()); + + // Clone default repository and include submodules + File directory = createTempDirectory("testCloneRepositoryWithNestedSubmodules"); + CloneCommand clone = Git.cloneRepository(); + clone.setDirectory(directory); + clone.setCloneSubmodules(true); + clone.setURI(git.getRepository().getDirectory().toURI().toString()); + Git git2 = clone.call(); + addRepoToClose(git2.getRepository()); + assertNotNull(git2); + + assertEquals(Constants.MASTER, git2.getRepository().getBranch()); + assertTrue(new File(git2.getRepository().getWorkTree(), path + + File.separatorChar + file).exists()); + assertTrue(new File(git2.getRepository().getWorkTree(), path + + File.separatorChar + path + File.separatorChar + file) + .exists()); + + SubmoduleStatusCommand status = new SubmoduleStatusCommand( + git2.getRepository()); + Map statuses = status.call(); + SubmoduleStatus pathStatus = statuses.get(path); + assertNotNull(pathStatus); + assertEquals(SubmoduleStatusType.INITIALIZED, pathStatus.getType()); + assertEquals(sub1Head, pathStatus.getHeadId()); + assertEquals(sub1Head, pathStatus.getIndexId()); + + SubmoduleWalk walk = SubmoduleWalk.forIndex(git2.getRepository()); + assertTrue(walk.next()); + Repository clonedSub1 = walk.getRepository(); + assertNotNull(clonedSub1); + status = new SubmoduleStatusCommand(clonedSub1); + statuses = status.call(); + pathStatus = statuses.get(path); + assertNotNull(pathStatus); + assertEquals(SubmoduleStatusType.INITIALIZED, pathStatus.getType()); + assertEquals(sub2Head, pathStatus.getHeadId()); + assertEquals(sub2Head, pathStatus.getIndexId()); + assertFalse(walk.next()); + } + @Test public void testCloneWithAutoSetupRebase() throws Exception { File directory = createTempDirectory("testCloneRepository1"); diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/CloneCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/CloneCommand.java index ef5b7291b..f354de165 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/CloneCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/CloneCommand.java @@ -66,6 +66,7 @@ import org.eclipse.jgit.lib.Repository; import org.eclipse.jgit.revwalk.RevCommit; import org.eclipse.jgit.revwalk.RevWalk; +import org.eclipse.jgit.submodule.SubmoduleWalk; import org.eclipse.jgit.transport.FetchResult; import org.eclipse.jgit.transport.RefSpec; import org.eclipse.jgit.transport.RemoteConfig; @@ -229,7 +230,7 @@ private void checkout(Repository clonedRepo, FetchResult result) } } - private void cloneSubmodules(Repository clonedRepo) { + private void cloneSubmodules(Repository clonedRepo) throws IOException { SubmoduleInitCommand init = new SubmoduleInitCommand(clonedRepo); if (init.call().isEmpty()) return; @@ -237,7 +238,14 @@ private void cloneSubmodules(Repository clonedRepo) { SubmoduleUpdateCommand update = new SubmoduleUpdateCommand(clonedRepo); configure(update); update.setProgressMonitor(monitor); - update.call(); + if (!update.call().isEmpty()) { + SubmoduleWalk walk = SubmoduleWalk.forIndex(clonedRepo); + while (walk.next()) { + Repository subRepo = walk.getRepository(); + if (subRepo != null) + cloneSubmodules(subRepo); + } + } } private Ref findBranchToCheckout(FetchResult result) {