5

我正在使用带有 sbt 的 Scala 2.10.1 将我的 webapp 打包为一个 war 文件。出于高效 rsync 增量的目的,我希望将 war 打包为 .war 文件,但不进行 zip 压缩。我只需要知道如何为此配置我的构建。

更新:
所有这些插件文档都假定所有这些关于语法如何工作以及如何将任务组合成新任务等的知识。我什至不知道如何创建一个执行打包然后命令的新任务。到目前为止,没有一个答案具体说,“这就是你所做的......”

为了清楚起见,这就是我所要求的:

我需要一个执行此操作的任务“packnozip”:

1)运行“包”

2)运行shell命令:

$ mkdir ./Whatever 
$ pushd ./Whatever 
$ jar xvf ../Whatever.war 
$ popd 
$ mv ./Whatever.war ./Whatever.war.orig 
$ jar cvM0f ./Whatever.war -C ./Whatever . 

所以我要说的是我想在 sbt 控制台中输入“packnozip”并让它执行 #1 然后 #2。

现在我只是手动做#2,如果它可以自动化的话,这似乎很愚蠢。还看着一个 30MB 的文件被 rsync b/c 完全反感,当一个 34MB 的未压缩文件仅多出 13% 的数据,并且需要几分之一秒的时间来发送 b/c 的有效差异时,它是不可区分的似乎很愚蠢,更不用说“-z”无论如何都会压缩传输。

4

2 回答 2

2

如果您将战争文件解压缩到一个目录中,您可以:

zip -r -0 project.war project/

那应该是零压缩。如果您没有看到这些选项,这是我的设置:

[node@hip1 dev]$ zip -v
Copyright (c) 1990-2008 Info-ZIP - Type 'zip "-L"' for software license.
This is Zip 3.0 (July 5th 2008), by Info-ZIP.

我相信,在打包战争之后,您可以将其作为运行任务执行。

更新 1

我相信这是满足您需求的最佳方式:

http://www.scala-sbt.org/release/docs/Detailed-Topics/Process

val exitcode = "zip -r -0 project.war project/"!

但是,如果您需要从特定目录工作(请参阅下面的更新 2):

将其修改为在目录中执行,但将 .war 放在目录上方。路径(第二个)参数应该包括目录,以便在其中执行 zip:

Process("zip" :: "-r" :: "-0" :: "../project.war" :: "." :: Nil, "/path/to/project/") !

这是 ProcessBuilder 上的另一个 SO 问题,它也可能有所帮助:

Scala 2.9 中的“scala.sys.process”是如何工作的?

(注意:不需要导入scala.sys.process._)

更新 2

对于以后的读者,请注意,压缩项目目录本身是行不通的,需要使用pushd在目录内执行war的zip,将生成的war放在目录之外,如OP在评论中提到的在这个答案下面。正如 Orange80 所说:

pushd ./project && zip -r -0 ../project.war ./ && popd

更新 3

看看这个,它可能完全符合您的需要,使用 0 表示指定不压缩的选项:

https://github.com/sbt/sbt-onejar

一个允许您创建单个可执行 jar 的插件,它可以使用选项(例如“0”,如“jar 0f blah.jar blah/”等命令中的“0”)我认为正如您在下面的评论中提到的那样创建没有压缩的jar文件。

对于用法,我在 SO 上找到了这个: SBT one-jar plugin

而且,如果它需要修改,它也是一个非常合理的插件示例,如果你将它放在你的家中 ~/.sbt/plugins 它将是全局的,并且可以在你的构建中使用注意到的方式在上面的SO答案中。我希望这至少有一点帮助/

于 2013-06-26T22:41:51.930 回答
0

无法通过 sbt 配置直接执行此操作,因为 sbt 假定 zip 和 jar 工件中的任何文件都应该被压缩。

一种解决方法是解压缩并重新压缩(不压缩)war 文件。您可以通过将以下设置添加到您的项目(例如在build.sbt中)来做到这一点:

packageWar in Compile <<= packageWar in Compile map { file =>
  println("(Re)packaging with zero compression...")
  import java.io.{FileInputStream,FileOutputStream,ByteArrayOutputStream}
  import java.util.zip.{CRC32,ZipEntry,ZipInputStream,ZipOutputStream}
  val zis = new ZipInputStream(new FileInputStream(file))
  val tmp = new File(file.getAbsolutePath + "_decompressed")
  val zos = new ZipOutputStream(new FileOutputStream(tmp))
  zos.setMethod(ZipOutputStream.STORED)
  Iterator.continually(zis.getNextEntry).
    takeWhile(ze => ze != null).
    foreach { ze =>
      val baos = new ByteArrayOutputStream
      Iterator.continually(zis.read()).
        takeWhile(-1 !=).
        foreach(baos.write)
      val bytes = baos.toByteArray
      ze.setMethod(ZipEntry.STORED)
      ze.setSize(baos.size)
      ze.setCompressedSize(baos.size)
      val crc = new CRC32
      crc.update(bytes)
      ze.setCrc(crc.getValue)
      zos.putNextEntry(ze)
      zos.write(bytes)
      zos.closeEntry
      zis.closeEntry
    } 
  zos.close
  zis.close
  tmp.renameTo(file)
  file
}

现在,当您package在 sbt 中运行时,最终的 war 文件将被解压缩,您可以使用unzip -vl path/to/package.war.

于 2013-08-16T21:25:01.213 回答