Copying files matching a regex in ant - regex

I'm having trouble copying some files which match a pattern in my ant script.
I have the following:
<property name="IncludedLocales" value="de_DE|es_ES|fr_FR|it_IT|ja_JP" />
<copy todir="${dest}">
<fileset dir="${src}" includes="**/*.properties" />
<mapper type="regexp" from="(messages(_${IncludedLocales})?\.properties)" to="\1" />
</copy>
${src} contains the files messages.properties, as well as messages_de_DE.properties, messages_es_ES.properties, etc.
But for some reason, only messages.properties, and messages_de_DE.properties get copied (and if I changed IncludedLocales to 'es_ES|de_DE|fr_FR|it_IT|ja_JP', messages_es_ES.properties gets copied instead of messages_de_DE.properties).
Am I missing something really simple?

Yes, I did miss something really simple, (messages(_${IncludedLocales})?\.properties) should have been (messages(_(${IncludedLocales}))?\.properties)

Related

ANT build : Variable inside resolver:artifacts is undefined

I have setup this ANT build.xml file which pulls in version info from a txt file , reads the first line, trims it and copies it into a variable called 'versionVal' with below code:
<target name="clean"
.
. do something more
.
<loadfile property="versionValTxt" srcfile="version.txt">
<filterchain>
<filterreader classname="org.apache.tools.ant.filters.HeadFilter">
<param name="lines" value="1" />
</filterreader>
</filterchain>
</loadfile>
<loadresource property="versionVal">
<propertyresource name="versionValTxt"/>
<filterchain>
<tokenfilter>
<filetokenizer/>
<replacestring from="V" to=""/>
</tokenfilter>
<striplinebreaks/>
</filterchain>
</loadresource>
<echo>"Building for version: ${versionVal}"</echo>
</target>
And in one of the targets I am trying to refer a resolver artifact which uses this versionVal to find a file with that specific version in its name as shown below:
<resolver:artifacts id="producedArtifacts" >
<resolver:artifact file="${dist.dir}/App.${versionVal}.zip"/>
</resolver:artifacts>
<target name="nexus">
<echo>"versionVal: ${versionVal}"</echo>
<resolver:deploy artifactsref="producedArtifacts">
<resolver:remoterepo refid="ossrh"/>
</resolver:deploy>
</target>
And the build keeps failing as below, where it shows the variable versionVal is undefined.
C:\Users\XYZ\git\App\WebContent\dist\App.${versionVal}.zip does not exist
Note that the block is able to recognize ${dist.dir} but it doesnt recognize ${versionVal}. However I am able to print the value using an echo inside the target-nexus.
Much appreciated if anyone can point me in the right direction. I am not able to figure out why this variable is not recognized under "resolver:artifact file" and if there are any alternatives to this problem.
Realised I had to include below resolver artifact inside a target block and then use that as depends in the nexus block. After making this change the variable 'versionVal' was recognized.
Solution:
<target name="packagedArtifact" >
<resolver:artifacts id="producedArtifacts" >
<resolver:artifact file="${dist.dir}/App.${versionVal}.zip"/>
</resolver:artifacts>
</target>
<target name="nexus" depends="packagedArtifact">
<resolver:deploy artifactsref="producedArtifacts">
<resolver:remoterepo refid="ossrh"/>
</resolver:deploy>
</target>

Ant copy files from dynamic directories further down

I am trying to copy files from some { dynamic } directories X into another location.
Some of the destination directories should be the ( same and static ) as in the source path.
The initial layout looks like this under new directory A/D.
(A)
|_(B)
|_(C)
|_{X}
|_{Y.js}
The final layout should look like this:
A
|_D
|_B
|_C
|_{X}
|_{Y.js}
I tried using a regexmapper, but I am getting messages that entries are skipped because copy doesn't know how to handle it.
<copy toDir="A/D/" verbose="true">
<fileset dir="A/" casesensitive="yes">
<include name="B/C/**/*.js"/>
</fileset>
<regexpmapper from="B/C/([^/]+)/(.+\.js)" to="B/C/\1/\2"/>
</copy>
Edit: I am currently trying on Windows but want this to be portable.
There is no need to use regexmapper and here is the solution I came up with:
<copy toDir="A/D" verbose="true">
<fileset dir="A" casesensitive="no" overwrite="true">
<include name="B/C/**/*.js"/>
</fileset>
</copy>

How can one modify an ItemDefinitionGroup from an MSBuild target?

I have an msbuild script I wrote to compile Google Protocol Buffers files:
<ItemGroup>
<ProtocolBuffer Include="Whitelist.proto" />
<ProtocolBuffer Include="Whitelist2.proto" />
</ItemGroup>
<ItemDefinitionGroup>
<ProtocolBuffer>
<ProtoPath>$(ProjectDir)</ProtoPath>
</ProtocolBuffer>
</ItemDefinitionGroup>
<PropertyGroup>
<ProtoC>$([System.IO.Path]::GetFullPath($(ProjectDir)..\ThirdParty\protobuf-2.4.1\protoc.exe))</ProtoC>
<ProtoOutPath>$(IntDir)CompiledProtocolBuffers</ProtoOutPath>
</PropertyGroup>
<Target Name="CompileProtocolBuffers"
BeforeTargets="ClCompile"
Inputs="#(ProtocolBuffer)"
Outputs="#(ProtocolBuffer->'$(ProtoOutPath)\%(FileName).pb.cc');#(ProtocolBuffer->'$(ProtoOutPath)\%(FileName).pb.h')">
<MakeDir Directories="$(ProtoOutPath)" />
<Exec
Command=""$(ProtoC)" --proto_path="$([System.IO.Path]::GetDirectoryName(%(ProtocolBuffer.ProtoPath)))" --cpp_out="$(ProtoOutPath)" "%(ProtocolBuffer.FullPath)" --error_format=msvs"
/>
<ItemGroup>
<ClInclude Include="$(ProtoOutPath)\%(ProtocolBuffer.FileName).pb.h" />
<ClCompile Include="$(ProtoOutPath)\%(ProtocolBuffer.FileName).pb.cc">
<AdditionalIncludeDirectories>$(MSBuildThisDirectory)..\ThirdParty\protobuf-2.4.1\src</AdditionalIncludeDirectories>
<PrecompiledHeader></PrecompiledHeader>
<DisableSpecificWarnings>4244;4276;4018;4355;4800;4251;4996;4146;4305</DisableSpecificWarnings>
<PreprocessorDefinitions>GOOGLE_PROTOBUF_NO_RTTI</PreprocessorDefinitions>
<WarningLevel>Level3</WarningLevel>
</ClCompile>
</ItemGroup>
</Target>
This compiles the protocol buffers files perfectly, and adds them to the compiler's inputs (yay!). However, my other source files that want to include the .pb.h files need to know where these files got generated -- that generation location needs to be put on the include path.
Therefore, if and only if the user has included a <ProtocolBuffer item somewhere in their script, I want to add the generation location (in this case $(ProtoOutPath) to ClCompile's <AdditionalIncludeDirectories>.
Is that possible or do I need to make .cpp files that want to use these generated bits jump through hoops?
Read your question and thought "can't be that hard". Man, was I wrong. First I thought just putting a condition on it, but of course one can't use ItemGroups in toplevel conditions because of evaluation order. Then I figured it's also not possible to put an ItemDefinitionGroup in a target (cause there one can use conditions) and modify it there. Then I bonked my head on the keyboard a couple of times after I realized that's probably why you asked the question :] (btw you know including a nonexisting directory is not really a problem since the compiler will happily ignore it?)
Maybe there's a simpler solution, but lastly I figured: if nothing works, my favourite msbuild toy aka CodeTaskFactory must be able to fix it. It does (I hope, didn't fully test the result), but it's not straightforward at all. Here you go, make sure to invoke the Test target somewhere before the C++ build starts.
<!--Uncomment the below to define some ProtocolBuffers-->
<!--<ItemGroup>
<ProtocolBuffer Include="Whitelist.proto" />
<ProtocolBuffer Include="Whitelist2.proto" />
</ItemGroup>-->
<!--Suppose these are your default include files defined in your C++ project-->
<ItemDefinitionGroup Label="DefaultIncludes">
<ClCompile>
<AdditionalIncludeDirectories>/path/to/x;/path/to/y</AdditionalIncludeDirectories>
</ClCompile>
</ItemDefinitionGroup>
<!--Include at least one item so we can play with it-->
<ItemGroup>
<ClCompile Include="iamaninclude"/>
</ItemGroup>
<!--Use code to append to AdditionalIncludeDirectories-->
<UsingTask TaskName="AppendMetadata" TaskFactory="CodeTaskFactory"
AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
<ParameterGroup>
<Append ParameterType="System.String" Required="true"/>
<ItemList ParameterType="Microsoft.Build.Framework.ITaskItem[]" Required="true"/>
<OutputItemList ParameterType="Microsoft.Build.Framework.ITaskItem[]" Output="true" />
</ParameterGroup>
<Task>
<Code>
<![CDATA[
const string dirz = "AdditionalIncludeDirectories";
foreach( var item in ItemList )
{
var cur = item.GetMetadata( dirz );
item.SetMetadata( dirz, cur + ";" + Append );
}
OutputItemList = ItemList;
]]>
</Code>
</Task>
</UsingTask>
<!--Main target-->
<Target Name="Test">
<!--stage 1: copy the itemgroup, then clear it:
if an Output TaskParameter is an Itemgroup, apparently the content
gets appended to the group instead of replacing it.
Found no documentation about this whatsoever though???-->
<ItemGroup Condition="#(ProtocolBuffer) != ''">
<ClCompileCopy Include="#(ClCompile)"/>
<ClCompile Remove="#(ClCompile)"/>
</ItemGroup>
<!--stage 2: append 'ProtoBufIncludeDir' to AdditionalIncludeDirectories,
and append the result to the origiginal again-->
<AppendMetadata ItemList="#(ClCompileCopy)" Append="ProtoBufIncludeDir" Condition="#(ProtocolBuffer) != ''">
<Output ItemName="ClCompile" TaskParameter="OutputItemList"/>
</AppendMetadata>
<!--stage 3: use modified itemgroup-->
<Message Text="#(ClCompile->'%(Identity): %(AdditionalIncludeDirectories)')"/>
</Target>
This prints
iamaninclude: /path/to/x;/path/to/y
unless the ProtocolBuffer is not empty in which case it prints
iamaninclude: /path/to/x;/path/to/y;ProtoBufIncludeDir

