Pick default archive format based on filename suffix

Introduce a setFilename() method for ArchiveCommand so callers can
specify the intended filename of the produced archive.  If the
filename ends with .tar, the format will default to tar; if .zip, zip;
if .tar.gz, gzip-compressed tar; and so on.

This doesn't affect "jgit archive" because it doesn't support the
--output=<file> option yet.  A later patch might do that.

Change-Id: Ic0236a70f7aa7f2271c3ef11083b21ee986b4df5
This commit is contained in:
Jonathan Nieder 2013-06-06 18:39:04 -07:00
parent ebfe85d037
commit 56cb2d925c
6 changed files with 111 additions and 3 deletions

View File

@ -44,6 +44,9 @@
import java.io.IOException;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.apache.commons.compress.archivers.ArchiveOutputStream;
import org.apache.commons.compress.archivers.tar.TarArchiveEntry;
@ -57,6 +60,9 @@
* Unix TAR format (ustar + some PAX extensions).
*/
public class TarFormat implements ArchiveCommand.Format<ArchiveOutputStream> {
private static final List<String> SUFFIXES =
Collections.unmodifiableList(Arrays.asList(".tar"));
public ArchiveOutputStream createArchiveOutputStream(OutputStream s) {
TarArchiveOutputStream out = new TarArchiveOutputStream(s, "UTF-8"); //$NON-NLS-1$
out.setLongFileMode(TarArchiveOutputStream.LONGFILE_POSIX);
@ -90,4 +96,8 @@ public void putEntry(ArchiveOutputStream out,
loader.copyTo(out);
out.closeArchiveEntry();
}
public Iterable<String> suffixes() {
return SUFFIXES;
}
}

View File

@ -44,6 +44,9 @@
import java.io.IOException;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.apache.commons.compress.archivers.ArchiveOutputStream;
import org.apache.commons.compress.compressors.bzip2.BZip2CompressorOutputStream;
@ -55,6 +58,10 @@
* bzip2-compressed tarball (tar.bz2) format.
*/
public class Tbz2Format implements ArchiveCommand.Format<ArchiveOutputStream> {
private static final List<String> SUFFIXES =
Collections.unmodifiableList(Arrays.asList(
".tar.bz2", ".tbz", ".tbz2"));
private final ArchiveCommand.Format<ArchiveOutputStream> tarFormat = new TarFormat();
public ArchiveOutputStream createArchiveOutputStream(OutputStream s)
@ -68,4 +75,8 @@ public void putEntry(ArchiveOutputStream out,
throws IOException {
tarFormat.putEntry(out, path, mode, loader);
}
public Iterable<String> suffixes() {
return SUFFIXES;
}
}

View File

@ -44,6 +44,9 @@
import java.io.IOException;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.apache.commons.compress.archivers.ArchiveOutputStream;
import org.apache.commons.compress.compressors.gzip.GzipCompressorOutputStream;
@ -55,6 +58,10 @@
* gzip-compressed tarball (tar.gz) format.
*/
public class TgzFormat implements ArchiveCommand.Format<ArchiveOutputStream> {
private static final List<String> SUFFIXES =
Collections.unmodifiableList(Arrays.asList(
".tar.gz", ".tgz"));
private final ArchiveCommand.Format<ArchiveOutputStream> tarFormat = new TarFormat();
public ArchiveOutputStream createArchiveOutputStream(OutputStream s)
@ -68,4 +75,8 @@ public void putEntry(ArchiveOutputStream out,
throws IOException {
tarFormat.putEntry(out, path, mode, loader);
}
public Iterable<String> suffixes() {
return SUFFIXES;
}
}

View File

@ -44,6 +44,9 @@
import java.io.IOException;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.apache.commons.compress.archivers.ArchiveOutputStream;
import org.apache.commons.compress.compressors.xz.XZCompressorOutputStream;
@ -55,6 +58,10 @@
* Xz-compressed tar (tar.xz) format.
*/
public class TxzFormat implements ArchiveCommand.Format<ArchiveOutputStream> {
private static final List<String> SUFFIXES =
Collections.unmodifiableList(Arrays.asList(
".tar.xz", ".txz"));
private final ArchiveCommand.Format<ArchiveOutputStream> tarFormat = new TarFormat();
public ArchiveOutputStream createArchiveOutputStream(OutputStream s)
@ -68,4 +75,8 @@ public void putEntry(ArchiveOutputStream out,
throws IOException {
tarFormat.putEntry(out, path, mode, loader);
}
public Iterable<String> suffixes() {
return SUFFIXES;
}
}

View File

@ -44,6 +44,9 @@
import java.io.IOException;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.apache.commons.compress.archivers.ArchiveOutputStream;
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
@ -56,6 +59,9 @@
* PKWARE's ZIP format.
*/
public class ZipFormat implements ArchiveCommand.Format<ArchiveOutputStream> {
private static final List<String> SUFFIXES =
Collections.unmodifiableList(Arrays.asList(".zip"));
public ArchiveOutputStream createArchiveOutputStream(OutputStream s) {
return new ZipArchiveOutputStream(s);
}
@ -79,4 +85,8 @@ public void putEntry(ArchiveOutputStream out,
loader.copyTo(out);
out.closeArchiveEntry();
}
public Iterable<String> suffixes() {
return SUFFIXES;
}
}

View File

@ -46,6 +46,8 @@
import java.io.IOException;
import java.io.OutputStream;
import java.text.MessageFormat;
import java.util.Collection;
import java.util.Iterator;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
@ -151,6 +153,18 @@ public static interface Format<T extends Closeable> {
*/
void putEntry(T out, String path, FileMode mode,
ObjectLoader loader) throws IOException;
/**
* Filename suffixes representing this format (e.g.,
* { ".tar.gz", ".tgz" }).
*
* The behavior is undefined when suffixes overlap (if
* one format claims suffix ".7z", no other format should
* take ".tar.7z").
*
* @return this format's suffixes
*/
Iterable<String> suffixes();
}
/**
@ -199,6 +213,8 @@ public String getFormat() {
* An archival format with that name was already registered.
*/
public static void registerFormat(String name, Format<?> fmt) {
// TODO(jrn): Check that suffixes don't overlap.
if (formats.putIfAbsent(name, fmt) != null)
throw new JGitInternalException(MessageFormat.format(
JGitText.get().archiveFormatAlreadyRegistered,
@ -220,6 +236,16 @@ public static void unregisterFormat(String name) {
name));
}
private static Format<?> formatBySuffix(String filenameSuffix)
throws UnsupportedFormatException {
if (filenameSuffix != null)
for (Format<?> fmt : formats.values())
for (String sfx : fmt.suffixes())
if (filenameSuffix.endsWith(sfx))
return fmt;
return lookupFormat("tar");
}
private static Format<?> lookupFormat(String formatName) throws UnsupportedFormatException {
Format<?> fmt = formats.get(formatName);
if (fmt == null)
@ -229,7 +255,10 @@ private static Format<?> lookupFormat(String formatName) throws UnsupportedForma
private OutputStream out;
private ObjectId tree;
private String format = "tar";
private String format;
/** Filename suffix, for automatically choosing a format. */
private String suffix;
/**
* @param repo
@ -282,7 +311,11 @@ private <T extends Closeable> OutputStream writeArchive(Format<T> fmt) {
public OutputStream call() throws GitAPIException {
checkCallable();
final Format<?> fmt = lookupFormat(format);
final Format<?> fmt;
if (format == null)
fmt = formatBySuffix(suffix);
else
fmt = lookupFormat(format);
return writeArchive(fmt);
}
@ -300,6 +333,26 @@ public ArchiveCommand setTree(ObjectId tree) {
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)}.
*
* @param filename
* intended filename for the archive
*/
public ArchiveCommand setFilename(String filename) {
int slash = filename.lastIndexOf('/');
int dot = filename.indexOf('.', slash + 1);
if (dot == -1)
this.suffix = "";
else
this.suffix = filename.substring(dot);
return this;
}
/**
* @param out
* the stream to which to write the archive
@ -312,7 +365,9 @@ public ArchiveCommand setOutputStream(OutputStream out) {
/**
* @param fmt
* archive format (e.g., "tar" or "zip")
* archive format (e.g., "tar" or "zip").
* null means to choose automatically based on
* the archive filename.
* @return this
*/
public ArchiveCommand setFormat(String fmt) {