]> source.dussan.org Git - jgit.git/commitdiff
archive: Use an empty directory for submodules 49/17949/7
authorJonathan Nieder <jrn@google.com>
Sat, 2 Nov 2013 03:28:58 +0000 (20:28 -0700)
committerJonathan Nieder <jrn@google.com>
Fri, 27 Dec 2013 17:02:53 +0000 (09:02 -0800)
When encountering a submodule entry, "jgit archive" tries to write its
content verbatim as an entry to the archive, which fails with a
JGitInternalException wrapping a MissingObjectException because the
submodule repository commits are typically not part of the
superproject.

When a subproject is available (for example because it has been
checked out as a subdirectory of a superproject worktree), it would be
nice to recurse into it and make one archive recording the state of
the entire project.  Unfortunately sometimes the subproject is not
available or it can be hard to find (e.g., it can be on another
server).  Even when some subprojects are available, "jgit archive"
should not produce different output for the same tree depending on
which subprojects it has easy access to, so there is no obvious good
default behavior that recurses without relying on access to all
subprojects.

Instead, replace each submodule entry with a placeholder empty
directory.  "git archive" does the same.

Change-Id: I1295086037b77fc948b3f93c21d47341e25483e5
Signed-off-by: Jonathan Nieder <jrn@google.com>
org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/ArchiveTest.java
org.eclipse.jgit/src/org/eclipse/jgit/api/ArchiveCommand.java

index 30f875ca5255dfc297a7d516e23f0184b1fde8bf..cf22ca2f1d8544279c9931355832f208a95ea8d2 100644 (file)
@@ -432,6 +432,46 @@ public class ArchiveTest extends CLIRepositoryTestCase {
                assertArrayEquals(expect, actual);
        }
 
+       @Test
+       public void testArchiveIncludesSubmoduleDirectory() throws Exception {
+               writeTrashFile("a", "a file with content!");
+               writeTrashFile("c", "after submodule");
+               git.add().addFilepattern("a").call();
+               git.add().addFilepattern("c").call();
+               git.commit().setMessage("initial commit").call();
+               git.submoduleAdd().setURI("./.").setPath("b").call().close();
+               git.commit().setMessage("add submodule").call();
+
+               final byte[] result = CLIGitCommand.rawExecute( //
+                               "git archive --format=zip master", db);
+               String[] expect = { ".gitmodules", "a", "b/", "c" };
+               String[] actual = listZipEntries(result);
+
+               Arrays.sort(expect);
+               Arrays.sort(actual);
+               assertArrayEquals(expect, actual);
+       }
+
+       @Test
+       public void testTarIncludesSubmoduleDirectory() throws Exception {
+               writeTrashFile("a", "a file with content!");
+               writeTrashFile("c", "after submodule");
+               git.add().addFilepattern("a").call();
+               git.add().addFilepattern("c").call();
+               git.commit().setMessage("initial commit").call();
+               git.submoduleAdd().setURI("./.").setPath("b").call().close();
+               git.commit().setMessage("add submodule").call();
+
+               final byte[] result = CLIGitCommand.rawExecute( //
+                               "git archive --format=tar master", db);
+               String[] expect = { ".gitmodules", "a", "b/", "c" };
+               String[] actual = listTarEntries(result);
+
+               Arrays.sort(expect);
+               Arrays.sort(actual);
+               assertArrayEquals(expect, actual);
+       }
+
        @Test
        public void testArchivePreservesMode() throws Exception {
                writeTrashFile("plain", "a file with content");
index 2e6b50a6a53a25a7a9ac802af5a983519323b476..ed91ae22e88c868825607c59ab9732c1a8539b4e 100644 (file)
@@ -279,11 +279,18 @@ public class ArchiveCommand extends GitCommand<OutputStream> {
                                walk.reset(rw.parseTree(tree));
                                while (walk.next()) {
                                        final String name = pfx + walk.getPathString();
-                                       final FileMode mode = walk.getFileMode(0);
+                                       FileMode mode = walk.getFileMode(0);
 
-                                       if (walk.isSubtree()) {
-                                               fmt.putEntry(outa, name + "/", mode, null);
+                                       if (walk.isSubtree())
                                                walk.enterSubtree();
+
+                                       if (mode == FileMode.GITLINK)
+                                               // TODO(jrn): Take a callback to recurse
+                                               // into submodules.
+                                               mode = FileMode.TREE;
+
+                                       if (mode == FileMode.TREE) {
+                                               fmt.putEntry(outa, name + "/", mode, null);
                                                continue;
                                        }
                                        walk.getObjectId(idBuf, 0);