Get XML Documentation files from TFS Team Build script - tfs

I have a dependency replication scheme setup in our TFS environment based on http://geekswithblogs.net/jakob/archive/2009/03/05/implementing-dependency-replication-with-tfs-team-build.aspx.
This uses the CompilationOutputs item group to get the built DLL files and branch/merge them into dependent projects. My problem is that the CompilationOutputs item group only contains the DLLs, and I'd like to also include the XML documentation files, so I can get intellisense documentation tips when using these libraries. Is there a different item group that contains these, or a different approach? Do I need to manually find the xml files and add them to an item group?
We're on TFS 2010 now, so if there's something new there, we can try to take advantage of it (though it'd be nice if I didn't have to convert this whole scheme to use a Workflow process...)

According to the article you copy and checkin the outputs:
<Copy SourceFiles="#(CompilationOutputs)" DestinationFolder="$(ReplicateSourceFolder)"/>
<Exec Command="$(TF) checkin /comment:"Checking in file from build" "$(ReplicateSourceFolder)" /recursive"/>
Couldn't you add a second copy line before the checkin to copy the xml files using the metadata?
<Copy SourceFiles="%(CompilationOutputs.RootDir)%(CompilationOutputs.Directory)\%(CompilationOutputs.Filename).xml" DestinationFolder="$(ReplicateSourceFolder)"/>
Here is another option using an inline task that builds another item group changing the extension so that it only adds doc files that actually exist:
<Target Name="Test">
<ChangeExtension InputFiles="#(CompilationOutputs)" Extension=".xml">
<Output TaskParameter="OutputFiles" ItemName="DocFiles" />
</ChangeExtension>
<Copy SourceFiles="#(CompilationOutputs)" DestinationFolder="$(ReplicateSourceFolder)"/>
<Copy SourceFiles="#(DocFiles)" DestinationFolder="$(ReplicateSourceFolder)"/>
</Target>
<UsingTask TaskName="ChangeExtension" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
<ParameterGroup>
<InputFiles ParameterType="Microsoft.Build.Framework.ITaskItem[]" Required="true"/>
<Extension ParameterType="System.String" Required="true"/>
<OutputFiles ParameterType="Microsoft.Build.Framework.ITaskItem[]" Output="true"/>
</ParameterGroup>
<Task>
<Code Type="Fragment" Language="cs">
<![CDATA[
if (InputFiles.Length > 0)
{
List<TaskItem> results = new List<TaskItem>();
for (int i = 0; i < InputFiles.Length; i++)
{
ITaskItem item = InputFiles[i];
string path = item.GetMetadata("FullPath");
string docfile = Path.ChangeExtension(path, Extension);
if (File.Exists(docfile))
{
results.Add(new TaskItem(docfile));
}
}
OutputFiles = results.ToArray();
}
]]>
</Code>
</Task>
</UsingTask>

Related

yguard not updating properties file in the jar

I have jar file having some properties files in it like log4j.properties and config.properties. Following is my ant script for yguard. Everything else is working but the properties file updation.
<target name="yguard">
<taskdef name="yguard" classname="com.yworks.yguard.YGuardTask" classpath="lib/yguard.jar" />
<yguard>
<inoutpairs resources="none">
<fileset dir="${basedir}">
<include name="MyApp.jar" />
</fileset>
<mapper type="glob" from="MyApp.jar" to="MyAppObs.jar" />
</inoutpairs>
<externalclasses>
<pathelement location="lib/log4j-1.2.17.jar" />
</externalclasses>
<rename conservemanifest="true" mainclass="com.amit.Application" >
<adjust replaceContent="true" >
<include name="**/*.properties" />
</adjust>
</rename>
</yguard>
</target>
config.properties file
com.amit.Application.param1 = something
I found some question in stackoverflow but they didn't help. One place it was mentioned that the file (like jsp, xml, properties) should be in the jar file which I already have. But my yguard obfuscated file just get the files copied as it is.
I tried many combinations with rename & adjust tags but nothing worked for me.
Following post I already visited
Is it possible to manage logs through Obfuscation with yGuard?
How to include obfuscated jar file into a war file
Apparently you want yGuard to obfuscate the name of the field param1, because com.amit.Application is obviously your entry point and yGuard excludes the given main class automatically. So basically you want the outcome to be something like
com.amit.Application.AÖÜF = something
This isn't possible, because yGuard can only adjust class names in property files, as state here: yGuard Manual

