diff options
author | Jonathan Nieder <jrn@google.com> | 2012-12-03 16:08:04 -0800 |
---|---|---|
committer | Jonathan Nieder <jrn@google.com> | 2012-12-04 15:37:42 -0800 |
commit | 78009782cdabdba42841f2a71fbd5867f2ae683f (patch) | |
tree | a17f08bb0f076ba41fd019b731083ea7e4a5ae60 /org.eclipse.jgit.pgm.test/tst/org/eclipse | |
parent | 345ab401ce27e9d4cb4002edd7f8e732b5e2e6fc (diff) | |
download | jgit-78009782cdabdba42841f2a71fbd5867f2ae683f.tar.gz jgit-78009782cdabdba42841f2a71fbd5867f2ae683f.zip |
archive: Add tar support
Unlike ZIP files, tar files do not treat symlinks as ordinary files
with a different mode, so tar support involves a little more code than
would be ideal.
Change-Id: Ica2568f4a0e443bf4b955ef0c029bc8eec62d369
Diffstat (limited to 'org.eclipse.jgit.pgm.test/tst/org/eclipse')
-rw-r--r-- | org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/ArchiveTest.java | 167 |
1 files changed, 160 insertions, 7 deletions
diff --git a/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/ArchiveTest.java b/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/ArchiveTest.java index cad379774e..bcf2728524 100644 --- a/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/ArchiveTest.java +++ b/org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/ArchiveTest.java @@ -53,11 +53,15 @@ import java.io.FileOutputStream; import java.io.InputStreamReader; import java.io.IOException; import java.io.OutputStream; - +import java.lang.Object; import java.lang.String; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.concurrent.Callable; +import java.util.concurrent.Executors; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Future; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; @@ -92,6 +96,13 @@ public class ArchiveTest extends CLIRepositoryTestCase { } @Test + public void testEmptyTar() throws Exception { + final byte[] result = CLIGitCommand.rawExecute( // + "git archive --format=tar " + emptyTree, db); + assertArrayEquals(new String[0], listTarEntries(result)); + } + + @Test public void testArchiveWithFiles() throws Exception { writeTrashFile("a", "a file with content!"); writeTrashFile("c", ""); // empty file @@ -133,6 +144,32 @@ public class ArchiveTest extends CLIRepositoryTestCase { } @Test + public void testTarWithSubdir() throws Exception { + writeTrashFile("a", "a file with content!"); + writeTrashFile("b.c", "before subdir in git sort order"); + writeTrashFile("b0c", "after subdir in git sort order"); + writeTrashFile("c", ""); + git.add().addFilepattern("a").call(); + git.add().addFilepattern("b.c").call(); + git.add().addFilepattern("b0c").call(); + git.add().addFilepattern("c").call(); + git.commit().setMessage("populate toplevel").call(); + writeTrashFile("b/b", "file in subdirectory"); + writeTrashFile("b/a", "another file in subdirectory"); + git.add().addFilepattern("b").call(); + git.commit().setMessage("add subdir").call(); + + final byte[] result = CLIGitCommand.rawExecute( // + "git archive --format=tar master", db); + String[] expect = { "a", "b.c", "b0c", "b/a", "b/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"); writeTrashFile("executable", "an executable file"); @@ -159,6 +196,32 @@ public class ArchiveTest extends CLIRepositoryTestCase { } @Test + public void testTarPreservesMode() throws Exception { + writeTrashFile("plain", "a file with content"); + writeTrashFile("executable", "an executable file"); + writeTrashFile("symlink", "plain"); + git.add().addFilepattern("plain").call(); + git.add().addFilepattern("executable").call(); + git.add().addFilepattern("symlink").call(); + + DirCache cache = db.lockDirCache(); + cache.getEntry("executable").setFileMode(FileMode.EXECUTABLE_FILE); + cache.getEntry("symlink").setFileMode(FileMode.SYMLINK); + cache.write(); + cache.commit(); + cache.unlock(); + + git.commit().setMessage("three files with different modes").call(); + + final byte[] archive = CLIGitCommand.rawExecute( // + "git archive --format=tar master", db); + writeRaw("with-modes.tar", archive); + assertTarContainsEntry("with-modes.tar", "-rw-r--r--", "plain"); + assertTarContainsEntry("with-modes.tar", "-rwxr-xr-x", "executable"); + assertTarContainsEntry("with-modes.tar", "l", "symlink -> plain"); + } + + @Test public void testArchivePreservesContent() throws Exception { final String payload = "“The quick brown fox jumps over the lazy dog!”"; writeTrashFile("xyzzy", payload); @@ -171,23 +234,45 @@ public class ArchiveTest extends CLIRepositoryTestCase { zipEntryContent(result, "xyzzy")); } - private void assertContainsEntryWithMode(String zipFilename, String mode, String name) // - throws Exception { + @Test + public void testTarPreservesContent() throws Exception { + final String payload = "“The quick brown fox jumps over the lazy dog!”"; + writeTrashFile("xyzzy", payload); + git.add().addFilepattern("xyzzy").call(); + git.commit().setMessage("add file with content").call(); + + final byte[] result = CLIGitCommand.rawExecute( // + "git archive --format=tar HEAD", db); + assertArrayEquals(new String[] { payload }, // + tarEntryContent(result, "xyzzy")); + } + + private Process spawnAssumingCommandPresent(String... cmdline) { final File cwd = db.getWorkTree(); - final ProcessBuilder procBuilder = new ProcessBuilder("zipinfo", zipFilename) // + final ProcessBuilder procBuilder = new ProcessBuilder(cmdline) // .directory(cwd) // .redirectErrorStream(true); Process proc = null; try { proc = procBuilder.start(); } catch (IOException e) { - // On machines without a "zipinfo" command, let the test pass. + // On machines without `cmdline[0]`, let the test pass. assumeNoException(e); } - proc.getOutputStream().close(); - final BufferedReader reader = new BufferedReader( // + return proc; + } + + private BufferedReader readFromProcess(Process proc) throws Exception { + return new BufferedReader( // new InputStreamReader(proc.getInputStream(), "UTF-8")); + } + + private void grepForEntry(String name, String mode, String... cmdline) // + throws Exception { + final Process proc = spawnAssumingCommandPresent(cmdline); + proc.getOutputStream().close(); + final BufferedReader reader = readFromProcess(proc); try { String line; while ((line = reader.readLine()) != null) @@ -201,6 +286,16 @@ public class ArchiveTest extends CLIRepositoryTestCase { } } + private void assertContainsEntryWithMode(String zipFilename, String mode, String name) // + throws Exception { + grepForEntry(name, mode, "zipinfo", zipFilename); + } + + private void assertTarContainsEntry(String tarfile, String mode, String name) // + throws Exception { + grepForEntry(name, mode, "tar", "tvf", tarfile); + } + private void writeRaw(String filename, byte[] data) // throws IOException { final File path = new File(db.getWorkTree(), filename); @@ -224,6 +319,43 @@ public class ArchiveTest extends CLIRepositoryTestCase { return l.toArray(new String[l.size()]); } + private static Future<Object> writeAsync(final OutputStream stream, final byte[] data) { + final ExecutorService executor = Executors.newSingleThreadExecutor(); + + return executor.submit(new Callable<Object>() { // + public Object call() throws IOException { + try { + stream.write(data); + return null; + } finally { + stream.close(); + } + } + }); + } + + private String[] listTarEntries(byte[] tarData) throws Exception { + final List<String> l = new ArrayList<String>(); + final Process proc = spawnAssumingCommandPresent("tar", "tf", "-"); + final BufferedReader reader = readFromProcess(proc); + final OutputStream out = proc.getOutputStream(); + + // Dump tarball to tar stdin in background + final Future<?> writing = writeAsync(out, tarData); + + try { + String line; + while ((line = reader.readLine()) != null) + l.add(line); + + return l.toArray(new String[l.size()]); + } finally { + writing.get(); + reader.close(); + proc.destroy(); + } + } + private static String[] zipEntryContent(byte[] zipData, String path) // throws IOException { final ZipInputStream in = new ZipInputStream( // @@ -246,4 +378,25 @@ public class ArchiveTest extends CLIRepositoryTestCase { // not found return null; } + + private String[] tarEntryContent(byte[] tarData, String path) // + throws Exception { + final List<String> l = new ArrayList<String>(); + final Process proc = spawnAssumingCommandPresent("tar", "Oxf", "-", path); + final BufferedReader reader = readFromProcess(proc); + final OutputStream out = proc.getOutputStream(); + final Future<?> writing = writeAsync(out, tarData); + + try { + String line; + while ((line = reader.readLine()) != null) + l.add(line); + + return l.toArray(new String[l.size()]); + } finally { + writing.get(); + reader.close(); + proc.destroy(); + } + } } |