]> source.dussan.org Git - jgit.git/commitdiff
ArchiveCommand: make archive formats non-inner classes 61/12561/7
authorJonathan Nieder <jrn@google.com>
Fri, 24 May 2013 01:08:35 +0000 (18:08 -0700)
committerJonathan Nieder <jrn@google.com>
Fri, 24 May 2013 01:08:35 +0000 (18:08 -0700)
First step toward making ArchiveCommand itself format-agnostic.

Change-Id: I3cff5fce28fa7a19e34f8291cfb5b62f16429713

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/archive/ArchiveCommand.java
org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/archive/TarFormat.java [new file with mode: 0644]
org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/archive/ZipFormat.java [new file with mode: 0644]
org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/internal/CLIText.java
org.eclipse.jgit/src/org/eclipse/jgit/api/errors/GitAPIException.java

index bcf2728524926995b0e8b8c95a5c794bad5b73b9..cb2a7258a60642803dda011f736312f1cb782557 100644 (file)
@@ -102,6 +102,13 @@ public class ArchiveTest extends CLIRepositoryTestCase {
                assertArrayEquals(new String[0], listTarEntries(result));
        }
 
+       @Test
+       public void testUnrecognizedFormat() throws Exception {
+               final String[] expect = new String[] { "fatal: Unknown archive format 'nonsense'" };
+               final String[] actual = execute("git archive --format=nonsense " + emptyTree);
+               assertArrayEquals(expect, actual);
+       }
+
        @Test
        public void testArchiveWithFiles() throws Exception {
                writeTrashFile("a", "a file with content!");
index cdf7123959ecc349031cf9f187d7491120e3744b..3fa167e95a8d5eb85cd54e15a3b9cc05b79f3191 100644 (file)
@@ -173,6 +173,7 @@ tooManyRefsGiven=Too many refs given
 unknownIoErrorStdout=An unknown I/O error occurred on standard output
 unknownMergeStrategy=unknown merge strategy {0} specified
 unmergedPaths=Unmerged paths:
+unsupportedArchiveFormat=Unknown archive format ''{0}''
 unsupportedOperation=Unsupported operation: {0}
 untrackedFiles=Untracked files:
 updating=Updating {0}..{1}
index 815c96bfe1a9070abbc5ce609c7ccd53e419a65a..6d4f5aa5145466296d5f346f3b9f4b0de7b32924 100644 (file)
@@ -43,6 +43,7 @@
 
 package org.eclipse.jgit.pgm;
 
+import org.eclipse.jgit.api.errors.GitAPIException;
 import org.eclipse.jgit.lib.ObjectId;
 import org.eclipse.jgit.pgm.TextBuiltin;
 import org.eclipse.jgit.pgm.archive.ArchiveCommand;
@@ -56,7 +57,7 @@ class Archive extends TextBuiltin {
        private ObjectId tree;
 
        @Option(name = "--format", metaVar = "metaVar_archiveFormat", usage = "usage_archiveFormat")
-       private ArchiveCommand.Format format = ArchiveCommand.Format.ZIP;
+       private String format = "zip";
 
        @Override
        protected void run() throws Exception {
@@ -68,6 +69,8 @@ class Archive extends TextBuiltin {
                        cmd.setTree(tree)
                                        .setFormat(format)
                                        .setOutputStream(outs).call();
+               } catch (GitAPIException e) {
+                       throw die(e.getMessage());
                } finally {
                        cmd.release();
                }
index 1235d0ae06161de94596805790bdf9894e63b4d7..ff5b0d0cd3a9e8c5a4f02f83ed3e7a018a1cdb5d 100644 (file)
@@ -44,15 +44,11 @@ package org.eclipse.jgit.pgm.archive;
 
 import java.io.IOException;
 import java.io.OutputStream;
-import java.util.EnumMap;
-import java.util.Map;
+import java.text.MessageFormat;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
 
 import org.apache.commons.compress.archivers.ArchiveOutputStream;
-import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
-import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
-import org.apache.commons.compress.archivers.tar.TarConstants;
-import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
-import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;
 import org.eclipse.jgit.api.Git;
 import org.eclipse.jgit.api.GitCommand;
 import org.eclipse.jgit.api.errors.GitAPIException;
@@ -89,7 +85,7 @@ import org.eclipse.jgit.treewalk.TreeWalk;
  * <pre>
  * try {
  *     cmd.setTree(db.resolve(&quot;master&quot;))
- *             .setFormat(ArchiveCommand.Format.ZIP)
+ *             .setFormat("zip")
  *             .setOutputStream(out).call();
  * } finally {
  *     cmd.release();
@@ -103,91 +99,69 @@ import org.eclipse.jgit.treewalk.TreeWalk;
  */
 public class ArchiveCommand extends GitCommand<OutputStream> {
        /**
-        * Available archival formats (corresponding to values for
-        * the --format= option)
+        * Archival format.
+        *
+        * Usage:
+        *      Repository repo = git.getRepository();
+        *      ArchiveOutputStream out = format.createArchiveOutputStream(System.out);
+        *      try {
+        *              for (...) {
+        *                      format.putEntry(path, mode, repo.open(objectId), out);
+        *              }
+        *      } finally {
+        *              out.close();
+        *      }
         */
-       public static enum Format {
-               /** Zip format */
-               ZIP,
-
-               /** Posix TAR-format */
-               TAR
-       }
-
-       private static interface Archiver {
+       public static interface Format {
                ArchiveOutputStream createArchiveOutputStream(OutputStream s);
                void putEntry(String path, FileMode mode, //
                                ObjectLoader loader, ArchiveOutputStream out) //
                                throws IOException;
        }
 
-       private static final Map<Format, Archiver> formats;
+       /**
+        * Signals an attempt to use an archival format that ArchiveCommand
+        * doesn't know about (for example due to a typo).
+        */
+       public static class UnsupportedFormatException extends GitAPIException {
+               private static final long serialVersionUID = 1L;
 
-       static {
-               Map<Format, Archiver> fmts = new EnumMap<Format, Archiver>(Format.class);
-               fmts.put(Format.ZIP, new Archiver() {
-                       public ArchiveOutputStream createArchiveOutputStream(OutputStream s) {
-                               return new ZipArchiveOutputStream(s);
-                       }
+               private final String format;
 
-                       public void putEntry(String path, FileMode mode, //
-                                       ObjectLoader loader, ArchiveOutputStream out) //
-                                       throws IOException {
-                               final ZipArchiveEntry entry = new ZipArchiveEntry(path);
+               /**
+                * @param format the problematic format name
+                */
+               public UnsupportedFormatException(String format) {
+                       super(MessageFormat.format(CLIText.get().unsupportedArchiveFormat, format));
+                       this.format = format;
+               }
 
-                               if (mode == FileMode.REGULAR_FILE) {
-                                       // ok
-                               } else if (mode == FileMode.EXECUTABLE_FILE
-                                               || mode == FileMode.SYMLINK) {
-                                       entry.setUnixMode(mode.getBits());
-                               } else {
-                                       // TODO(jrn): Let the caller know the tree contained
-                                       // an entry with unsupported mode (e.g., a submodule).
-                               }
-                               entry.setSize(loader.getSize());
-                               out.putArchiveEntry(entry);
-                               loader.copyTo(out);
-                               out.closeArchiveEntry();
-                       }
-               });
-               fmts.put(Format.TAR, new Archiver() {
-                       public ArchiveOutputStream createArchiveOutputStream(OutputStream s) {
-                               return new TarArchiveOutputStream(s);
-                       }
+               /**
+                * @return the problematic format name
+                */
+               public String getFormat() {
+                       return format;
+               }
+       }
 
-                       public void putEntry(String path, FileMode mode, //
-                                       ObjectLoader loader, ArchiveOutputStream out) //
-                                       throws IOException {
-                               if (mode == FileMode.SYMLINK) {
-                                       final TarArchiveEntry entry = new TarArchiveEntry( //
-                                                       path, TarConstants.LF_SYMLINK);
-                                       entry.setLinkName(new String( //
-                                                       loader.getCachedBytes(100), "UTF-8")); //$NON-NLS-1$
-                                       out.putArchiveEntry(entry);
-                                       out.closeArchiveEntry();
-                                       return;
-                               }
+       private static final ConcurrentMap<String, Format> formats =
+                       new ConcurrentHashMap<String, Format>();
 
-                               final TarArchiveEntry entry = new TarArchiveEntry(path);
-                               if (mode == FileMode.REGULAR_FILE ||
-                                   mode == FileMode.EXECUTABLE_FILE) {
-                                       entry.setMode(mode.getBits());
-                               } else {
-                                       // TODO(jrn): Let the caller know the tree contained
-                                       // an entry with unsupported mode (e.g., a submodule).
-                               }
-                               entry.setSize(loader.getSize());
-                               out.putArchiveEntry(entry);
-                               loader.copyTo(out);
-                               out.closeArchiveEntry();
-                       }
-               });
-               formats = fmts;
+       static {
+               formats.put("zip", new ZipFormat());
+               formats.put("tar", new TarFormat());
+       }
+
+       private static Format lookupFormat(String formatName) throws UnsupportedFormatException {
+               Format fmt = formats.get(formatName);
+               if (fmt == null)
+                       throw new UnsupportedFormatException(formatName);
+               return fmt;
        }
 
        private OutputStream out;
        private TreeWalk walk;
-       private Format format = Format.TAR;
+       private String format = "tar";
 
        /**
         * @param repo
@@ -213,7 +187,7 @@ public class ArchiveCommand extends GitCommand<OutputStream> {
        @Override
        public OutputStream call() throws GitAPIException {
                final MutableObjectId idBuf = new MutableObjectId();
-               final Archiver fmt = formats.get(format);
+               final Format fmt = lookupFormat(format);
                final ArchiveOutputStream outa = fmt.createArchiveOutputStream(out);
                final ObjectReader reader = walk.getObjectReader();
 
@@ -268,10 +242,10 @@ public class ArchiveCommand extends GitCommand<OutputStream> {
 
        /**
         * @param fmt
-        *            archive format (e.g., Format.TAR)
+        *            archive format (e.g., "tar" or "zip")
         * @return this
         */
-       public ArchiveCommand setFormat(Format fmt) {
+       public ArchiveCommand setFormat(String fmt) {
                this.format = fmt;
                return this;
        }
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/archive/TarFormat.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/archive/TarFormat.java
new file mode 100644 (file)
index 0000000..c27fb35
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2012 Google Inc.
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ *   copyright notice, this list of conditions and the following
+ *   disclaimer in the documentation and/or other materials provided
+ *   with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ *   names of its contributors may be used to endorse or promote
+ *   products derived from this software without specific prior
+ *   written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.eclipse.jgit.pgm.archive;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.commons.compress.archivers.ArchiveOutputStream;
+import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
+import org.apache.commons.compress.archivers.tar.TarArchiveOutputStream;
+import org.apache.commons.compress.archivers.tar.TarConstants;
+import org.eclipse.jgit.lib.FileMode;
+import org.eclipse.jgit.lib.ObjectLoader;
+
+class TarFormat implements ArchiveCommand.Format {
+       public ArchiveOutputStream createArchiveOutputStream(OutputStream s) {
+               return new TarArchiveOutputStream(s);
+       }
+
+       public void putEntry(String path, FileMode mode, ObjectLoader loader,
+                               ArchiveOutputStream out) throws IOException {
+               if (mode == FileMode.SYMLINK) {
+                       final TarArchiveEntry entry = new TarArchiveEntry(
+                                       path, TarConstants.LF_SYMLINK);
+                       entry.setLinkName(new String(
+                                       loader.getCachedBytes(100), "UTF-8")); //$NON-NLS-1$
+                       out.putArchiveEntry(entry);
+                       out.closeArchiveEntry();
+                       return;
+               }
+
+               final TarArchiveEntry entry = new TarArchiveEntry(path);
+               if (mode == FileMode.REGULAR_FILE ||
+                   mode == FileMode.EXECUTABLE_FILE) {
+                       entry.setMode(mode.getBits());
+               } else {
+                       // TODO(jrn): Let the caller know the tree contained
+                       // an entry with unsupported mode (e.g., a submodule).
+               }
+               entry.setSize(loader.getSize());
+               out.putArchiveEntry(entry);
+               loader.copyTo(out);
+               out.closeArchiveEntry();
+       }
+}
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/archive/ZipFormat.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/archive/ZipFormat.java
new file mode 100644 (file)
index 0000000..d08428f
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2012 Google Inc.
+ * and other copyright owners as documented in the project's IP log.
+ *
+ * This program and the accompanying materials are made available
+ * under the terms of the Eclipse Distribution License v1.0 which
+ * accompanies this distribution, is reproduced below, and is
+ * available at http://www.eclipse.org/org/documents/edl-v10.php
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or
+ * without modification, are permitted provided that the following
+ * conditions are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ *
+ * - Redistributions in binary form must reproduce the above
+ *   copyright notice, this list of conditions and the following
+ *   disclaimer in the documentation and/or other materials provided
+ *   with the distribution.
+ *
+ * - Neither the name of the Eclipse Foundation, Inc. nor the
+ *   names of its contributors may be used to endorse or promote
+ *   products derived from this software without specific prior
+ *   written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
+ * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+package org.eclipse.jgit.pgm.archive;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+import org.apache.commons.compress.archivers.ArchiveOutputStream;
+import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
+import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;
+import org.eclipse.jgit.lib.FileMode;
+import org.eclipse.jgit.lib.ObjectLoader;
+
+class ZipFormat implements ArchiveCommand.Format {
+       public ArchiveOutputStream createArchiveOutputStream(OutputStream s) {
+               return new ZipArchiveOutputStream(s);
+       }
+
+       public void putEntry(String path, FileMode mode, ObjectLoader loader,
+                               ArchiveOutputStream out) throws IOException {
+               final ZipArchiveEntry entry = new ZipArchiveEntry(path);
+
+               if (mode == FileMode.REGULAR_FILE) {
+                       // ok
+               } else if (mode == FileMode.EXECUTABLE_FILE
+                               || mode == FileMode.SYMLINK) {
+                       entry.setUnixMode(mode.getBits());
+               } else {
+                       // TODO(jrn): Let the caller know the tree contained
+                       // an entry with unsupported mode (e.g., a submodule).
+               }
+               entry.setSize(loader.getSize());
+               out.putArchiveEntry(entry);
+               loader.copyTo(out);
+               out.closeArchiveEntry();
+       }
+}
index 62865d51c1af2d08322ff295d6f219ca9c94835d..937707bd32dd16474b0269111830a5507489d32c 100644 (file)
@@ -236,6 +236,7 @@ public class CLIText extends TranslationBundle {
        /***/ public char[] unknownIoErrorStdout;
        /***/ public String unknownMergeStrategy;
        /***/ public String unmergedPaths;
+       /***/ public String unsupportedArchiveFormat;
        /***/ public String unsupportedOperation;
        /***/ public String untrackedFiles;
        /***/ public String updating;
index ba38529ab3dbe7ab5c28d1ca6f04d88ded22666c..92599ca7d6c914847b7fa6762c7ce5a119c35301 100644 (file)
@@ -45,11 +45,19 @@ package org.eclipse.jgit.api.errors;
 public abstract class GitAPIException extends Exception {
        private static final long serialVersionUID = 1L;
 
-       GitAPIException(String message, Throwable cause) {
+       /**
+        * Constructs a new exception with the specified detail
+        * message and cause.
+        */
+       protected GitAPIException(String message, Throwable cause) {
                super(message, cause);
        }
 
-       GitAPIException(String message) {
+       /**
+        * Constructs a new exception with the specified detail
+        * message and no cause.
+        */
+       protected GitAPIException(String message) {
                super(message);
        }
 }