Remove version number from jar in ant task

I'm trying to copy all JARs from one directory to another. During this process I want to remove version numbers at the end of the file names. (E.g. my-jar-1.2.3.jar to my-jar.jar)
I tried to wrap my head around mapper but I can't find a regexp to get that to work. I've tried this:
<copy todir="lib" flatten="true">
<mapper type="regexp" from="(.*)-[^.]*(\.jar)" to="\1\2" />
<fileset dir="my.files.dir">
<include name="**/*.jar" />
<type type="file" />
</fileset>
</copy>
here is a better version of the below answer:
<project>
<mkdir dir="lib"/>
<copy todir="lib"
verbose="true">
<fileset dir="jars/">
<include name="*.jar"/>
</fileset>
<mapper type="regexp"
from="^(.+?)-[0-9]+.*\.jar$"
to="\1.jar"/>
</copy>
</project>
to handle "That last one is a trouble maker"
This should work properly:
<copy todir="lib" flatten="true">
<mapper type="regexp" from="(.*)-[^-]*(\.jar)" to="\1\2" />
<fileset dir="my.files.dir">
<include name="**/*.jar" />
<type type="file" />
</fileset>
</copy>
THere's a mapper in the maven-ant-task-lib which does just that.
Try this...
<project>
<mkdir dir="lib"/>
<copy todir="lib"
verbose="true">
<fileset dir="jars/">
<include name="*.jar"/>
</fileset>
<mapper type="regexp"
from="^(.+?)-[0-9].*$"
to="\1.jar"/>
</copy>
</project>
In a regex mapper, the from parameter must match the entire name. I use the +? non-greedy pattern matcher. This matches the pattern of . which means any character but not greedily. Normally, this would match the entire line. However, I'm capturing up to the first time a dash followed by a number is found.
The problem happens if the jar has no version number, or it's starts with a non-numeric value. I can successfully, do these:
foo-2.3.2.jar
foo-2r1.jar
But not these:
foo-alpha.jar
foo.jar
So, I tweaked the pattern a bit:
<project>
<mkdir dir="lib"/>
<copy todir="lib"
verbose="true">
<fileset dir="jars/">
<include name="*.jar"/>
</fileset>
<mapper type="regexp"
from="^(.+?)-[0-9]*.*\.jar$"
to="\1.jar"/>
</copy>
</project>
$ ant
[mkdir] Created dir: lib
[copy] Copying 5 files to lib
[copy] Copying jars/bar-3.4.5.jar to lib/bar.jar
[copy] Copying biff-86.4.2.jar to lib/biff.jar
[copy] Copying jars/boff-2.31.2.jar to lib/boff.jar
[copy] Copying jars/foo-1.2.3.jar tolib/foo.jar
[copy] Copying jars/foo-bar-3.3.2.3.jar to lib/foo.jar
That last one is a trouble maker...
It might be worth doing this in two copies: One to take care if a version number is found, and a second to take care of jars without version numbers.

Javac exclusion of package in ANT build.xml

I'm trying to compile all my packages except two of them, here is what my javac in build.xml looks like
<javac srcdir="${src}" destdir="${output}" debug="${debug}" failonerror="yes" >
<exclude name="com/abc/uyyy/**"/>
<exclude name="com/abc/zzz/**"/>
<include name="com/abc/zzz/Text.java"/>
<patternset refid="excluded.from.compilation.abc"/>
<classpath refid="abc.module.classpath"/>
</javac>
But all the files in package are compiled :(.
I've read the documentation (http://ant.apache.org/manual/Tasks/javac.html), but still no success, any help?
NOTE: After the Text.java is compiled, I need to build the WSDL file and then build the excluded packages. I'm using Metro to write and build my WS.
Is it not possbile to compile all the class files into one directory, then use the copy task like below to only copy the ones you want for WSDL?
<target name="copy_all_class_files">
<copy todir="${output}">
<fileset dir="classes">
<include name="com/abc/zzz/Text.class"/>
<exclude name="com/abc/uyyy/**"/>
<exclude name="com/abc/zzz/**"/>
</fileset>
</copy>
</target>
Ok here is what I did,I wrote a new target to compile only the WS file and then generate the classes, it works fine :)
<target name="compile-ws-server">
<javac srcdir="${src}" destdir="${output}"
debug="${debug}" failonerror="yes">
<include name="com/abc/xxx/Text.java"/>
<exclude name="${src}/abc/xxx/**"/>
<classpath refid="abc.module.classpath"/>
</javac>
</target>
All Above is not proper way ...
I have done like
<target name="compile" depends="init">
<javac srcdir="${src}" destdir="${build}" excludes="com/company/example/test/**" />
</target>
Here we should avoid placing ${src} and start from inside src folder.