Ant copy task corrupts UTF-8 symbols

I have a .properties file with translations in Arabic. I am using it to replace strings in an html file. However, when I start the copy task, it completely corrupts the symbols and I get something like this:
اÙÙزادات
Any idea what's causing this and how I can fix it?
build.xml
<target name="copyAndReplace">
<copy todir="..." overwrite="yes" encoding="UTF-8">
<fileset dir="..." includes="*.html"></fileset>
<filterset>
<filtersfile file="***.properties" />
</filterset>
</copy>
</target>
I see some possible problems:
In Java, Properties files are assumed to have ISO-8859-1 encoding. Even if you're not dealing directly with Java, ant is reading a property file. I've run into this problem when opening a property file in Vim and NetBeans editor. Vim saved it in UTF-8 and NetBeans in ISO-8859-1.
You should use the outputencoding attribute of copy task. In Windows, UTF-8 is not the default encoding.
i encountered the same issue, but with images.
In the ant manual i found the following remark:
Note: If you employ filters in your copy operation, you should limit the copy to text files. Binary files will be corrupted by the copy operation. This applies whether the filters are implicitly defined by the filter task or explicitly provided to the copy operation as filtersets. See encoding note.
Maybe that is the source of the problem. I will need to check on my own whether this solves my problem.
Kind regards,
Marc
As mentioned by #Jean Waghetti above, ANT expects the files to be ISO-8859-1 encoded. I posted a similar stack overflow question for Chinese characters.
The only solution I've found is by ensuring my .properties file was ISO-8859-1 and the characters were escaped.
For example مرحبا بالعالم
Would be:
\u0645\u0631\u062D\u0628\u0627 \u0628\u0627\u0644\u0639\u0627\u0644\u0645
This is not ideal as it's not terribly human-readable. I have noticed that eclipse automatically converts it on hover.
You can add some code to translate the utf-8 properties to iso-8859-1 properties and the use the converted and escaped properties
<project name="xyz" default="copyAndReplace">
<property name="srcdir" value="src" />
<property name="propdir" value="src" />
<property name="tmpdir" value="tmp" />
<target name="encodeProps">
<script language="javascript">
importPackage(java.io);
importPackage(java.lang);
var files = new java.io.File(propdir).listFiles();
for (var i in files) {
var f = files[i];
if (!f.getName().endsWith(".properties")) continue;
var io = new InputStreamReader(new FileInputStream(f), "utf-8");
var out = new FileOutputStream(new File(tmpdir, f.getName()));
do {
var c = io.read();
if (c == -1) break;
if (c > 127) {
var s = Integer.toHexString(c);
s = new StringBuilder().append("\\u").append("0000".substring(s.length())).append(s).toString();
out.write(s.getBytes());
} else {
out.write(c);
}
} while (true);
io.close();
out.close();
}
</script>
</target>
<target name="copyAndReplace" depends="encodeProps">
<copy todir="dst" overwrite="yes" encoding="UTF-8" filtering="true">
<fileset dir="${srcdir}" includes="*.html">
</fileset>
<filterset>
<filtersfile file="${tmpdir}/c.properties" />
</filterset>
</copy>
</target>
</project>

Ant Copy task with Path instead of FileSet

