Permalink
Browse files

Generated zip files now attempt to preserve executable permissions.

  • Loading branch information...
1 parent 98ea622 commit 3e3c50e2df768655a12f4d0f665cc744aae6f7ab @jsuereth jsuereth committed Jan 4, 2013
View
@@ -8,6 +8,8 @@ version := "0.5.0"
scalacOptions in Compile += "-deprecation"
+libraryDependencies += "org.apache.commons" % "commons-compress" % "1.4.1"
+
site.settings
com.typesafe.sbt.SbtSite.SiteKeys.siteMappings <+= (baseDirectory) map { dir =>
@@ -3,14 +3,16 @@ package packager
package universal
import sbt._
+
/** Helper methods to package up files into compressed archives. */
object Archives {
+
/** Makes a zip file in the given target directory using the given name. */
def makeZip(target: File, name: String, mappings: Seq[(File, String)]): File = {
val zip = target / (name + ".zip")
// TODO - If mappings already start with the given name, don't add it?
val m2 = mappings map { case (f, p) => f -> (name +"/"+p) }
- sbt.IO.zip(m2, zip)
+ ZipHelper.zip(m2, zip)
zip
}
@@ -0,0 +1,73 @@
+package com.typesafe.sbt
+package packager
+package universal
+
+import sbt._
+import org.apache.commons.compress.archivers.zip._
+import org.apache.commons.compress.compressors.{
+ CompressorStreamFactory,
+ CompressorOutputStream
+}
+import java.util.zip.Deflater
+import org.apache.commons.compress.utils.IOUtils
+
+object ZipHelper {
+ case class FileMapping(file: File, name: String, unixMode: Option[Int] = None)
+
+
+ /** Creates a zip file attempting to give files the appropriate unix permissions using Java 6 APIs.
+ * @param sources The files to include in the zip file.
+ * @param outputZip The location of the output file.
+ */
+ def zip(sources: Traversable[(File,String)], outputZip: File): Unit = {
+ val mappings =
+ for {
+ (file, name) <- sources.toSeq
+ // TODO - Figure out if this is good enough....
+ perm = if(file.isDirectory || file.canExecute) 0755 else 0644
+ } yield FileMapping(file, name, Some(perm))
+ archive(mappings, outputZip)
+ }
+
+ /** Creates a zip file using the given set of filters
+ * @param sources The files to include in the zip file. A File, Location, Permission pairing.
+ * @param outputZip The location of the output file.
+ */
+ def zipWithPerms(sources: Traversable[(File,String, Int)], outputZip: File): Unit = {
+ val mappings =
+ for {
+ (file, name, perm) <- sources
+ } yield FileMapping(file, name, Some(perm))
+ archive(mappings.toSeq, outputZip)
+ }
+
+
+ private def archive(sources: Seq[FileMapping], outputFile: File): Unit = {
+ if(outputFile.isDirectory) sys.error("Specified output file " + outputFile + " is a directory.")
+ else {
+ val outputDir = outputFile.getParentFile
+ IO createDirectory outputDir
+ withZipOutput(outputFile) { output =>
+ for(FileMapping(file, name, mode) <- sources; if !file.isDirectory) {
+ val entry = new ZipArchiveEntry(file, name)
+ // Now check to see if we have permissions for this sucker.
+ mode foreach (entry.setUnixMode)
+ output putArchiveEntry entry
+ // TODO - Write file into output?
+ IOUtils.copy(new java.io.FileInputStream(file), output)
+ output.closeArchiveEntry()
+ }
+ }
+ }
+ }
+
+
+ private def withZipOutput(file: File)(f: ZipArchiveOutputStream => Unit): Unit = {
+ val zipOut = new ZipArchiveOutputStream(file)
+ zipOut setLevel Deflater.BEST_COMPRESSION
+ try { f(zipOut) }
+ finally {
+ zipOut.close()
+ }
+ }
+}

0 comments on commit 3e3c50e

Please sign in to comment.