我正在开发一个Ant脚本,旨在模仿VSS的“影子文件夹”概念,作为从VSS迁移到Subversion的临时解决方案(无需重新配置我们的构建管理软件)。该脚本非常简单:
在我将整个行李箱拉入构建文件夹并从那里开始的情况下,所有工作都很顺利......除了需要30多分钟才能“构建”,我希望将其作为一部分启动提交后事件(再次模仿VSS的“影子文件夹”功能,它将所有文件的“最新”副本保存在独立于VSS数据库的文件夹中,并在响应所有签入时进行更新。) / p>
我一直在破解脚本,目标是只对已经更改过的文件执行更有针对性的下载(svn diff为我提供了文件列表,svn export可以用来单独删除它们,我相信)。
现在,问题是:有没有一种方法,使用Ant Core,“迭代地”为列表的每个元素调用目标?这是此处发布的问题的重复:
In ant, how to apply a target on a list of files (without ant-contrib)?
但我拒绝承认这不可能是原生的。这篇文章:
How to distribute each element of a list to argument of a task Ant?
给了我希望,但我缺乏对Ant如何工作(或被设计)放弃的基本理解。我希望我可以做类似的事情:
<?xml version="1.0" encoding="UTF-8"?>
<project name="Test XmlProperty" default="test" basedir=".">
<target name="test">
<xmlproperty file="log.xml" collapseAttributes="true" />
<echo>Affected resources: ${log.logentry.paths.path}</echo>
<macrodef name="svnExportFile">
<attribute name="svnRepoUrls"/>
<sequential>
<loadresource property="lead.path">
<string value="${svnRepoUrls}"/>
<filterchain>
<tokenfilter>
<replaceregex pattern="(\w+)[,${line.separator}]*.*" replace="\1" flags="g"/>
</tokenfilter>
</filterchain>
</loadresource>
<loadresource property="rest.paths">
<string value="${svnRepoUrls}"/>
<filterchain>
<tokenfilter>
<replaceregex pattern="(\w+)[,${line.separator}]*(.*)" replace="\2" flags="g"/>
</tokenfilter>
</filterchain>
</loadresource>
<echo message="${lead.path}"/>
<echo message="${rest.paths}"/>
<svnExportFile svnRepoUrls="${rest.paths}"/>
</sequential>
</macrodef>
<svnExportFile svnRepoUrls="${log.logentry.paths.path}"/>
</target>
</project>
虽然我没有正则表达式正常工作。这是Ant的主要违规吗?我应该放弃希望并简单地使用Ant-contrib运行吗?我采用它一直很慢,因为它似乎自2008年以来没有更新,我希望限制所有这些东西所需的依赖数量。
有什么想法吗?
编辑:我越来越近了(某种程度)......上面的代码在初始帖子中没有被正确引用,我没有机会在发布之前尝试一下(需要离开而不是想要失去我输入的所有东西)。无论如何,没有办法停止递归(我怀疑属性是不可变的,因此不会像我希望的那样重置),所以它不起作用(还是?)。
我试图完成与上面相同的基本概念(我知道它不赞成,但它很方便,它允许你通过'if / unless属性有条件地执行任务) - 这不起作用,虽然,因为Ant显然不希望允许递归:
'antcall任务调用自己的父目标'
尝试启动递归依赖:
'循环依赖:svn.export.file&lt; - svn.export.file'
如果有人好奇,这是版本:
<?xml version="1.0" encoding="UTF-8"?>
<project name="Test XmlProperty" default="test" basedir=".">
<target name="test">
<xmlproperty file="log.xml" collapseAttributes="true" />
<echo>Affected resources: ${log.logentry.paths.path}</echo>
<antcall target="svn.export.file" inheritAll="false">
<param name="svnRepoUrls" value="${log.logentry.paths.path}"/>
</antcall>
</target>
<target name="svn.export.file" if="svnRepoUrls">
<loadresource property="lead.path">
<string value="${svnRepoUrls}"/>
<filterchain>
<tokenfilter>
<replaceregex pattern="(\w+)[,${line.separator}]*.*" replace="\1" flags="g"/>
</tokenfilter>
</filterchain>
</loadresource>
<loadresource property="rest.paths">
<string value="${svnRepoUrls}"/>
<filterchain>
<tokenfilter>
<replaceregex pattern="(\w+)[,${line.separator}]*(.*)" replace="\2" flags="g"/>
</tokenfilter>
</filterchain>
</loadresource>
<echo message="${lead.path}"/>
<echo message="${rest.paths}"/>
<antcall target="svn.export.file" inheritAll="false">
<param name="svnRepoUrls" value="${rest.paths}"/>
</antcall>
</target>
</project>
答案 0 :(得分:0)
我承认,它很丑......我不太确定我是否会坚持使用它作为我的解决方案(我想我可以继续安装ant-contrib,因为这个'代码'都是丑陋和混乱) - 但它似乎做了伎俩,它有点证明我的理论,是的,你可以在不依赖的情况下为列表中的每个元素调用一个目标!
<?xml version="1.0" encoding="UTF-8"?>
<project name="Test XmlProperty" default="test" basedir=".">
<target name="test">
<xmlproperty file="log.xml" collapseAttributes="true" />
<echo>Affected resources: ${log.logentry.paths.path}</echo>
<antcall target="svn.export" inheritAll="false">
<param name="svn.repo.urls" value="${log.logentry.paths.path}"/>
</antcall>
</target>
<target name="svn.export" if="svn.repo.urls">
<macrodef name="svnExportFile">
<attribute name="urls"/>
<sequential>
<macrodef name="parsePath">
<attribute name="property"/>
<attribute name="replacePart"/>
<sequential>
<loadresource property="@{property}">
<string value="@{urls}"/>
<filterchain>
<tokenfilter>
<replaceregex pattern="([^,]+),?(.*)" replace="@{replacePart}" flags="g"/>
</tokenfilter>
</filterchain>
</loadresource>
</sequential>
</macrodef>
<parsePath property="lead.path" replacePart="\1"/>
<fail>
<condition>
<not>
<isset property="lead.path"/>
</not>
</condition>
</fail>
<parsePath property="rest.paths" replacePart="\2"/>
<echo>lead.path:${lead.path}</echo>
<echo>rest.paths:${rest.paths}</echo>
<antcall target="svn.export.deux"/>
</sequential>
</macrodef>
<svnExportFile urls="${svn.repo.urls}"/>
</target>
<target name="svn.export.deux" if="rest.paths">
<echo>rest.paths:${rest.paths}</echo>
<echo>svn.repo.urls:${svn.repo.urls}</echo>
<antcall target="svn.export" inheritAll="false">
<param name="svn.repo.urls" value="${rest.paths}"/>
</antcall>
</target>
</project>