Ant : Process the files in the subfolder using tasks - ant

I have a folder structure as follows
+ [BASE]
+++ [DIR 1]
++++++ File.zip
+++ [DIR 2]
++++++ File.zip
....
I have a build.xml in BASE. I need to have a task where I can unzip the File.zip in each DIR* . I needed it to be such that a new DIR added also should be handled.
I tried the following, in order to get the dir names but don't know how to proceed further
<dirset id="contents" dir="." />
<property name="prop.contents" refid="contents"/>

You could try an embedded groovy script. Something like this:
<target name="unzip">
<taskdef name="groovy" classname="org.codehaus.groovy.ant.Groovy" classpathref="build.path"/>
<fileset id="zips" dir="." includes="**/*.zip"/>
<groovy>
project.references.zips.each { fileResource ->
def file = new File(fileResource.toString())
ant.unzip(src:file, dest:file.parent)
}
</groovy>
</target>

Related

Ant: how to detect the properties of a file

Is there a way to detect the properties of a file using ant.
For example: date created, date modified, size, etc...?
I can't find anything built in that allows me to do that.
Thanks
Correct, nothing built in.
The following example uses the groovy ant task to call the Java NIO libraries:
<project name="demo" default="build">
<taskdef name="groovy" classname="org.codehaus.groovy.ant.Groovy"/>
<macrodef name="getMetadata">
<attribute name="file"/>
<sequential>
<groovy>
import java.nio.file.*
import java.nio.file.attribute.*
import java.text.*
def path = Paths.get("#{file}")
def attributes = Files.getFileAttributeView(path, BasicFileAttributeView.class).readAttributes()
def df = new SimpleDateFormat("dd-MMM-yyyy hh:mm:ss", Locale.US)
properties.'#{file}_size' = attributes.size()
properties.'#{file}_ctime' = df.format(new Date(attributes.creationTime().toMillis()))
properties.'#{file}_mtime' = df.format(new Date(attributes.lastModifiedTime().toMillis()))
properties.'#{file}_atime' = df.format(new Date(attributes.lastAccessTime().toMillis()))
</groovy>
</sequential>
</macrodef>
<target name="build">
<getMetadata file="src/foo/bar/A.txt"/>
<echo message="File : src/foo/bar/A.txt"/>
<echo message="Size : ${src/foo/bar/A.txt_size}"/>
<echo message="Create time : ${src/foo/bar/A.txt_ctime}"/>
<echo message="Modified time : ${src/foo/bar/A.txt_mtime}"/>
<echo message="Last access time: ${src/foo/bar/A.txt_atime}"/>
</target>
</project>
Update
Run the following commands to install the groovy task jar into a location that ANT can use:
mkdir -p ~/.ant/lib
curl http://search.maven.org/remotecontent?filepath=org/codehaus/groovy/groovy-all/2.3.7/groovy-all-2.3.7.jar -L -o ~/.ant/lib/groovy-all.jar
Additionally, I'm using ANT 1.9.4 and Java 1.7.0_25

Get directories with modified files with Ant

I need to process a directory if it has at least one modified file in it. I wrote a block that reduces a fileset to a unique list of the directories that contain those files, but I think this would be easier if there was a way to do this without the script.
Is there a way?
Tricky to do this with core ANT.
Here's an example using an embedded groovy script:
<project name="demo" default="process-modified-dirs">
<path id="build.path">
<pathelement location="/path/to/groovy-all/jar/groovy-all-2.1.1.jar"/>
</path>
<fileset id="modifiedfiles" dir="src">
<modified/>
</fileset>
<target name="process-modified-dirs">
<taskdef name="groovy" classname="org.codehaus.groovy.ant.Groovy" classpathref="build.path"/>
<groovy>
dirs = project.references.modifiedfiles.collect {
new File(it.toString()).parent
}
dirs.unique().each {
ant.echo("Do something with this dir: ${it}")
}
</groovy>
</target>
</project>

Showing alert message in logs while doing copy in Ant

I have fromfolder=xxx it has one.txt and
tofolder=yyy same file is there one.txt
While performing copy operation by using ant if it found same name of file is present then it will show alert message like files already present one.txt in log and should not overwrite the file.
<target name="copyPublicHtml" description="Copy Public_html to output directory" >
<touch>
<fileset dir="../html"/>
</touch>
<copy todir="../html" failonerror="on" verbose="on" overwrite="false">
<fileset dir="../src">
</copy>
</target>
You can use the groovy task to iterate thru the files:
<target name="copyPublicHtml" depends="init" description="Copy Public_html to output directory">
<taskdef name="groovy" classname="org.codehaus.groovy.ant.Groovy" classpathref="build.path"/>
<fileset id="srcFiles" dir="src"/>
<groovy>
project.references.srcFiles.each {
def src = new File(it.toString())
def trg = new File("html", src.name)
if (trg.exists()) {
project.log "File already exists: ${trg}"
}
ant.copy(file:it, todir:"html", verbose:"true", overwrite:"false")
}
</groovy>
</target>

Can ant generate a unified script including all imports similar to maven's effective pom?

I have an ant script that imports other scripts which import additional scripts leading to web of places where definitions can happen.
Can ant pull in all the definitions and output a file much like maven's help:effective-pom?
I'd like to add this as an output file with my build to make debugging somewhat easier.
You can create another target which will create that kind of file. For example it can look like this:
main build.xml which do some work and also can generate effective build:
<project name="testxml" default="build">
<import file="build1.xml" />
<import file="build2.xml" />
<target name="build">
<echo>build project</echo>
</target>
<target name="effective.build">
<taskdef name="groovy" classname="org.codehaus.groovy.ant.Groovy" classpath="C:\Program Files (x86)\groovy-2.1.4\embeddable\groovy-all-2.1.4.jar" />
<groovy>
def regex = ~/import file="(.*)"/
def buildXmlContent = new File('build.xml').text
new File('build.xml').eachLine {
line -> regex.matcher(line).find() {
def file = new File(it[1])
if (file.exists()) {
def replacement = file.getText().replaceAll(/<project.*/, '').replaceAll(/<\/project.*/, '')
buildXmlContent = buildXmlContent.replaceFirst(/<import.*/, replacement)
}
}
}
new File('build.effective.xml') << buildXmlContent
</groovy>
</target>
</project>
Two build.xml's created for tests:
<project name="testxml2" default="build">
<target name="clean">
<echo>clean project</echo>
</target>
</project>
<project name="testxml1" default="build">
<target name="test">
<echo>test project</echo>
</target>
</project>
If you will run ant effective.build you will get new build.effective.xml file with this content:
<project name="testxml" default="build">
<target name="test">
<echo>test project</echo>
</target>
<target name="clean">
<echo>clean project</echo>
</target>
<target name="build">
<echo>build project</echo>
</target>
<target name="effective.build">
<taskdef name="groovy" classname="org.codehaus.groovy.ant.Groovy" classpath="C:\Program Files (x86)\groovy-2.1.4\embeddable\groovy-all-2.1.4.jar" />
<groovy>
import java.util.regex.Pattern
def regex = ~/import file="(.*)"/
def buildXmlContent = new File('build.xml').text
new File('build.xml').eachLine {
line -> regex.matcher(line).find() {
def file = new File(it[1])
if (file.exists()) {
def replacement = file.getText().replaceAll(/<project.*/, '').replaceAll(/<\/project.*/, '')
buildXmlContent = buildXmlContent.replaceFirst(/<import.*/, replacement)
}
}
}
new File('build.effective.xml') << buildXmlContent
</groovy>
</target>
</project>
I chose groovy (because I learn it actually) for this purpose but you can create it in another langage. You can also compile this groovy code to ant task and use it as new task, for example <effectiveant outfile="build.effective.xml">. My example isn't perfect but it shows one of the solutions.

Move a ant dir project after the ant or subant task completes

Currently i'm using a shell script to do the following:
cd myproject1/
ant
cd ..
if grep 'sucessful' myproject/buil.log then move myproject ../backup/today/
And so on for myproject2, myproject3.
If some error happens, the project stay in the current dir to be reprocessed but the whole process continues.
I want to migrate this process to an ant build script but i have no clue on how to do this.
I have looked at ant and subant tasks. Ant looks more suitable to the job but i can't find a way to loop through a directory list using ant and move task togheter, checking if the ant task completes or not.
Thank you.
Checkout this answer:
running specific target in different ant scripts in different directories
I recommend that your submodule builds should throw an error rather than try and duplicate the log parsing logic.
Update
If this is designed to support deployment, perhaps you should consider a groovy script?
Would better support exception conditions:
def ant = new AntBuilder()
scanner = ant.fileScanner {
fileset(dir:".", includes:"test*/build.xml")
}
scanner.each { f ->
try {
ant.ant(antfile:f)
}
catch (e) {
ant.mkdir(dir:"backup")
ant.move(todir:"backup", file:f.parent)
}
}
Groovy has excellent ANT integration and can also be embedded within your ANT build:
<target name="run">
<taskdef name="groovy" classname="org.codehaus.groovy.ant.Groovy" classpathref="build.path"/>
<fileset id="buildFiles" dir="." includes="test*/build.xml"/>
<groovy>
project.references.buildFiles.each {
def f = new File(it.toString())
try {
ant.ant(antfile:f)
}
catch(e) {
ant.mkdir(dir:"backup")
ant.move(todir:"backup", file:f.parent)
}
}
</groovy>
</target>
Something along these lines may be what you're looking for :
<target name="compile" >
<javac srcdir="${src.dir}" destdir="${class.dir}" />
</target >
<target name="copy" depends="compile" >
<mkdir dir="${dest.dir}" />
<copy todir="${dest.dir}" overwrite="true">
<fileset dir="${class.dir}" includes="**" />
<fileset dir="${src.dir}" includes="**" />
...
</copy>
</target>

Resources