From 56cb2d925c93eadf03a551a2f40bbc9cb2b3241a Mon Sep 17 00:00:00 2001 From: Jonathan Nieder Date: Thu, 6 Jun 2013 18:39:04 -0700 Subject: [PATCH] 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= option yet. A later patch might do that. Change-Id: Ic0236a70f7aa7f2271c3ef11083b21ee986b4df5 --- .../org/eclipse/jgit/archive/TarFormat.java | 10 +++ .../org/eclipse/jgit/archive/Tbz2Format.java | 11 ++++ .../org/eclipse/jgit/archive/TgzFormat.java | 11 ++++ .../org/eclipse/jgit/archive/TxzFormat.java | 11 ++++ .../org/eclipse/jgit/archive/ZipFormat.java | 10 +++ .../org/eclipse/jgit/api/ArchiveCommand.java | 61 ++++++++++++++++++- 6 files changed, 111 insertions(+), 3 deletions(-) diff --git a/org.eclipse.jgit.archive/src/org/eclipse/jgit/archive/TarFormat.java b/org.eclipse.jgit.archive/src/org/eclipse/jgit/archive/TarFormat.java index 228de7c37..23f4beda1 100644 --- a/org.eclipse.jgit.archive/src/org/eclipse/jgit/archive/TarFormat.java +++ b/org.eclipse.jgit.archive/src/org/eclipse/jgit/archive/TarFormat.java @@ -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 { + private static final List 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 suffixes() { + return SUFFIXES; + } } diff --git a/org.eclipse.jgit.archive/src/org/eclipse/jgit/archive/Tbz2Format.java b/org.eclipse.jgit.archive/src/org/eclipse/jgit/archive/Tbz2Format.java index 9883118ea..d3482d181 100644 --- a/org.eclipse.jgit.archive/src/org/eclipse/jgit/archive/Tbz2Format.java +++ b/org.eclipse.jgit.archive/src/org/eclipse/jgit/archive/Tbz2Format.java @@ -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 { + private static final List SUFFIXES = + Collections.unmodifiableList(Arrays.asList( + ".tar.bz2", ".tbz", ".tbz2")); + private final ArchiveCommand.Format 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 suffixes() { + return SUFFIXES; + } } diff --git a/org.eclipse.jgit.archive/src/org/eclipse/jgit/archive/TgzFormat.java b/org.eclipse.jgit.archive/src/org/eclipse/jgit/archive/TgzFormat.java index 1c72bf8dc..fe1350cbb 100644 --- a/org.eclipse.jgit.archive/src/org/eclipse/jgit/archive/TgzFormat.java +++ b/org.eclipse.jgit.archive/src/org/eclipse/jgit/archive/TgzFormat.java @@ -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 { + private static final List SUFFIXES = + Collections.unmodifiableList(Arrays.asList( + ".tar.gz", ".tgz")); + private final ArchiveCommand.Format 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 suffixes() { + return SUFFIXES; + } } diff --git a/org.eclipse.jgit.archive/src/org/eclipse/jgit/archive/TxzFormat.java b/org.eclipse.jgit.archive/src/org/eclipse/jgit/archive/TxzFormat.java index d1547c683..c09b0621a 100644 --- a/org.eclipse.jgit.archive/src/org/eclipse/jgit/archive/TxzFormat.java +++ b/org.eclipse.jgit.archive/src/org/eclipse/jgit/archive/TxzFormat.java @@ -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 { + private static final List SUFFIXES = + Collections.unmodifiableList(Arrays.asList( + ".tar.xz", ".txz")); + private final ArchiveCommand.Format 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 suffixes() { + return SUFFIXES; + } } diff --git a/org.eclipse.jgit.archive/src/org/eclipse/jgit/archive/ZipFormat.java b/org.eclipse.jgit.archive/src/org/eclipse/jgit/archive/ZipFormat.java index a0906d4dd..00c962bc9 100644 --- a/org.eclipse.jgit.archive/src/org/eclipse/jgit/archive/ZipFormat.java +++ b/org.eclipse.jgit.archive/src/org/eclipse/jgit/archive/ZipFormat.java @@ -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 { + private static final List 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 suffixes() { + return SUFFIXES; + } } diff --git a/org.eclipse.jgit/src/org/eclipse/jgit/api/ArchiveCommand.java b/org.eclipse.jgit/src/org/eclipse/jgit/api/ArchiveCommand.java index 7726e15ee..ab94d3a80 100644 --- a/org.eclipse.jgit/src/org/eclipse/jgit/api/ArchiveCommand.java +++ b/org.eclipse.jgit/src/org/eclipse/jgit/api/ArchiveCommand.java @@ -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 { */ 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 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 OutputStream writeArchive(Format 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) {