]> source.dussan.org Git - jgit.git/commitdiff
archive: Prepend a specified prefix to all entry filenames 87/19887/3
authorJonathan Nieder <jrn@google.com>
Tue, 17 Dec 2013 19:22:46 +0000 (11:22 -0800)
committerJonathan Nieder <jrn@google.com>
Tue, 17 Dec 2013 19:22:46 +0000 (11:22 -0800)
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>
org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/ArchiveTest.java
org.eclipse.jgit.pgm/resources/org/eclipse/jgit/pgm/internal/CLIText.properties
org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Archive.java
org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/internal/CLIText.java
org.eclipse.jgit/src/org/eclipse/jgit/api/ArchiveCommand.java

index 87137b475fab6c552f2a7438388c80aa334aa1d9..816094aef9b8b2910b204fa414a7b6e7e4c2c12b 100644 (file)
@@ -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");
index d23f37899344c2713674951994755718cf8dd44e..1d2a8971f7c37d4b1af8d57638b1cbb0600f3f70 100644 (file)
@@ -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
index 7b88a943450ed196214c4baff9607123c5b079ee..80bb9ec9df1e1fc81b7eebe37adbec1d9aa0e855 100644 (file)
@@ -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);
index a51313ae1e50cb813db87f0025e3361693ce4bb4..c42e5fb59d1ea8063fa0eee5a5f8bebda610dc7d 100644 (file)
@@ -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;
index 42d0f6512d5253cfaf8e23b67b74adbcbe936aad..c17330e6f165f1ebb7d0bf0941c157a8d73a9a05 100644 (file)
@@ -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)
@@ -329,6 +331,18 @@ public class ArchiveCommand extends GitCommand<OutputStream> {
                return this;
        }
 
+       /**
+        * @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