蚂蚁校验和比较?

Ant checksum comparison?

当回显调试输出清楚地显示校验和确实匹配时,我一直在竭尽全力试图找出此代码失败的原因:

<macrodef name="compare">
<attribute name="getChecksumFor"/>
<attribute name="getChecksumFrom"/>
  <sequential>
    <checksum file="@{getChecksumFor}" property="md5.for"/>
    <loadfile srcfile="@{getChecksumFrom}" property="md5.from"/>
    <fail message="WARNING:  Checksums do not match:
    installed FILE=@{getChecksumFor}
    installed FILE=${md5.for}
     required FILE=${md5.from}">
      <condition>
        <not>
          <equals arg1="${md5.from}" arg2="${md5.for}"/>
        </not>
      </condition>
    </fail>
  </sequential>
</macrodef>

怎么回事?为什么 arg1 和 arg2 匹配时比较失败?

Apache Ant 中进行校验和比较的“标准方法”是什么?

这里的问题是,当你检查 checksum task 的输出文件时,你会注意到末尾有一个换行符,这就是为什么比较总是失败的原因,即使哈希都一样。

要解决此问题,您需要使用 filterchain with <striplinebreaks/> when you loadfile:

<macrodef name="compare">
<attribute name="getChecksumFor"/>
<attribute name="getChecksumFrom"/>
  <sequential>
    <checksum file="@{getChecksumFor}" property="md5.for"/>
    <loadfile srcfile="@{getChecksumFrom}" property="md5.from">
      <filterchain>
        <striplinebreaks/>
      </filterchain>
    </loadfile>
    <fail message="WARNING:  Checksums do not match:
    installed FILE=@{getChecksumFor}
    installed FILE=${md5.for}
     required FILE=${md5.from}">
      <condition>
        <not>
          <equals arg1="${md5.from}" arg2="${md5.for}"/>
        </not>
      </condition>
    </fail>
  </sequential>
</macrodef>

这种方法的明显问题是这个 macrodef <compare> 只能使用一次,因为属性 md5.formd5.from 只能设置一次。 运行 您的文件带有详细模式的 ant -v 选项,您将看到警告:

Override ignored for property "md5.for"

一个可能的修复方法是在设置属性之前使用 ant-contrib 取消设置。或者,如果您使用的是 Ant 版本 1.8.0+,那么您可以定义 local 属性。

这是另一种方法:

<macrodef name="compare">
<attribute name="getChecksumFor"/>
<sequential>
  <fail message="WARNING: Incorrect checksum for @{getChecksumFor}">
    <condition>
      <not>
        <checksum>
          <fileset file="@{getChecksumFor}"/>
        </checksum>
      </not>
    </condition>
  </fail>
</sequential>
</macrodef>

这将计算“file1.ext”(例如)的校验和,并将其与相应的“file1.ext.MD5”文件进行比较:这是有效的,因为 Checksum class implements the Condition interface,这将 return 一个布尔值。已经过测试并且可以正常工作!!!

那么,如果文件和MD5文件存放在不同的目录下,如何进行比较呢?我不确定正确的“蚂蚁方式”是什么,但是对 copy them both to some temporary location, pass them into the macro, then delete 它们来说,一个快速而肮脏的解决方案是这样的:

<target name="init">
  <mkdir dir="${temp}"/>
</target>

<target name="check1" depends="init">
  <copy file="${dir1}/${file1.ext}" todir="${temp}" overwrite="true"/>
  <copy file="${dir2}/${file1.ext}.MD5" todir="${temp}" overwrite="true"/>
  <compare getChecksumFor="${temp}/${file1.ext}"/>
  <delete file="${temp}/${file1.ext}"/>
  <delete file="${temp}/${file1.ext}.MD5"/>
  <delete dir="${temp}"/>
</target>

<target name="target1" depends="check1">
  <!-- check1 passed:  Safe to proceed -->
</target>

这里的问题是,我将其设计为快速失败,这意味着如果失败,将永远不会执行对临时文件的删除:但对我来说幸运的是,这个 ${temp} 目录已经是我清理任务的一部分了。

<target name="clean">
  <delete dir="${temp}"/>
</target>

这是一个替代解决方案,其中宏将承担将文件复制到同一目录的工作:

<macrodef name="compare">
<attribute name="getChecksumFor"/>
<attribute name="getChecksumFrom"/>
<sequential>
  <delete dir="${temp}/checksums"/>
  <mkdir dir="${temp}/checksums"/>
  <copy file="@{getChecksumFor}" todir="${temp}/checksums" overwrite="true"/>
  <copy file="@{getChecksumFrom}" todir="${temp}/checksums" overwrite="true"/>
  <fail message="WARNING: Incorrect checksum for @{getChecksumFor}">
    <condition>
      <not>
        <checksum>
          <fileset dir="${temp}/checksums">
            <exclude name="*.MD5"/>
          </fileset>
        </checksum>
      </not>
    </condition>
  </fail>
  <delete dir="${temp}/checksums"/>
</sequential>
</macrodef>