Add support for "jgit archive --output=<filename>"
If the --format option is not given and the output filename is, then infer the format from that filename. Otherwise match "git archive" by defaulting to tar (this is a change from the existing "jgit archive" default behavior, which was to default to zip). Change-Id: I5806bc48a403d05e4cfc3c180b82b33ad7cfae7f
This commit is contained in:
parent
56cb2d925c
commit
1153a59e38
|
@ -46,9 +46,11 @@
|
|||
import static org.junit.Assert.fail;
|
||||
import static org.junit.Assume.assumeNoException;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.IOException;
|
||||
|
@ -91,7 +93,7 @@ public void setUp() throws Exception {
|
|||
@Test
|
||||
public void testEmptyArchive() throws Exception {
|
||||
final byte[] result = CLIGitCommand.rawExecute( //
|
||||
"git archive " + emptyTree, db);
|
||||
"git archive --format=zip " + emptyTree, db);
|
||||
assertArrayEquals(new String[0], listZipEntries(result));
|
||||
}
|
||||
|
||||
|
@ -119,11 +121,171 @@ public void testArchiveWithFiles() throws Exception {
|
|||
git.commit().setMessage("populate toplevel").call();
|
||||
|
||||
final byte[] result = CLIGitCommand.rawExecute( //
|
||||
"git archive HEAD", db);
|
||||
"git archive --format=zip HEAD", db);
|
||||
assertArrayEquals(new String[] { "a", "c" }, //
|
||||
listZipEntries(result));
|
||||
}
|
||||
|
||||
private void commitGreeting() throws Exception {
|
||||
writeTrashFile("greeting", "hello, world!");
|
||||
git.add().addFilepattern("greeting").call();
|
||||
git.commit().setMessage("a commit with a file").call();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDefaultFormatIsTar() throws Exception {
|
||||
commitGreeting();
|
||||
final byte[] result = CLIGitCommand.rawExecute( //
|
||||
"git archive HEAD", db);
|
||||
assertArrayEquals(new String[] { "greeting" }, //
|
||||
listTarEntries(result));
|
||||
}
|
||||
|
||||
private static String shellQuote(String s) {
|
||||
return "'" + s.replace("'", "'\\''") + "'";
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFormatOverridesFilename() throws Exception {
|
||||
final File archive = new File(db.getWorkTree(), "format-overrides-name.tar");
|
||||
final String path = archive.getAbsolutePath();
|
||||
|
||||
commitGreeting();
|
||||
assertArrayEquals(new String[] { "" },
|
||||
execute("git archive " +
|
||||
"--format=zip " +
|
||||
shellQuote("--output=" + path) + " " +
|
||||
"HEAD"));
|
||||
assertContainsEntryWithMode(path, "", "greeting");
|
||||
assertIsZip(archive);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUnrecognizedExtensionMeansTar() throws Exception {
|
||||
final File archive = new File(db.getWorkTree(), "example.txt");
|
||||
final String path = archive.getAbsolutePath();
|
||||
|
||||
commitGreeting();
|
||||
assertArrayEquals(new String[] { "" },
|
||||
execute("git archive " +
|
||||
shellQuote("--output=" + path) + " " +
|
||||
"HEAD"));
|
||||
assertTarContainsEntry(path, "", "greeting");
|
||||
assertIsTar(archive);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoExtensionMeansTar() throws Exception {
|
||||
final File archive = new File(db.getWorkTree(), "example");
|
||||
final String path = archive.getAbsolutePath();
|
||||
|
||||
commitGreeting();
|
||||
assertArrayEquals(new String[] { "" },
|
||||
execute("git archive " +
|
||||
shellQuote("--output=" + path) + " " +
|
||||
"HEAD"));
|
||||
assertIsTar(archive);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExtensionMatchIsAnchored() throws Exception {
|
||||
final File archive = new File(db.getWorkTree(), "two-extensions.zip.bak");
|
||||
final String path = archive.getAbsolutePath();
|
||||
|
||||
commitGreeting();
|
||||
assertArrayEquals(new String[] { "" },
|
||||
execute("git archive " +
|
||||
shellQuote("--output=" + path) + " " +
|
||||
"HEAD"));
|
||||
assertIsTar(archive);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testZipExtension() throws Exception {
|
||||
final File archiveWithDot = new File(db.getWorkTree(), "greeting.zip");
|
||||
final File archiveNoDot = new File(db.getWorkTree(), "greetingzip");
|
||||
|
||||
commitGreeting();
|
||||
execute("git archive " +
|
||||
shellQuote("--output=" + archiveWithDot.getAbsolutePath()) + " " +
|
||||
"HEAD");
|
||||
execute("git archive " +
|
||||
shellQuote("--output=" + archiveNoDot.getAbsolutePath()) + " " +
|
||||
"HEAD");
|
||||
assertIsZip(archiveWithDot);
|
||||
assertIsTar(archiveNoDot);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTarExtension() throws Exception {
|
||||
final File archive = new File(db.getWorkTree(), "tarball.tar");
|
||||
final String path = archive.getAbsolutePath();
|
||||
|
||||
commitGreeting();
|
||||
assertArrayEquals(new String[] { "" },
|
||||
execute("git archive " +
|
||||
shellQuote("--output=" + path) + " " +
|
||||
"HEAD"));
|
||||
assertIsTar(archive);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTgzExtensions() throws Exception {
|
||||
commitGreeting();
|
||||
|
||||
for (String ext : Arrays.asList("tar.gz", "tgz")) {
|
||||
final File archiveWithDot = new File(db.getWorkTree(), "tarball." + ext);
|
||||
final File archiveNoDot = new File(db.getWorkTree(), "tarball" + ext);
|
||||
|
||||
execute("git archive " +
|
||||
shellQuote("--output=" + archiveWithDot.getAbsolutePath()) + " " +
|
||||
"HEAD");
|
||||
execute("git archive " +
|
||||
shellQuote("--output=" + archiveNoDot.getAbsolutePath()) + " " +
|
||||
"HEAD");
|
||||
assertIsGzip(archiveWithDot);
|
||||
assertIsTar(archiveNoDot);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTbz2Extension() throws Exception {
|
||||
commitGreeting();
|
||||
|
||||
for (String ext : Arrays.asList("tar.bz2", "tbz", "tbz2")) {
|
||||
final File archiveWithDot = new File(db.getWorkTree(), "tarball." + ext);
|
||||
final File archiveNoDot = new File(db.getWorkTree(), "tarball" + ext);
|
||||
|
||||
execute("git archive " +
|
||||
shellQuote("--output=" + archiveWithDot.getAbsolutePath()) + " " +
|
||||
"HEAD");
|
||||
execute("git archive " +
|
||||
shellQuote("--output=" + archiveNoDot.getAbsolutePath()) + " " +
|
||||
"HEAD");
|
||||
assertIsBzip2(archiveWithDot);
|
||||
assertIsTar(archiveNoDot);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTxzExtension() throws Exception {
|
||||
commitGreeting();
|
||||
|
||||
for (String ext : Arrays.asList("tar.xz", "txz")) {
|
||||
final File archiveWithDot = new File(db.getWorkTree(), "tarball." + ext);
|
||||
final File archiveNoDot = new File(db.getWorkTree(), "tarball" + ext);
|
||||
|
||||
execute("git archive " +
|
||||
shellQuote("--output=" + archiveWithDot.getAbsolutePath()) + " " +
|
||||
"HEAD");
|
||||
execute("git archive " +
|
||||
shellQuote("--output=" + archiveNoDot.getAbsolutePath()) + " " +
|
||||
"HEAD");
|
||||
assertIsXz(archiveWithDot);
|
||||
assertIsTar(archiveNoDot);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testArchiveWithSubdir() throws Exception {
|
||||
writeTrashFile("a", "a file with content!");
|
||||
|
@ -141,7 +303,7 @@ public void testArchiveWithSubdir() throws Exception {
|
|||
git.commit().setMessage("add subdir").call();
|
||||
|
||||
final byte[] result = CLIGitCommand.rawExecute( //
|
||||
"git archive master", db);
|
||||
"git archive --format=zip master", db);
|
||||
String[] expect = { "a", "b.c", "b0c", "b/a", "b/b", "c" };
|
||||
String[] actual = listZipEntries(result);
|
||||
|
||||
|
@ -195,7 +357,7 @@ public void testArchivePreservesMode() throws Exception {
|
|||
git.commit().setMessage("three files with different modes").call();
|
||||
|
||||
final byte[] zipData = CLIGitCommand.rawExecute( //
|
||||
"git archive master", db);
|
||||
"git archive --format=zip master", db);
|
||||
writeRaw("zip-with-modes.zip", zipData);
|
||||
assertContainsEntryWithMode("zip-with-modes.zip", "-rw-", "plain");
|
||||
assertContainsEntryWithMode("zip-with-modes.zip", "-rwx", "executable");
|
||||
|
@ -238,7 +400,7 @@ public void testArchiveWithLongFilename() throws Exception {
|
|||
git.commit().setMessage("file with long name").call();
|
||||
|
||||
final byte[] result = CLIGitCommand.rawExecute( //
|
||||
"git archive HEAD", db);
|
||||
"git archive --format=zip HEAD", db);
|
||||
assertArrayEquals(new String[] { filename },
|
||||
listZipEntries(result));
|
||||
}
|
||||
|
@ -266,7 +428,7 @@ public void testArchivePreservesContent() throws Exception {
|
|||
git.commit().setMessage("add file with content").call();
|
||||
|
||||
final byte[] result = CLIGitCommand.rawExecute( //
|
||||
"git archive HEAD", db);
|
||||
"git archive --format=zip HEAD", db);
|
||||
assertArrayEquals(new String[] { payload }, //
|
||||
zipEntryContent(result, "xyzzy"));
|
||||
}
|
||||
|
@ -323,6 +485,44 @@ private void grepForEntry(String name, String mode, String... cmdline) //
|
|||
}
|
||||
}
|
||||
|
||||
private void assertMagic(long offset, byte[] magicBytes, File file) throws Exception {
|
||||
BufferedInputStream in = new BufferedInputStream(
|
||||
new FileInputStream(file));
|
||||
try {
|
||||
in.skip(offset);
|
||||
|
||||
byte[] actual = new byte[magicBytes.length];
|
||||
in.read(actual);
|
||||
assertArrayEquals(magicBytes, actual);
|
||||
} finally {
|
||||
in.close();
|
||||
}
|
||||
}
|
||||
|
||||
private void assertMagic(byte[] magicBytes, File file) throws Exception {
|
||||
assertMagic(0, magicBytes, file);
|
||||
}
|
||||
|
||||
private void assertIsTar(File file) throws Exception {
|
||||
assertMagic(257, new byte[] { 'u', 's', 't', 'a', 'r', 0 }, file);
|
||||
}
|
||||
|
||||
private void assertIsZip(File file) throws Exception {
|
||||
assertMagic(new byte[] { 'P', 'K', 3, 4 }, file);
|
||||
}
|
||||
|
||||
private void assertIsGzip(File file) throws Exception {
|
||||
assertMagic(new byte[] { 037, (byte) 0213 }, file);
|
||||
}
|
||||
|
||||
private void assertIsBzip2(File file) throws Exception {
|
||||
assertMagic(new byte[] { 'B', 'Z', 'h' }, file);
|
||||
}
|
||||
|
||||
private void assertIsXz(File file) throws Exception {
|
||||
assertMagic(new byte[] { (byte) 0xfd, '7', 'z', 'X', 'Z', 0 }, file);
|
||||
}
|
||||
|
||||
private void assertContainsEntryWithMode(String zipFilename, String mode, String name) //
|
||||
throws Exception {
|
||||
grepForEntry(name, mode, "zipinfo", zipFilename);
|
||||
|
|
|
@ -43,6 +43,11 @@
|
|||
|
||||
package org.eclipse.jgit.pgm;
|
||||
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import org.eclipse.jgit.api.ArchiveCommand;
|
||||
import org.eclipse.jgit.api.Git;
|
||||
import org.eclipse.jgit.api.errors.GitAPIException;
|
||||
import org.eclipse.jgit.archive.ArchiveFormats;
|
||||
|
@ -62,21 +67,39 @@ class Archive extends TextBuiltin {
|
|||
private ObjectId tree;
|
||||
|
||||
@Option(name = "--format", metaVar = "metaVar_archiveFormat", usage = "usage_archiveFormat")
|
||||
private String format = "zip";
|
||||
private String format;
|
||||
|
||||
@Option(name = "--output", aliases = { "-o" }, metaVar = "metaVar_file", usage = "usage_archiveOutput")
|
||||
private String output;
|
||||
|
||||
@Override
|
||||
protected void run() throws Exception {
|
||||
if (tree == null)
|
||||
throw die(CLIText.get().treeIsRequired);
|
||||
|
||||
OutputStream stream = null;
|
||||
try {
|
||||
new Git(db).archive()
|
||||
if (output != null)
|
||||
stream = new FileOutputStream(output);
|
||||
else
|
||||
stream = outs;
|
||||
|
||||
try {
|
||||
ArchiveCommand cmd = new Git(db).archive()
|
||||
.setTree(tree)
|
||||
.setFormat(format)
|
||||
.setOutputStream(outs)
|
||||
.call();
|
||||
.setOutputStream(stream);
|
||||
if (output != null)
|
||||
cmd.setFilename(output);
|
||||
cmd.call();
|
||||
} catch (GitAPIException e) {
|
||||
throw die(e.getMessage());
|
||||
}
|
||||
} catch (FileNotFoundException e) {
|
||||
throw die(e.getMessage());
|
||||
} finally {
|
||||
if (output != null && stream != null)
|
||||
stream.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue