ant checksum directory does not reflect removed files - ant

I have the following ant targets defined. The idea is to do the heavy work only, if some contents of a folder have changed.
<target name="checksumAssets">
<echo message="verify checksums" />
<checksum todir="${bin.loc}/../checksums" verifyproperty="checksum.isUpToDate.test">
<fileset dir="${bin.loc}/assets/" id="filelist">
<include name="somefolder/" />
<exclude name="somefolder/result.swf"/>
</fileset>
</checksum>
<echo message="${toString:filelist}"/>
<echoproperties regex="checksum.isUpToDate.test"/>
</target>
<target name="createAsset" depends="checksumAssets" unless="${checksum.isUpToDate.test}">
<!-- do create the assets and other magic -->
<echo message="create checksum files" />
<checksum todir="${bin.loc}/../checksums" >
<fileset refid="filelist" />
</checksum>
</target>
somefolder contains images which will be processed and result in a swf file containing these assets.
i want this heavy processing only to take place if something in the asset folder changes.
this works as espected in two cases:
i add a new file to somefolder
i change an existing file in somefolder
my problem is:
it does not work when i delete a file from this folder.
this means, the createAsset Target is not called on ant createAsset if i remove a file from the folder in question. it is called in the two aforementioned cases and if there are no checksum files present in the checksums folder.
is there something i missed?
ant version is 1.8.2

i've found a workaround.
since <checksum> only saves the checksum of single files, it cannot know if a file is missing from a previous run. for this it would need to save the checksum of a complete filelist on disk.
this is what i accomplished:
<target name="checksumAssets">
<echo message="verify checksums" />
<!-- generate filelist.txt with actual content of somefolder -->
<fileset dir="${bin.loc}/assets/somefolder/" id="filelist">
<exclude name="result.swf"/>
<exclude name="filelist.txt"/>
</fileset>
<concat destfile="${bin.loc}/assets/somefolder/filelist.txt" fixlastline="true">${toString:filelist}</concat>
<!-- checksum folder including the filelist.txt -->
<checksum todir="${bin.loc}/../checksums" verifyproperty="checksum.isUpToDate.test">
<fileset dir="${bin.loc}/assets/" id="checkedlist">
<include name="somefolder/" />
<exclude name="somefolder/result.swf"/>
</fileset>
</checksum>
</target>
<target name="createAsset" depends="checksumAssets" unless="${checksum.isUpToDate.test}">
<!-- do create the assets and other magic -->
<echo message="create checksum files" />
<checksum todir="${bin.loc}/../checksums" >
<fileset refid="checkedlist" />
</checksum>
</target>
first i generate a filelist.txt with the content of the current folder.
then i generate checksums of all files in this folder, including the filelist.txt
on every an run, filelist.txt will be generated and checked against the filelist.txt from the last successful run of createAsset.
now the createAsset target is run if a content file changes or if the content of this folder changes.
mission accomplished ;)

Related

How to delete tarfileset after creation of archive?

I have following ant target to create an archive of log files.
It collects all log files from the .metadata directory of an eclipse workspace recursively and log files from the project directories non-recursively.
I would like to delete the files after they have been archived. How can I achieve this?
I cannot use fileset as I need the extra attributes of the tarfileset.
<target name="tar_logfiles">
<tar destfile="logs.tgz" compression="gzip">
<tarfileset dir=".metadata" preserveLeadingSlashes="true" prefix=".metadata">
<include name="**/.log*" />
<include name="**/*.log" />
</tarfileset>
<tarfileset dir="${basedir}" preserveLeadingSlashes="true">
<include name="*/.log" />
</tarfileset>
</tar>
</target>

Relocate contents of dynamic folder

