1

I'm banging my head against a brick wall playing with ant filesets/ regexpmapper to try and simply rename a directory (in the middle of a path)...

The situation is really simple:

  • I have path component/DB/ that I'm copying to DB/api/src/main/distribution/component.
  • Path component/DB contains a set of install.sql scripts and a directory called api (or "API" or "Api"). This "api" directory contains additional sql and will be copied wholesale into the target DB/api/component (so creating DB/api/src/main/distribution/component/api).
  • As part of this copy, I simply want to lowercase the "api" directory name for consistency.

Sounds simple and I've been playing with filesets and regexpmapper (or mapper type=regexp) to achieve this. However, I've had mixed results... notably that it doesn't work as soon as I put a '/' in (or '\\' or '/' or ${file.separator}, even if using regexpmapper.handledirsep=yes).

Here is obfuscated source path structure (from find):

component/DB/
component/DB/API
component/DB/API/file1.sql
component/DB/API/file2.sql
component/DB/xyz.sql
component/DB/Install_API.sql
component/DB/excludes1/...

My basic copy is as below:

<copy todir="${my.db.api.dir}/src/main/distribution/component" verbose="true">
    <fileset dir="${component.src.dir}/DB">
        <exclude name="exclude1"/>
        <exclude name="exclude1/**/*"/>
    </fileset>
    <regexpmapper handledirsep="yes"
            from="(.*)/API(.*)" to="\1/api\2"/>
    <!--mapper type="regexp" from="(.*)/API(.*)" to="\1/api\2"/-->
</copy>

I've left plain '/' in for clarity. You can see the basic premise is to spot "API", grab the surrounding text and replay it with "api" instead. If I omit the '/' in the from then this does actually work but as soon as I put the '/' (or it's friends) in, the directory is not copied at all. Note that I want the preceding '/' as I only want to rename that dir, not the Install_API.sql file contained within it.

There are a lot of examples on-line but no-one seems to have had this issue as the supposedly working examples all seem to use plain '/', '\' or claim to be handled by the handledirset attribute.

ant 1.8.4 on RH6.3

Many thanks.

wmorrison365
  • 5,995
  • 2
  • 27
  • 40

1 Answers1

1

Your fileset's base directory is the DB dir which means that the paths your mapper will be mapping are of the form

API/file1.sql
Install_API.sql
excludes1/...

relative to that directory. Thus there is no slash in front of the API directory name and your from pattern never matches. But there's a deeper problem, which is that a regexpmapper completely ignores any file names that do not match the from pattern. This is not what you want, as you need to change API to api but leave non-API file names unchanged. So rather than a regexpmapper you need a filtermapper with a replaceregex filter:

<copy todir="${my.db.api.dir}/src/main/distribution/component" verbose="true">
    <fileset dir="${component.src.dir}/DB">
        <exclude name="exclude1"/>
        <exclude name="exclude1/**/*"/>
    </fileset>
    <filtermapper>
        <!-- look for either just "API" with no trailer, or API followed by
             a slash, in any combination of case -->
        <replaceregex pattern="^API(?=${file.separator}|$$)" replace="api"
                      flags="i"/><!-- case-insensitive search, finds API, Api, ... -->
    </filtermapper>
</copy>
Ian Roberts
  • 120,891
  • 16
  • 170
  • 183
  • That's fantastic thanks and a well-put lesson that I'd missed. I have one follow-up question if that's ok... In my output I'm now seeing `/src/main/distribution/component\api` (which I want) but also `/src/main/distribution/component/API` (with verbose logging telling me "[copy] API added as API doesn't exist." and "Copied 1 empty directory to 1 empty directory under ...component". I can delete this afterwards but was wondering if it was a config issue (having a read at the mo). Thanks very much for your help. – wmorrison365 Sep 26 '14 at 16:05
  • @wmorrison365 that's odd, I thought a `fileset` was supposed to be a set of _files_, not including the `API` directory as one of its entries (and I tested on a case-insensitive FS so didn't spot this at first). I've changed my regex slightly so it matches just "API" as well as "API/something". – Ian Roberts Sep 26 '14 at 16:18
  • Thanks again @ianroberts. I'd thought not to include the file sep and just use ^, given your explanation. I'll try out your improvement though. Much appreciated! – wmorrison365 Sep 27 '14 at 11:15
  • [This answer](http://stackoverflow.com/a/7280971/758831) is also quite relevant in how mappers work - together with the ant mappers docs. – wmorrison365 Sep 28 '14 at 12:34