当echo调试输出清楚地显示校验和事实上匹配时,我一直在努力找出这个代码失败的原因:
<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和amp;arg2匹配时失败?
什么是";标准方式";在Apache Ant中进行校验和比较?
这里的问题是,当您检查校验和任务的输出文件时,您会注意到末尾有一个换行符,这就是为什么即使哈希相同,比较也总是失败的原因。
要解决此问题,您需要在加载file:时使用带有<striplinebreaks/>
的过滤器链
<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>
这种方法的突出问题是,这个宏定义<compare>
只能使用一次,因为属性md5.for
&md5.from
只能设置一次。使用详细模式的ant -v
选项运行文件,您会看到警告:
属性"的覆盖被忽略;md5;
一个可能的修复方法是在设置任何属性之前使用ant contrib取消设置这些属性。或者,如果您使用的是Ant 1.8.0+版本,那么您可以定义本地属性。
这是另一种方法:
<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>
这将计算"0"的校验和;file1.ext";(例如(,并将其与相应的";file1.ext.MD5";file:这是因为Checksum类实现了Condition接口,该接口将返回布尔值。测试&工作
那么,如果文件&MD5文件存储在不同的目录中?我不确定什么是正确的";蚂蚁之路;是,但快速&肮脏的解决方案是将它们都复制到某个临时位置,将它们传递到宏中,然后删除它们,如下所示:
<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>