I have a zip file which has one base folder inside it with other content inside that. I don't always know what that base folder is going to be called until I unzip it.
I'd like to move that base folder, and rename it at the same time, in ant - but can't seem to find out how. I've written code to extract the contents of the zip file to ${local.sdk.dir}/temp/ but from here i can't work out how to rename/move the extracted folder
<move todir="${local.sdk.dir}/${remote.sdk.file.name}">
<fileset dir="${local.sdk.dir}/temp/<WHAT_DO_I_PUT_HERE?>"></fileset>
</move>
also tried
<move todir="${local.sdk.dir}/${remote.sdk.file.name}" includeEmptyDirs="yes" verbose="true">
<fileset dir="${local.sdk.dir}/temp/" >
<include name="**/*" />
</fileset>
</move>
and played about with this, but closest I can get without ant throwing an error is to copy the contents of the temp dir, not the base folder within temp.
You can do all this in one step - copy from the zip file and rename the files changing the dir name as you copy. The copy task accepts a nested resource collection, so you can use a zipfileset to specify the files to copy directly from the zip file.
In order to rename the files as they are copied, you can use a mapper, which the copy task also takes as a nested element. In this case, a cutsdirmapper looks like the tool for the job.
So, if I've understood what you want to do correctly, something like this should work:
<copy todir="${local.sdk.dir}/${remote.sdk.file.name}">
<zipfileset src="${your.zip.file}" />
<cutdirsmapper dirs="1" />
</copy>
cutdirsmapper is only available in Ant 1.8.2 onward, so if you're using an earlier version, you could try a regexpmapper:
<regexpmapper from="[^/]*(.*)" to="\1" />
Similar to this question
<target name="relocate_sdk_folder">
<path id="sdk_folder_name">
<dirset dir="${local.sdk.dir}/temp/">
<include name="*"/>
</dirset>
</path>
<property name="sdk_folder_name" refid="sdk_folder_name" />
<echo message="renaming ${sdk_folder_name} to ${remote.sdk.file.name}" />
<move file="${sdk_folder_name}" tofile="${local.sdk.dir}/${remote.sdk.file.name}" />
</target>

Ant Copying Empty Directories

I am still very new to ant and, although I know coldfusion, I don't know very much about java conventions, but I know that ant is built using java conventions. That being said I am working on an ant process to copy a project to a temp folder, change some code in the project, and then push the temp directory up to an FTP. I am trying to exclude all of my git, eclipse, and ant files from the copy so that my testing platform doesn't get cluttered. I setup a target to do the copy, but it seems that Ant not only is ignoring my excludes (which I am sure I wrote wrong), but it is only copying top level directories and files. No recursive copy. My current target is:
<target name="moveToTemp" depends="init">
<delete dir="./.ant/temp" />
<mkdir dir="./.ant/temp" />
<copy todir="./.ant/temp">
<fileset dir=".">
<include name="*" />
<exclude name=".*/**" />
<exclude name=".*" />
<exclude name="build.xml" />
<exclude name="settings.xml" />
<exclude name="WEB-INF/**" />
</fileset>
<filterset>
<filter token="set(environment='design')" value="set(environment='testing')" />
</filterset>
</copy>
</target>
I know that I am not doing my excludes right, but I don't know what I am doing wrong with them. I see double asterisks (**) used all the time in Ant but I can't figure out
By default an Ant fileset will (recursively) include all files under the specified directory, equivalent to:
<include name="**/*" />
That's the implicit include. If you supply an include, it overrides the implicit one.
Your include
<include name="*" />
Says 'match any file in the fileset directory', but that excludes traversal of subdirectories, hence your issue. Only files and the top-level directories are being copied.
See Patterns in the Ant docs for directory-based tasks: ** matches any directory tree (zero or more directories).
For your case you should be able to simply remove the 'include', so that the implicit 'include all' applies.
Suggest you also investigate the defaultexcludes task, which lets you set up this sort of thing once for the whole project.
Responding to the title of the question. You can include copy of empty directories as follows. (includeemptydirs attribute)
Example:
<copy includeemptydirs="true" todir="${directory}${file.separator}sentinel_files">
<fileset dir="${basedir}${file.separator}sentinel_files"/>
</copy>
Use the documentation provided in:
https://ant.apache.org/manual/Tasks/copy.html

Ant Zip Extracted Parent Directory

I have several zip files that I need to unzip within an Ant target. All the zip files are in the same directory, and have the same internal directory and file structure.
So I am using the following snippet to unzip all the zip files in the directory, but each zip file does not contain a parent folder at the root, so each successive zip file is unzipped and overwrites the previous files.
<unzip dest="C:/Program Files/Samsung/Samsung TV Apps SDK/Apps">
<fileset dir=".">
<include name="**/*.zip"/>
</fileset>
</unzip>
Is there a better way to unzip a group of files, and create a directory to unzip them to that is based on the zip file name?
So, if the zip files are:
1.zip
2.zip
3.zip
then the content of each will be extracted to:
1/
2/
3/
Thanks
One solution might be to use the ant-contrib 'for' and 'propertyregex' tasks to do this:
<for param="my.zip">
<fileset dir="." includes="**/*.zip" />
<sequential>
<propertyregex property="my.zip.dir"
input="#{my.zip}"
regexp="(.*)\..*"
select="\1"
override="yes" />
<unzip src="#{my.zip}" dest="${my.zip.dir}" />
</sequential>
</for>
The 'propertyregex' strips the .zip extension from the zip file name to use as the target directory name.
Without ant-contrib:
https://stackoverflow.com/a/12169523/957081
<!-- Get the path of the war file. I know the file name pattern in this case -->
<path id="warFilePath">
<fileset dir="./tomcat/webapps/">
<include name="myApp-*.war"/>
</fileset>
</path>
<property name="warFile" refid="warFilePath" />
<!-- Get file name without extension -->
<basename property="warFilename" file="${warFile}" suffix=".war" />
<!-- Create directory with the same name as the war file name -->
<mkdir dir="./tomcat/webapps/${warFilename}" />
<!-- unzip war file -->
<unwar dest="./tomcat/webapps/${warFilename}">
<fileset dir="./tomcat/webapps/">
<include name="${warFilename}.war"/>
</fileset>
</unwar>

