Question

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.

  • Input: two properties files
  • Output: list of property keys that are in one file but not in the other.

Just to be clear: it should perform properties-file-syntax-aware comparison, comparing the existence of keys, but ignoring the values.

Was it helpful?

Solution 2

You could try to combine a groovy ant task with the java-diff-utils library

Example

├── 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]]

build.xml

<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:

file1.properties

one=1
two=2
three=3
four=4
five=5

file2.properties

one=1
three=3
threeandhalf=3.5
four=4
five=55555

Revised Example

Returns the properties in the first file missing in the second:

diff:
   [groovy] Missing keys: [two]

build.xml

<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>

OTHER TIPS

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.

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>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top