First step toward making ArchiveCommand itself format-agnostic.
Change-Id: I3cff5fce28fa7a19e34f8291cfb5b62f16429713
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!");
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}
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;
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 {
cmd.setTree(tree)
.setFormat(format)
.setOutputStream(outs).call();
+ } catch (GitAPIException e) {
+ throw die(e.getMessage());
} finally {
cmd.release();
}
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;
* <pre>
* try {
* cmd.setTree(db.resolve("master"))
- * .setFormat(ArchiveCommand.Format.ZIP)
+ * .setFormat("zip")
* .setOutputStream(out).call();
* } finally {
* cmd.release();
*/
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
@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();
/**
* @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;
}
--- /dev/null
+/*
+ * 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();
+ }
+}
--- /dev/null
+/*
+ * 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();
+ }
+}
/***/ public char[] unknownIoErrorStdout;
/***/ public String unknownMergeStrategy;
/***/ public String unmergedPaths;
+ /***/ public String unsupportedArchiveFormat;
/***/ public String unsupportedOperation;
/***/ public String untrackedFiles;
/***/ public String updating;
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);
}
}