How do I "expand" an ant path (accessed with refId=..) to all files in the path except some?

I am trying to get ant4eclipse to work and I have used ant a bit, but not much above a simple scripting language. We have multiple source folders in our Eclipse projects so the example in the ant4eclipse documentation needs adapting:
Currently I have the following:
<target name="build">
<!-- resolve the eclipse output location -->
<getOutputpath property="classes.dir" workspace="${workspace}" projectName="${project.name}" />
<!-- init output location -->
<delete dir="${classes.dir}" />
<mkdir dir="${classes.dir}" />
<!-- resolve the eclipse source location -->
<getSourcepath pathId="source.path" project="." allowMultipleFolders='true'/>
<!-- read the eclipse classpath -->
<getEclipseClasspath pathId="build.classpath"
workspace="${workspace}" projectName="${project.name}" />
<!-- compile -->
<javac destdir="${classes.dir}" classpathref="build.classpath" verbose="false" encoding="iso-8859-1">
<src refid="source.path" />
</javac>
<!-- copy resources from src to bin -->
<copy todir="${classes.dir}" preservelastmodified="true">
<fileset refid="source.path">
<include name="**/*"/>
<!--
patternset refid="not.java.files"/>
-->
</fileset>
</copy>
</target>
The task runs successfully, but I cannot get the to work - it is supposed to copy all non-java files over too to emulate the behaviour of eclipse.
So, I have a pathId named source.path which contains multiple directories, which I somehow needs to massage into something the copy-task like. I have tried nesting which is not valid, and some other wild guesses.
How can I do this - thanks in advance.
You might consider using pathconvert to build a pattern that fileset includes can work with.
<pathconvert pathsep="/**/*," refid="source.path" property="my_fileset_pattern">
<filtermapper>
<replacestring from="${basedir}/" to="" />
</filtermapper>
</pathconvert>
That will populate ${my_fileset_pattern} with a string like:
1/**/*,2/**/*,3
if source.path consisted of the three directories 1, 2, and 3 under the basedir. We're using the pathsep to insert wildcards that will expand to the full set of files later.
The property can now be used to generate a fileset of all the files. Note that an extra trailing /**/* is needed to expand out the last directory in the set. Exclusion can be applied at this point.
<fileset dir="." id="my_fileset" includes="${my_fileset_pattern}/**/*">
<exclude name="**/*.java" />
</fileset>
The copy of all the non-java files then becomes:
<copy todir="${classes.dir}" preservelastmodified="true">
<fileset refid="my_fileset" />
</copy>
That will copy the source files over retaining the source directory structure under todir. If needed, the flatten attribute of the copy task can be set to instead make all the source files copy directly to todir.
Note that the pathconvert example here is for a unix fileseystem, rather than windows. If something portable is needed, then the file.separator property should be used to build up the pattern:
<property name="wildcard" value="${file.separator}**${file.separator}*" />
<pathconvert pathsep="${wildcard}," refid="source.path" property="my_fileset">
...
You could use the foreach task from the ant-contrib library:
<target name="build">
...
<!-- copy resources from src to bin -->
<foreach target="copy.resources" param="resource.dir">
<path refid="source.path"/>
</foreach>
</target>
<target name="copy.resources">
<copy todir="${classes.dir}" preservelastmodified="true">
<fileset dir="${resource.dir}" exclude="**/*.java">
</copy>
</target>
If your source.path contains file paths as well then you could the if task (also from ant-contrib) to prevent attempting to copy files for a file path, e.g.
<target name="copy.resources">
<if>
<available file="${classes.dir}" type="dir"/>
<then>
<copy todir="${classes.dir}" preservelastmodified="true">
<fileset dir="${resource.dir}" exclude="**/*.java">
</copy>
</then>
</if>
</target>

Resources