Reputation: 9150
Does anyone know of an Ant task that would compare two (Java) properties files? I could not find any but I would like to be sure before I go off and implement it.
Just to be clear: it should perform properties-file-syntax-aware comparison, comparing the existence of keys, but ignoring the values.
Upvotes: 0
Views: 4708
Reputation: 301
The best option is to use PropDiff utility. It has options to compare, combine and intersect Java Properties files. It's open source, so you can modify it according to your requirements.
Here is the documentation for PropDiff.
Upvotes: 2
Reputation: 693
Here is another approach that only requires the ant-contrib library:
<target name="checkPropertyFiles">
<antcall target="ensureTwoFilesHaveSameProperties">
<param name="file1" value="file1.properties"/>
<param name="file2" value="file2.properties"/>
</antcall>
</target>
<target name="ensureTwoFilesHaveSameProperties">
<loadproperties srcFile="${file1}" prefix="prefixfile1"/>
<loadproperties srcFile="${file2}" prefix="prefixfile2"/>
<propertyselector property="file1.list" delimiter="," match="prefixfile1\.(.+)" select="\1"/>
<propertyselector property="file2.list" delimiter="," match="prefixfile2\.(.+)" select="\1"/>
<for list="${file1.list}" param="file1.property">
<sequential>
<if>
<not>
<matches pattern=",@{file1.property}," string=",${file2.list}," />
</not>
<then>
<property name="error.encountered" value="true"/>
<echo message="Property @{file1.property} is present in ${file1} but not in ${file2}"/>
</then>
</if>
</sequential>
</for>
<for list="${file2.list}" param="file2.property">
<sequential>
<if>
<not>
<matches pattern=",@{file2.property}," string=",${file1.list}," />
</not>
<then>
<property name="error.encountered" value="true"/>
<echo message="Property @{file2.property} is present in ${file2} but not in ${file1}"/>
</then>
</if>
</sequential>
</for>
<fail message="Property files do not have the same set of keys.">
<condition>
<isset property="error.encountered"/>
</condition>
</fail>
<echo message="OK: ${file1} has same properties as ${file2}"/>
</target>
Upvotes: 1
Reputation: 77971
You could try to combine a groovy ant task with the java-diff-utils library
├── build.xml
├── file1.properties
└── file2.properties
Running the build produces the following output:
diff:
[groovy] [DeleteDelta, position: 1, lines: [two=2]]
[groovy] [InsertDelta, position: 3, lines: [threeandhalf=3.5]]
[groovy] [ChangeDelta, position: 4, lines: [five=5] to [five=55555]]
<project name="demo" default="diff" xmlns:ivy="antlib:org.apache.ivy.ant">
<target name="resolve">
<ivy:cachepath pathid="build.path">
<dependency org="org.codehaus.groovy" name="groovy-all" rev="2.1.0-rc-1" conf="default"/>
<dependency org="com.googlecode.java-diff-utils" name="diffutils" rev="1.2.1" conf="default"/>
</ivy:cachepath>
</target>
<target name="diff" depends="resolve">
<taskdef name="groovy" classname="org.codehaus.groovy.ant.Groovy" classpathref="build.path"/>
<groovy>
import difflib.*
def original = new File("file1.properties").readLines()
def revised = new File("file2.properties").readLines()
Patch patch = DiffUtils.diff(original, revised)
patch.getDeltas().each {
println it
}
</groovy>
</target>
</project>
Notes:
one=1
two=2
three=3
four=4
five=5
one=1
three=3
threeandhalf=3.5
four=4
five=55555
Returns the properties in the first file missing in the second:
diff:
[groovy] Missing keys: [two]
<project name="demo" default="diff" xmlns:ivy="antlib:org.apache.ivy.ant">
<target name="resolve">
<ivy:cachepath pathid="build.path">
<dependency org="org.codehaus.groovy" name="groovy-all" rev="2.1.0-rc-1" conf="default"/>
</ivy:cachepath>
</target>
<target name="diff" depends="resolve">
<taskdef name="groovy" classname="org.codehaus.groovy.ant.Groovy" classpathref="build.path"/>
<groovy>
def source = new Properties()
def target = new Properties()
new File("file1.properties").withInputStream { source.load(it) }
new File("file2.properties").withInputStream { target.load(it) }
def diff = source.findResults { k,v ->
k in target ? null : k
}
println "Missing keys: ${diff}"
</groovy>
</target>
</project>
Upvotes: 1