Assume I have a directory which contains several files with the same name prefix and a timestamp, e.g.
my-directory:
- file-0749
- file-1253
- file-2304
How can I tell ANT to select the latest modified file from my directory (in this case this would be file-2304)?
You can do that with the TimestampSelector task from ant-contrib.
<timestampselector property="latest.modified">
<path>
<fileset dir="${my-directory.dir}">
<include name="file-*" />
</fileset>
</path>
</timestampselector>
<echo message="${latest.modified}" />
Found a way without an additional library:
<copy todir="${tmp.last.modified.dir}">
<last id="last.modified">
<sort>
<date />
<fileset dir="${my.dir}" />
</sort>
</last>
</copy>
<echo message="last modified file in ${my.dir}: ${ant.refid:last.modified}" />
You can work directly with ant.refid:last.modified like the echo task does. Don't forget to delete tmp.last.modified.dir.
Related
I have an ant task to concatenate javascript files in a directory and output to concat.js What I want to do is first check if any files have a later modified time than that of concact.js before proceeding.
Here is the existing task:
<target name="minijs" depends="lintjs">
<echo>Concatinating ${plugins.dir} to ${plugins.concat}</echo>
<concat destfile="${plugins.concat}">
<fileset dir="${plugins.dir}">
<exclude name="**/vendor/**" />
<exclude name="*beconcat*" />
<include name="**/*.js" />
</fileset>
</concat>
This is what the uptodate task has been created for
<uptodate property="isUpToDate"
targetfile="${plugins.concat}">
<srcfiles dir="${plugins.dir}">
<exclude name="**/vendor/**" />
<exclude name="*beconcat*" />
<include name="**/*.js" />
</srcfiles>
will set the property isUpToDate if none of the files is newer than the target file - and not set the property at all if one of the files is. You can then use unless to conditionally rebuild the file.
I have this code which takes all the files in the folder collection and merges them with the covers.js file. The problem is there are 2 files inside of collections that need to be merged below covers.
But possibly I may want to control the order of how the files are being merged from the collection
folder. IS there a dependency attribute I can use.
<target name="merge box">
<echo>${box.file}</echo>
<concat destfile="${box.file}" fixlastline="yes" append="no">
<fileset dir="${js.src.dir}/components/covers/" includes="**/*.js"/>
<fileset dir="${js.src.dir}/collection/" includes="**/*.js" excludes="base.js"/>
</concat>
</target>
Update
I also tried this but still doesn't work.
<fileset dir="${js.src.dir}/collection" >
<includesfile name="Templates.js" />
<includesfile name="popup.js" />
<includesfile name="popup-extend.js" />
</fileset>
Latest Update
Tried this and it works but it doesn't hold the order of the include files.
<target name="merge box">
<echo>${box.file}</echo>
<concat destfile="${box.file}" fixlastline="yes" append="no">
<fileset dir="${js.src.dir}/components/covers/" includes="**/*.js"/>
<fileset dir="${js.src.dir}/collection" >
<include name="Templates.js" />
<include name="popup.js" />
<include name="popup-extend.js" />
</fileset>
</concat>
</target>
popup-extend is meant to be merged below the popup code but its not doing that matter what order I put them in it will always put it in this order.
Templates
popup
popup-extend
The order I'm trying to get it in is
Templates
popup-extend
popup
Try this:
<target name="merge box">
<echo>${box.file}</echo>
<concat destfile="${box.file}" fixlastline="yes" append="no">
<fileset dir="${js.src.dir}/components/covers/" includes="**/*.js"/>
<fileset file="${js.src.dir}/collection/Templates.js" />
<fileset file="${js.src.dir}/collection/popup.js" />
<fileset file="${js.src.dir}/collection/popup-extend.js" />
</concat>
</target>
Or look here: How to preserve file order in Ant concat?
I'm having trouble producing a bundle after converting a maven project to an ant project. The bnd ant task creates test.jar but the file only includes a META-INF. The eclipse project is named testproj. What am I missing? Also, does anyone know of a place with more bnd ant task examples? The bnd site itself is a little lacking in this regard, especially with how to build the classpath values.
<project name="testproj" basedir="." default="build">
<patternset id="project.deploy.jars">
<include name="slf4j-api-1.6.1.jar" />
<include name="logback-core-0.9.28.jar" />
<include name="logback-classic-0.9.28.jar" />
<include name="org.osgi.compendium-4.2.0.jar" />
<include name="org.apache.felix.http.jetty-2.2.0.jar" />
<include name="jcl-over-slf4j-1.6.1.jar" />
<include name="mail-1.4.4-1.0.0.jar" />
<include name="commons-io-2.0.1.jar" />
<include name="commons-lang-2.6.jar" />
<include name="commons-codec-1.5.jar" />
<include name="commons-httpclient-3.1-osgi-1.0.0.jar" />
<include name="bndlib-1.43.0.jar" />
<include name="ojdbc5-osgi-1.0.0.jar" />
<include name="joda-time-1.6.2.jar" />
<include name="cxf-dosgi-ri-singlebundle-distribution-1.2.jar" />
</patternset>
<path id="bnd.classpath">
<fileset dir="setup/external">
<patternset refid="project.deploy.jars" />
</fileset>
</path>
<target name="build" description="Build the bundle">
<taskdef resource="aQute/bnd/ant/taskdef.properties"
classpath="setup/dev/biz.aQute.bnd.jar"
/>
<pathconvert property="bnd.classpath.string" pathsep=",">
<path refid="bnd.classpath" />
<mapper>
<chainedmapper>
<flattenmapper/>
<regexpmapper from="(.*)" to="setup/external/\1" casesensitive="no"/>
</chainedmapper>
</mapper>
</pathconvert>
<echo>${bnd.classpath.string}</echo>
<bnd
classpath="target/classes,${bnd.classpath.string}"
eclipse="true"
failok="false"
exceptions="true"
output="test.jar"
files="test.bnd"/>
</target>
</project>
test.bnd:
Import-Package:com.test.service, oracle.sql, oracle.jdbc, oracle.jdbc.driver, *
Export-Package:com.test.service
Service-Component:com.test.*
1) Did you look at the ant support included in bndtools? Neil and I go out of our way to make bndtools run in offline mode.
2) The build.xml looks not proper ant syntax? Can you make a small example and post the proper files?
3) bnd should never generate a jar without a MANIFEST.MF file. Does the run have an error?
If you can't solve the problem feel free to send me a zip file with the setup and I'll check what's going on (and report here).
Following help from the group at Google Groups bndtools (which is a group for for both bndtools and bnd), the issue is apparently that the .bnd file does not contain the Private-Package header. This is used to specify the implementation package so make it a base package for all the classes you want brought in.
After I added it, all the classes showed up and the component xml appeared again.
Thanks for your help everyone!
How to preserve file order in Ant concat?
Simple concat with fileset & includesfile produces rather "random" order, as order is not guaranteed:
<concat destfile="C:/targetdir/concatenated.file">
<fileset dir="C:/sourcedir/">
<includesfile name="C:/targetdir/includes.file" />
</fileset>
</concat>
What I need is concatenation in specific order that the files are listed in the includes file.
So far I've found resourcelist, which should preserve order, but I can't seem to be able to produce any concatenated file with it. :/
<concat destfile="C:/targetdir/concatenated.file">
<resourcelist>
<file file="C:/targetdir/includes.file"/>
<filterchain>
<striplinecomments>
<comment value="#"/>
</striplinecomments>
<prefixlines prefix="C:/sourcedir/"/>
</filterchain>
</resourcelist>
</concat>
Plus, the resourcelist can't seem to handle rows like
LibraryX/A/Stuff/Morestuff/*
Instead the row just produces a ".../Morestuff/* does not exist." -error
Includes file has list of relative paths:
LibraryX/A/Stuff/FileA.txt
LibraryX/A/Stuff/FileB.txt
LibraryX/A/Stuff/FileC.txt
LibraryX/A/Stuff/FileY.txt
I was able to get a filelist working pretty easily:
<concat destfile="C:/targetdir/concatenated.file">
<filelist dir="C:/sourcedir/">
<file name="i.txt" />
<file name="n.txt" />
<file name="o.txt" />
<file name="r.txt" />
<file name="d.txt" />
<file name="e.txt" />
<file name="r.txt" />
</filelist>
</concat>
Hope that helps!
If you are using Ant 1.7+, you can use the sort command
<concat destfile="C:/targetdir/concatenated.file">
<sort>
<fileset dir="C:/sourcedir/">
<include name="C:/targetdir/*.file" />
</fileset>
</sort>
</concat>
You can find the documentation of sort here
[On Ant 1.8.2+] You can also pass the fileset via a sort, and sort on filename, like below:
<concat destfile="./${dir.publish}/${dir.js}/b.main-${build.number}.debug.js">
<sort xmlns:rcmp="antlib:org.apache.tools.ant.types.resources.comparators">
<fileset dir="./${dir.publish}/">
<include name="**/${dir.js.main}/**/*.js"/>
<exclude name="**/${dir.js.main}/**/*.min.js"/>
</fileset>
<rcmp:name />
</sort>
</concat>
Couple of things to watch out for:
Directories are sorted before files
Capitals come before lowercase
UPDATE: Another alternative if you need to manually specify order:
<!-- create a ordered list of all the build files so that CIAPI & CIAPI.widget are built first
(can't find a smarter way to do this, since ant filesets are unordered) -->
<fileset id="a" dir="."><include name="CIAPI/build.project.xml"/></fileset>
<fileset id="b" dir="."><include name="CIAPI.widget/build.project.xml"/></fileset>
<fileset id="c" dir=".">
<include name="**/build.project.xml"/>
<exclude name="CIAPI/build.project.xml" />
<exclude name="CIAPI.widget/build.project.xml" />
</fileset>
<union id="all_build_files">
<fileset refid="a"/>
<fileset refid="b"/>
<fileset refid="c"/>
</union>
Ugly, but, erm, this is ant?
try this, put in alphabetical order
<project name="concatPath" default="full">
<target name="full">
<fileset id="fs" dir="./files" />
<pathconvert refid="fs" property="concatList" pathsep=";" targetos="unix"/>
<echo>${concatList}</echo>
</target>
</project>
this can be used with hierarchical structure of directories, and the order will be the exposed by David.
Remember that XML is not order-dependent, by definition.
To concatenate files in a sorted order, consider using <replace> instead.
Create an order file that defines the order. Then, in your build file:
Copy the order file to the destination file with <copy>
Concatenate your files together into a temporary file with <concat>
Load the files into properties with <loadfile>
Insert the text from those files into the destination file with <replace>
Example order file order_file.txt:
FILE_A_HERE
CONCAT_FILES_HERE
Example ant build file build.xml:
<copy file="order_file.txt" tofile="destination.txt" overwrite="yes">
<concat destfile="tempfile.txt">
<fileset dir="includes/">
<include name="*.txt">
<exclude name="fileA.txt">
</fileset>
</concat>
<loadfile property="fileA" srcFile="includes/fileA.txt" />
<loadfile property="concatFile" srcFile="tempfile.txt" />
<replace file="destination.txt" token="FILE_A_HERE" value="fileA" />
<replace file="destination.txt" token="CONCAT_FILES_HERE" value="concatFile" />
In a project we have several source paths, so we defined a reference path for them:
<path id="de.his.path.srcpath">
<pathelement path="${de.his.dir.src.qis.java}"/>
<pathelement path="${de.his.dir.src.h1.java}"/>
...
</path>
Using the reference works fine in the <javac> tag:
<src refid="de.his.path.srcpath" />
In the next step, we have to copy non-java files to the classpath folder:
<copy todir="${de.his.dir.bin.classes}" overwrite="true">
<fileset refid="de.his.path.srcpath">
<exclude name="**/*.java" />
</fileset>
</copy>
Unfortunately, this does not work because "refid" and nested elements may not be mixed.
Is there a way I can get a set of all non-java files in my source path without copying the list of source paths into individual filesets?
Here's an option. First, use the pathconvert task to make a pattern suitable for generating a fileset:
<pathconvert pathsep="/**/*,"
refid="de.his.path.srcpath"
property="my_fileset_pattern">
<filtermapper>
<replacestring from="${basedir}/" to="" />
</filtermapper>
</pathconvert>
Next make the fileset from all the files in the paths, except the java sources. Note the trailing wildcard /**/* needed as pathconvert only does the wildcards within the list, not the one needed at the end:
<fileset dir="." id="my_fileset" includes="${my_fileset_pattern}/**/*" >
<exclude name="**/*.java" />
</fileset>
Then your copy task would be:
<copy todir="${de.his.dir.bin.classes}" overwrite="true" >
<fileset refid="my_fileset" />
</copy>
For portability, instead of hard-coding the unix wildcard /**/* you might consider using something like:
<property name="wildcard" value="${file.separator}**${file.separator}*" />