I'm using Ant 1.7, want to copy files from different paths (they have no relationship, so i cannot use the include selector to filter them out of their root directory). I try to use the <path> inside the <copy> instead of <fileset>, because with <path> i can specify multi paths which is in <fileset> not possible. My ant script looks like this, but it doesn't work.
<target name="copytest">
<!-- copy all files in test1 and test2 into test3 -->
<copy todir="E:/test3">
<path>
<pathelement path="C:/test1;D:/test2"></pathelement>
</path>
</copy>
</target>
Anybody has idea about how to use the <path> inside <copy>? Or maybe anybody has the advise about how to copy files from different source without selector?
Btw, i don't want to hard code the source directories, they will be read from a propertiy file, so writing multi <fileset> inside <copy> should not be considered.
thanks in advance!
This only works if the flatten attribute is set to true:
<copy todir="E:/test3" flatten="true">
<path>
<pathelement path="C:/test1;D:/test2"></pathelement>
</path>
</copy>
This is documented in the Examples section of the Ant Copy task documentation.
<pathelement> generally uses it's path attribute as a reference to classpath or some other predefined location, if you want to give specific file locations outside of the classpath try with location attribute
<pathelement location="D:\lib\helper.jar"/>
The location attribute specifies a single file or directory relative
to the project's base directory (or an absolute filename), while the
path attribute accepts colon- or semicolon-separated lists of
locations. The path attribute is intended to be used with predefined
paths - in any other case, multiple elements with location attributes
should be preferred.
We have the same problem
A bit more complicated that we need to add a specified pattern set to each fileset converted from path
For example, this is the incoming data
<path id="myDirList" path="C:/test1;D:/test2" />
<patternset id="myPatterns" includes="*.html, *.css, etc, " />
We wrote a script to solve this problem
<resources id="myFilesetGroup">
<!-- mulitiple filesets to be generated here
<fileset dir="... dir1, dir2 ...">
<patternset refid="myPatterns"/>
</fileset>
-->
</resources>
<script language="javascript"><![CDATA[
(function () {
var resources = project.getReference("myFilesetGroup");
var sourceDirs = project.getReference("myDirList").list();
var patterRef = new Packages.org.apache.tools.ant.types.Reference(project, "myPatterns");
for (var i = 0; i < sourceDirs.length; i++) {
var fileSet = project.createDataType("fileset");
fileSet.dir = new java.io.File(sourceDirs[i]);
fileSet.createPatternSet().refid = patterRef;
resources.add(fileSet);
}
})();
]]></script>
now you can use this resources in you copy task
<!-- copy all files in test1 and test2 into test3 -->
<copy todir="E:/test3">
<resources refid="myFilesetGroup">
</copy>
I tried this and works fine
<fileset file="${jackson.jaxrs.lib}"/>

Ant XSLT task to build on mutiple dependencies

I have an XSL style sheet that merges external documents, this way
<xsl:copy-of select="document('snippets.xml')/snippets/xxxx/form"/>
I would like that the XSLT Ant build task rebuilds if the file or any of its dependencies changed.
The current Ant task looks like this
<xslt basedir="xxxx/pages/${doc.locale}"
destdir="xxxx/dir/${doc.locale}"
includes="*.xml"
excludes="snippets.xml"
style="build/xxxx/${doc.locale}/myStyle.xsl">
<param name="lang" expression="${doc.locale}"/>
<xmlcatalog refid="docDTDs"/>
Basically I would like to rebuild if the snippets.xml document is changed.
Ant has the uptodate task to check if a target is up-to-date, file modtime-wise, from a set of source files. I'm not completely clear on what your dependency is since the XSLT task could create multiple files (resulting in multiple targets), or if it creates a single file. One of your comments imply a single file.
The following is one way to use uptodate. You basically use the task to set a property that can then be put in the unless attribute of a target:
<property name="file.that.depends.on.snippets"
location="some/path"/>
<property name="snippets.file"
location="xxxx/pages/${doc.locale}/snippets.xml"/>
<target name="process-snippets"
unless="snippets.uptodate"
depends="snippets-uptodate-check">
<xslt basedir="xxxx/pages/${doc.locale}"
destdir="xxxx/dir/${doc.locale}"
includes="*.xml"
excludes="snippets.xml"
style="build/xxxx/${doc.locale}/myStyle.xsl">
<param name="lang" expression="${doc.locale}"/>
<xmlcatalog refid="docDTDs"/>
</xslt>
</target>
<target name="snippets-uptodate-check">
<uptodate property="snippets.uptodate"
targetfile="$file.that.depends.on.snippets">
<srcfiles dir="xxxx/pages/${doc.locale}"
includes="*.xml"
excludes="snippets.xml"/>
</uptodate>
</target>
The XSLT task should do this for you by default. It has an optional "force" attribute
Recreate target files, even if they
are newer than their corresponding
source files or the stylesheet
which is false by default. So by default, unless you override with the "force" attribute, dependencies are checked by the XSLT task.

Where are classpath, path and pathelement documented in Ant version 1.8.0?

