Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use Ant's 'sync' task, but based on file contents

Tags:

ant

I really like the Ant 'sync' task, but what I need to do is to copy files from a source folder to a destination folder based on whether or not the destination file's contents match the source file's contents, instead of checking the file modification date (which is what 'sync' does currently). Is there any way to accomplish this? I noticed that there is an Ant comparator for file content, as well as a 'checksum' task which may come in handy.

Thanks!

like image 586
Jon Onstott Avatar asked May 09 '11 18:05

Jon Onstott


3 Answers

For anyone else that hits this and needs code, here is a task for syncing one location with another based on contents rather than timestamp, it uses a modified selector rather than the different selector in the other answer to give more control over how file differences are calculated:

<project name="Demo" default="newSync">
  <description>
    Sync from ${foo} to ${bar}
  </description>

  <macrodef name="syncContents">
    <attribute name="from"/>
    <attribute name="to"/>
    <sequential>
      <fileset id="selectCopyFiles" dir="@{from}">
        <modified algorithm="hashvalue"/>
      </fileset>
      <fileset id="selectDeleteFiles" dir="@{to}">
        <not>
          <present targetdir="@{from}"/>
        </not>
      </fileset>

      <copy overwrite="true" todir="@{to}">
        <fileset refid="selectCopyFiles"/>
      </copy>
      <delete includeEmptyDirs="true">
        <fileset refid="selectDeleteFiles"/>               
      </delete>
    </sequential>
  </macrodef>

  <target name="newSync">
    <syncContents from="${foo}" to="${bar}"/>
  </target>
</project>

Note that this makes bar mirror foo (sync A->B), if you want a bidirectional sync you can replace the delete with a copy from B->A, and supply a concat task for dealing with changes to the same file in both locations.

like image 60
MilesHampson Avatar answered Sep 28 '22 00:09

MilesHampson


I was able to accomplish this using Ant's 'copy' task, which had a fileset with the different selector (see http://ant.apache.org/manual/Types/selectors.html#differentselect). It's powerful stuff.

like image 44
Jon Onstott Avatar answered Sep 28 '22 01:09

Jon Onstott


Thank you for this task !

However, the selectCopyFiles fileset was incorrect. I have also another solution for the selectDeleteFiles fileset.

Here is the new code of the macrodef :

<macrodef name="syncContents">
    <attribute name="from"/>
    <attribute name="to"/>
    <sequential>
        <echo>syncContents     : @{from} -> @{to}</echo>
        <fileset id="selectCopyFiles" dir="@{from}">
            <different targetdir="@{to}"
             ignoreFileTimes="true"/>
        </fileset>
        <fileset id="selectDeleteFiles" dir="@{to}">
            <present present="srconly" targetdir="@{from}"/>
        </fileset>

        <copy overwrite="true" todir="@{to}" preservelastmodified="true" verbose="true">
            <fileset refid="selectCopyFiles"/>
        </copy>
        <delete includeEmptyDirs="true" verbose="true">
            <fileset refid="selectDeleteFiles"/>
        </delete>
        <echo>End syncContents : @{from} -> @{to}</echo>
    </sequential>
</macrodef>
like image 35
Patrick Bourges Avatar answered Sep 28 '22 00:09

Patrick Bourges