Browse Source

ArchiveCommand: make archive formats non-inner classes

First step toward making ArchiveCommand itself format-agnostic.

Change-Id: I3cff5fce28fa7a19e34f8291cfb5b62f16429713
stable-3.1
Jonathan Nieder 11 years ago
parent
commit
d4932620e0
  1. 7
      org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/ArchiveTest.java
  2. 1
      org.eclipse.jgit.pgm/resources/org/eclipse/jgit/pgm/internal/CLIText.properties
  3. 5
      org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Archive.java
  4. 134
      org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/archive/ArchiveCommand.java
  5. 85
      org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/archive/TarFormat.java
  6. 77
      org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/archive/ZipFormat.java
  7. 1
      org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/internal/CLIText.java
  8. 12
      org.eclipse.jgit/src/org/eclipse/jgit/api/errors/GitAPIException.java

7
org.eclipse.jgit.pgm.test/tst/org/eclipse/jgit/pgm/ArchiveTest.java

@ -102,6 +102,13 @@ public class ArchiveTest extends CLIRepositoryTestCase {
assertArrayEquals(new String[0], listTarEntries(result)); 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 @Test
public void testArchiveWithFiles() throws Exception { public void testArchiveWithFiles() throws Exception {
writeTrashFile("a", "a file with content!"); writeTrashFile("a", "a file with content!");

1
org.eclipse.jgit.pgm/resources/org/eclipse/jgit/pgm/internal/CLIText.properties

@ -173,6 +173,7 @@ tooManyRefsGiven=Too many refs given
unknownIoErrorStdout=An unknown I/O error occurred on standard output unknownIoErrorStdout=An unknown I/O error occurred on standard output
unknownMergeStrategy=unknown merge strategy {0} specified unknownMergeStrategy=unknown merge strategy {0} specified
unmergedPaths=Unmerged paths: unmergedPaths=Unmerged paths:
unsupportedArchiveFormat=Unknown archive format ''{0}''
unsupportedOperation=Unsupported operation: {0} unsupportedOperation=Unsupported operation: {0}
untrackedFiles=Untracked files: untrackedFiles=Untracked files:
updating=Updating {0}..{1} updating=Updating {0}..{1}

5
org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Archive.java

@ -43,6 +43,7 @@
package org.eclipse.jgit.pgm; package org.eclipse.jgit.pgm;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.pgm.TextBuiltin; import org.eclipse.jgit.pgm.TextBuiltin;
import org.eclipse.jgit.pgm.archive.ArchiveCommand; import org.eclipse.jgit.pgm.archive.ArchiveCommand;
@ -56,7 +57,7 @@ class Archive extends TextBuiltin {
private ObjectId tree; private ObjectId tree;
@Option(name = "--format", metaVar = "metaVar_archiveFormat", usage = "usage_archiveFormat") @Option(name = "--format", metaVar = "metaVar_archiveFormat", usage = "usage_archiveFormat")
private ArchiveCommand.Format format = ArchiveCommand.Format.ZIP; private String format = "zip";
@Override @Override
protected void run() throws Exception { protected void run() throws Exception {
@ -68,6 +69,8 @@ class Archive extends TextBuiltin {
cmd.setTree(tree) cmd.setTree(tree)
.setFormat(format) .setFormat(format)
.setOutputStream(outs).call(); .setOutputStream(outs).call();
} catch (GitAPIException e) {
throw die(e.getMessage());
} finally { } finally {
cmd.release(); cmd.release();
} }

134
org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/archive/ArchiveCommand.java

@ -44,15 +44,11 @@ package org.eclipse.jgit.pgm.archive;
import java.io.IOException; import java.io.IOException;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.EnumMap; import java.text.MessageFormat;
import java.util.Map; import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import org.apache.commons.compress.archivers.ArchiveOutputStream; 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.Git;
import org.eclipse.jgit.api.GitCommand; import org.eclipse.jgit.api.GitCommand;
import org.eclipse.jgit.api.errors.GitAPIException; import org.eclipse.jgit.api.errors.GitAPIException;
@ -89,7 +85,7 @@ import org.eclipse.jgit.treewalk.TreeWalk;
* <pre> * <pre>
* try { * try {
* cmd.setTree(db.resolve(&quot;master&quot;)) * cmd.setTree(db.resolve(&quot;master&quot;))
* .setFormat(ArchiveCommand.Format.ZIP) * .setFormat("zip")
* .setOutputStream(out).call(); * .setOutputStream(out).call();
* } finally { * } finally {
* cmd.release(); * cmd.release();
@ -103,91 +99,69 @@ import org.eclipse.jgit.treewalk.TreeWalk;
*/ */
public class ArchiveCommand extends GitCommand<OutputStream> { public class ArchiveCommand extends GitCommand<OutputStream> {
/** /**
* Available archival formats (corresponding to values for * Archival format.
* the --format= option) *
* 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 { public static interface Format {
/** Zip format */
ZIP,
/** Posix TAR-format */
TAR
}
private static interface Archiver {
ArchiveOutputStream createArchiveOutputStream(OutputStream s); ArchiveOutputStream createArchiveOutputStream(OutputStream s);
void putEntry(String path, FileMode mode, // void putEntry(String path, FileMode mode, //
ObjectLoader loader, ArchiveOutputStream out) // ObjectLoader loader, ArchiveOutputStream out) //
throws IOException; 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 { private final String format;
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);
}
public void putEntry(String path, FileMode mode, // /**
ObjectLoader loader, ArchiveOutputStream out) // * @param format the problematic format name
throws IOException { */
final ZipArchiveEntry entry = new ZipArchiveEntry(path); public UnsupportedFormatException(String format) {
super(MessageFormat.format(CLIText.get().unsupportedArchiveFormat, format));
this.format = format;
}
if (mode == FileMode.REGULAR_FILE) { /**
// ok * @return the problematic format name
} else if (mode == FileMode.EXECUTABLE_FILE */
|| mode == FileMode.SYMLINK) { public String getFormat() {
entry.setUnixMode(mode.getBits()); return format;
} 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);
}
public void putEntry(String path, FileMode mode, // private static final ConcurrentMap<String, Format> formats =
ObjectLoader loader, ArchiveOutputStream out) // new ConcurrentHashMap<String, Format>();
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); static {
if (mode == FileMode.REGULAR_FILE || formats.put("zip", new ZipFormat());
mode == FileMode.EXECUTABLE_FILE) { formats.put("tar", new TarFormat());
entry.setMode(mode.getBits()); }
} else {
// TODO(jrn): Let the caller know the tree contained private static Format lookupFormat(String formatName) throws UnsupportedFormatException {
// an entry with unsupported mode (e.g., a submodule). Format fmt = formats.get(formatName);
} if (fmt == null)
entry.setSize(loader.getSize()); throw new UnsupportedFormatException(formatName);
out.putArchiveEntry(entry); return fmt;
loader.copyTo(out);
out.closeArchiveEntry();
}
});
formats = fmts;
} }
private OutputStream out; private OutputStream out;
private TreeWalk walk; private TreeWalk walk;
private Format format = Format.TAR; private String format = "tar";
/** /**
* @param repo * @param repo
@ -213,7 +187,7 @@ public class ArchiveCommand extends GitCommand<OutputStream> {
@Override @Override
public OutputStream call() throws GitAPIException { public OutputStream call() throws GitAPIException {
final MutableObjectId idBuf = new MutableObjectId(); final MutableObjectId idBuf = new MutableObjectId();
final Archiver fmt = formats.get(format); final Format fmt = lookupFormat(format);
final ArchiveOutputStream outa = fmt.createArchiveOutputStream(out); final ArchiveOutputStream outa = fmt.createArchiveOutputStream(out);
final ObjectReader reader = walk.getObjectReader(); final ObjectReader reader = walk.getObjectReader();
@ -268,10 +242,10 @@ public class ArchiveCommand extends GitCommand<OutputStream> {
/** /**
* @param fmt * @param fmt
* archive format (e.g., Format.TAR) * archive format (e.g., "tar" or "zip")
* @return this * @return this
*/ */
public ArchiveCommand setFormat(Format fmt) { public ArchiveCommand setFormat(String fmt) {
this.format = fmt; this.format = fmt;
return this; return this;
} }

85
org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/archive/TarFormat.java

@ -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();
}
}

77
org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/archive/ZipFormat.java

@ -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();
}
}

1
org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/internal/CLIText.java

@ -236,6 +236,7 @@ public class CLIText extends TranslationBundle {
/***/ public char[] unknownIoErrorStdout; /***/ public char[] unknownIoErrorStdout;
/***/ public String unknownMergeStrategy; /***/ public String unknownMergeStrategy;
/***/ public String unmergedPaths; /***/ public String unmergedPaths;
/***/ public String unsupportedArchiveFormat;
/***/ public String unsupportedOperation; /***/ public String unsupportedOperation;
/***/ public String untrackedFiles; /***/ public String untrackedFiles;
/***/ public String updating; /***/ public String updating;

12
org.eclipse.jgit/src/org/eclipse/jgit/api/errors/GitAPIException.java

@ -45,11 +45,19 @@ package org.eclipse.jgit.api.errors;
public abstract class GitAPIException extends Exception { public abstract class GitAPIException extends Exception {
private static final long serialVersionUID = 1L; 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); super(message, cause);
} }
GitAPIException(String message) { /**
* Constructs a new exception with the specified detail
* message and no cause.
*/
protected GitAPIException(String message) {
super(message); super(message);
} }
} }

Loading…
Cancel
Save