I'm looking over the documentation that comes with Apache Ant version 1.8.0 and can't find where classpath, path and pathelement are documented. I've found a page that describes path like structures but it doesn't list the valid attributes or nested elements for these. Another thing I can't find in the documentation is a description of the relationships between filelist, fileset, patternset and path and how to convert them back and forth. For instance there has to be an easier way to compile only those classes in one package while removing all class dependencies on the package classes and update documentation.
<!-- Get list of files in which we're interested. -->
<fileset id = "java.source.set"
dir = "${src}">
<include name = "**/Package/*.java" />
</fileset>
<!-- Get a COMMA separated list of classes to compile. -->
<pathconvert property = "java.source.list"
refid = "java.source.set"
pathsep = ",">
<globmapper from = "${src}/*.#{src.extent}"
to = "*.class" />
</pathconvert>
<!-- Remove ALL dependencies on package classes. -->
<depend srcdir = "${src}"
destdir = "${build}"
includes = "${java.source.list}"
closure = "yes" />
<!-- Get a list of up to date classes. -->
<fileset id = "class.uptodate.set"
dir = "${build}">
<include name = "**/*.class" />
</fileset>
<!-- Get list of source files for up to date classes. -->
<pathconvert property = "java.uptodate.list"
refid = "class.uptodate.set"
pathsep = ",">
<globmapper from="${build}/*.class" to="*.java" />
</pathconvert>
<!-- Compile only those classes in package that are not up to date. -->
<javac srcdir = "${src}"
destdir = "${build}"
classpathref = "compile.classpath"
includes = "${java.source.list}"
excludes = "${java.uptodate.list}"/>
<!-- Get list of directories of class files for package. --:
<pathconvert property = "class.dir.list"
refid = "java.source.set"
pathsep = ",">
<globmapper from = "${src}/*.java"
to = "${build}*" />
</pathconvert>
<!-- Convert directory list to path. -->
<path id = "class.dirs.path">
<dirset dir = "${build}"
includes = "class.dir.list" />
</path>
<!-- Update package documentation. -->
<jdepend outputfile = "${docs}/jdepend-report.txt">
<classpath refid = "compile.classpath" />
<classpath location = "${build}" />
<classespath>
<path refid = "class.dirs.path" />
</classespath>
<exclude name = "java.*" />
<exclude name = "javax.*" />
</jdepend>
Notice there's a number of conversions between filesets, paths and comma separated list just to get the proper 'type' required for the different ant tasks. Is there a way to simplify this while still processing the fewest files in a complex directory structure?
This is the closest I could find to documentation on classpath.
http://ant.apache.org/manual/using.html#path
Path:
This object represents a path as used by CLASSPATH or PATH environment variable. A path might also be described as a collection of unique filesystem resources.
and PathElement:
Helper class, holds the nested <pathelement> values.
are defined directly in the JavaDoc.
ClassPathis an implementation of AbstractClasspathResource:
A Resource representation of anything that is accessed via a Java classloader. The core methods to set/resolve the classpath are provided.
which is a direct subclass of Resource:
Describes a "File-like" resource (File, ZipEntry, etc.). This class is meant to be used by classes needing to record path and date/time information about a file, a zip entry or some similar resource (URL, archive in a version control repository, ...).
FileSet is defined as:
A FileSet is a group of files. These files can be found in a directory tree starting in a base directory and are matched by patterns taken from a number of PatternSets and Selectors.
Selectors is defined as:
Selectors are a mechanism whereby the files that make up a <fileset> can be selected based on criteria other than filename as provided by the <include> and <exclude> tags.
PatternSet is defined as:
Patterns can be grouped to sets and later be referenced by their id attribute. They are defined via a patternset element, which can appear nested into a FileSet or a directory-based task that constitutes an implicit FileSet. In addition, patternsets can be defined as a stand alone element at the same level as target — i.e., as children of project as well as as children of target.
FileList is defined as:
FileLists are explicitly named lists of files. Whereas FileSets act as filters, returning only those files that exist in the file system and match specified patterns, FileLists are useful for specifying files that may or may not exist. Multiple files are specified as a list of files, relative to the specified directory, with no support for wildcard expansion (filenames with wildcards will be included in the list unchanged). FileLists can appear inside tasks that support this feature or as stand-alone types.
In Schematron, you could validate this by the following:
<sch:pattern>
<sch:title>Check allowed elements</sch:title>
<sch:rule context="target/*[name() = ancestor::*/taskdef/#name]">
<sch:assert test="true()">
The target element may contain user-defined tasks.
</sch:assert>
</sch:rule>
</sch:pattern>
References
Types - Apache Ant Manual
AntLib
Apache Ant/Build File Structure - Wikibooks, open books for an open world
Meeting new challenges with Ant1.7 (pdf)
Ant Extending Ant
Apache Ant - Apache AntUnit
Validating Ant with Schematron
Ant Script Visualizer

Resources