summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJonathan Nieder <jrn@google.com>2013-12-17 11:22:46 -0800
committerJonathan Nieder <jrn@google.com>2013-12-17 11:22:46 -0800
commitf2abbd0ea99aed638ca098e336f60f52bc923237 (patch)
treef35a719bc3f26b8c80a21135d443625608ad088b
parentaad7dee3ef492e9333581e8d6b2269dc091ea1d2 (diff)
downloadjgit-f2abbd0ea99aed638ca098e336f60f52bc923237.tar.gz
jgit-f2abbd0ea99aed638ca098e336f60f52bc923237.zip
archive: Prepend a specified prefix to all entry filenames
Common practice when distributing tarballs is to prefix all entries with a single directory name so when the tarball is extracted it all falls neatly into a single directory. Add a setPrefix() method to ArchiveCommand to support this. Change-Id: I16b2832ef98c30977f6b77b646728b83d93c196f Signed-off-by: Jonathan Nieder <jrn@google.com>
-rw-r--r--org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/ArchiveTest.java93
-rw-r--r--org.eclipse.jgit.pgm/resources/org/eclipse/jgit/pgm/internal/CLIText.properties2
-rw-r--r--org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Archive.java4
-rw-r--r--org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/internal/CLIText.java1
-rw-r--r--org.eclipse.jgit/src/org/eclipse/jgit/api/ArchiveCommand.java16
5 files changed, 115 insertions, 1 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 87137b475f..816094aef9 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
@@ -338,6 +338,99 @@ public class ArchiveTest extends CLIRepositoryTestCase {
assertArrayEquals(expect, actual);
}
+ private void commitBazAndFooSlashBar() throws Exception {
+ writeTrashFile("baz", "a file");
+ writeTrashFile("foo/bar", "another file");
+ git.add().addFilepattern("baz").call();
+ git.add().addFilepattern("foo").call();
+ git.commit().setMessage("sample commit").call();
+ }
+
+ @Test
+ public void testArchivePrefixOption() throws Exception {
+ commitBazAndFooSlashBar();
+ byte[] result = CLIGitCommand.rawExecute(
+ "git archive --prefix=x/ --format=zip master", db);
+ String[] expect = { "x/baz", "x/foo/bar" };
+ String[] actual = listZipEntries(result);
+
+ Arrays.sort(expect);
+ Arrays.sort(actual);
+ assertArrayEquals(expect, actual);
+ }
+
+ @Test
+ public void testTarPrefixOption() throws Exception {
+ commitBazAndFooSlashBar();
+ byte[] result = CLIGitCommand.rawExecute(
+ "git archive --prefix=x/ --format=tar master", db);
+ String[] expect = { "x/baz", "x/foo/bar" };
+ String[] actual = listTarEntries(result);
+
+ Arrays.sort(expect);
+ Arrays.sort(actual);
+ assertArrayEquals(expect, actual);
+ }
+
+ private void commitFoo() throws Exception {
+ writeTrashFile("foo", "a file");
+ git.add().addFilepattern("foo").call();
+ git.commit().setMessage("boring commit").call();
+ }
+
+ @Test
+ public void testPrefixDoesNotNormalizeDoubleSlash() throws Exception {
+ commitFoo();
+ byte[] result = CLIGitCommand.rawExecute(
+ "git archive --prefix=x// --format=zip master", db);
+ String[] expect = { "x//foo" };
+ assertArrayEquals(expect, listZipEntries(result));
+ }
+
+ @Test
+ public void testPrefixDoesNotNormalizeDoubleSlashInTar() throws Exception {
+ commitFoo();
+ final byte[] result = CLIGitCommand.rawExecute( //
+ "git archive --prefix=x// --format=tar master", db);
+ String[] expect = { "x//foo" };
+ assertArrayEquals(expect, listTarEntries(result));
+ }
+
+ /**
+ * The prefix passed to "git archive" need not end with '/'.
+ * In practice it is not very common to have a nonempty prefix
+ * that does not name a directory (and hence end with /), but
+ * since git has historically supported other prefixes, we do,
+ * too.
+ *
+ * @throws Exception
+ */
+ @Test
+ public void testPrefixWithoutTrailingSlash() throws Exception {
+ commitBazAndFooSlashBar();
+ byte[] result = CLIGitCommand.rawExecute(
+ "git archive --prefix=my- --format=zip master", db);
+ String[] expect = { "my-baz", "my-foo/bar" };
+ String[] actual = listZipEntries(result);
+
+ Arrays.sort(expect);
+ Arrays.sort(actual);
+ assertArrayEquals(expect, actual);
+ }
+
+ @Test
+ public void testTarPrefixWithoutTrailingSlash() throws Exception {
+ commitBazAndFooSlashBar();
+ final byte[] result = CLIGitCommand.rawExecute( //
+ "git archive --prefix=my- --format=tar master", db);
+ String[] expect = { "my-baz", "my-foo/bar" };
+ 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");
diff --git a/org.eclipse.jgit.pgm/resources/org/eclipse/jgit/pgm/internal/CLIText.properties b/org.eclipse.jgit.pgm/resources/org/eclipse/jgit/pgm/internal/CLIText.properties
index d23f378993..1d2a8971f7 100644
--- a/org.eclipse.jgit.pgm/resources/org/eclipse/jgit/pgm/internal/CLIText.properties
+++ b/org.eclipse.jgit.pgm/resources/org/eclipse/jgit/pgm/internal/CLIText.properties
@@ -74,6 +74,7 @@ mergeWentWellStoppedBeforeCommitting=Automatic merge went well; stopped before c
metaVar_DAG=DAG
metaVar_KEY=KEY
metaVar_archiveFormat=format
+metaVar_archivePrefix=prefix/
metaVar_arg=ARG
metaVar_author=AUTHOR
metaVar_base=base
@@ -229,6 +230,7 @@ usage_approveDestructionOfRepository=approve destruction of repository
usage_archive=zip up files from the named tree
usage_archiveFormat=archive format. Currently supported formats: 'tar', 'zip', 'tgz', 'tbz2', 'txz'
usage_archiveOutput=output file to write the archive to
+usage_archivePrefix=string to prepend to each pathname in the archive
usage_blameLongRevision=show long revision
usage_blameRange=annotate only the given range
usage_blameRawTimestamp=show raw timestamp
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Archive.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Archive.java
index 7b88a94345..80bb9ec9df 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Archive.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Archive.java
@@ -69,6 +69,9 @@ class Archive extends TextBuiltin {
@Option(name = "--format", metaVar = "metaVar_archiveFormat", usage = "usage_archiveFormat")
private String format;
+ @Option(name = "--prefix", metaVar = "metaVar_archivePrefix", usage = "usage_archivePrefix")
+ private String prefix;
+
@Option(name = "--output", aliases = { "-o" }, metaVar = "metaVar_file", usage = "usage_archiveOutput")
private String output;
@@ -88,6 +91,7 @@ class Archive extends TextBuiltin {
ArchiveCommand cmd = new Git(db).archive()
.setTree(tree)
.setFormat(format)
+ .setPrefix(prefix)
.setOutputStream(stream);
if (output != null)
cmd.setFilename(output);
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/internal/CLIText.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/internal/CLIText.java
index a51313ae1e..c42e5fb59d 100644
--- a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/internal/CLIText.java
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/internal/CLIText.java
@@ -143,6 +143,7 @@ public class CLIText extends TranslationBundle {
/***/ public String mergeWentWellStoppedBeforeCommitting;
/***/ public String metaVar_KEY;
/***/ public String metaVar_archiveFormat;
+ /***/ public String metaVar_archivePrefix;
/***/ public String metaVar_arg;
/***/ public String metaVar_author;
/***/ public String metaVar_bucket;
diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/ArchiveCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/ArchiveCommand.java
index 42d0f6512d..c17330e6f1 100644
--- a/org.eclipse.jgit/src/org/eclipse/jgit/api/ArchiveCommand.java
+++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/ArchiveCommand.java
@@ -250,6 +250,7 @@ public class ArchiveCommand extends GitCommand<OutputStream> {
private OutputStream out;
private ObjectId tree;
+ private String prefix;
private String format;
/** Filename suffix, for automatically choosing a format. */
@@ -264,6 +265,7 @@ public class ArchiveCommand extends GitCommand<OutputStream> {
}
private <T extends Closeable> OutputStream writeArchive(Format<T> fmt) {
+ final String pfx = prefix == null ? "" : prefix;
final TreeWalk walk = new TreeWalk(repo);
try {
final T outa = fmt.createArchiveOutputStream(out);
@@ -275,7 +277,7 @@ public class ArchiveCommand extends GitCommand<OutputStream> {
walk.reset(rw.parseTree(tree));
walk.setRecursive(true);
while (walk.next()) {
- final String name = walk.getPathString();
+ final String name = pfx + walk.getPathString();
final FileMode mode = walk.getFileMode(0);
if (mode == FileMode.TREE)
@@ -330,6 +332,18 @@ public class ArchiveCommand extends GitCommand<OutputStream> {
}
/**
+ * @param prefix
+ * string prefixed to filenames in archive (e.g., "master/").
+ * null means to not use any leading prefix.
+ * @return this
+ * @since 3.3
+ */
+ public ArchiveCommand setPrefix(String prefix) {
+ this.prefix = prefix;
+ return this;
+ }
+
+ /**
* Set the intended filename for the produced archive. Currently the only
* effect is to determine the default archive format when none is specified
* with {@link #setFormat(String)}.