[svn.haxx.se] · SVN Dev · SVN Users · SVN Org · TSVN Dev · TSVN Users · Subclipse Dev · Subclipse Users · this month's index

SvnAnt Committer? (patch #384 and #393)

From: JP Fiset <jp_at_fiset.ca>
Date: 2005-11-10 21:03:54 CET

Is there a committer for svn-ant out there I could talk to about the
patch I submitted a while back about #384 and #393? I submitted the
patch 3 weeks ago and I have not heard anything since. I know the
Subclipse project has been busy with a release, but I am wondering if
there is something fundamentally wrong with the work or if the delay is
just circumstantial.

JP

P.S. I re-submit here, again providing attached documentation to explain
the work.

[[[

Fix: Issue #384 (enhancement) File Selectors in svn-ant
Fix: Issue #393 (enhancement) Custom fileset for svn-ant

Patch by: Jean-Pierre Fiset (jpfiset)

Thanks:
* Matt Benson (dev@ant.apache.org mailing list), for answering questions
about custom file sets
* Graham Lea, for providing me with source code implementing a custom
file set.

Introduction:

    Add file selectors (normal, added, modified, conflicted, ignored,
replaced, locked, unversioned, missing,
    deleted) to svnAnt. For example, to copy a number of files with the
status 'added' from their location
    in workingcopy to a new directory called test, the following ant
task can be used:
    <copy todir="test">
        <fileset dir="workingcopy">
            <svnAdded/>
        </fileset>
    </copy>
   
    Add custom file set. For example, to revert a number of deleted files:
    <svn>
        <revert>
            <svnFileSet dir="workingcopy">
                <svnDeleted/>
            </svnFileSet>
        </revert>
    </svn>

Details:
                   
    In ANT, it is possible to add file selectors that complement file
sets. Those are known as custom file
    selectors. File sets are the basic types used to make up a list of
files for most tasks. Therefore, it
    is necessary to be able to discriminate files, within file sets,
based on the Subversion status.
    The file selectors presented do just that: extend file sets to
select files based on the Subversion
    status.
   
    Also missing are custom file sets. Although the custom file
selectors work well with the classic
    ANT file set, there are two types of files that can not be returned
by the latter: deleted and
    missing files. Therefore, a need for custom file set, based on svn
status, was necessary.
   
    Because these are major enhancements, some documentation was
required. I developed a rudimentary XML
    schema and XSL stylesheet, that validate and parse XML document
about ant-types and generate
    HTML documentation. This is nothing earth shattering, however it
produces documentation that has
    a similar look to the one previously produced for the svn task.
Added a table of content and
    a main page with frames for a more compelling user experience.

Testing:

    All regression tests were passed using JavaHL bindings. Command Line
Interface client currently
    provided with svn-ant has a bug with querying a status for a normal
file. Latest version of
    svnClientAdapter seems to have fixed problem. JavaSVN does not
support tests for lack of file://
    protocol.
   
Files in patch:

M build.properties
    Added directory definition 'src.doc.dir = src/doc', which is where
XML source
    documentation is located.
M build.xml
    Added target 'docs' to build HTML documentation based on XML
document for file selectors. It is
    also used by target 'makeDistrib'.

M src/testcases/org/tigris/subversion/svnant/SvnTest.java
    Added a fair number of test cases to verify functionality of new
custom file selectors,
    as well as the new custom file set. Can not test 'locked' selector
automatically since there is no
    task defined to 'lock'.
   
A test/svn/model/selectorTest
A test/svn/model/selectorTest/replaced2.txt
A test/svn/model/selectorTest/modified1.txt
A test/svn/model/selectorTest/modified2.txt
A test/svn/model/selectorTest/ignored1.txt
A test/svn/model/selectorTest/ignored2.txt
A test/svn/model/selectorTest/normal1.txt
A test/svn/model/selectorTest/normal2.txt
A test/svn/model/selectorTest/conflicted_v1.txt
A test/svn/model/selectorTest/conflicted_v2.txt
A test/svn/model/selectorTest/unversioned1.txt
A test/svn/model/selectorTest/added1.txt
A test/svn/model/selectorTest/unversioned2.txt
A test/svn/model/selectorTest/added2.txt
A test/svn/model/selectorTest/deleted1.txt
A test/svn/model/selectorTest/deleted2.txt
A test/svn/model/selectorTest/missing1.txt
A test/svn/model/selectorTest/missing2.txt
A test/svn/model/selectorTest/conflicted1.txt
A test/svn/model/selectorTest/conflicted2.txt
A test/svn/model/selectorTest/replaced1.txt
    Files that implement a test used by all svnant file selectors test
cases.

A test/svn/model/updateSvnFileSetTest
A test/svn/model/updateSvnFileSetTest/dir1
A test/svn/model/updateSvnFileSetTest/dir1/normal2.txt
A test/svn/model/updateSvnFileSetTest/dir1/missing2.txt
A test/svn/model/updateSvnFileSetTest/normal1.txt
A test/svn/model/updateSvnFileSetTest/missing1.txt
    Files that implement a test case for verifying functionality where the
    custom svn file set is used with svn update task.

A test/svn/model/addSvnFileSetTest
A test/svn/model/addSvnFileSetTest/added1.txt
A test/svn/model/addSvnFileSetTest/added2.txt
A test/svn/model/addSvnFileSetTest/normal1.txt
A test/svn/model/addSvnFileSetTest/normal2.txt
    Files that implement a test case for verifying functionality where the
    custom svn file set is used with svn add task.

A test/svn/model/commitSvnFileSetTest
A test/svn/model/commitSvnFileSetTest/dir1
A test/svn/model/commitSvnFileSetTest/dir1/file1.txt
A test/svn/model/commitSvnFileSetTest/file2.txt
    Files that implement a test case for verifying functionality where the
    custom svn file set is used with svn commit task.
   
A test/svn/model/deleteSvnFileSetTest
A test/svn/model/deleteSvnFileSetTest/dir1
A test/svn/model/deleteSvnFileSetTest/dir1/normal2.txt
A test/svn/model/deleteSvnFileSetTest/dir1/missing2.txt
A test/svn/model/deleteSvnFileSetTest/normal1.txt
A test/svn/model/deleteSvnFileSetTest/missing1.txt
    Files that implement a test case for verifying functionality where the
    custom svn file set is used with svn delete task.
   
A test/svn/model/keywordsSvnFileSetTest
A test/svn/model/keywordsSvnFileSetTest/dir1
A test/svn/model/keywordsSvnFileSetTest/dir1/file2.txt
A test/svn/model/keywordsSvnFileSetTest/file1.txt
    Files that implement a test case for verifying functionality where the
    custom svn file set is used with svn keywords-based task.
   
A test/svn/model/revertSvnFileSetTest
A test/svn/model/revertSvnFileSetTest/dir1
A test/svn/model/revertSvnFileSetTest/dir1/deleted2.txt
A test/svn/model/revertSvnFileSetTest/dir1/normal2.txt
A test/svn/model/revertSvnFileSetTest/deleted1.txt
A test/svn/model/revertSvnFileSetTest/normal1.txt
    Files that implement a test case for verifying functionality where the
    custom svn file set is used with svn revert task.
   
A test\svn\model\svnFileSetExcludesTest
A test\svn\model\svnFileSetExcludesTest\file11.txt
A test\svn\model\svnFileSetExcludesTest\file12.txt
A test\svn\model\svnFileSetExcludesTest\dir
A test\svn\model\svnFileSetExcludesTest\dir\file21.txt
A test\svn\model\svnFileSetExcludesTest\dir\file22.txt
    Files that implement a test case for verifying functionality where the
    'excludes' attribute is used with the custom svn file set.

A test\svn\model\svnFileSetIncludesTest
A test\svn\model\svnFileSetIncludesTest\file11.txt
A test\svn\model\svnFileSetIncludesTest\file12.txt
A test\svn\model\svnFileSetIncludesTest\dir
A test\svn\model\svnFileSetIncludesTest\dir\file21.txt
A test\svn\model\svnFileSetIncludesTest\dir\file22.txt
    Files that implement a test case for verifying functionality where the
    'includes' attribute is used with the custom svn file set.

A test\svn\model\svnFileSetNestedExcludeTest
A test\svn\model\svnFileSetNestedExcludeTest\file11.txt
A test\svn\model\svnFileSetNestedExcludeTest\file12.txt
A test\svn\model\svnFileSetNestedExcludeTest\dir
A test\svn\model\svnFileSetNestedExcludeTest\dir\file21.txt
A test\svn\model\svnFileSetNestedExcludeTest\dir\file22.txt
    Files that implement a test case for verifying functionality where the
    nested type 'exclude' is used with the custom svn file set.

A test\svn\model\svnFileSetNestedIncludeTest
A test\svn\model\svnFileSetNestedIncludeTest\file11.txt
A test\svn\model\svnFileSetNestedIncludeTest\file12.txt
A test\svn\model\svnFileSetNestedIncludeTest\dir
A test\svn\model\svnFileSetNestedIncludeTest\dir\file21.txt
A test\svn\model\svnFileSetNestedIncludeTest\dir\file22.txt
    Files that implement a test case for verifying functionality where the
    nested type 'include' is used with the custom svn file set.
   
A test\svn\model\svnFileSetPatternSetTest
A test\svn\model\svnFileSetPatternSetTest\dir1
A test\svn\model\svnFileSetPatternSetTest\dir1\file3.xml
A test\svn\model\svnFileSetPatternSetTest\dir1\file4.txt
A test\svn\model\svnFileSetPatternSetTest\file2.txt
A test\svn\model\svnFileSetPatternSetTest\file1.xml
A test\svn\model\svnFileSetPatternSetTest\dir2
A test\svn\model\svnFileSetPatternSetTest\dir2\file5.xml
A test\svn\model\svnFileSetPatternSetTest\dir2\file6.txt
    Files that implement a test case for verifying functionality where the
    nested type 'patternset' is used with the custom svn file set.
   
M test/svn/build.xml
    Replaced <taskdef> by <typedef>. Added a number of tests to support
SvnTest class.
    Note that a new dependency "init-selectors" create a working copy
with many files
    in various 'subverison status'. This is onerous and repeated for
each selector
    test. However, it is thorough and necessary.
   
 M doc
    Added selectors.html and types.html to svn:ignore, since they are
dynamically generated.

A doc/toc.html
    HTML document that contains the table of content for the user guide.

A doc/svnant-user.html
    Top HTML document for the user guide. Uses frames to link table of
content (TOC) and
    the various topics (svn.html, selectors.html, types.html)

M src/main/org/tigris/subversion/svnant/Delete.java
M src/main/org/tigris/subversion/svnant/Revert.java
M src/main/org/tigris/subversion/svnant/Keywords.java
M src/main/org/tigris/subversion/svnant/Update.java
M src/main/org/tigris/subversion/svnant/Commit.java
M src/main/org/tigris/subversion/svnant/Add.java
    These classes were modified to accept the custom file set. Previously,
    these classes accepted only the classic ANT file set.

M src/main/org/tigris/subversion/svnant/SvnTask.java
    isJavahlAvailable() and isJavaSVNAvailable() were changed from
'private' to
    'static public' so that the logic could be shared with the selector
and file set code. Ideally,
    this logic should find its way into a higher level class
(refactoring), but this is probably
    not within the mandate of this feature. Modified local variable to
'static' to support this
    change.

A src/main/org/tigris/subversion/svnant/selectors
    New package to hold all custom file selectors

A src/main/org/tigris/subversion/svnant/selectors/Replaced.java
    Class that implements 'svnReplaced' selector.
   
A src/main/org/tigris/subversion/svnant/selectors/Modified.java
    Class that implements 'svnModified' selector.
   
A src/main/org/tigris/subversion/svnant/selectors/Added.java
    Class that implements 'svnAdded' selector.
        
A src/main/org/tigris/subversion/svnant/selectors/Unversioned.java
    Class that implements 'svnUnversioned' selector.
        
A src/main/org/tigris/subversion/svnant/selectors/Locked.java
    Class that implements 'svnLocked' selector.

A src/main/org/tigris/subversion/svnant/selectors/BaseSvnSelector.java
    This is an abstract class that provides common funcitonality between
all file
    selectors. It handles the attributes ('javahl' and 'javasvn') common
to all
    selectors. It also retrieves the correct SVN client adapter and
passes it to
    the subclass. Here, design would benefit of caching the client adapter,
    but it is not in the mandate of this feature.

A
src/main/org/tigris/subversion/svnant/selectors/StatusBasedSelector.java
    This is an abstract class that provides common functionality between
all file
    selectors that uses an item's subversion status as the basis for
selection.
    Retrieves the status, handles error and then pass control flow to
subclass.

A src/main/org/tigris/subversion/svnant/selectors/Deleted.java
    Class that implements 'svnDeleted' selector. Must be used with the
custom file set
    to be effective.
   
A src/main/org/tigris/subversion/svnant/selectors/Ignored.java
    Class that implements 'svnIgnored' selector.

A src/main/org/tigris/subversion/svnant/selectors/Normal.java
    Class that implements 'svnNormal' selector.

A src/main/org/tigris/subversion/svnant/selectors/Missing.java
    Class that implements 'svnMissing' selector. Must be used with the
custom file set
    to be effective.
   
A src/main/org/tigris/subversion/svnant/selectors/Conflicted.java
    Class that implements 'svnConflicted' selector.
        
A src/main/org/tigris/subversion/svnant/types
    New package to hold all custom ANT types. At the present time,
contains only SvnFileSet.
   
A src/main/org/tigris/subversion/svnant/types/SvnFileSet.java
    Class that implements 'svnFileSet', the custom file set based on the
subversion status
    command.
   
A src/main/org/tigris/subversion/svnant/types/SvnDirScanner.java
    Support class for svnFileSet. Follows the interface laid out by the
classic file set
    and its support class: DirectoryScanner.
   
A src/main/svntypes.xml
    New resource file that should be used instead of svntask.properties.
The previous file
    is left for backward compatibility, but to use custom file set and
selectors, users will
    have to migrate to this new file. Therfore, instead of:
        <taskdef resource="svntask.properties"
classpathref="svnant.classpath"/>
    one shoud use:
        <typedef resource="svntypes.xml" classpathref="svnant.classpath"/>

A src/doc
    New directory where XML source documentation is saved.

A src/doc/ant-types.xsd
    XML schema used to define the structure of a XML document where ANT
type extensions are described.
                   
A src/doc/ant-types.xsl
    XSL stylesheet that transforms a XML document conforming to
ant-types.xsd
    into a HTML document with a format similar (although not exact) to the
    documentation written by Cédric Chabanois for the 'svn' task in svn.html
   
A src/doc/selectors.xml
    XML document conforming to ant-types.xsd and used to document all
new custom file selectors
    submitted in this patch.
   
A src/doc/types.xml
    XML document conforming to ant-types.xsd and used to document the
new custom file set
    submitted in this patch.
   
A src/doc/javahl_javasvn.txt
    File used as an external entity by selectors.xml and types.xml.

            
]]]

Index: test/svn/model/svnFileSetExcludesTest/file11.txt
===================================================================
--- test/svn/model/svnFileSetExcludesTest/file11.txt (revision 0)
+++ test/svn/model/svnFileSetExcludesTest/file11.txt (revision 0)
@@ -0,0 +1 @@
+This is just a test file
\ No newline at end of file

Property changes on: test\svn\model\svnFileSetExcludesTest\file11.txt
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Index: test/svn/model/svnFileSetExcludesTest/file12.txt
===================================================================
--- test/svn/model/svnFileSetExcludesTest/file12.txt (revision 0)
+++ test/svn/model/svnFileSetExcludesTest/file12.txt (revision 0)
@@ -0,0 +1 @@
+This is just a test file
\ No newline at end of file

Property changes on: test\svn\model\svnFileSetExcludesTest\file12.txt
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Index: test/svn/model/svnFileSetExcludesTest/dir/file21.txt
===================================================================
--- test/svn/model/svnFileSetExcludesTest/dir/file21.txt (revision 0)
+++ test/svn/model/svnFileSetExcludesTest/dir/file21.txt (revision 0)
@@ -0,0 +1 @@
+This is just a test file
\ No newline at end of file

Property changes on: test\svn\model\svnFileSetExcludesTest\dir\file21.txt
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Index: test/svn/model/svnFileSetExcludesTest/dir/file22.txt
===================================================================
--- test/svn/model/svnFileSetExcludesTest/dir/file22.txt (revision 0)
+++ test/svn/model/svnFileSetExcludesTest/dir/file22.txt (revision 0)
@@ -0,0 +1 @@
+This is just a test file
\ No newline at end of file

Property changes on: test\svn\model\svnFileSetExcludesTest\dir\file22.txt
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Index: test/svn/model/selectorTest/replaced2.txt
===================================================================
--- test/svn/model/selectorTest/replaced2.txt (revision 0)
+++ test/svn/model/selectorTest/replaced2.txt (revision 0)
@@ -0,0 +1 @@
+This file will be replaced
\ No newline at end of file

Property changes on: test\svn\model\selectorTest\replaced2.txt
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Index: test/svn/model/selectorTest/modified1.txt
===================================================================
--- test/svn/model/selectorTest/modified1.txt (revision 0)
+++ test/svn/model/selectorTest/modified1.txt (revision 0)
@@ -0,0 +1 @@
+This file will be modified
\ No newline at end of file

Property changes on: test\svn\model\selectorTest\modified1.txt
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Index: test/svn/model/selectorTest/modified2.txt
===================================================================
--- test/svn/model/selectorTest/modified2.txt (revision 0)
+++ test/svn/model/selectorTest/modified2.txt (revision 0)
@@ -0,0 +1 @@
+This file will be modified
\ No newline at end of file

Property changes on: test\svn\model\selectorTest\modified2.txt
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Index: test/svn/model/selectorTest/ignored1.txt
===================================================================
--- test/svn/model/selectorTest/ignored1.txt (revision 0)
+++ test/svn/model/selectorTest/ignored1.txt (revision 0)
@@ -0,0 +1 @@
+Just a test file
\ No newline at end of file

Property changes on: test\svn\model\selectorTest\ignored1.txt
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Index: test/svn/model/selectorTest/ignored2.txt
===================================================================
--- test/svn/model/selectorTest/ignored2.txt (revision 0)
+++ test/svn/model/selectorTest/ignored2.txt (revision 0)
@@ -0,0 +1 @@
+Just a test file
\ No newline at end of file

Property changes on: test\svn\model\selectorTest\ignored2.txt
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Index: test/svn/model/selectorTest/normal1.txt
===================================================================
--- test/svn/model/selectorTest/normal1.txt (revision 0)
+++ test/svn/model/selectorTest/normal1.txt (revision 0)
@@ -0,0 +1 @@
+Just a test file
\ No newline at end of file

Property changes on: test\svn\model\selectorTest\normal1.txt
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Index: test/svn/model/selectorTest/normal2.txt
===================================================================
--- test/svn/model/selectorTest/normal2.txt (revision 0)
+++ test/svn/model/selectorTest/normal2.txt (revision 0)
@@ -0,0 +1 @@
+Just a test file
\ No newline at end of file

Property changes on: test\svn\model\selectorTest\normal2.txt
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Index: test/svn/model/selectorTest/conflicted_v1.txt
===================================================================
--- test/svn/model/selectorTest/conflicted_v1.txt (revision 0)
+++ test/svn/model/selectorTest/conflicted_v1.txt (revision 0)
@@ -0,0 +1 @@
+First version of conflict
\ No newline at end of file

Property changes on: test\svn\model\selectorTest\conflicted_v1.txt
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Index: test/svn/model/selectorTest/conflicted_v2.txt
===================================================================
--- test/svn/model/selectorTest/conflicted_v2.txt (revision 0)
+++ test/svn/model/selectorTest/conflicted_v2.txt (revision 0)
@@ -0,0 +1 @@
+Second version of conflict
\ No newline at end of file

Property changes on: test\svn\model\selectorTest\conflicted_v2.txt
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Index: test/svn/model/selectorTest/unversioned1.txt
===================================================================
--- test/svn/model/selectorTest/unversioned1.txt (revision 0)
+++ test/svn/model/selectorTest/unversioned1.txt (revision 0)
@@ -0,0 +1 @@
+Just a test file
\ No newline at end of file

Property changes on: test\svn\model\selectorTest\unversioned1.txt
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Index: test/svn/model/selectorTest/added1.txt
===================================================================
--- test/svn/model/selectorTest/added1.txt (revision 0)
+++ test/svn/model/selectorTest/added1.txt (revision 0)
@@ -0,0 +1 @@
+Just a test file
\ No newline at end of file

Property changes on: test\svn\model\selectorTest\added1.txt
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Index: test/svn/model/selectorTest/unversioned2.txt
===================================================================
--- test/svn/model/selectorTest/unversioned2.txt (revision 0)
+++ test/svn/model/selectorTest/unversioned2.txt (revision 0)
@@ -0,0 +1 @@
+Just a test file
\ No newline at end of file

Property changes on: test\svn\model\selectorTest\unversioned2.txt
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Index: test/svn/model/selectorTest/added2.txt
===================================================================
--- test/svn/model/selectorTest/added2.txt (revision 0)
+++ test/svn/model/selectorTest/added2.txt (revision 0)
@@ -0,0 +1 @@
+Just a test file
\ No newline at end of file

Property changes on: test\svn\model\selectorTest\added2.txt
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Index: test/svn/model/selectorTest/deleted1.txt
===================================================================
--- test/svn/model/selectorTest/deleted1.txt (revision 0)
+++ test/svn/model/selectorTest/deleted1.txt (revision 0)
@@ -0,0 +1 @@
+Just a test file
\ No newline at end of file

Property changes on: test\svn\model\selectorTest\deleted1.txt
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Index: test/svn/model/selectorTest/deleted2.txt
===================================================================
--- test/svn/model/selectorTest/deleted2.txt (revision 0)
+++ test/svn/model/selectorTest/deleted2.txt (revision 0)
@@ -0,0 +1 @@
+Just a test file
\ No newline at end of file

Property changes on: test\svn\model\selectorTest\deleted2.txt
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Index: test/svn/model/selectorTest/missing1.txt
===================================================================
--- test/svn/model/selectorTest/missing1.txt (revision 0)
+++ test/svn/model/selectorTest/missing1.txt (revision 0)
@@ -0,0 +1 @@
+Just a test file
\ No newline at end of file

Property changes on: test\svn\model\selectorTest\missing1.txt
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Index: test/svn/model/selectorTest/missing2.txt
===================================================================
--- test/svn/model/selectorTest/missing2.txt (revision 0)
+++ test/svn/model/selectorTest/missing2.txt (revision 0)
@@ -0,0 +1 @@
+Just a test file
\ No newline at end of file

Property changes on: test\svn\model\selectorTest\missing2.txt
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Index: test/svn/model/selectorTest/conflicted1.txt
===================================================================
--- test/svn/model/selectorTest/conflicted1.txt (revision 0)
+++ test/svn/model/selectorTest/conflicted1.txt (revision 0)
@@ -0,0 +1 @@
+Just a test file
\ No newline at end of file

Property changes on: test\svn\model\selectorTest\conflicted1.txt
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Index: test/svn/model/selectorTest/conflicted2.txt
===================================================================
--- test/svn/model/selectorTest/conflicted2.txt (revision 0)
+++ test/svn/model/selectorTest/conflicted2.txt (revision 0)
@@ -0,0 +1 @@
+Just a test file
\ No newline at end of file

Property changes on: test\svn\model\selectorTest\conflicted2.txt
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Index: test/svn/model/selectorTest/replaced1.txt
===================================================================
--- test/svn/model/selectorTest/replaced1.txt (revision 0)
+++ test/svn/model/selectorTest/replaced1.txt (revision 0)
@@ -0,0 +1 @@
+This file will be replaced
\ No newline at end of file

Property changes on: test\svn\model\selectorTest\replaced1.txt
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Index: test/svn/model/updateSvnFileSetTest/dir1/normal2.txt
===================================================================
--- test/svn/model/updateSvnFileSetTest/dir1/normal2.txt (revision 0)
+++ test/svn/model/updateSvnFileSetTest/dir1/normal2.txt (revision 0)
@@ -0,0 +1 @@
+Just a test file
\ No newline at end of file

Property changes on: test\svn\model\updateSvnFileSetTest\dir1\normal2.txt
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Index: test/svn/model/updateSvnFileSetTest/dir1/missing2.txt
===================================================================
--- test/svn/model/updateSvnFileSetTest/dir1/missing2.txt (revision 0)
+++ test/svn/model/updateSvnFileSetTest/dir1/missing2.txt (revision 0)
@@ -0,0 +1 @@
+Just a test file
\ No newline at end of file

Property changes on: test\svn\model\updateSvnFileSetTest\dir1\missing2.txt
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Index: test/svn/model/updateSvnFileSetTest/normal1.txt
===================================================================
--- test/svn/model/updateSvnFileSetTest/normal1.txt (revision 0)
+++ test/svn/model/updateSvnFileSetTest/normal1.txt (revision 0)
@@ -0,0 +1 @@
+Just a test file
\ No newline at end of file

Property changes on: test\svn\model\updateSvnFileSetTest\normal1.txt
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Index: test/svn/model/updateSvnFileSetTest/missing1.txt
===================================================================
--- test/svn/model/updateSvnFileSetTest/missing1.txt (revision 0)
+++ test/svn/model/updateSvnFileSetTest/missing1.txt (revision 0)
@@ -0,0 +1 @@
+Just a test file
\ No newline at end of file

Property changes on: test\svn\model\updateSvnFileSetTest\missing1.txt
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Index: test/svn/model/addSvnFileSetTest/added1.txt
===================================================================
--- test/svn/model/addSvnFileSetTest/added1.txt (revision 0)
+++ test/svn/model/addSvnFileSetTest/added1.txt (revision 0)
@@ -0,0 +1 @@
+Just a test file
\ No newline at end of file

Property changes on: test\svn\model\addSvnFileSetTest\added1.txt
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Index: test/svn/model/addSvnFileSetTest/added2.txt
===================================================================
--- test/svn/model/addSvnFileSetTest/added2.txt (revision 0)
+++ test/svn/model/addSvnFileSetTest/added2.txt (revision 0)
@@ -0,0 +1 @@
+Just a test file
\ No newline at end of file

Property changes on: test\svn\model\addSvnFileSetTest\added2.txt
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Index: test/svn/model/addSvnFileSetTest/normal1.txt
===================================================================
--- test/svn/model/addSvnFileSetTest/normal1.txt (revision 0)
+++ test/svn/model/addSvnFileSetTest/normal1.txt (revision 0)
@@ -0,0 +1 @@
+Just a test file
\ No newline at end of file

Property changes on: test\svn\model\addSvnFileSetTest\normal1.txt
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Index: test/svn/model/addSvnFileSetTest/normal2.txt
===================================================================
--- test/svn/model/addSvnFileSetTest/normal2.txt (revision 0)
+++ test/svn/model/addSvnFileSetTest/normal2.txt (revision 0)
@@ -0,0 +1 @@
+Just a test file
\ No newline at end of file

Property changes on: test\svn\model\addSvnFileSetTest\normal2.txt
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Index: test/svn/model/commitSvnFileSetTest/dir1/file1.txt
===================================================================
--- test/svn/model/commitSvnFileSetTest/dir1/file1.txt (revision 0)
+++ test/svn/model/commitSvnFileSetTest/dir1/file1.txt (revision 0)
@@ -0,0 +1 @@
+testing, that's all
\ No newline at end of file

Property changes on: test\svn\model\commitSvnFileSetTest\dir1\file1.txt
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Index: test/svn/model/commitSvnFileSetTest/file2.txt
===================================================================
--- test/svn/model/commitSvnFileSetTest/file2.txt (revision 0)
+++ test/svn/model/commitSvnFileSetTest/file2.txt (revision 0)
@@ -0,0 +1 @@
+testing, that's all
\ No newline at end of file

Property changes on: test\svn\model\commitSvnFileSetTest\file2.txt
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Index: test/svn/model/deleteSvnFileSetTest/dir1/normal2.txt
===================================================================
--- test/svn/model/deleteSvnFileSetTest/dir1/normal2.txt (revision 0)
+++ test/svn/model/deleteSvnFileSetTest/dir1/normal2.txt (revision 0)
@@ -0,0 +1 @@
+just a test file
\ No newline at end of file

Property changes on: test\svn\model\deleteSvnFileSetTest\dir1\normal2.txt
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Index: test/svn/model/deleteSvnFileSetTest/dir1/missing2.txt
===================================================================
--- test/svn/model/deleteSvnFileSetTest/dir1/missing2.txt (revision 0)
+++ test/svn/model/deleteSvnFileSetTest/dir1/missing2.txt (revision 0)
@@ -0,0 +1 @@
+just a test file
\ No newline at end of file

Property changes on: test\svn\model\deleteSvnFileSetTest\dir1\missing2.txt
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Index: test/svn/model/deleteSvnFileSetTest/normal1.txt
===================================================================
--- test/svn/model/deleteSvnFileSetTest/normal1.txt (revision 0)
+++ test/svn/model/deleteSvnFileSetTest/normal1.txt (revision 0)
@@ -0,0 +1 @@
+just a test file
\ No newline at end of file

Property changes on: test\svn\model\deleteSvnFileSetTest\normal1.txt
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Index: test/svn/model/deleteSvnFileSetTest/missing1.txt
===================================================================
--- test/svn/model/deleteSvnFileSetTest/missing1.txt (revision 0)
+++ test/svn/model/deleteSvnFileSetTest/missing1.txt (revision 0)
@@ -0,0 +1 @@
+just a test file
\ No newline at end of file

Property changes on: test\svn\model\deleteSvnFileSetTest\missing1.txt
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Index: test/svn/model/svnFileSetIncludesTest/file11.txt
===================================================================
--- test/svn/model/svnFileSetIncludesTest/file11.txt (revision 0)
+++ test/svn/model/svnFileSetIncludesTest/file11.txt (revision 0)
@@ -0,0 +1 @@
+This is just a test file
\ No newline at end of file

Property changes on: test\svn\model\svnFileSetIncludesTest\file11.txt
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Index: test/svn/model/svnFileSetIncludesTest/file12.txt
===================================================================
--- test/svn/model/svnFileSetIncludesTest/file12.txt (revision 0)
+++ test/svn/model/svnFileSetIncludesTest/file12.txt (revision 0)
@@ -0,0 +1 @@
+This is just a test file
\ No newline at end of file

Property changes on: test\svn\model\svnFileSetIncludesTest\file12.txt
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Index: test/svn/model/svnFileSetIncludesTest/dir/file21.txt
===================================================================
--- test/svn/model/svnFileSetIncludesTest/dir/file21.txt (revision 0)
+++ test/svn/model/svnFileSetIncludesTest/dir/file21.txt (revision 0)
@@ -0,0 +1 @@
+This is just a test file
\ No newline at end of file

Property changes on: test\svn\model\svnFileSetIncludesTest\dir\file21.txt
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Index: test/svn/model/svnFileSetIncludesTest/dir/file22.txt
===================================================================
--- test/svn/model/svnFileSetIncludesTest/dir/file22.txt (revision 0)
+++ test/svn/model/svnFileSetIncludesTest/dir/file22.txt (revision 0)
@@ -0,0 +1 @@
+This is just a test file
\ No newline at end of file

Property changes on: test\svn\model\svnFileSetIncludesTest\dir\file22.txt
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Index: test/svn/model/revertSvnFileSetTest/dir1/deleted2.txt
===================================================================
--- test/svn/model/revertSvnFileSetTest/dir1/deleted2.txt (revision 0)
+++ test/svn/model/revertSvnFileSetTest/dir1/deleted2.txt (revision 0)
@@ -0,0 +1 @@
+Just a test file
\ No newline at end of file

Property changes on: test\svn\model\revertSvnFileSetTest\dir1\deleted2.txt
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Index: test/svn/model/revertSvnFileSetTest/dir1/normal2.txt
===================================================================
--- test/svn/model/revertSvnFileSetTest/dir1/normal2.txt (revision 0)
+++ test/svn/model/revertSvnFileSetTest/dir1/normal2.txt (revision 0)
@@ -0,0 +1 @@
+Just a test file
\ No newline at end of file

Property changes on: test\svn\model\revertSvnFileSetTest\dir1\normal2.txt
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Index: test/svn/model/revertSvnFileSetTest/deleted1.txt
===================================================================
--- test/svn/model/revertSvnFileSetTest/deleted1.txt (revision 0)
+++ test/svn/model/revertSvnFileSetTest/deleted1.txt (revision 0)
@@ -0,0 +1 @@
+Just a test file
\ No newline at end of file

Property changes on: test\svn\model\revertSvnFileSetTest\deleted1.txt
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Index: test/svn/model/revertSvnFileSetTest/normal1.txt
===================================================================
--- test/svn/model/revertSvnFileSetTest/normal1.txt (revision 0)
+++ test/svn/model/revertSvnFileSetTest/normal1.txt (revision 0)
@@ -0,0 +1 @@
+Just a test file
\ No newline at end of file

Property changes on: test\svn\model\revertSvnFileSetTest\normal1.txt
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Index: test/svn/model/keywordsSvnFileSetTest/dir1/file2.txt
===================================================================
--- test/svn/model/keywordsSvnFileSetTest/dir1/file2.txt (revision 0)
+++ test/svn/model/keywordsSvnFileSetTest/dir1/file2.txt (revision 0)
@@ -0,0 +1 @@
+$LastChangedRevision$
\ No newline at end of file

Property changes on: test\svn\model\keywordsSvnFileSetTest\dir1\file2.txt
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Index: test/svn/model/keywordsSvnFileSetTest/file1.txt
===================================================================
--- test/svn/model/keywordsSvnFileSetTest/file1.txt (revision 0)
+++ test/svn/model/keywordsSvnFileSetTest/file1.txt (revision 0)
@@ -0,0 +1 @@
+$LastChangedRevision$
\ No newline at end of file

Property changes on: test\svn\model\keywordsSvnFileSetTest\file1.txt
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Index: test/svn/build.xml
===================================================================
--- test/svn/build.xml (revision 1649)
+++ test/svn/build.xml (working copy)
@@ -17,7 +17,7 @@
     <pathelement location="${jsch.jar}"/>
   </path>
   
- <taskdef resource="svntask.properties" classpathref="project.classpath"/>
+ <typedef resource="svntypes.xml" classpathref="project.classpath"/>
 
 
   <target name="clean">
@@ -26,6 +26,7 @@
     <delete dir="coHEAD"/>
     <delete dir="co0"/>
     <delete dir="export1"/>
+ <delete dir="test"/>
   </target>
 
 
@@ -60,6 +61,106 @@
     </svn>
   </target>
 
+ <!-- init-selectors is run before each test for file selectors, since they all
+ share the same model of a working copy -->
+ <target name="init-selectors" depends="init">
+ <echo message="javahl = ${javahl} javasvn = ${javasvn}"/>
+ <copy todir="workingcopy">
+ <fileset dir="model/selectorTest"></fileset>
+ </copy>
+ <svn javahl="${javahl}" javasvn="${javasvn}">
+ <!-- Normal files -->
+ <add file="workingcopy/normal1.txt"/>
+ <add file="workingcopy/normal2.txt"/>
+ <commit file="workingcopy/normal1.txt" message="normal file"/>
+ <commit file="workingcopy/normal2.txt" message="normal file"/>
+
+ <!-- Added files -->
+ <add file="workingcopy/added1.txt"/>
+ <add file="workingcopy/added2.txt"/>
+
+ <!-- Deleted files -->
+ <add file="workingcopy/deleted1.txt"/>
+ <add file="workingcopy/deleted2.txt"/>
+ <commit file="workingcopy/deleted1.txt" message="deleted file"/>
+ <commit file="workingcopy/deleted2.txt" message="deleted file"/>
+ <delete file="workingcopy/deleted1.txt"/>
+ <delete file="workingcopy/deleted2.txt"/>
+
+ <!-- Missing files (part 1 of 2) -->
+ <add file="workingcopy/missing1.txt"/>
+ <add file="workingcopy/missing2.txt"/>
+ <commit file="workingcopy/missing1.txt" message="missing file"/>
+ <commit file="workingcopy/missing2.txt" message="missing file"/>
+
+ <!-- Modified files (part 1 of 2) -->
+ <add file="workingcopy/modified1.txt"/>
+ <add file="workingcopy/modified2.txt"/>
+ <commit file="workingcopy/modified1.txt" message="modified file"/>
+ <commit file="workingcopy/modified2.txt" message="modified file"/>
+
+ <!-- Ignored files -->
+ <ignore file="workingcopy/ignored1.txt"/>
+ <ignore file="workingcopy/ignored2.txt"/>
+
+ <!-- Conflicted files (part 1 of 2) -->
+ <add file="workingcopy/conflicted1.txt"/>
+ <add file="workingcopy/conflicted2.txt"/>
+ <commit file="workingcopy/conflicted1.txt" message="conflicted file"/>
+ <commit file="workingcopy/conflicted2.txt" message="conflicted file"/>
+
+ <!-- Replaced files (part 1 of 2) -->
+ <add file="workingcopy/replaced1.txt"/>
+ <add file="workingcopy/replaced2.txt"/>
+ <commit file="workingcopy/replaced1.txt" message="replaced file"/>
+ <commit file="workingcopy/replaced2.txt" message="replaced file"/>
+ <delete file="workingcopy/replaced1.txt"/>
+ <delete file="workingcopy/replaced2.txt"/>
+ </svn>
+
+ <!-- Checkout a second working copy -->
+ <mkdir dir="workingcopy2"/>
+ <svn javahl="${javahl}" javasvn="${javasvn}">
+ <checkout url="${urlRepos}" destPath="workingcopy2" />
+ </svn>
+
+ <!-- Conflicted files (part 2 of 2) -->
+ <copy file="workingcopy/conflicted_v1.txt" tofile="workingcopy/conflicted1.txt" overwrite="true"/>
+ <copy file="workingcopy/conflicted_v1.txt" tofile="workingcopy/conflicted2.txt" overwrite="true"/>
+ <copy file="workingcopy/conflicted_v2.txt" tofile="workingcopy2/conflicted1.txt" overwrite="true"/>
+ <copy file="workingcopy/conflicted_v2.txt" tofile="workingcopy2/conflicted2.txt" overwrite="true"/>
+ <svn javahl="${javahl}" javasvn="${javasvn}">
+ <commit message="conflicted file" file="workingcopy2/conflicted1.txt" />
+ <commit message="conflicted file" file="workingcopy2/conflicted2.txt" />
+ <update file="workingcopy/conflicted1.txt" />
+ <update file="workingcopy/conflicted2.txt" />
+ </svn>
+ <delete file="workingcopy/conflicted_v1.txt"/>
+ <delete file="workingcopy/conflicted_v2.txt"/>
+ <delete>
+ <fileset dir="workingcopy">
+ <include name="conflicted1.txt.*"/>
+ <include name="conflicted2.txt.*"/>
+ </fileset>
+ </delete>
+
+ <!-- Missing files (part 2 of 2) -->
+ <delete file="workingcopy/missing1.txt"/>
+ <delete file="workingcopy/missing2.txt"/>
+
+ <!-- Modified files (part 2 of 2) -->
+ <copy file="workingcopy/normal1.txt" tofile="workingcopy/modified1.txt" overwrite="true"/>
+ <copy file="workingcopy/normal2.txt" tofile="workingcopy/modified2.txt" overwrite="true"/>
+
+ <!-- Replaced files (part 2 of 2) -->
+ <copy file="workingcopy/normal1.txt" tofile="workingcopy/replaced1.txt" overwrite="true"/>
+ <copy file="workingcopy/normal2.txt" tofile="workingcopy/replaced2.txt" overwrite="true"/>
+ <svn javahl="${javahl}" javasvn="${javasvn}">
+ <add file="workingcopy/replaced1.txt"/>
+ <add file="workingcopy/replaced2.txt"/>
+ </svn>
+ </target>
+
   <!-- this test does not test svnant but svnClientAdapter -->
   <target name="testList" depends="init">
     <copy todir="workingcopy/listTest">
@@ -437,6 +538,313 @@
     </svn>
   </target>
         
+ <target name="testNormalSelector" depends="init-selectors">
+ <mkdir dir="test"/>
+ <copy todir="test">
+ <fileset dir="workingcopy">
+ <svnNormal javahl="${javahl}" javasvn="${javasvn}"/>
+ </fileset>
+ </copy>
+ </target>
+
+ <target name="testAddedSelector" depends="init-selectors">
+ <mkdir dir="test"/>
+ <copy todir="test">
+ <fileset dir="workingcopy">
+ <svnAdded javahl="${javahl}" javasvn="${javasvn}"/>
+ </fileset>
+ </copy>
+ </target>
+
+ <target name="testUnversionedSelector" depends="init-selectors">
+ <mkdir dir="test"/>
+ <copy todir="test">
+ <fileset dir="workingcopy">
+ <svnUnversioned javahl="${javahl}" javasvn="${javasvn}"/>
+ </fileset>
+ </copy>
+ </target>
+
+ <target name="testModifiedSelector" depends="init-selectors">
+ <mkdir dir="test"/>
+ <copy todir="test">
+ <fileset dir="workingcopy">
+ <svnModified javahl="${javahl}" javasvn="${javasvn}"/>
+ </fileset>
+ </copy>
+ </target>
+
+ <target name="testIgnoredSelector" depends="init-selectors">
+ <mkdir dir="test"/>
+ <copy todir="test">
+ <fileset dir="workingcopy">
+ <svnIgnored javahl="${javahl}" javasvn="${javasvn}"/>
+ </fileset>
+ </copy>
+ </target>
+
+ <target name="testConflictedSelector" depends="init-selectors">
+ <mkdir dir="test"/>
+ <copy todir="test">
+ <fileset dir="workingcopy">
+ <svnConflicted javahl="${javahl}" javasvn="${javasvn}"/>
+ </fileset>
+ </copy>
+ </target>
+
+ <target name="testReplacedSelector" depends="init-selectors">
+ <mkdir dir="test"/>
+ <copy todir="test">
+ <fileset dir="workingcopy">
+ <svnReplaced javahl="${javahl}" javasvn="${javasvn}"/>
+ </fileset>
+ </copy>
+ </target>
+
+ <target name="testEmbeddedSelector" depends="init-selectors">
+ <mkdir dir="test"/>
+ <svn javahl="${javahl}" javasvn="${javasvn}">
+ <add>
+ <fileset dir="workingcopy">
+ <svnUnversioned javahl="${javahl}" javasvn="${javasvn}"/>
+ </fileset>
+ </add>
+ </svn>
+ <copy todir="test">
+ <fileset dir="workingcopy">
+ <svnUnversioned javahl="${javahl}" javasvn="${javasvn}"/>
+ </fileset>
+ </copy>
+ </target>
+
+ <target name="testAddSvnFileSet" depends="init">
+ <!-- Prepare test -->
+ <copy todir="workingcopy">
+ <fileset dir="model/addSvnFileSetTest"/>
+ </copy>
+ <svn javahl="${javahl}" javasvn="${javasvn}">
+ <add file="workingcopy/normal1.txt"/>
+ <add file="workingcopy/normal2.txt"/>
+ <commit file="workingcopy/normal1.txt" message="ci"/>
+ <commit file="workingcopy/normal2.txt" message="ci"/>
+ </svn>
+
+ <!-- Perform test -->
+ <svn javahl="${javahl}" javasvn="${javasvn}">
+ <add>
+ <svnFileSet dir="workingcopy" javahl="${javahl}" javasvn="${javasvn}">
+ <svnUnversioned javahl="${javahl}" javasvn="${javasvn}"/>
+ </svnFileSet>
+ </add>
+ </svn>
+
+ <!-- Verify -->
+ <mkdir dir="test"/>
+ <copy todir="test">
+ <fileset dir="workingcopy">
+ <svnAdded javahl="${javahl}" javasvn="${javasvn}"/>
+ </fileset>
+ </copy>
+ </target>
+
+ <target name="testCommitSvnFileSet" depends="init">
+ <!-- Prepare test -->
+ <copy todir="workingcopy">
+ <fileset dir="model/commitSvnFileSetTest"/>
+ </copy>
+ <svn javahl="${javahl}" javasvn="${javasvn}">
+ <add file="workingcopy/file2.txt"/>
+ <add dir="workingcopy/dir1"/>
+ </svn>
+
+ <!-- Perform test -->
+ <svn javahl="${javahl}" javasvn="${javasvn}">
+ <commit message="ci">
+ <svnFileSet dir="workingcopy" javahl="${javahl}" javasvn="${javasvn}">
+ <svnAdded javahl="${javahl}" javasvn="${javasvn}"/>
+ </svnFileSet>
+ </commit>
+ </svn>
+
+ <!-- Verify -->
+ <mkdir dir="test"/>
+ <copy todir="test">
+ <fileset dir="workingcopy">
+ <svnNormal javahl="${javahl}" javasvn="${javasvn}"/>
+ </fileset>
+ </copy>
+ </target>
+
+ <target name="testDeleteSvnFileSet" depends="init">
+ <!-- Prepare test -->
+ <copy todir="workingcopy">
+ <fileset dir="model/deleteSvnFileSetTest"/>
+ </copy>
+ <svn javahl="${javahl}" javasvn="${javasvn}">
+ <add file="workingcopy/normal1.txt"/>
+ <add file="workingcopy/missing1.txt"/>
+ <add dir="workingcopy/dir1"/>
+ <commit file="workingcopy/normal1.txt" message="ci"/>
+ <commit file="workingcopy/missing1.txt" message="ci"/>
+ <commit dir="workingcopy/dir1" message="ci"/>
+ </svn>
+ <delete file="workingcopy/missing1.txt"/>
+ <delete file="workingcopy/dir1/missing2.txt"/>
+
+ <!-- Perform test -->
+ <svn javahl="${javahl}" javasvn="${javasvn}">
+ <delete>
+ <svnFileSet dir="workingcopy" javahl="${javahl}" javasvn="${javasvn}">
+ <svnMissing javahl="${javahl}" javasvn="${javasvn}"/>
+ </svnFileSet>
+ </delete>
+ <commit dir="workingcopy" message="ci"/>
+ </svn>
+
+ <!-- Verify -->
+ <mkdir dir="workingcopy2"/>
+ <svn javahl="${javahl}" javasvn="${javasvn}">
+ <checkout url="${urlRepos}" destPath="workingcopy2" />
+ </svn>
+ </target>
+
+ <target name="testKeywordsSvnFileSet" depends="init">
+ <!-- Prepare test -->
+ <copy todir="workingcopy">
+ <fileset dir="model/keywordsSvnFileSetTest"/>
+ </copy>
+ <svn javahl="${javahl}" javasvn="${javasvn}">
+ <add file="workingcopy/file1.txt"/>
+ <add dir="workingcopy/dir1"/>
+ <commit file="workingcopy/file1.txt" message="ci"/>
+ <commit dir="workingcopy/dir1" message="ci"/>
+ </svn>
+
+ <!-- Perform test -->
+ <svn javahl="${javahl}" javasvn="${javasvn}">
+ <keywordsset keywords="LastChangedRevision">
+ <svnFileSet dir="workingcopy" javahl="${javahl}" javasvn="${javasvn}">
+ <svnNormal javahl="${javahl}" javasvn="${javasvn}"/>
+ </svnFileSet>
+ </keywordsset>
+ <commit dir="workingcopy" message="ci"/>
+ </svn>
+ </target>
+
+ <target name="testRevertSvnFileSet" depends="init">
+ <!-- Prepare test -->
+ <copy todir="workingcopy">
+ <fileset dir="model/revertSvnFileSetTest"/>
+ </copy>
+ <svn javahl="${javahl}" javasvn="${javasvn}">
+ <add file="workingcopy/normal1.txt"/>
+ <add file="workingcopy/deleted1.txt"/>
+ <add dir="workingcopy/dir1"/>
+ <commit file="workingcopy/normal1.txt" message="ci"/>
+ <commit file="workingcopy/deleted1.txt" message="ci"/>
+ <commit dir="workingcopy/dir1" message="ci"/>
+ <delete file="workingcopy/deleted1.txt"/>
+ <delete file="workingcopy/dir1/deleted2.txt"/>
+ </svn>
+
+ <!-- Perform test -->
+ <svn javahl="${javahl}" javasvn="${javasvn}">
+ <revert>
+ <svnFileSet dir="workingcopy" javahl="${javahl}" javasvn="${javasvn}">
+ <svnDeleted javahl="${javahl}" javasvn="${javasvn}"/>
+ </svnFileSet>
+ </revert>
+ </svn>
+ </target>
+
+ <target name="testUpdateSvnFileSet" depends="init">
+ <!-- Prepare test -->
+ <copy todir="workingcopy">
+ <fileset dir="model/updateSvnFileSetTest"/>
+ </copy>
+ <svn javahl="${javahl}" javasvn="${javasvn}">
+ <add file="workingcopy/normal1.txt"/>
+ <add file="workingcopy/missing1.txt"/>
+ <add dir="workingcopy/dir1"/>
+ <commit file="workingcopy/normal1.txt" message="ci"/>
+ <commit file="workingcopy/missing1.txt" message="ci"/>
+ <commit dir="workingcopy/dir1" message="ci"/>
+ </svn>
+ <delete file="workingcopy/missing1.txt"/>
+ <delete file="workingcopy/dir1/missing2.txt"/>
+
+ <!-- Perform test : update should restore missing files -->
+ <svn javahl="${javahl}" javasvn="${javasvn}">
+ <update>
+ <svnFileSet dir="workingcopy" javahl="${javahl}" javasvn="${javasvn}">
+ <svnMissing javahl="${javahl}" javasvn="${javasvn}"/>
+ </svnFileSet>
+ </update>
+ </svn>
+ </target>
+
+ <target name="testSvnFileSetAsRefId" depends="init-selectors">
+ <svnFileSet id="svnFileSetId_1" dir="workingcopy" javahl="${javahl}" javasvn="${javasvn}">
+ <svnAdded javahl="${javahl}" javasvn="${javasvn}"/>
+ </svnFileSet>
+ <mkdir dir="test"/>
+ <copy todir="test">
+ <fileset refid="svnFileSetId_1"/>
+ </copy>
+ </target>
+
+ <target name="testSvnFileSetIncludes" depends="init">
+ <!-- Prepare test -->
+ <copy todir="workingcopy">
+ <fileset dir="model/svnFileSetIncludesTest"/>
+ </copy>
+ <svn javahl="${javahl}" javasvn="${javasvn}">
+ <add file="workingcopy/file11.txt"/>
+ <add file="workingcopy/file12.txt"/>
+ <add dir="workingcopy/dir"/>
+ <commit file="workingcopy/file11.txt" message="ci"/>
+ <commit file="workingcopy/file12.txt" message="ci"/>
+ <commit dir="workingcopy/dir" message="ci"/>
+ </svn>
+
+ <!-- Conduct Test -->
+ <svnFileSet
+ id="svnFileSetIncludes"
+ dir="workingcopy"
+ includes="**/*1.txt"
+ javahl="${javahl}" javasvn="${javasvn}"/>
+ <mkdir dir="test"/>
+ <copy todir="test">
+ <fileset refid="svnFileSetIncludes"/>
+ </copy>
+ </target>
+
+ <target name="testSvnFileSetExcludes" depends="init">
+ <!-- Prepare test -->
+ <copy todir="workingcopy">
+ <fileset dir="model/svnFileSetExcludesTest"/>
+ </copy>
+ <svn javahl="${javahl}" javasvn="${javasvn}">
+ <add file="workingcopy/file11.txt"/>
+ <add file="workingcopy/file12.txt"/>
+ <add dir="workingcopy/dir"/>
+ <commit file="workingcopy/file11.txt" message="ci"/>
+ <commit file="workingcopy/file12.txt" message="ci"/>
+ <commit dir="workingcopy/dir" message="ci"/>
+ </svn>
+
+ <!-- Conduct Test -->
+ <svnFileSet
+ id="svnFileSetExcludes"
+ dir="workingcopy"
+ excludes="**/*1.txt"
+ javahl="${javahl}" javasvn="${javasvn}"/>
+ <mkdir dir="test"/>
+ <copy todir="test">
+ <fileset refid="svnFileSetExcludes"/>
+ </copy>
+ </target>
+
   <target name="all" depends="init">
   </target>
         

Property changes on: doc
___________________________________________________________________
Name: svn:ignore
   +
selectors.html
fileset.html
types.html

Index: doc/toc.html
===================================================================
--- doc/toc.html (revision 0)
+++ doc/toc.html (revision 0)
@@ -0,0 +1,16 @@
+<html>
+ <head>
+ <meta http-equiv="Content-Language" content="en-us"/>
+ <title>SvnAnt User Manual</title>
+ <base target="mainFrame"/>
+ </head>
+ <body>
+ <h2>SvnAnt</h2>
+ <h3>Table of Content</h3>
+ Tasks
+ <br/>
+ Types
+ <br/>
+ Selectors
+ </body>
+</html>

Property changes on: doc\toc.html
___________________________________________________________________
Name: svn:mime-type
   + text/html

Index: doc/svnant-user.html
===================================================================
--- doc/svnant-user.html (revision 0)
+++ doc/svnant-user.html (revision 0)
@@ -0,0 +1,18 @@
+<html>
+ <head>
+ <meta http-equiv="Content-Language" content="en-us">
+ <title>SvnAnt User Manual</title>
+ </head>
+
+ <frameset cols="18%,82%">
+ <frame src="toc.html" name="navFrame">
+ <frame src="svn.html" name="mainFrame">
+ </frameset>
+ <noframes>
+ <h3>No Frames!</h3>
+ <p>
+ Your browser does not display frames. This link will
+ bring you to the table of content: SvnAnt - Table of Content
+ </p>
+ </noframes>
+</html>
\ No newline at end of file

Property changes on: doc\svnant-user.html
___________________________________________________________________
Name: svn:mime-type
   + text/html

Index: src/main/org/tigris/subversion/svnant/Delete.java
===================================================================
--- src/main/org/tigris/subversion/svnant/Delete.java (revision 1649)
+++ src/main/org/tigris/subversion/svnant/Delete.java (working copy)
@@ -230,4 +230,11 @@
                 filesets.addElement(set);
         }
         
+ /**
+ * Adds a set of files to add
+ */
+ public void add(FileSet set) {
+ filesets.addElement(set);
+ }
+
 }
Index: src/main/org/tigris/subversion/svnant/Keywords.java
===================================================================
--- src/main/org/tigris/subversion/svnant/Keywords.java (revision 1649)
+++ src/main/org/tigris/subversion/svnant/Keywords.java (working copy)
@@ -173,6 +173,13 @@
     }
 
     /**
+ * Adds a set of files on which to apply keywords substitution
+ */
+ public void add(FileSet set) {
+ filesets.addElement(set);
+ }
+
+ /**
      * set the keywords
      * @param keywords
      */
Index: src/main/org/tigris/subversion/svnant/Revert.java
===================================================================
--- src/main/org/tigris/subversion/svnant/Revert.java (revision 1649)
+++ src/main/org/tigris/subversion/svnant/Revert.java (working copy)
@@ -197,4 +197,11 @@
                 filesets.addElement(set);
         }
         
+ /**
+ * Adds a set of files to add
+ */
+ public void add(FileSet set) {
+ filesets.addElement(set);
+ }
+
 }
Index: src/main/org/tigris/subversion/svnant/Update.java
===================================================================
--- src/main/org/tigris/subversion/svnant/Update.java (revision 1649)
+++ src/main/org/tigris/subversion/svnant/Update.java (working copy)
@@ -205,4 +205,10 @@
                 filesets.addElement(set);
         }
         
+ /**
+ * Adds a set of files to update
+ */
+ public void add(FileSet set) {
+ filesets.addElement(set);
+ }
 }
Index: src/main/org/tigris/subversion/svnant/selectors/Replaced.java
===================================================================
--- src/main/org/tigris/subversion/svnant/selectors/Replaced.java (revision 0)
+++ src/main/org/tigris/subversion/svnant/selectors/Replaced.java (revision 0)
@@ -0,0 +1,20 @@
+package org.tigris.subversion.svnant.selectors;
+
+import org.tigris.subversion.svnclientadapter.ISVNStatus;
+import org.tigris.subversion.svnclientadapter.SVNStatusKind;
+
+/**
+ * This class implements an Ant custom file selector. Instances of this
+ * class selects a file based on the associated status in Subversion.
+ * This selector accepts files or directories with the 'replaced' status.
+ *
+ * @author Jean-Pierre Fiset <a href="mailto:jp@fiset.ca">jp@fiset.ca</a>
+ *
+ */
+public class Replaced extends StatusBasedSelector {
+
+ public boolean isSelected(ISVNStatus status_) {
+ return status_.getTextStatus().equals(SVNStatusKind.REPLACED);
+ }
+
+}
Index: src/main/org/tigris/subversion/svnant/selectors/Modified.java
===================================================================
--- src/main/org/tigris/subversion/svnant/selectors/Modified.java (revision 0)
+++ src/main/org/tigris/subversion/svnant/selectors/Modified.java (revision 0)
@@ -0,0 +1,20 @@
+package org.tigris.subversion.svnant.selectors;
+
+import org.tigris.subversion.svnclientadapter.ISVNStatus;
+import org.tigris.subversion.svnclientadapter.SVNStatusKind;
+
+/**
+ * This class implements an Ant custom file selector. Instances of this
+ * class selects a file based on the associated status in Subversion.
+ * This selector accepts files or directories with the 'modified' status.
+ *
+ * @author Jean-Pierre Fiset <a href="mailto:jp@fiset.ca">jp@fiset.ca</a>
+ *
+ */
+public class Modified extends StatusBasedSelector {
+
+ public boolean isSelected(ISVNStatus status_) {
+ return status_.getTextStatus().equals(SVNStatusKind.MODIFIED);
+ }
+
+}
Index: src/main/org/tigris/subversion/svnant/selectors/Added.java
===================================================================
--- src/main/org/tigris/subversion/svnant/selectors/Added.java (revision 0)
+++ src/main/org/tigris/subversion/svnant/selectors/Added.java (revision 0)
@@ -0,0 +1,20 @@
+package org.tigris.subversion.svnant.selectors;
+
+import org.tigris.subversion.svnclientadapter.ISVNStatus;
+import org.tigris.subversion.svnclientadapter.SVNStatusKind;
+
+/**
+ * This class implements an Ant custom file selector. Instances of this
+ * class selects a file based on the associated status in Subversion.
+ * This selector accepts files or directories with the 'added' status.
+ *
+ * @author Jean-Pierre Fiset <a href="mailto:jp@fiset.ca">jp@fiset.ca</a>
+ *
+ */
+public class Added extends StatusBasedSelector {
+
+ public boolean isSelected(ISVNStatus status_) {
+ return status_.getTextStatus().equals(SVNStatusKind.ADDED);
+ }
+
+}
Index: src/main/org/tigris/subversion/svnant/selectors/Unversioned.java
===================================================================
--- src/main/org/tigris/subversion/svnant/selectors/Unversioned.java (revision 0)
+++ src/main/org/tigris/subversion/svnant/selectors/Unversioned.java (revision 0)
@@ -0,0 +1,20 @@
+package org.tigris.subversion.svnant.selectors;
+
+import org.tigris.subversion.svnclientadapter.ISVNStatus;
+import org.tigris.subversion.svnclientadapter.SVNStatusKind;
+
+/**
+ * This class implements an Ant custom file selector. Instances of this
+ * class selects a file based on the associated status in Subversion.
+ * This selector accepts files or directories with the 'unversioned' status.
+ *
+ * @author Jean-Pierre Fiset <a href="mailto:jp@fiset.ca">jp@fiset.ca</a>
+ *
+ */
+public class Unversioned extends StatusBasedSelector {
+
+ public boolean isSelected(ISVNStatus status_) {
+ return status_.getTextStatus().equals(SVNStatusKind.UNVERSIONED);
+ }
+
+}
Index: src/main/org/tigris/subversion/svnant/selectors/Locked.java
===================================================================
--- src/main/org/tigris/subversion/svnant/selectors/Locked.java (revision 0)
+++ src/main/org/tigris/subversion/svnant/selectors/Locked.java (revision 0)
@@ -0,0 +1,19 @@
+package org.tigris.subversion.svnant.selectors;
+
+import org.tigris.subversion.svnclientadapter.ISVNStatus;
+
+/**
+ * This class implements an Ant custom file selector. Instances of this
+ * class selects a file based on the associated status in Subversion.
+ * This selector accepts files or directories with the 'locked' status.
+ *
+ * @author Jean-Pierre Fiset <a href="mailto:jp@fiset.ca">jp@fiset.ca</a>
+ *
+ */
+public class Locked extends StatusBasedSelector {
+
+ public boolean isSelected(ISVNStatus status_) {
+ return ( null != status_.getLockOwner() );
+ }
+
+}
Index: src/main/org/tigris/subversion/svnant/selectors/BaseSvnSelector.java
===================================================================
--- src/main/org/tigris/subversion/svnant/selectors/BaseSvnSelector.java (revision 0)
+++ src/main/org/tigris/subversion/svnant/selectors/BaseSvnSelector.java (revision 0)
@@ -0,0 +1,106 @@
+package org.tigris.subversion.svnant.selectors;
+
+import java.io.File;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.types.selectors.BaseExtendSelector;
+import org.tigris.subversion.svnant.SvnTask;
+import org.tigris.subversion.svnclientadapter.ISVNClientAdapter;
+import org.tigris.subversion.svnclientadapter.SVNClientAdapterFactory;
+import org.tigris.subversion.svnclientadapter.commandline.CmdLineClientAdapterFactory;
+import org.tigris.subversion.svnclientadapter.javahl.JavaSvnClientAdapterFactory;
+import org.tigris.subversion.svnclientadapter.javahl.JhlClientAdapterFactory;
+
+/**
+ * This is an abstract class that implements all functionality shared
+ * between all file selectors in svn-ant. In particular, it implements
+ * the handling of the common parameters: javahl and javasvn. It provides
+ * the logic to select the approrpriate client adapter. Finally, it implements
+ * the method required by all Ant selectors (isSelected) and redirects
+ * the control flow to a subclass implementation while providing the
+ * appropriate client adapter.
+ *
+ * @author Jean-Pierre Fiset <a href="mailto:jp@fiset.ca">jp@fiset.ca</a>
+ *
+ */
+public abstract class BaseSvnSelector extends BaseExtendSelector {
+
+
+
+ /**
+ * 'javahl' property for file selector. If set,
+ * JAVAHL bindings are used, if available. Preempts
+ * JavaSVN and command line.
+ */
+ private boolean javahl = true;
+
+ /**
+ * 'javasvn' property for file selector. If set,
+ * JavaSVN client is used, if available. Preempts
+ * command line, but not JAVAHL bindings.
+ */
+ private boolean javasvn = true;
+
+ /**
+ * Accessor method to 'javahl' property. If reset (false),
+ * JavaHL is not used.
+ * @param javahl_ New value for javahl property.
+ */
+ public void setJavahl(boolean javahl_) {
+ javahl = javahl_;
+ }
+
+ /**
+ * Accessor method to 'javasvn' property. If reset (false),
+ * JavaSVN is not used.
+ * @param javasvn_ New value for javasvn property.
+ */
+ public void setJavasvn(boolean javasvn_) {
+ javasvn = javasvn_;
+ }
+
+ final public boolean isSelected(File basedir_, String filename_, File file_) throws BuildException {
+ return isSelected(getClientAdapter(), basedir_, filename_, file_);
+ }
+
+ /**
+ * Method that needs to be reimplemented by each subclass. It is equivalent to 'isSelected',
+ * inherited from BaseExtendSelector, with the exception that a SVN client adaptor is provided.
+ * @param svnClient_ The SVN client that should be used to perform repository access
+ * @param basedir_ A java.io.File object for the base directory
+ * @param filename_ The name of the file to check
+ * @param file_ A File object for this filename
+ * @exception BuildException if an error occurs
+ * @return Returns true if the file should be selected. Otherwise, false.
+ */
+ abstract public boolean isSelected(ISVNClientAdapter svnClient_, File basedir_, String filename_, File file_) throws BuildException;
+
+ /**
+ * This method returns a SVN client adapter, based on the property set when the file selector
+ * was declared. More specifically, the 'javahl' and 'javasvn' flags are verified, as well as the
+ * availability of JAVAHL ad JavaSVN adapters, to decide what flavour to use.
+ * @return An instance of SVN client adapter that meets the specified constraints, if any.
+ * @throws BuildException Thrown in a situation where no adapter can fit the constraints.
+ */
+ private ISVNClientAdapter getClientAdapter() throws BuildException {
+ ISVNClientAdapter svnClient;
+
+ if( true == javahl && true == SvnTask.isJavahlAvailable() ) {
+ svnClient = SVNClientAdapterFactory.createSVNClient(JhlClientAdapterFactory.JAVAHL_CLIENT);
+ log("Using javahl");
+ }
+ else if( true == javasvn && true == SvnTask.isJavaSVNAvailable() ) {
+ svnClient = SVNClientAdapterFactory.createSVNClient(JavaSvnClientAdapterFactory.JAVASVN_CLIENT);
+ log("Using javasvn");
+ }
+ else if( true == SvnTask.isCommandLineAvailable() ) {
+ svnClient = SVNClientAdapterFactory.createSVNClient(CmdLineClientAdapterFactory.COMMANDLINE_CLIENT);
+ log("Using command line interface");
+ }
+ else {
+ throw new BuildException("Cannot use javahl, JavaSVN nor command line svn client");
+ }
+
+ return svnClient;
+ }
+}
Index: src/main/org/tigris/subversion/svnant/selectors/StatusBasedSelector.java
===================================================================
--- src/main/org/tigris/subversion/svnant/selectors/StatusBasedSelector.java (revision 0)
+++ src/main/org/tigris/subversion/svnant/selectors/StatusBasedSelector.java (revision 0)
@@ -0,0 +1,40 @@
+package org.tigris.subversion.svnant.selectors;
+
+import java.io.File;
+
+import org.apache.tools.ant.BuildException;
+import org.tigris.subversion.svnclientadapter.ISVNClientAdapter;
+import org.tigris.subversion.svnclientadapter.ISVNStatus;
+import org.tigris.subversion.svnclientadapter.SVNClientException;
+
+/**
+ * This is an abstract class that implements all functionality shared
+ * between all file selectors, within svn-ant, that depends on a file
+ * status. It implements the 'isSelected' method, and redirects the
+ * control flow to one of the subclasses by providing the svn status.
+ *
+ * @author Jean-Pierre Fiset <a href="mailto:jp@fiset.ca">jp@fiset.ca</a>
+ *
+ */
+public abstract class StatusBasedSelector extends BaseSvnSelector {
+
+ final public boolean isSelected(ISVNClientAdapter svnClient_, File basedir_, String filename_, File file_) throws BuildException {
+ ISVNStatus status;
+ try {
+ status = svnClient_.getSingleStatus(file_);
+ } catch (SVNClientException e) {
+ throw new BuildException("Error occurred while obtaining status of " + file_.getAbsolutePath(), e);
+ }
+
+ return isSelected(status);
+ }
+
+ /**
+ * This method must be reimplemented by all subclasses. A subclass must
+ * decide the selection criteria based on the given status.
+ * @param status_ Status of the file being selected.
+ * @return True if the file should be selected. Otherwise, false.
+ */
+ abstract public boolean isSelected(ISVNStatus status_);
+
+}
Index: src/main/org/tigris/subversion/svnant/selectors/Deleted.java
===================================================================
--- src/main/org/tigris/subversion/svnant/selectors/Deleted.java (revision 0)
+++ src/main/org/tigris/subversion/svnant/selectors/Deleted.java (revision 0)
@@ -0,0 +1,20 @@
+package org.tigris.subversion.svnant.selectors;
+
+import org.tigris.subversion.svnclientadapter.ISVNStatus;
+import org.tigris.subversion.svnclientadapter.SVNStatusKind;
+
+/**
+ * This class implements an Ant custom file selector. Instances of this
+ * class selects a file based on the associated status in Subversion.
+ * This selector accepts files or directories with the 'deleted' status.
+ *
+ * @author Jean-Pierre Fiset <a href="mailto:jp@fiset.ca">jp@fiset.ca</a>
+ *
+ */
+public class Deleted extends StatusBasedSelector {
+
+ public boolean isSelected(ISVNStatus status_) {
+ return status_.getTextStatus().equals(SVNStatusKind.DELETED);
+ }
+
+}
Index: src/main/org/tigris/subversion/svnant/selectors/Ignored.java
===================================================================
--- src/main/org/tigris/subversion/svnant/selectors/Ignored.java (revision 0)
+++ src/main/org/tigris/subversion/svnant/selectors/Ignored.java (revision 0)
@@ -0,0 +1,20 @@
+package org.tigris.subversion.svnant.selectors;
+
+import org.tigris.subversion.svnclientadapter.ISVNStatus;
+import org.tigris.subversion.svnclientadapter.SVNStatusKind;
+
+/**
+ * This class implements an Ant custom file selector. Instances of this
+ * class selects a file based on the associated status in Subversion.
+ * This selector accepts files or directories with the 'ignored' status.
+ *
+ * @author Jean-Pierre Fiset <a href="mailto:jp@fiset.ca">jp@fiset.ca</a>
+ *
+ */
+public class Ignored extends StatusBasedSelector {
+
+ public boolean isSelected(ISVNStatus status_) {
+ return status_.getTextStatus().equals(SVNStatusKind.IGNORED);
+ }
+
+}
Index: src/main/org/tigris/subversion/svnant/selectors/Normal.java
===================================================================
--- src/main/org/tigris/subversion/svnant/selectors/Normal.java (revision 0)
+++ src/main/org/tigris/subversion/svnant/selectors/Normal.java (revision 0)
@@ -0,0 +1,20 @@
+package org.tigris.subversion.svnant.selectors;
+
+import org.tigris.subversion.svnclientadapter.ISVNStatus;
+import org.tigris.subversion.svnclientadapter.SVNStatusKind;
+
+/**
+ * This class implements an Ant custom file selector. Instances of this
+ * class selects a file based on the associated status in Subversion.
+ * This selector accepts files or directories with the 'normal' status.
+ *
+ * @author Jean-Pierre Fiset <a href="mailto:jp@fiset.ca">jp@fiset.ca</a>
+ *
+ */
+public class Normal extends StatusBasedSelector {
+
+ public boolean isSelected(ISVNStatus status_) {
+ return status_.getTextStatus().equals(SVNStatusKind.NORMAL);
+ }
+
+}
Index: src/main/org/tigris/subversion/svnant/selectors/Missing.java
===================================================================
--- src/main/org/tigris/subversion/svnant/selectors/Missing.java (revision 0)
+++ src/main/org/tigris/subversion/svnant/selectors/Missing.java (revision 0)
@@ -0,0 +1,20 @@
+package org.tigris.subversion.svnant.selectors;
+
+import org.tigris.subversion.svnclientadapter.ISVNStatus;
+import org.tigris.subversion.svnclientadapter.SVNStatusKind;
+
+/**
+ * This class implements an Ant custom file selector. Instances of this
+ * class selects a file based on the associated status in Subversion.
+ * This selector accepts files or directories with the 'missing' status.
+ *
+ * @author Jean-Pierre Fiset <a href="mailto:jp@fiset.ca">jp@fiset.ca</a>
+ *
+ */
+public class Missing extends StatusBasedSelector {
+
+ public boolean isSelected(ISVNStatus status_) {
+ return status_.getTextStatus().equals(SVNStatusKind.MISSING);
+ }
+
+}
Index: src/main/org/tigris/subversion/svnant/selectors/Conflicted.java
===================================================================
--- src/main/org/tigris/subversion/svnant/selectors/Conflicted.java (revision 0)
+++ src/main/org/tigris/subversion/svnant/selectors/Conflicted.java (revision 0)
@@ -0,0 +1,19 @@
+package org.tigris.subversion.svnant.selectors;
+
+import org.tigris.subversion.svnclientadapter.ISVNStatus;
+
+/**
+ * This class implements an Ant custom file selector. Instances of this
+ * class selects a file based on the associated status in Subversion.
+ * This selector accepts files or directories with the 'conflicted' status.
+ *
+ * @author Jean-Pierre Fiset <a href="mailto:jp@fiset.ca">jp@fiset.ca</a>
+ *
+ */
+public class Conflicted extends StatusBasedSelector {
+
+ public boolean isSelected(ISVNStatus status_) {
+ return ( null != status_.getConflictWorking() );
+ }
+
+}
Index: src/main/org/tigris/subversion/svnant/types/SvnDirScanner.java
===================================================================
--- src/main/org/tigris/subversion/svnant/types/SvnDirScanner.java (revision 0)
+++ src/main/org/tigris/subversion/svnant/types/SvnDirScanner.java (revision 0)
@@ -0,0 +1,1316 @@
+package org.tigris.subversion.svnant.types;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.Map;
+import java.util.Set;
+import java.util.Vector;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.DirectoryScanner;
+import org.apache.tools.ant.taskdefs.condition.Os;
+import org.apache.tools.ant.types.Resource;
+import org.apache.tools.ant.types.selectors.FileSelector;
+import org.apache.tools.ant.types.selectors.SelectorUtils;
+import org.apache.tools.ant.util.FileUtils;
+import org.tigris.subversion.svnclientadapter.ISVNClientAdapter;
+import org.tigris.subversion.svnclientadapter.ISVNStatus;
+import org.tigris.subversion.svnclientadapter.SVNClientException;
+import org.tigris.subversion.svnclientadapter.SVNNodeKind;
+
+/**
+ * This class supports a custom FileSet for ANT. It returns a set of files
+ * based on the result of Subversion status command, as opposed to the list
+ * of files actually on the file system. Two main differences:
+ * <ol>
+ * <li>Missing and deleted files are provided</li>
+ * <li>Internal subversion file (.svn) are skipped</li>
+ * </ol>
+ *
+ * This is a copy of the class org.apache.tools.ant.DirectoryScanner,
+ * obtained from ANT. This is to support the same level of functionality
+ * with regards to includes, excludes, etc. of the regular file set. The changes
+ * from the original code are as follows:
+ * 1. Modify constructor to accept a ISVNClientAdapter
+ * 2. In scandir(), call method list() instead of File.list()
+ * 3. In method list(), use ISVNClientAdapter.getStatus to obtain list of files
+ *
+ * @author Jean-Pierre Fiset <a href="mailto:jp@fiset.ca">jp@fiset.ca</a>
+ */
+public class SvnDirScanner extends DirectoryScanner {
+
+ private ISVNClientAdapter m_clientAdapter;
+
+ /**
+ * Sole constructor.
+ */
+ public SvnDirScanner( ISVNClientAdapter clientAdapter_ ) {
+ m_clientAdapter = clientAdapter_;
+ }
+
+ /**
+ * Return a cached result of list performed on file, if
+ * available. Invokes the method and caches the result otherwise.
+ *
+ * @param file File (dir) to list.
+ * @since Ant 1.6
+ */
+ private ISVNStatus[] list(File file) {
+ ISVNStatus[] files = (ISVNStatus[]) fileListMap.get(file);
+ if (files == null) {
+ // Obtain the entries from the client adapter
+ try {
+ files = m_clientAdapter.getStatus(file,false,true); // descend=false, getAll=true
+ } catch (SVNClientException e) {
+ throw new IllegalStateException("Error scanning: " + e, e);
+ }
+
+ // Count children entries
+ int count = 0;
+ for(int loop=0; loop<files.length; ++loop) {
+ if( false == files[loop].getFile().equals( file ) ) {
+ ++count;
+ }
+ }
+
+ // Copy children entries
+ ISVNStatus[] copy = new ISVNStatus[count];
+ int index = 0;
+ for(int loop=0; loop<files.length; ++loop) {
+ if( false == files[loop].getFile().equals( file ) ) {
+ copy[index] = files[loop];
+ ++index;
+ }
+ }
+ files = copy;
+
+ // Cache
+ fileListMap.put(file, files);
+ }
+ return files;
+ }
+
+
+ /** Is OpenVMS the operating system we're running on? */
+ private static final boolean ON_VMS = Os.isFamily("openvms");
+
+ /**
+ * Patterns which should be excluded by default.
+ *
+ * <p>Note that you can now add patterns to the list of default
+ * excludes. Added patterns will not become part of this array
+ * that has only been kept around for backwards compatibility
+ * reasons.</p>
+ *
+ * @deprecated use the {@link #getDefaultExcludes
+ * getDefaultExcludes} method instead.
+ */
+ protected static final String[] DEFAULTEXCLUDES = {
+ // Miscellaneous typical temporary files
+ "**/*~",
+ "**/#*#",
+ "**/.#*",
+ "**/%*%",
+ "**/._*",
+
+ // CVS
+ "**/CVS",
+ "**/CVS/**",
+ "**/.cvsignore",
+
+ // SCCS
+ "**/SCCS",
+ "**/SCCS/**",
+
+ // Visual SourceSafe
+ "**/vssver.scc",
+
+ // Subversion
+ "**/.svn",
+ "**/.svn/**",
+
+ // Mac
+ "**/.DS_Store"
+ };
+
+ /**
+ * Patterns which should be excluded by default.
+ *
+ * @see #addDefaultExcludes()
+ */
+ private static Vector defaultExcludes = new Vector();
+ static {
+ resetDefaultExcludes();
+ }
+
+ /** The base directory to be scanned. */
+ protected File basedir;
+
+ /** The patterns for the files to be included. */
+ protected String[] includes;
+
+ /** The patterns for the files to be excluded. */
+ protected String[] excludes;
+
+ /** Selectors that will filter which files are in our candidate list. */
+ protected FileSelector[] selectors = null;
+
+ /** The files which matched at least one include and no excludes
+ * and were selected.
+ */
+ protected Vector filesIncluded;
+
+ /** The files which did not match any includes or selectors. */
+ protected Vector filesNotIncluded;
+
+ /**
+ * The files which matched at least one include and at least
+ * one exclude.
+ */
+ protected Vector filesExcluded;
+
+ /** The directories which matched at least one include and no excludes
+ * and were selected.
+ */
+ protected Vector dirsIncluded;
+
+ /** The directories which were found and did not match any includes. */
+ protected Vector dirsNotIncluded;
+
+ /**
+ * The directories which matched at least one include and at least one
+ * exclude.
+ */
+ protected Vector dirsExcluded;
+
+ /** The files which matched at least one include and no excludes and
+ * which a selector discarded.
+ */
+ protected Vector filesDeselected;
+
+ /** The directories which matched at least one include and no excludes
+ * but which a selector discarded.
+ */
+ protected Vector dirsDeselected;
+
+ /** Whether or not our results were built by a slow scan. */
+ protected boolean haveSlowResults = false;
+
+ /**
+ * Whether or not the file system should be treated as a case sensitive
+ * one.
+ */
+ protected boolean isCaseSensitive = true;
+
+ /**
+ * Whether or not symbolic links should be followed.
+ *
+ * @since Ant 1.5
+ */
+ private boolean followSymlinks = true;
+
+ /** Helper. */
+ private static final FileUtils fileUtils = FileUtils.newFileUtils();
+
+ /** Whether or not everything tested so far has been included. */
+ protected boolean everythingIncluded = true;
+
+ /**
+ * Tests whether or not a given path matches the start of a given
+ * pattern up to the first "**".
+ * <p>
+ * This is not a general purpose test and should only be used if you
+ * can live with false positives. For example, <code>pattern=**\a</code>
+ * and <code>str=b</code> will yield <code>true</code>.
+ *
+ * @param pattern The pattern to match against. Must not be
+ * <code>null</code>.
+ * @param str The path to match, as a String. Must not be
+ * <code>null</code>.
+ *
+ * @return whether or not a given path matches the start of a given
+ * pattern up to the first "**".
+ */
+ protected static boolean matchPatternStart(String pattern, String str) {
+ return SelectorUtils.matchPatternStart(pattern, str);
+ }
+ /**
+ * Tests whether or not a given path matches the start of a given
+ * pattern up to the first "**".
+ * <p>
+ * This is not a general purpose test and should only be used if you
+ * can live with false positives. For example, <code>pattern=**\a</code>
+ * and <code>str=b</code> will yield <code>true</code>.
+ *
+ * @param pattern The pattern to match against. Must not be
+ * <code>null</code>.
+ * @param str The path to match, as a String. Must not be
+ * <code>null</code>.
+ * @param isCaseSensitive Whether or not matching should be performed
+ * case sensitively.
+ *
+ * @return whether or not a given path matches the start of a given
+ * pattern up to the first "**".
+ */
+ protected static boolean matchPatternStart(String pattern, String str,
+ boolean isCaseSensitive) {
+ return SelectorUtils.matchPatternStart(pattern, str, isCaseSensitive);
+ }
+
+ /**
+ * Tests whether or not a given path matches a given pattern.
+ *
+ * @param pattern The pattern to match against. Must not be
+ * <code>null</code>.
+ * @param str The path to match, as a String. Must not be
+ * <code>null</code>.
+ *
+ * @return <code>true</code> if the pattern matches against the string,
+ * or <code>false</code> otherwise.
+ */
+ protected static boolean matchPath(String pattern, String str) {
+ return SelectorUtils.matchPath(pattern, str);
+ }
+
+ /**
+ * Tests whether or not a given path matches a given pattern.
+ *
+ * @param pattern The pattern to match against. Must not be
+ * <code>null</code>.
+ * @param str The path to match, as a String. Must not be
+ * <code>null</code>.
+ * @param isCaseSensitive Whether or not matching should be performed
+ * case sensitively.
+ *
+ * @return <code>true</code> if the pattern matches against the string,
+ * or <code>false</code> otherwise.
+ */
+ protected static boolean matchPath(String pattern, String str,
+ boolean isCaseSensitive) {
+ return SelectorUtils.matchPath(pattern, str, isCaseSensitive);
+ }
+
+ /**
+ * Tests whether or not a string matches against a pattern.
+ * The pattern may contain two special characters:<br>
+ * '*' means zero or more characters<br>
+ * '?' means one and only one character
+ *
+ * @param pattern The pattern to match against.
+ * Must not be <code>null</code>.
+ * @param str The string which must be matched against the pattern.
+ * Must not be <code>null</code>.
+ *
+ * @return <code>true</code> if the string matches against the pattern,
+ * or <code>false</code> otherwise.
+ */
+ public static boolean match(String pattern, String str) {
+ return SelectorUtils.match(pattern, str);
+ }
+
+ /**
+ * Tests whether or not a string matches against a pattern.
+ * The pattern may contain two special characters:<br>
+ * '*' means zero or more characters<br>
+ * '?' means one and only one character
+ *
+ * @param pattern The pattern to match against.
+ * Must not be <code>null</code>.
+ * @param str The string which must be matched against the pattern.
+ * Must not be <code>null</code>.
+ * @param isCaseSensitive Whether or not matching should be performed
+ * case sensitively.
+ *
+ *
+ * @return <code>true</code> if the string matches against the pattern,
+ * or <code>false</code> otherwise.
+ */
+ protected static boolean match(String pattern, String str,
+ boolean isCaseSensitive) {
+ return SelectorUtils.match(pattern, str, isCaseSensitive);
+ }
+
+
+ /**
+ * Get the list of patterns that should be excluded by default.
+ *
+ * @return An array of <code>String</code> based on the current
+ * contents of the <code>defaultExcludes</code>
+ * <code>Vector</code>.
+ *
+ * @since Ant 1.6
+ */
+ public static String[] getDefaultExcludes() {
+ return (String[]) defaultExcludes.toArray(new String[defaultExcludes
+ .size()]);
+ }
+
+ /**
+ * Add a pattern to the default excludes unless it is already a
+ * default exclude.
+ *
+ * @param s A string to add as an exclude pattern.
+ * @return <code>true</code> if the string was added
+ * <code>false</code> if it already
+ * existed.
+ *
+ * @since Ant 1.6
+ */
+ public static boolean addDefaultExclude(String s) {
+ if (defaultExcludes.indexOf(s) == -1) {
+ defaultExcludes.add(s);
+ return true;
+ }
+ return false;
+ }
+
+ /**
+ * Remove a string if it is a default exclude.
+ *
+ * @param s The string to attempt to remove.
+ * @return <code>true</code> if <code>s</code> was a default
+ * exclude (and thus was removed),
+ * <code>false</code> if <code>s</code> was not
+ * in the default excludes list to begin with
+ *
+ * @since Ant 1.6
+ */
+ public static boolean removeDefaultExclude(String s) {
+ return defaultExcludes.remove(s);
+ }
+
+ /**
+ * Go back to the hard wired default exclude patterns
+ *
+ * @since Ant 1.6
+ */
+ public static void resetDefaultExcludes() {
+ defaultExcludes = new Vector();
+
+ for (int i = 0; i < DEFAULTEXCLUDES.length; i++) {
+ defaultExcludes.add(DEFAULTEXCLUDES[i]);
+ }
+ }
+
+ /**
+ * Sets the base directory to be scanned. This is the directory which is
+ * scanned recursively. All '/' and '\' characters are replaced by
+ * <code>File.separatorChar</code>, so the separator used need not match
+ * <code>File.separatorChar</code>.
+ *
+ * @param basedir The base directory to scan.
+ * Must not be <code>null</code>.
+ */
+ public void setBasedir(String basedir) {
+ setBasedir(new File(basedir.replace('/', File.separatorChar).replace(
+ '\\', File.separatorChar)));
+ }
+
+ /**
+ * Sets the base directory to be scanned. This is the directory which is
+ * scanned recursively.
+ *
+ * @param basedir The base directory for scanning.
+ * Should not be <code>null</code>.
+ */
+ public void setBasedir(File basedir) {
+ this.basedir = basedir;
+ }
+
+ /**
+ * Returns the base directory to be scanned.
+ * This is the directory which is scanned recursively.
+ *
+ * @return the base directory to be scanned
+ */
+ public File getBasedir() {
+ return basedir;
+ }
+
+ /**
+ * Find out whether include exclude patterns are matched in a
+ * case sensitive way
+ * @return whether or not the scanning is case sensitive
+ * @since ant 1.6
+ */
+ public boolean isCaseSensitive() {
+ return isCaseSensitive;
+ }
+ /**
+ * Sets whether or not include and exclude patterns are matched
+ * in a case sensitive way
+ *
+ * @param isCaseSensitive whether or not the file system should be
+ * regarded as a case sensitive one
+ */
+ public void setCaseSensitive(boolean isCaseSensitive) {
+ this.isCaseSensitive = isCaseSensitive;
+ }
+
+ /**
+ * gets whether or not a DirectoryScanner follows symbolic links
+ *
+ * @return flag indicating whether symbolic links should be followed
+ *
+ * @since ant 1.6
+ */
+ public boolean isFollowSymlinks() {
+ return followSymlinks;
+ }
+
+ /**
+ * Sets whether or not symbolic links should be followed.
+ *
+ * @param followSymlinks whether or not symbolic links should be followed
+ */
+ public void setFollowSymlinks(boolean followSymlinks) {
+ this.followSymlinks = followSymlinks;
+ }
+
+ /**
+ * Sets the list of include patterns to use. All '/' and '\' characters
+ * are replaced by <code>File.separatorChar</code>, so the separator used
+ * need not match <code>File.separatorChar</code>.
+ * <p>
+ * When a pattern ends with a '/' or '\', "**" is appended.
+ *
+ * @param includes A list of include patterns.
+ * May be <code>null</code>, indicating that all files
+ * should be included. If a non-<code>null</code>
+ * list is given, all elements must be
+ * non-<code>null</code>.
+ */
+ public void setIncludes(String[] includes) {
+ if (includes == null) {
+ this.includes = null;
+ } else {
+ this.includes = new String[includes.length];
+ for (int i = 0; i < includes.length; i++) {
+ String pattern;
+ pattern = includes[i].replace('/', File.separatorChar).replace(
+ '\\', File.separatorChar);
+ if (pattern.endsWith(File.separator)) {
+ pattern += "**";
+ }
+ this.includes[i] = pattern;
+ }
+ }
+ }
+
+
+ /**
+ * Sets the list of exclude patterns to use. All '/' and '\' characters
+ * are replaced by <code>File.separatorChar</code>, so the separator used
+ * need not match <code>File.separatorChar</code>.
+ * <p>
+ * When a pattern ends with a '/' or '\', "**" is appended.
+ *
+ * @param excludes A list of exclude patterns.
+ * May be <code>null</code>, indicating that no files
+ * should be excluded. If a non-<code>null</code> list is
+ * given, all elements must be non-<code>null</code>.
+ */
+ public void setExcludes(String[] excludes) {
+ if (excludes == null) {
+ this.excludes = null;
+ } else {
+ this.excludes = new String[excludes.length];
+ for (int i = 0; i < excludes.length; i++) {
+ String pattern;
+ pattern = excludes[i].replace('/', File.separatorChar).replace(
+ '\\', File.separatorChar);
+ if (pattern.endsWith(File.separator)) {
+ pattern += "**";
+ }
+ this.excludes[i] = pattern;
+ }
+ }
+ }
+
+
+ /**
+ * Sets the selectors that will select the filelist.
+ *
+ * @param selectors specifies the selectors to be invoked on a scan
+ */
+ public void setSelectors(FileSelector[] selectors) {
+ this.selectors = selectors;
+ }
+
+
+ /**
+ * Returns whether or not the scanner has included all the files or
+ * directories it has come across so far.
+ *
+ * @return <code>true</code> if all files and directories which have
+ * been found so far have been included.
+ */
+ public boolean isEverythingIncluded() {
+ return everythingIncluded;
+ }
+
+ /**
+ * Scans the base directory for files which match at least one include
+ * pattern and don't match any exclude patterns. If there are selectors
+ * then the files must pass muster there, as well.
+ *
+ * @exception IllegalStateException if the base directory was set
+ * incorrectly (i.e. if it is <code>null</code>, doesn't exist,
+ * or isn't a directory).
+ */
+ public void scan() throws IllegalStateException {
+ if (basedir == null) {
+ throw new IllegalStateException("No basedir set");
+ }
+ if (!basedir.exists()) {
+ throw new IllegalStateException("basedir " + basedir
+ + " does not exist");
+ }
+ if (!basedir.isDirectory()) {
+ throw new IllegalStateException("basedir " + basedir
+ + " is not a directory");
+ }
+
+ if (includes == null) {
+ // No includes supplied, so set it to 'matches all'
+ includes = new String[1];
+ includes[0] = "**";
+ }
+ if (excludes == null) {
+ excludes = new String[0];
+ }
+
+ filesIncluded = new Vector();
+ filesNotIncluded = new Vector();
+ filesExcluded = new Vector();
+ filesDeselected = new Vector();
+ dirsIncluded = new Vector();
+ dirsNotIncluded = new Vector();
+ dirsExcluded = new Vector();
+ dirsDeselected = new Vector();
+
+ if (isIncluded("")) {
+ if (!isExcluded("")) {
+ if (isSelected("", basedir)) {
+ dirsIncluded.addElement("");
+ } else {
+ dirsDeselected.addElement("");
+ }
+ } else {
+ dirsExcluded.addElement("");
+ }
+ } else {
+ dirsNotIncluded.addElement("");
+ }
+ checkIncludePatterns();
+ clearCaches();
+ }
+
+ /**
+ * this routine is actually checking all the include patterns in
+ * order to avoid scanning everything under base dir
+ * @since ant1.6
+ */
+ private void checkIncludePatterns() {
+ Hashtable newroots = new Hashtable();
+ // put in the newroots vector the include patterns without
+ // wildcard tokens
+ for (int icounter = 0; icounter < includes.length; icounter++) {
+ String newpattern =
+ SelectorUtils.rtrimWildcardTokens(includes[icounter]);
+ newroots.put(newpattern, includes[icounter]);
+ }
+
+ if (newroots.containsKey("")) {
+ // we are going to scan everything anyway
+ scandir(basedir, "", true);
+ } else {
+ // only scan directories that can include matched files or
+ // directories
+ Enumeration enum2 = newroots.keys();
+
+ File canonBase = null;
+ try {
+ canonBase = basedir.getCanonicalFile();
+ } catch (IOException ex) {
+ throw new BuildException(ex);
+ }
+
+ while (enum2.hasMoreElements()) {
+ String currentelement = (String) enum2.nextElement();
+ String originalpattern = (String) newroots.get(currentelement);
+ File myfile = new File(basedir, currentelement);
+
+ if (myfile.exists()) {
+ // may be on a case insensitive file system. We want
+ // the results to show what's really on the disk, so
+ // we need to double check.
+ try {
+ File canonFile = myfile.getCanonicalFile();
+ String path = fileUtils.removeLeadingPath(canonBase,
+ canonFile);
+ if (!path.equals(currentelement) || ON_VMS) {
+ myfile = findFile(basedir, currentelement);
+ if (myfile != null) {
+ currentelement =
+ fileUtils.removeLeadingPath(basedir,
+ myfile);
+ }
+ }
+ } catch (IOException ex) {
+ throw new BuildException(ex);
+ }
+ }
+
+ if ((myfile == null || !myfile.exists()) && !isCaseSensitive) {
+ File f = findFileCaseInsensitive(basedir, currentelement);
+ if (f.exists()) {
+ // adapt currentelement to the case we've
+ // actually found
+ currentelement = fileUtils.removeLeadingPath(basedir,
+ f);
+ myfile = f;
+ }
+ }
+
+ if (myfile != null && myfile.exists()) {
+ if (!followSymlinks
+ && isSymlink(basedir, currentelement)) {
+ continue;
+ }
+
+ if (myfile.isDirectory()) {
+ if (isIncluded(currentelement)
+ && currentelement.length() > 0) {
+ accountForIncludedDir(currentelement, myfile, true);
+ } else {
+ if (currentelement.length() > 0) {
+ if (currentelement.charAt(currentelement
+ .length() - 1)
+ != File.separatorChar) {
+ currentelement =
+ currentelement + File.separatorChar;
+ }
+ }
+ scandir(myfile, currentelement, true);
+ }
+ } else {
+ if (isCaseSensitive
+ && originalpattern.equals(currentelement)) {
+ accountForIncludedFile(currentelement, myfile);
+ } else if (!isCaseSensitive
+ && originalpattern
+ .equalsIgnoreCase(currentelement)) {
+ accountForIncludedFile(currentelement, myfile);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ /**
+ * Top level invocation for a slow scan. A slow scan builds up a full
+ * list of excluded/included files/directories, whereas a fast scan
+ * will only have full results for included files, as it ignores
+ * directories which can't possibly hold any included files/directories.
+ * <p>
+ * Returns immediately if a slow scan has already been completed.
+ */
+ protected void slowScan() {
+ if (haveSlowResults) {
+ return;
+ }
+
+ String[] excl = new String[dirsExcluded.size()];
+ dirsExcluded.copyInto(excl);
+
+ String[] notIncl = new String[dirsNotIncluded.size()];
+ dirsNotIncluded.copyInto(notIncl);
+
+ for (int i = 0; i < excl.length; i++) {
+ if (!couldHoldIncluded(excl[i])) {
+ scandir(new File(basedir, excl[i]),
+ excl[i] + File.separator, false);
+ }
+ }
+
+ for (int i = 0; i < notIncl.length; i++) {
+ if (!couldHoldIncluded(notIncl[i])) {
+ scandir(new File(basedir, notIncl[i]),
+ notIncl[i] + File.separator, false);
+ }
+ }
+
+ haveSlowResults = true;
+ }
+
+ /**
+ * Scans the given directory for files and directories. Found files and
+ * directories are placed in their respective collections, based on the
+ * matching of includes, excludes, and the selectors. When a directory
+ * is found, it is scanned recursively.
+ *
+ * @param dir The directory to scan. Must not be <code>null</code>.
+ * @param vpath The path relative to the base directory (needed to
+ * prevent problems with an absolute path when using
+ * dir). Must not be <code>null</code>.
+ * @param fast Whether or not this call is part of a fast scan.
+ *
+ * @see #filesIncluded
+ * @see #filesNotIncluded
+ * @see #filesExcluded
+ * @see #dirsIncluded
+ * @see #dirsNotIncluded
+ * @see #dirsExcluded
+ * @see #slowScan
+ */
+ protected void scandir(File dir, String vpath, boolean fast) {
+ // avoid double scanning of directories, can only happen in fast mode
+ if (fast && hasBeenScanned(vpath)) {
+ return;
+ }
+ ISVNStatus[] newfiles = list(dir);
+
+ if (newfiles == null) {
+ /*
+ * two reasons are mentioned in the API docs for File.list
+ * (1) dir is not a directory. This is impossible as
+ * we wouldn't get here in this case.
+ * (2) an IO error occurred (why doesn't it throw an exception
+ * then???)
+ */
+ throw new BuildException("IO error scanning directory "
+ + dir.getAbsolutePath());
+ }
+
+ for (int i = 0; i < newfiles.length; i++) {
+ String name = vpath + newfiles[i].getFile().getName();
+ File file = new File(dir, newfiles[i].getFile().getName());
+ if( SVNNodeKind.DIR == newfiles[i].getNodeKind()
+ || (SVNNodeKind.UNKNOWN == newfiles[i].getNodeKind() && newfiles[i].getFile().isDirectory()) ) {
+ if (isIncluded(name)) {
+ accountForIncludedDir(name, file, fast);
+ } else {
+ everythingIncluded = false;
+ dirsNotIncluded.addElement(name);
+ if (fast && couldHoldIncluded(name)) {
+ scandir(file, name + File.separator, fast);
+ }
+ }
+ if (!fast) {
+ scandir(file, name + File.separator, fast);
+ }
+ } else if( SVNNodeKind.FILE == newfiles[i].getNodeKind()
+ || (SVNNodeKind.UNKNOWN == newfiles[i].getNodeKind() && newfiles[i].getFile().isFile()) ) {
+ if (isIncluded(name)) {
+ accountForIncludedFile(name, file);
+ } else {
+ everythingIncluded = false;
+ filesNotIncluded.addElement(name);
+ }
+ }
+ }
+ }
+ /**
+ * process included file
+ * @param name path of the file relative to the directory of the fileset
+ * @param file included file
+ */
+ private void accountForIncludedFile(String name, File file) {
+ if (!filesIncluded.contains(name)
+ && !filesExcluded.contains(name)
+ && !filesDeselected.contains(name)) {
+
+ if (!isExcluded(name)) {
+ if (isSelected(name, file)) {
+ filesIncluded.addElement(name);
+ } else {
+ everythingIncluded = false;
+ filesDeselected.addElement(name);
+ }
+ } else {
+ everythingIncluded = false;
+ filesExcluded.addElement(name);
+ }
+ }
+ }
+
+ /**
+ *
+ * @param name path of the directory relative to the directory of
+ * the fileset
+ * @param file directory as file
+ * @param fast
+ */
+ private void accountForIncludedDir(String name, File file, boolean fast) {
+ if (!dirsIncluded.contains(name)
+ && !dirsExcluded.contains(name)
+ && !dirsDeselected.contains(name)) {
+
+ if (!isExcluded(name)) {
+ if (isSelected(name, file)) {
+ dirsIncluded.addElement(name);
+ if (fast) {
+ scandir(file, name + File.separator, fast);
+ }
+ } else {
+ everythingIncluded = false;
+ dirsDeselected.addElement(name);
+ if (fast && couldHoldIncluded(name)) {
+ scandir(file, name + File.separator, fast);
+ }
+ }
+
+ } else {
+ everythingIncluded = false;
+ dirsExcluded.addElement(name);
+ if (fast && couldHoldIncluded(name)) {
+ scandir(file, name + File.separator, fast);
+ }
+ }
+ }
+ }
+ /**
+ * Tests whether or not a name matches against at least one include
+ * pattern.
+ *
+ * @param name The name to match. Must not be <code>null</code>.
+ * @return <code>true</code> when the name matches against at least one
+ * include pattern, or <code>false</code> otherwise.
+ */
+ protected boolean isIncluded(String name) {
+ for (int i = 0; i < includes.length; i++) {
+ if (matchPath(includes[i], name, isCaseSensitive)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Tests whether or not a name matches the start of at least one include
+ * pattern.
+ *
+ * @param name The name to match. Must not be <code>null</code>.
+ * @return <code>true</code> when the name matches against the start of at
+ * least one include pattern, or <code>false</code> otherwise.
+ */
+ protected boolean couldHoldIncluded(String name) {
+ for (int i = 0; i < includes.length; i++) {
+ if (matchPatternStart(includes[i], name, isCaseSensitive)) {
+ if (isMorePowerfulThanExcludes(name, includes[i])) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ /**
+ * find out whether one particular include pattern is more powerful
+ * than all the excludes
+ * note : the power comparison is based on the length of the include pattern
+ * and of the exclude patterns without the wildcards
+ * ideally the comparison should be done based on the depth
+ * of the match, that is to say how many file separators have been matched
+ * before the first ** or the end of the pattern
+ *
+ * IMPORTANT : this function should return false "with care"
+ *
+ * @param name the relative path that one want to test
+ * @param includepattern one include pattern
+ * @return true if there is no exclude pattern more powerful than this include pattern
+ * @since ant1.6
+ */
+ private boolean isMorePowerfulThanExcludes(String name, String includepattern) {
+ String soughtexclude = name + File.separator + "**";
+ for (int counter = 0; counter < excludes.length; counter++) {
+ if (excludes[counter].equals(soughtexclude)) {
+ return false;
+ }
+ }
+ return true;
+ }
+ /**
+ * Tests whether or not a name matches against at least one exclude
+ * pattern.
+ *
+ * @param name The name to match. Must not be <code>null</code>.
+ * @return <code>true</code> when the name matches against at least one
+ * exclude pattern, or <code>false</code> otherwise.
+ */
+ protected boolean isExcluded(String name) {
+ for (int i = 0; i < excludes.length; i++) {
+ if (matchPath(excludes[i], name, isCaseSensitive)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Tests whether a name should be selected.
+ *
+ * @param name the filename to check for selecting
+ * @param file the java.io.File object for this filename
+ * @return <code>false</code> when the selectors says that the file
+ * should not be selected, <code>true</code> otherwise.
+ */
+ protected boolean isSelected(String name, File file) {
+ if (selectors != null) {
+ for (int i = 0; i < selectors.length; i++) {
+ if (!selectors[i].isSelected(basedir, name, file)) {
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Returns the names of the files which matched at least one of the
+ * include patterns and none of the exclude patterns.
+ * The names are relative to the base directory.
+ *
+ * @return the names of the files which matched at least one of the
+ * include patterns and none of the exclude patterns.
+ */
+ public String[] getIncludedFiles() {
+ String[] files = new String[filesIncluded.size()];
+ filesIncluded.copyInto(files);
+ Arrays.sort(files);
+ return files;
+ }
+
+ /**
+ * Returns the names of the files which matched none of the include
+ * patterns. The names are relative to the base directory. This involves
+ * performing a slow scan if one has not already been completed.
+ *
+ * @return the names of the files which matched none of the include
+ * patterns.
+ *
+ * @see #slowScan
+ */
+ public String[] getNotIncludedFiles() {
+ slowScan();
+ String[] files = new String[filesNotIncluded.size()];
+ filesNotIncluded.copyInto(files);
+ return files;
+ }
+
+ /**
+ * Returns the names of the files which matched at least one of the
+ * include patterns and at least one of the exclude patterns.
+ * The names are relative to the base directory. This involves
+ * performing a slow scan if one has not already been completed.
+ *
+ * @return the names of the files which matched at least one of the
+ * include patterns and at least one of the exclude patterns.
+ *
+ * @see #slowScan
+ */
+ public String[] getExcludedFiles() {
+ slowScan();
+ String[] files = new String[filesExcluded.size()];
+ filesExcluded.copyInto(files);
+ return files;
+ }
+
+ /**
+ * <p>Returns the names of the files which were selected out and
+ * therefore not ultimately included.</p>
+ *
+ * <p>The names are relative to the base directory. This involves
+ * performing a slow scan if one has not already been completed.</p>
+ *
+ * @return the names of the files which were deselected.
+ *
+ * @see #slowScan
+ */
+ public String[] getDeselectedFiles() {
+ slowScan();
+ String[] files = new String[filesDeselected.size()];
+ filesDeselected.copyInto(files);
+ return files;
+ }
+
+ /**
+ * Returns the names of the directories which matched at least one of the
+ * include patterns and none of the exclude patterns.
+ * The names are relative to the base directory.
+ *
+ * @return the names of the directories which matched at least one of the
+ * include patterns and none of the exclude patterns.
+ */
+ public String[] getIncludedDirectories() {
+ String[] directories = new String[dirsIncluded.size()];
+ dirsIncluded.copyInto(directories);
+ Arrays.sort(directories);
+ return directories;
+ }
+
+ /**
+ * Returns the names of the directories which matched none of the include
+ * patterns. The names are relative to the base directory. This involves
+ * performing a slow scan if one has not already been completed.
+ *
+ * @return the names of the directories which matched none of the include
+ * patterns.
+ *
+ * @see #slowScan
+ */
+ public String[] getNotIncludedDirectories() {
+ slowScan();
+ String[] directories = new String[dirsNotIncluded.size()];
+ dirsNotIncluded.copyInto(directories);
+ return directories;
+ }
+
+ /**
+ * Returns the names of the directories which matched at least one of the
+ * include patterns and at least one of the exclude patterns.
+ * The names are relative to the base directory. This involves
+ * performing a slow scan if one has not already been completed.
+ *
+ * @return the names of the directories which matched at least one of the
+ * include patterns and at least one of the exclude patterns.
+ *
+ * @see #slowScan
+ */
+ public String[] getExcludedDirectories() {
+ slowScan();
+ String[] directories = new String[dirsExcluded.size()];
+ dirsExcluded.copyInto(directories);
+ return directories;
+ }
+
+ /**
+ * <p>Returns the names of the directories which were selected out and
+ * therefore not ultimately included.</p>
+ *
+ * <p>The names are relative to the base directory. This involves
+ * performing a slow scan if one has not already been completed.</p>
+ *
+ * @return the names of the directories which were deselected.
+ *
+ * @see #slowScan
+ */
+ public String[] getDeselectedDirectories() {
+ slowScan();
+ String[] directories = new String[dirsDeselected.size()];
+ dirsDeselected.copyInto(directories);
+ return directories;
+ }
+
+ /**
+ * Adds default exclusions to the current exclusions set.
+ */
+ public void addDefaultExcludes() {
+ int excludesLength = excludes == null ? 0 : excludes.length;
+ String[] newExcludes;
+ newExcludes = new String[excludesLength + defaultExcludes.size()];
+ if (excludesLength > 0) {
+ System.arraycopy(excludes, 0, newExcludes, 0, excludesLength);
+ }
+ String[] defaultExcludesTemp = getDefaultExcludes();
+ for (int i = 0; i < defaultExcludesTemp.length; i++) {
+ newExcludes[i + excludesLength] =
+ defaultExcludesTemp[i].replace('/', File.separatorChar)
+ .replace('\\', File.separatorChar);
+ }
+ excludes = newExcludes;
+ }
+
+ /**
+ * Get the named resource
+ * @param name path name of the file relative to the dir attribute.
+ *
+ * @return the resource with the given name.
+ * @since Ant 1.5.2
+ */
+ public Resource getResource(String name) {
+ File f = fileUtils.resolveFile(basedir, name);
+ return new Resource(name, f.exists(), f.lastModified(),
+ f.isDirectory());
+ }
+
+ /**
+ * temporary table to speed up the various scanning methods below
+ *
+ * @since Ant 1.6
+ */
+ private Map fileListMap = new HashMap();
+
+ /**
+ * From <code>base</code> traverse the filesystem in a case
+ * insensitive manner in order to find a file that matches the
+ * given name.
+ *
+ * @return File object that points to the file in question. if it
+ * hasn't been found it will simply be <code>new File(base,
+ * path)</code>.
+ *
+ * @since Ant 1.6
+ */
+ private File findFileCaseInsensitive(File base, String path) {
+ File f = findFileCaseInsensitive(base,
+ SelectorUtils.tokenizePath(path));
+ return f == null ? new File(base, path) : f;
+ }
+
+ /**
+ * From <code>base</code> traverse the filesystem in a case
+ * insensitive manner in order to find a file that matches the
+ * given stack of names.
+ *
+ * @return File object that points to the file in question or null.
+ *
+ * @since Ant 1.6
+ */
+ private File findFileCaseInsensitive(File base, Vector pathElements) {
+ if (pathElements.size() == 0) {
+ return base;
+ } else {
+ if (!base.isDirectory()) {
+ return null;
+ }
+ ISVNStatus[] files = list(base);
+ if (files == null) {
+ throw new BuildException("IO error scanning directory "
+ + base.getAbsolutePath());
+ }
+ String current = (String) pathElements.remove(0);
+ for (int i = 0; i < files.length; i++) {
+ String name = files[i].getFile().getName();
+ if( name.equals(current) ) {
+ base = new File(base, name);
+ return findFileCaseInsensitive(base, pathElements);
+ }
+ }
+ for (int i = 0; i < files.length; i++) {
+ String name = files[i].getFile().getName();
+ if( name.equalsIgnoreCase(current) ) {
+ base = new File(base, name);
+ return findFileCaseInsensitive(base, pathElements);
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * From <code>base</code> traverse the filesystem in order to find
+ * a file that matches the given name.
+ *
+ * @return File object that points to the file in question or null.
+ *
+ * @since Ant 1.6
+ */
+ private File findFile(File base, String path) {
+ return findFile(base, SelectorUtils.tokenizePath(path));
+ }
+
+ /**
+ * From <code>base</code> traverse the filesystem in order to find
+ * a file that matches the given stack of names.
+ *
+ * @return File object that points to the file in question or null.
+ *
+ * @since Ant 1.6
+ */
+ private File findFile(File base, Vector pathElements) {
+ if (pathElements.size() == 0) {
+ return base;
+ } else {
+ if (!base.isDirectory()) {
+ return null;
+ }
+ ISVNStatus[] files = list(base);
+ if (files == null) {
+ throw new BuildException("IO error scanning directory "
+ + base.getAbsolutePath());
+ }
+ String current = (String) pathElements.remove(0);
+ for (int i = 0; i < files.length; i++) {
+ String name = files[i].getFile().getName();
+ if( name.equals(current) ) {
+ base = new File(base, name);
+ return findFile(base, pathElements);
+ }
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Do we have to traverse a symlink when trying to reach path from
+ * basedir?
+ * @since Ant 1.6
+ */
+ private boolean isSymlink(File base, String path) {
+ return isSymlink(base, SelectorUtils.tokenizePath(path));
+ }
+
+ /**
+ * Do we have to traverse a symlink when trying to reach path from
+ * basedir?
+ * @since Ant 1.6
+ */
+ private boolean isSymlink(File base, Vector pathElements) {
+ if (pathElements.size() > 0) {
+ String current = (String) pathElements.remove(0);
+ try {
+ if (fileUtils.isSymbolicLink(base, current)) {
+ return true;
+ } else {
+ base = new File(base, current);
+ return isSymlink(base, pathElements);
+ }
+ } catch (IOException ioe) {
+ String msg = "IOException caught while checking "
+ + "for links, couldn't get canonical path!";
+ // will be caught and redirected to Ant's logging system
+ System.err.println(msg);
+ return false;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * List of all scanned directories.
+ *
+ * @since Ant 1.6
+ */
+ private Set scannedDirs = new HashSet();
+
+ /**
+ * Has the directory with the given path relative to the base
+ * directory already been scanned?
+ *
+ * <p>Registers the given directory as scanned as a side effect.</p>
+ *
+ * @since Ant 1.6
+ */
+ private boolean hasBeenScanned(String vpath) {
+ return !scannedDirs.add(vpath);
+ }
+
+ /**
+ * Clear internal caches.
+ *
+ * @since Ant 1.6
+ */
+ private void clearCaches() {
+ fileListMap.clear();
+ scannedDirs.clear();
+ }
+}
+
Index: src/main/org/tigris/subversion/svnant/types/SvnFileSet.java
===================================================================
--- src/main/org/tigris/subversion/svnant/types/SvnFileSet.java (revision 0)
+++ src/main/org/tigris/subversion/svnant/types/SvnFileSet.java (revision 0)
@@ -0,0 +1,194 @@
+package org.tigris.subversion.svnant.types;
+
+import java.io.File;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.DirectoryScanner;
+import org.apache.tools.ant.Project;
+import org.apache.tools.ant.types.Reference;
+import org.tigris.subversion.svnant.SvnTask;
+import org.tigris.subversion.svnclientadapter.ISVNClientAdapter;
+import org.tigris.subversion.svnclientadapter.SVNClientAdapterFactory;
+import org.tigris.subversion.svnclientadapter.commandline.CmdLineClientAdapterFactory;
+import org.tigris.subversion.svnclientadapter.javahl.JavaSvnClientAdapterFactory;
+import org.tigris.subversion.svnclientadapter.javahl.JhlClientAdapterFactory;
+
+/**
+ * This class implements a custom FileSet for ANT. It returns a set of files
+ * based on the result of Subversion status command, as opposed to the list
+ * of files actually on the file system. Two main differences:
+ * <ol>
+ * <li>Missing and deleted files are provided</li>
+ * <li>Internal subversion file (.svn) are skipped</li>
+ * </ol>
+ *
+ * This class is implemented as a subclass of org.apache.tools.ant.types.FileSet,
+ * which is an opportunistic design, at best. However, it is necessary at the
+ * present time to go around practicality issues between ANT 1.6 (which does not
+ * support custom filesets yet) and ANT 1.7 where a lot of changes are made to support
+ * custom filesets. For backward compatibility reasons, the new approach in ANT
+ * will not be practical until much later, when we can safely assume that everyone
+ * is using at least ANT 1.7, and that the majority of the tasks based on filesets
+ * have migrated to the new structure.
+ *
+ * @author Jean-Pierre Fiset <a href="mailto:jp@fiset.ca">jp@fiset.ca</a>
+ */
+public class SvnFileSet extends org.apache.tools.ant.types.FileSet {
+
+ /**
+ * 'javahl' property for file selector. If set,
+ * JAVAHL bindings are used, if available. Preempts
+ * JavaSVN and command line.
+ */
+ private boolean javahl = true;
+
+ /**
+ * 'javasvn' property for file selector. If set,
+ * JavaSVN client is used, if available. Preempts
+ * command line, but not JAVAHL bindings.
+ */
+ private boolean javasvn = true;
+
+ /**
+ * Constructor for FileSet.
+ */
+ public SvnFileSet() {
+ super();
+ }
+
+ /**
+ * Constructor for FileSet, with FileSet to shallowly clone.
+ * @param fileset the fileset to clone
+ */
+ protected SvnFileSet(SvnFileSet fileset_) {
+ this.javahl = fileset_.javahl;
+ this.javahl = fileset_.javahl;
+ }
+
+ /**
+ * Creates a deep clone of this instance, except for the nested
+ * selectors (the list of selectors is a shallow clone of this
+ * instance's list).
+ * @return the cloned object
+ */
+ public synchronized Object clone() {
+ SvnFileSet fs = (SvnFileSet) super.clone();
+ return fs;
+ }
+
+ /**
+ * Accessor method to 'javahl' property. If reset (false),
+ * JavaHL is not used.
+ * @param javahl_ New value for javahl property.
+ */
+ public void setJavahl(boolean javahl_) {
+ javahl = javahl_;
+ }
+
+ /**
+ * Accessor method to 'javasvn' property. If reset (false),
+ * JavaSVN is not used.
+ * @param javasvn_ New value for javasvn property.
+ */
+ public void setJavasvn(boolean javasvn_) {
+ javasvn = javasvn_;
+ }
+
+ /**
+ * This method returns a SVN client adapter, based on the property set when the file selector
+ * was declared. More specifically, the 'javahl' and 'javasvn' flags are verified, as well as the
+ * availability of JAVAHL ad JavaSVN adapters, to decide what flavour to use.
+ * @return An instance of SVN client adapter that meets the specified constraints, if any.
+ * @throws BuildException Thrown in a situation where no adapter can fit the constraints.
+ */
+ private ISVNClientAdapter getClientAdapter() throws BuildException {
+ ISVNClientAdapter svnClient;
+
+ if( true == javahl && true == SvnTask.isJavahlAvailable() ) {
+ svnClient = SVNClientAdapterFactory.createSVNClient(JhlClientAdapterFactory.JAVAHL_CLIENT);
+ log("Using javahl");
+ }
+ else if( true == javasvn && true == SvnTask.isJavaSVNAvailable() ) {
+ svnClient = SVNClientAdapterFactory.createSVNClient(JavaSvnClientAdapterFactory.JAVASVN_CLIENT);
+ log("Using javasvn");
+ }
+ else if( true == SvnTask.isCommandLineAvailable() ) {
+ svnClient = SVNClientAdapterFactory.createSVNClient(CmdLineClientAdapterFactory.COMMANDLINE_CLIENT);
+ log("Using command line interface");
+ }
+ else {
+ throw new BuildException("Cannot use javahl, JavaSVN nor command line svn client");
+ }
+
+ return svnClient;
+ }
+
+ /**
+ * Returns the directory scanner needed to access the files to process.
+ * @return a <code>DirectoryScanner</code> instance.
+ */
+ public DirectoryScanner getDirectoryScanner(Project p) {
+ if (isReference()) {
+ return getRef(p).getDirectoryScanner(p);
+ }
+
+ File dir = getDir(p);
+ boolean followSymlinks = false;
+
+
+ if (dir == null) {
+ throw new BuildException("No directory specified for "
+ + getDataTypeName() + ".");
+ }
+ if (!dir.exists()) {
+ throw new BuildException(dir.getAbsolutePath() + " not found.");
+ }
+ if (!dir.isDirectory()) {
+ throw new BuildException(dir.getAbsolutePath()
+ + " is not a directory.");
+ }
+ DirectoryScanner ds = new SvnDirScanner( getClientAdapter() );
+ setupDirectoryScanner(ds, p);
+ ds.setFollowSymlinks(followSymlinks);
+ ds.scan();
+ return ds;
+ }
+
+ /**
+ * This attribute is not supported by svnFileSet.
+ * @throws BuildException always
+ */
+ public void setRefid(Reference r) throws BuildException {
+ throw (BuildException) notSupported("refid", true).fillInStackTrace();
+ }
+
+ /**
+ * This attribute is not supported by svnFileSet.
+ * @throws BuildException always
+ */
+ public void setFollowSymlinks(boolean followSymlinks) {
+ throw (BuildException) notSupported("followSymlinks", true).fillInStackTrace();
+ }
+
+ /**
+ * Builds and returns an exception that can be used to report an attribute
+ * that is not supported.
+ * @param featureName_ The name of attribute or nested element
+ * @param attribute_ True if the name refers to an attribute
+ * @return An exception that can be thrown to report an invalid
+ * usage of the receiver.
+ */
+ private BuildException notSupported(String featureName_, boolean attribute_)
+ {
+ StringBuffer message = new StringBuffer();
+ message.append(getProject().getElementName(this))
+ .append(" doesn't support the ");
+
+ if (attribute_)
+ message.append(featureName_).append(" attribute.");
+ else
+ message.append("nested ").append(featureName_).append(" element.");
+
+ return new BuildException(message.toString());
+ }
+}
Index: src/main/org/tigris/subversion/svnant/Commit.java
===================================================================
--- src/main/org/tigris/subversion/svnant/Commit.java (revision 1649)
+++ src/main/org/tigris/subversion/svnant/Commit.java (working copy)
@@ -333,4 +333,11 @@
         filesets.addElement(set);
     }
 
+ /**
+ * Adds a set of files to add
+ */
+ public void add(FileSet set) {
+ filesets.addElement(set);
+ }
+
 }
Index: src/main/org/tigris/subversion/svnant/Add.java
===================================================================
--- src/main/org/tigris/subversion/svnant/Add.java (revision 1649)
+++ src/main/org/tigris/subversion/svnant/Add.java (working copy)
@@ -313,4 +313,10 @@
         filesets.addElement(set);
     }
 
+ /**
+ * Adds a set of files to add
+ */
+ public void add(FileSet set) {
+ filesets.addElement(set);
+ }
 }
Index: src/main/org/tigris/subversion/svnant/SvnTask.java
===================================================================
--- src/main/org/tigris/subversion/svnant/SvnTask.java (revision 1649)
+++ src/main/org/tigris/subversion/svnant/SvnTask.java (working copy)
@@ -216,7 +216,7 @@
      * check if javahl is available
      * @return true if javahl is available
      */
- private boolean isJavahlAvailable() {
+ static public boolean isJavahlAvailable() {
             if (javahlAvailableInitialized == false) {
             // we don't initiliaze javahlAvailable in the static field because we
             // don't want the check to occur if javahl is set to false
@@ -237,7 +237,7 @@
      * check if JavaSVN is available
      * @return true if JavaSVN is available
      */
- private boolean isJavaSVNAvailable() {
+ static public boolean isJavaSVNAvailable() {
         if (javaSVNAvailableInitialized == false) {
             // we don't initiliaze javaSVNAvailable in the static field because we
             // don't want the check to occur if javaSVN is set to false
@@ -258,7 +258,7 @@
      * check if command line interface is available
      * @return true if command line interface is available
      */
- private boolean isCommandLineAvailable() {
+ static public boolean isCommandLineAvailable() {
         if (commandLineAvailableInitialized == false) {
             try {
                 CmdLineClientAdapterFactory.setup();
Index: src/main/svntypes.xml
===================================================================
--- src/main/svntypes.xml (revision 0)
+++ src/main/svntypes.xml (revision 0)
@@ -0,0 +1,31 @@
+<antlib>
+ <!-- Tasks -->
+ <taskdef name="svn"
+ classname="org.tigris.subversion.svnant.SvnTask" />
+
+ <!-- Types -->
+ <typedef name="svnFileSet"
+ classname="org.tigris.subversion.svnant.types.SvnFileSet" />
+
+ <!-- Selectors -->
+ <typedef name="svnNormal"
+ classname="org.tigris.subversion.svnant.selectors.Normal" />
+ <typedef name="svnAdded"
+ classname="org.tigris.subversion.svnant.selectors.Added" />
+ <typedef name="svnReplaced"
+ classname="org.tigris.subversion.svnant.selectors.Replaced" />
+ <typedef name="svnModified"
+ classname="org.tigris.subversion.svnant.selectors.Modified" />
+ <typedef name="svnConflicted"
+ classname="org.tigris.subversion.svnant.selectors.Conflicted" />
+ <typedef name="svnIgnored"
+ classname="org.tigris.subversion.svnant.selectors.Ignored" />
+ <typedef name="svnUnversioned"
+ classname="org.tigris.subversion.svnant.selectors.Unversioned" />
+ <typedef name="svnLocked"
+ classname="org.tigris.subversion.svnant.selectors.Locked" />
+ <typedef name="svnMissing"
+ classname="org.tigris.subversion.svnant.selectors.Missing" />
+ <typedef name="svnDeleted"
+ classname="org.tigris.subversion.svnant.selectors.Deleted" />
+</antlib>
\ No newline at end of file

Property changes on: src\main\svntypes.xml
___________________________________________________________________
Name: svn:mime-type
   + text/xml

Index: src/doc/ant-types.xsd
===================================================================
--- src/doc/ant-types.xsd (revision 0)
+++ src/doc/ant-types.xsd (revision 0)
@@ -0,0 +1,144 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xs:schema
+ targetNamespace="http://www.fiset.ca/ant-docs/v1"
+ xmlns="http://www.fiset.ca/ant-docs/v1"
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
+ elementFormDefault="qualified"
+ attributeFormDefault="unqualified"
+>
+ <xs:annotation>
+ <xs:documentation xml:lang="en">
+ This schema should be used to document types used in ANT, an Apache project, which is a to
+ to define build processes. This schema defines the struture of an XML document that should be
+ used to capture information about extensions to the types offered by Ant, such as tasks,
+ selectors and the like. Tools, such as a stylesheet, can then interpret the XML document
+ and generate human-friendly documentation relating to your types.
+ </xs:documentation>
+ </xs:annotation>
+
+ <!-- Root node -->
+ <xs:element name="types">
+ <xs:annotation>
+ <xs:documentation xml:lang="en">
+ Root element for ant-types documents. It is made of a title, a preamble text and a set of
+ defined types.
+ </xs:documentation>
+ </xs:annotation>
+ <xs:complexType>
+ <xs:sequence>
+ <!-- Title -->
+ <xs:element name="title" type="xs:string">
+ <xs:annotation>
+ <xs:documentation xml:lang="en">Title of this document</xs:documentation>
+ </xs:annotation>
+ </xs:element>
+ <!-- Introduction text -->
+ <xs:element name="introduction">
+ <xs:annotation>
+ <xs:documentation xml:lang="en">
+ Introductory text to the set of types. HTML tags can be used within this field.
+ </xs:documentation>
+ </xs:annotation>
+ <xs:complexType mixed="true">
+ <xs:sequence>
+ <xs:any namespace="##any" processContents="skip" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <!-- Type [0-n] -->
+ <xs:element name="type" type="type" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+
+ <!-- **************************************** -->
+ <xs:complexType name="type">
+ <xs:annotation>
+ <xs:documentation xml:lang="en">This element is used to describe a single ANT type</xs:documentation>
+ </xs:annotation>
+ <xs:sequence>
+ <!-- Short description -->
+ <xs:element name="shortDescription" type="xs:string">
+ <xs:annotation>
+ <xs:documentation xml:lang="en">One line description of type, used for tables of content and similar indexing</xs:documentation>
+ </xs:annotation>
+ </xs:element>
+ <!-- Full description -->
+ <xs:element name="fullDescription">
+ <xs:annotation>
+ <xs:documentation xml:lang="en">Full description of type. HTML tags can be used within this field.</xs:documentation>
+ </xs:annotation>
+ <xs:complexType mixed="true">
+ <xs:sequence>
+ <xs:any namespace="##any" processContents="skip" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <!-- Parameters -->
+ <xs:element name="parameter" type="parameter" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ <!-- Name -->
+ <xs:attribute name="name" type="xs:string" use="required">
+ <xs:annotation>
+ <xs:documentation xml:lang="en">Specifies the usual name for a type. For example: copy, delete.</xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ <!-- Class name -->
+ <xs:attribute name="className" type="xs:string" use="required">
+ <xs:annotation>
+ <xs:documentation xml:lang="en">Specifies the name of the class that implement this type.</xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ </xs:complexType>
+
+ <!-- **************************************** -->
+ <xs:complexType name="parameter">
+ <xs:annotation>
+ <xs:documentation xml:lang="en">This element is used to describe a single parameter within a type.</xs:documentation>
+ </xs:annotation>
+ <xs:all>
+ <!-- Description -->
+ <xs:element name="description">
+ <xs:annotation>
+ <xs:documentation xml:lang="en">Description of the parameter. HTML tags can be used within this field.</xs:documentation>
+ </xs:annotation>
+ <xs:complexType mixed="true">
+ <xs:sequence>
+ <xs:any namespace="##any" processContents="skip" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ <!-- Required -->
+ <xs:element name="required">
+ <xs:annotation>
+ <xs:documentation xml:lang="en">Description of the parameter's requirements. HTML tags can be used within this field.</xs:documentation>
+ </xs:annotation>
+ <xs:complexType mixed="true">
+ <xs:sequence>
+ <xs:any namespace="##any" processContents="skip" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+ </xs:element>
+ </xs:all>
+ <!-- Name -->
+ <xs:attribute name="name" type="xs:string" use="required">
+ <xs:annotation>
+ <xs:documentation xml:lang="en">The name of the attribute</xs:documentation>
+ </xs:annotation>
+ </xs:attribute>
+ </xs:complexType>
+
+ <!-- **************************************** -->
+ <xs:complexType name="example" mixed="true">
+ <xs:annotation>
+ <xs:documentation xml:lang="en">
+ This free form element can be used within fields where HTML is allowed. It
+ defines text that should be highlighted as an example.
+ </xs:documentation>
+ </xs:annotation>
+ <xs:sequence>
+ <xs:any namespace="##any" processContents="skip" minOccurs="0" maxOccurs="unbounded"/>
+ </xs:sequence>
+ </xs:complexType>
+
+</xs:schema>
Index: src/doc/selectors.xml
===================================================================
--- src/doc/selectors.xml (revision 0)
+++ src/doc/selectors.xml (revision 0)
@@ -0,0 +1,401 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE types [
+ <!ENTITY common_params SYSTEM "javahl_javasvn.txt">
+]>
+
+<ant:types
+ xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:ant="http://www.fiset.ca/ant-docs/v1"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.fiset.ca/ant-docs/v1 ant-types.xsd"
+ >
+ <ant:title>Svn Selectors</ant:title>
+
+ <ant:introduction>
+ <p>
+ This document describes the file selectors offered in svnAnt. To use those selectors,
+ you must first obtain a copy of svnant.jar, add it to the classpath of your ant project
+ and define the types. Fortunately, there is a resource file, within the distributed JAR file,
+ and all those steps can be accomplished with the following code:
+ <ant:example>
+ <![CDATA[
+<path id="svnant.classpath">
+ <pathelement location="${svnant.dir}/lib/svnant.jar" />
+ <pathelement location="${svnant.dir}/lib/svnClientAdapter.jar" />
+</path>
+
+<typedef resource="svntypes.xml" classpathref="project.classpath"/>
+ ]]>
+ </ant:example>
+ </p>
+ <p>
+ If you are upgrading from an earlier version of svnAnt, and the following line was used
+ in your <i>build.xml</i> file, then replace it with the ones above.
+ <ant:example>
+ <![CDATA[
+<taskdef resource="svntask.properties" classpathref="svnant.classpath"/>
+ ]]>
+ </ant:example>
+ </p>
+ <h3><a name="bindings">Bindings</a></h3>
+ <p>
+ All file selectors offer two parameters: <b>javahl</b> and <b>javasvn</b>. Those parameters
+ are booleans, which means their values can be set to either <b>true</b> or <b>false</b>.
+ If not specified, those parameters are assumed to be set (true). These two parameters are used
+ to select which client is used to access Subversion.
+ </p>
+ <p>
+ There are three clients used by svnAnt to access Subversion:
+ <ul>
+ <li>JavaHL;</li>
+ <li>JavaSVN; and,</li>
+ <li>Command Line Interface.</li>
+ </ul>
+ To better understand the difference between those three clients, please refer to
+ documentation on <b>svnClientAdapter.jar</b>.
+ </p>
+ <p>
+ The property <b>javahl</b> is considered only if the javahl libraries are available. Similarly,
+ the property <b>javasvn</b> is considered only if JavaSVN is present. Finally, <b>javahl</b>
+ takes precedence over <b>javasvn</b>.
+ </p>
+ <p>
+ To better illustrate the previous paragraph, use the following steps:
+ <ol>
+ <li>If <b>javahl</b> is <i>true</i> and JavaHL bindings are available, then JavaHL is used.</li>
+ <li>If <b>javasvn</b> is <i>true</i> and JavaSVN is present, then JavaSVN is used.</li>
+ <li>If the two previous tests failed, for any reason, then the Command Line Interface is used.</li>
+ </ol>
+ </p>
+ </ant:introduction>
+
+ <!-- ***************************** -->
+ <ant:type name="svnAdded" className="org.tigris.subclipse.svnant.selectors.Added">
+ <ant:shortDescription>File selector that performs discrimination based on the 'added' subversion status. </ant:shortDescription>
+ <ant:fullDescription>
+ <p>
+ This file selector is used to discriminate files within a <b>fileset</b> based on a Subversion
+ status. In particular, this selector keeps files that are recognized as 'added'.
+ </p>
+ <p>
+ An 'added' file or directory is one that has been added to the repository, but not yet
+ commited. In general, <b>svn status</b> displays those items with the letter <i>A</i>
+ preceeding the name.
+ </p>
+ <p>
+ Example: to copy a number of files with the status 'added' from their location in
+ <b>workingcopy</b> to a new directory called <b>test</b>, the following ant task can
+ be used:
+ <ant:example>
+<![CDATA[
+<copy todir="test">
+ <fileset dir="workingcopy">
+ <svnAdded/>
+ </fileset>
+</copy>
+]]>
+ </ant:example>
+ </p>
+ </ant:fullDescription>
+ &common_params;
+ </ant:type>
+
+ <!-- ***************************** -->
+ <ant:type name="svnModified" className="org.tigris.subclipse.svnant.selectors.Modified">
+ <ant:shortDescription>File selector that performs discrimination based on the 'modified' subversion status. </ant:shortDescription>
+ <ant:fullDescription>
+ <p>
+ This file selector is used to discriminate files within a <b>fileset</b> based on a Subversion
+ status. In particular, this selector keeps files that are recognized as 'modified'.
+ </p>
+ <p>
+ A 'modified' file or directory is one that has been changed since the last update and where
+ the changes have not yet been commited to the repository. In general, <b>svn status</b>
+ display those items with the letter <i>M</i> preceeding the name. It is important to note
+ that other items can also be considered modified, such as conflicted ones.
+ </p>
+ <p>
+ Example: to copy a number of files with the status 'modified' from their location in
+ <b>workingcopy</b> to a new directory called <b>test</b>, the following ant task can
+ be used:
+ <ant:example>
+<![CDATA[
+<copy todir="test">
+ <fileset dir="workingcopy">
+ <svnModified/>
+ </fileset>
+</copy>
+]]>
+ </ant:example>
+ </p>
+ </ant:fullDescription>
+ &common_params;
+ </ant:type>
+
+ <!-- ***************************** -->
+ <ant:type name="svnUnversioned" className="org.tigris.subclipse.svnant.selectors.Unversioned">
+ <ant:shortDescription>File selector that performs discrimination based on the 'unversioned' subversion status. </ant:shortDescription>
+ <ant:fullDescription>
+ <p>
+ This file selector is used to discriminate files within a <b>fileset</b> based on a Subversion
+ status. In particular, this selector keeps files that are recognized as 'unversioned'.
+ </p>
+ <p>
+ An 'unversioned' file or directory is one that is present in a working copy but is not yet
+ known to the repository. In general, <b>svn status</b>
+ display those items with a question mark (<i>?</i>) preceeding the name. Note that 'ignored'
+ items are not considered 'unversioned'.
+ </p>
+ <p>
+ Eexample: to copy a number of files with the status 'unversioned' from their location in
+ <b>workingcopy</b> to a new directory called <b>test</b>, the following ant task can
+ be used:
+ <ant:example>
+<![CDATA[
+<copy todir="test">
+ <fileset dir="workingcopy">
+ <svnUnversioned/>
+ </fileset>
+</copy>
+]]>
+ </ant:example>
+ </p>
+ </ant:fullDescription>
+ &common_params;
+ </ant:type>
+
+ <!-- ***************************** -->
+ <ant:type name="svnConflicted" className="org.tigris.subclipse.svnant.selectors.Conflicted">
+ <ant:shortDescription>File selector that performs discrimination based on the 'conflicted' subversion status. </ant:shortDescription>
+ <ant:fullDescription>
+ <p>
+ This file selector is used to discriminate files within a <b>fileset</b> based on a Subversion
+ status. In particular, this selector keeps files that are recognized as 'conflicted'.
+ </p>
+ <p>
+ When updating a subversion item (file or directory), it is possible to have two sets of
+ changes merged into the working item. This happens when the item was modified locally as
+ well as remotely during the period since the last update. If the two sets of changes conflict
+ (same lines of a file changes, same directory entries modified), then the item is marked
+ as 'conflicted'. In general, <b>svn status</b> displays 'conflicted' items with the letter
+ <i>C</i> preceeding the name. Note that 'conflicted' items are also considered 'modified'.
+ </p>
+ <p>
+ Example: to copy a number of files with the status 'conflicted' from their location in
+ <b>workingcopy</b> to a new directory called <b>test</b>, the following ant task can
+ be used:
+ <ant:example>
+<![CDATA[
+<copy todir="test">
+ <fileset dir="workingcopy">
+ <svnConflicted/>
+ </fileset>
+</copy>
+]]>
+ </ant:example>
+ </p>
+ </ant:fullDescription>
+ &common_params;
+ </ant:type>
+
+ <!-- ***************************** -->
+ <ant:type name="svnIgnored" className="org.tigris.subclipse.svnant.selectors.Ignored">
+ <ant:shortDescription>File selector that performs discrimination based on the 'ignored' subversion status. </ant:shortDescription>
+ <ant:fullDescription>
+ <p>
+ This file selector is used to discriminate files within a <b>fileset</b> based on a Subversion
+ status. In particular, this selector keeps files that are recognized as 'ignored'.
+ </p>
+ <p>
+ An 'ignored' file or directory is one which name match the patterns found in the parent
+ directory's <b>svn:ignore</b> property. In general, <b>svn status --no-ignore</b>
+ display those items with the letter <i>I</i> preceeding the name.
+ </p>
+ <p>
+ Example: to copy a number of files with the status 'ignored' from their location in
+ <b>workingcopy</b> to a new directory called <b>test</b>, the following ant task can
+ be used:
+ <ant:example>
+<![CDATA[
+<copy todir="test">
+ <fileset dir="workingcopy">
+ <svnIgnored/>
+ </fileset>
+</copy>
+]]>
+ </ant:example>
+ </p>
+ </ant:fullDescription>
+ &common_params;
+ </ant:type>
+
+ <!-- ***************************** -->
+ <ant:type name="svnLocked" className="org.tigris.subclipse.svnant.selectors.Locked">
+ <ant:shortDescription>File selector that performs discrimination based on the 'locked' subversion status. </ant:shortDescription>
+ <ant:fullDescription>
+ <p>
+ This file selector is used to discriminate files within a <b>fileset</b> based on a Subversion
+ status. In particular, this selector keeps files that are recognized as 'locked'.
+ </p>
+ <p>
+ A 'locked' file or directory is one where the repository has been informed of the
+ intent of a user to prevent others from modifying the file. For a working copy to
+ be aware of this fact, it must have been 'updated' since the lock status was changed.
+ In general, <b>svn status</b> displays those items with one of the letters <i>K</i>,
+ <i>O</i> or <i>B</i> in the sixth column. The 'lock' status is independent of most other
+ conditions such as 'modified', 'conflicted', etc.
+ </p>
+ <p>
+ Example: to copy a number of files with the status 'locked' from their location in
+ <b>workingcopy</b> to a new directory called <b>test</b>, the following ant task can
+ be used:
+ <ant:example>
+<![CDATA[
+<copy todir="test">
+ <fileset dir="workingcopy">
+ <svnLocked/>
+ </fileset>
+</copy>
+]]>
+ </ant:example>
+ </p>
+ </ant:fullDescription>
+ &common_params;
+ </ant:type>
+
+ <!-- ***************************** -->
+ <ant:type name="svnNormal" className="org.tigris.subclipse.svnant.selectors.Normal">
+ <ant:shortDescription>File selector that performs discrimination based on the 'normal' subversion status. </ant:shortDescription>
+ <ant:fullDescription>
+ <p>
+ This file selector is used to discriminate files within a <b>fileset</b> based on a Subversion
+ status. In particular, this selector keeps files that are recognized as 'normal'.
+ </p>
+ <p>
+ A 'normal' file or directory is one that has not undergone any changes since the last
+ update. In general, this is the great majority of the files in a working copy. <b>svn status</b>
+ returns no special character for those items (a space in the first column).
+ </p>
+ <p>
+ Example: to copy a number of files with the status 'normal' from their location in
+ <b>workingcopy</b> to a new directory called <b>test</b>, the following ant task can
+ be used:
+ <ant:example>
+<![CDATA[
+<copy todir="test">
+ <fileset dir="workingcopy">
+ <svnNormal/>
+ </fileset>
+</copy>
+]]>
+ </ant:example>
+ </p>
+ </ant:fullDescription>
+ &common_params;
+ </ant:type>
+
+ <!-- ***************************** -->
+ <ant:type name="svnReplaced" className="org.tigris.subclipse.svnant.selectors.Replaced">
+ <ant:shortDescription>File selector that performs discrimination based on the 'replaced' subversion status. </ant:shortDescription>
+ <ant:fullDescription>
+ <p>
+ This file selector is used to discriminate files within a <b>fileset</b> based on a Subversion
+ status. In particular, this selector keeps files that are recognized as 'replaced'.
+ </p>
+ <p>
+ A 'replaced' file or directory is one that has been deleted, then created anew and finally
+ added back to the repository. Also, those changes must not have been comitted.
+ In general, <b>svn status</b> displays those items with the letter <i>R</i> preceeding
+ the name.
+ </p>
+ <p>
+ Example: to copy a number of files with the status 'replaced' from their location in
+ <b>workingcopy</b> to a new directory called <b>test</b>, the following ant task can
+ be used:
+ <ant:example>
+<![CDATA[
+<copy todir="test">
+ <fileset dir="workingcopy">
+ <svnReplaced/>
+ </fileset>
+</copy>
+]]>
+ </ant:example>
+ </p>
+ </ant:fullDescription>
+ &common_params;
+ </ant:type>
+
+ <!-- ***************************** -->
+ <ant:type name="svnMissing" className="org.tigris.subclipse.svnant.selectors.Missing">
+ <ant:shortDescription>File selector that performs discrimination based on the 'missing' subversion status. </ant:shortDescription>
+ <ant:fullDescription>
+ <p>
+ This file selector is used to discriminate files within a <b>fileset</b> based on a Subversion
+ status. In particular, this selector keeps files that are recognized as 'missing'.
+ </p>
+ <p>
+ A 'missing' file or directory is one that is managed by Subversion and
+ has been deleted without using the remove command. In general, <b>svn status</b>
+ displays those items with the exclamation point (<i>!</i>) preceeding the name.
+ </p>
+ <p>
+ It is important to note that a regular FileSet (the one supplied by ANT) can not
+ detect a missing item, since it does not exist on the file system. To detect
+ Subversion missing items, use the FileSet provided by svn-ant (svnFileSet).
+ </p>
+ <p>
+ Example: to delete missing files from the repository associated with a <b>workingcopy</b>:
+ <ant:example>
+<![CDATA[
+<svn>
+ <delete>
+ <svnFileSet dir="workingcopy">
+ <svnMissing/>
+ </svnFileSet>
+ </delete>
+</svn>
+]]>
+ </ant:example>
+ </p>
+ </ant:fullDescription>
+ &common_params;
+ </ant:type>
+
+ <!-- ***************************** -->
+ <ant:type name="svnDeleted" className="org.tigris.subclipse.svnant.selectors.Deleted">
+ <ant:shortDescription>File selector that performs discrimination based on the 'deleted' subversion status. </ant:shortDescription>
+ <ant:fullDescription>
+ <p>
+ This file selector is used to discriminate files within a <b>fileset</b> based on a Subversion
+ status. In particular, this selector keeps files that are recognized as 'deleted'.
+ </p>
+ <p>
+ A 'deleted' file or directory is one that has been erased using Subversion's 'remove'
+ command. In general, <b>svn status</b> displays those items with the letter <i>D</i>
+ preceeding the name.
+ </p>
+ <p>
+ It is important to note that a regular FileSet (the one supplied by ANT) can not
+ detect a deleted item, since it does not exist on the file system. To detect
+ Subversion deleted items, use the FileSet provided by svn-ant (svnFileSet).
+ </p>
+ <p>
+ Example: to revert deleted files from a <b>workingcopy</b>:
+ <ant:example>
+<![CDATA[
+<svn>
+ <revert>
+ <svnFileSet dir="workingcopy">
+ <svnDeleted/>
+ </svnFileSet>
+ </revert>
+</svn>
+]]>
+ </ant:example>
+ </p>
+ </ant:fullDescription>
+ &common_params;
+ </ant:type>
+
+</ant:types>
\ No newline at end of file

Property changes on: src\doc\selectors.xml
___________________________________________________________________
Name: svn:mime-type
   + text/xml

Index: src/doc/types.xml
===================================================================
--- src/doc/types.xml (revision 0)
+++ src/doc/types.xml (revision 0)
@@ -0,0 +1,254 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE types [
+ <!ENTITY common_params SYSTEM "javahl_javasvn.txt">
+]>
+
+<ant:types
+ xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:ant="http://www.fiset.ca/ant-docs/v1"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://www.fiset.ca/ant-docs/v1 ant-types.xsd"
+ >
+ <ant:title>Svn Types</ant:title>
+
+ <ant:introduction>
+ <p>
+ This document describes the type extensions that svn-ant brings to Ant. To use those types,
+ you must first obtain a copy of svnant.jar, add it to the classpath of your ant project
+ and define the types. Fortunately, there is a resource file, within the distributed JAR file,
+ and all those steps can be accomplished with the following code:
+ <ant:example>
+ <![CDATA[
+<path id="svnant.classpath">
+ <pathelement location="${svnant.dir}/lib/svnant.jar" />
+ <pathelement location="${svnant.dir}/lib/svnClientAdapter.jar" />
+</path>
+
+<typedef resource="svntypes.xml" classpathref="project.classpath"/>
+ ]]>
+ </ant:example>
+ </p>
+ <p>
+ If you are upgrading from an earlier version of svnAnt, and the following line was used
+ in your <i>build.xml</i> file, then replace it with the ones above.
+ <ant:example>
+ <![CDATA[
+<taskdef resource="svntask.properties" classpathref="svnant.classpath"/>
+ ]]>
+ </ant:example>
+ </p>
+ <h3><a name="bindings">Bindings</a></h3>
+ <p>
+ All types offer two parameters: <b>javahl</b> and <b>javasvn</b>. Those parameters
+ are booleans, which means their values can be set to either <b>true</b> or <b>false</b>.
+ If not specified, those parameters are assumed to be set (true). These two parameters are used
+ to select which client is used to access Subversion.
+ </p>
+ <p>
+ There are three clients used by svnAnt to access Subversion:
+ <ul>
+ <li>JavaHL;</li>
+ <li>JavaSVN; and,</li>
+ <li>Command Line Interface.</li>
+ </ul>
+ To better understand the difference between those three clients, please refer to
+ documentation on <b>svnClientAdapter.jar</b>.
+ </p>
+ <p>
+ The property <b>javahl</b> is considered only if the javahl libraries are available. Similarly,
+ the property <b>javasvn</b> is considered only if JavaSVN is present. Finally, <b>javahl</b>
+ takes precedence over <b>javasvn</b>.
+ </p>
+ <p>
+ To better illustrate the previous paragraph, use the following steps:
+ <ol>
+ <li>If <b>javahl</b> is <i>true</i> and JavaHL bindings are available, then JavaHL is used.</li>
+ <li>If <b>javasvn</b> is <i>true</i> and JavaSVN is present, then JavaSVN is used.</li>
+ <li>If the two previous tests failed, for any reason, then the Command Line Interface is used.</li>
+ </ol>
+ </p>
+ </ant:introduction>
+
+ <!-- ***************************** -->
+ <ant:type name="svnFileSet" className="org.tigris.subclipse.svnant.SvnFileSet">
+ <ant:shortDescription>FileSet replacement that operates on list of files obtained from Subversion.</ant:shortDescription>
+ <ant:fullDescription>
+ <p>
+ This type implements a FileSet. Instances of FileSet are used in tasks that operates on a number of files. The files
+ selected by a FileSet can be tailored by a number of patterns and selectors. More information about file sets is available
+ with the Ant documentation.
+ </p>
+ <p>
+ The motivation with creating a replacement FileSet that is based on Subversion was to have the ability of creating
+ sets of files that include deleted and missing files. In fact, the classic fileset operates only on files that are reported
+ by the file system and can not predict deleted and missing files. Furthermore, there are useful commands that can be performed
+ on deleted and missing files, such as 'revert', 'delete', 'update' and others.
+ </p>
+ <p>
+ At the present time, <b>svnFileSet</b> is experimental. It supports selectors but it does not yet accept any patterns
+ (include, exclude). Those enhancments are to come later.
+ </p>
+ <p>
+ <b>svnFileSet</b> can be used within any svn-ant task that supports a nested file sets. It can also be used in any task
+ that is based on a file set. If you have a problem using <b>svnFileSet</b> within a task that works well with the classic
+ fileset, then report the problem to the author of the task. However, for the time being, there is a work around your
+ problem. Instead of using a <b>svnFileSet</b> directly in the targeted task, use it indirectly via a classic fileset and
+ a reference. For example, if ANT complains about a task similar to the following:
+ <ant:example>
+<![CDATA[
+<target name="example">
+ <mkdir dir="test"/>
+ <copy todir="test">
+ <svnFileSet dir="workingcopy">
+ <svnAdded/>
+ </svnFileSet>
+ </copy>
+</target>
+]]>
+ </ant:example>
+
+ you can rewrite it, using a reference, as:
+
+ <ant:example>
+<![CDATA[
+<target name="example">
+ <svnFileSet id="svnFileSetId_1" dir="workingcopy">
+ <svnAdded/>
+ </svnFileSet>
+ <mkdir dir="test"/>
+ <copy todir="test">
+ <fileset refid="svnFileSetId_1"/>
+ </copy>
+</target>
+]]>
+ </ant:example>
+ </p>
+ <p>
+ If you are the author of a fileset-based task and that you can not understand
+ why your task does not accept <b>svnFileSet</b> while it works perfectly well
+ with the classic fileset, here is a thing you can check. If your task
+ accepts instances of FileSet with a method similar to:
+ <ant:example>
+<![CDATA[
+public void addFileset(FileSet set) {
+ ...
+}
+]]>
+ </ant:example>
+ then adding the following method should fix the problem:
+ <ant:example>
+<![CDATA[
+public void add(FileSet set) {
+ addFileSet(set);
+}
+]]>
+ </ant:example>
+ </p>
+ <h3>Examples</h3>
+ <p>
+ The following ant script can be used to remove all missing files from the associated repository:
+ <ant:example>
+<![CDATA[
+<svn>
+ <delete>
+ <svnFileSet dir="workingcopy">
+ <svnMissing/>
+ </svnFileSet>
+ </delete>
+ <commit
+ dir="workingcopy"
+ message="automatically removing missing files"/>
+</svn>
+]]>
+ </ant:example>
+ </p>
+ <p>
+ The following ant script can be used to add all new files to the associated repository:
+ <ant:example>
+<![CDATA[
+<svn>
+ <add>
+ <svnFileSet dir="workingcopy">
+ <svnUnversioned/>
+ </svnFileSet>
+ </add>
+ <commit
+ dir="workingcopy"
+ message="automatically adding files"/>
+</svn>
+]]>
+ </ant:example>
+ </p>
+ <p>
+ The following ant script can be used to restore all deleted files:
+ <ant:example>
+<![CDATA[
+<svn>
+ <revert>
+ <svnFileSet dir="workingcopy">
+ <svnDeleted/>
+ </svnFileSet>
+ </revert>
+</svn>
+]]>
+ </ant:example>
+ </p>
+ <p>
+ If, in the previous example, you wanted svn-ant to use the command line adapter:
+ <ant:example>
+<![CDATA[
+<svn javahl="false" javasvn="false">
+ <revert>
+ <svnFileSet
+ dir="workingcopy"
+ javahl="false"
+ javasvn="false">
+ <svnDeleted
+ javahl="false"
+ javasvn="false"/>
+ </svnFileSet>
+ </revert>
+</svn>
+]]>
+ </ant:example>
+ </p>
+ </ant:fullDescription>
+ <ant:parameter name="dir">
+ <ant:description>
+ Specifies the root directory used by the file set. It should specify
+ a directory managed by Subversion.
+ </ant:description>
+ <ant:required>
+ Either dir or file must be specified
+ </ant:required>
+ </ant:parameter>
+ <ant:parameter name="file">
+ <ant:description>
+ If used, specifies a fileset that contains a single file.
+ </ant:description>
+ <ant:required>
+ Either dir or file must be specified
+ </ant:required>
+ </ant:parameter>
+ <ant:parameter name="includes">
+ <ant:description>
+ Comma-seperated or space-separated list of patterns, which describe files that are
+ included. If this attribute if not specified, then all files are included.
+ </ant:description>
+ <ant:required>
+ No
+ </ant:required>
+ </ant:parameter>
+ <ant:parameter name="excludes">
+ <ant:description>
+ Comma-seperated or space-separated list of patterns, which describe files that are
+ excluded. If this attribute if not specified, then no files are excluded.
+ </ant:description>
+ <ant:required>
+ No
+ </ant:required>
+ </ant:parameter>
+ &common_params;
+ </ant:type>
+
+</ant:types>
\ No newline at end of file

Property changes on: src\doc\types.xml
___________________________________________________________________
Name: svn:mime-type
   + text/xml

Index: src/doc/ant-types.xsl
===================================================================
--- src/doc/ant-types.xsl (revision 0)
+++ src/doc/ant-types.xsl (revision 0)
@@ -0,0 +1,228 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet
+ version="2.0"
+ xmlns="http://www.w3.org/1999/xhtml"
+ xmlns:html="http://www.w3.org/1999/xhtml"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:ant="http://www.fiset.ca/ant-docs/v1"
+>
+
+<xsl:output
+ method="xml"
+ encoding="UTF-8"
+ standalone="yes"
+ version="1.0"
+ doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN"
+ doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
+ indent="yes"/>
+
+<!-- =================================================== -->
+<xsl:template match="/ant:types">
+ <html>
+ <head>
+ <META HTTP-EQUIV="CONTENT-TYPE" CONTENT="text/html; charset=windows-1252"/>
+ <title>
+ <xsl:value-of select="ant:title"/>
+ </title>
+ <META HTTP-EQUIV="Content-Language" CONTENT="en-us"/>
+ <style type="text/css">
+ <![CDATA[
+ body {
+ font: 80% Verdana, Arial, Helvetica, sans-serif;
+ margin: 0; padding: 0;
+ /* background: rgb(95%,95%,80%); */
+ color: black;
+ }
+ h1 {
+ font-size: 200%; letter-spacing: 3px;
+ margin-bottom: 1em;
+ padding: 0.66em 0 0.33em 1em;
+ background: rgb(85%,85%,70%);
+ }
+ h2 {
+ background: rgb(85%,85%,70%);
+ }
+ h3 {
+ border:1px solid rgb(85%,85%,70%);
+ color: rgb(85%,85%,70%);
+ padding: 0.66em 0 0.33em 1em;
+ background-color: #f3f1f4;
+ }
+ .sample {
+ font-family: Courier, "Courier New", monospace;
+ background-color: #f3f1f4;
+ }
+ div.sample {
+ margin-left: 10px;
+ margin-right: 10px;
+ padding-top: 3px;
+ padding-bottom: 3px;
+ padding-left: 3px;
+ padding-right: 3px;
+ border:1px dashed black;
+ width: 80%;
+ }
+ table.params {
+ width: 80%;
+ border: 1px solid gray;
+ margin-bottom:1em;
+ }
+ th.params, td.params {
+ padding: 0 0.5em;
+ border-left: 1px solid #DDD;
+ border-bottom: 1px solid #DDD;
+ font: 70%
+ }
+ th.params {
+
+ }
+ table.toc {
+ width: 80%;
+ border: 1px solid gray;
+ margin-bottom:1em;
+ }
+ td.toc {
+ padding: 0 0.5em;
+ border: none
+ font: 70%
+ }
+ table.type {
+ width: 80%;
+ border: none;
+ margin-bottom:1em;
+ }
+ th.type, td.type {
+ text-align: left;
+ padding: 0 0.5em;
+ border: none
+ font: 70%
+ }
+ th.type {
+ font-weight: bold;
+ }
+ ]]>
+ </style>
+ </head>
+ <body lang="en-US" dir="LTR">
+ <!-- Table of content -->
+ <h1>
+ <xsl:value-of select="ant:title"/>
+ </h1>
+
+ <h2>Table of Content</h2>
+ <table class="toc">
+ <tbody class="toc">
+ <xsl:for-each select="ant:type">
+ <tr class="toc">
+ <td class="toc">
+ <a>
+ <xsl:attribute name="href">
+ <xsl:text>#</xsl:text>
+ <xsl:value-of select="@name"/>
+ </xsl:attribute>
+
+ <xsl:value-of select="@name"/>
+ </a>
+ </td>
+ <td class="toc">
+ <xsl:value-of select="ant:shortDescription"/>
+ </td>
+ </tr>
+ </xsl:for-each>
+ </tbody>
+ </table>
+
+ <h2>Introduction</h2>
+
+ <xsl:apply-templates select="ant:introduction"/>
+
+
+ <!-- Insert all defined types here -->
+ <xsl:apply-templates select="ant:type"/>
+
+ </body>
+ </html>
+</xsl:template>
+
+<!-- =================================================== -->
+<xsl:template match="ant:type">
+ <h1>
+ <a name="svn">
+ <xsl:attribute name="name" select="@name"/>
+ <xsl:value-of select="@name"/>
+ </a>
+ </h1>
+
+ <p>
+ <xsl:value-of select="ant:shortDescription"/>
+ </p>
+
+ <xsl:if test="@className">
+ <table class="type">
+ <tbody class="type">
+ <tr class="type">
+ <th class="type">Implementation:</th>
+ <td class="type">
+ <xsl:value-of select="@className"/>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </xsl:if>
+
+ <h2>Parameters</h2>
+ <xsl:choose>
+ <xsl:when test="count(./ant:parameter) = 0">
+ <xsl:text>No parameters defined for this type.</xsl:text>
+ </xsl:when>
+ <xsl:otherwise>
+ <table class="params">
+ <tr class="params">
+ <th class="params">Attribute</th>
+ <th class="params">Description</th>
+ <th class="params">Required</th>
+ </tr>
+ <xsl:apply-templates select="ant:parameter"/>
+ </table>
+ </xsl:otherwise>
+ </xsl:choose>
+
+ <!-- Full description -->
+ <xsl:apply-templates select="ant:fullDescription"/>
+
+
+</xsl:template>
+
+<!-- =================================================== -->
+<xsl:template match="ant:parameter">
+ <tr class="params">
+ <td class="params">
+ <xsl:value-of select="@name"/>
+ </td>
+ <td class="params">
+ <xsl:apply-templates select="ant:description"/>
+ </td>
+ <td class="params">
+ <xsl:apply-templates select="ant:required"/>
+ </td>
+ </tr>
+</xsl:template>
+
+<!-- =================================================== -->
+<xsl:template match="ant:example">
+ <div class="sample">
+ <pre class="sample">
+ <xsl:apply-templates select="child::node()"/>
+ </pre>
+ </div>
+</xsl:template>
+
+<!-- =================================================== -->
+<xsl:template match="*|@*|text()|comment()">
+ <xsl:copy>
+ <xsl:apply-templates select="@*"/>
+ <xsl:apply-templates select="child::node()"/>
+ </xsl:copy>
+</xsl:template>
+
+</xsl:stylesheet>
\ No newline at end of file

Property changes on: src\doc\ant-types.xsl
___________________________________________________________________
Name: svn:mime-type
   + text/xml

Index: src/doc/javahl_javasvn.txt
===================================================================
--- src/doc/javahl_javasvn.txt (revision 0)
+++ src/doc/javahl_javasvn.txt (revision 0)
@@ -0,0 +1,20 @@
+<ant:parameter name="javahl">
+ <ant:description>
+ If set, instructs the use of JavaHL bindings, if available.
+ Set to <b>false</b> to use command line client interface to subversion.
+ Defaults to true. See note for more details.
+ </ant:description>
+ <ant:required>
+ No
+ </ant:required>
+</ant:parameter>
+<ant:parameter name="javasvn">
+ <ant:description>
+ If set, instructs the use of JavaSvn bindings, if available.
+ Set to <b>false</b> to use command line client interface to subversion.
+ Defaults to true. See note for more details.
+ </ant:description>
+ <ant:required>
+ No
+ </ant:required>
+</ant:parameter>

Property changes on: src\doc\javahl_javasvn.txt
___________________________________________________________________
Name: svn:mime-type
   + text/plain

Index: src/testcases/org/tigris/subversion/svnant/SvnTest.java
===================================================================
--- src/testcases/org/tigris/subversion/svnant/SvnTest.java (revision 1649)
+++ src/testcases/org/tigris/subversion/svnant/SvnTest.java (working copy)
@@ -4,12 +4,14 @@
  */
 package org.tigris.subversion.svnant;
 
+import java.io.BufferedReader;
 import java.io.DataInputStream;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.InputStreamReader;
 import java.net.MalformedURLException;
 import java.util.HashSet;
 import java.util.Set;
@@ -44,6 +46,8 @@
 
         protected ISVNClientAdapter svnClient;
         protected static final String WORKINGCOPY_DIR = "test/svn/workingcopy";
+ protected static final String WORKINGCOPY2_DIR = "test/svn/workingcopy2";
+ protected static final String TEST_DIR = "test/svn/test";
 
     public SvnTest(String name) {
         super(name);
@@ -452,6 +456,280 @@
             executeTarget("testSwitch");
     }
 
+ public void testNormalSelector() throws Exception {
+ executeTarget("testNormalSelector");
+
+ // Count number of files in test directory
+ File dir2 = new File(TEST_DIR);
+ assertTrue( dir2.exists() );
+ assertTrue( dir2.isDirectory() );
+ assertEquals(2, dir2.listFiles().length);
+
+ // Verify that the expected files are present
+ assertTrue( (new File(dir2, "normal1.txt")).exists() );
+ assertTrue( (new File(dir2, "normal2.txt")).exists() );
+ }
+
+ public void testAddedSelector() throws Exception {
+ executeTarget("testAddedSelector");
+
+ // Count number of files in test directory
+ File dir2 = new File(TEST_DIR);
+ assertTrue( dir2.exists() );
+ assertTrue( dir2.isDirectory() );
+ assertEquals(2, dir2.listFiles().length);
+
+ // Verify that the expected files are present
+ assertTrue( (new File(dir2, "added1.txt")).exists() );
+ assertTrue( (new File(dir2, "added2.txt")).exists() );
+ }
+
+ public void testUnversionedSelector() throws Exception {
+ executeTarget("testUnversionedSelector");
+
+ // Count number of files in test directory
+ File dir2 = new File(TEST_DIR);
+ assertTrue( dir2.exists() );
+ assertTrue( dir2.isDirectory() );
+ assertEquals(2, dir2.listFiles().length);
+
+ // Verify that the expected files are present
+ assertTrue( (new File(dir2, "unversioned1.txt")).exists() );
+ assertTrue( (new File(dir2, "unversioned2.txt")).exists() );
+ }
+
+ public void testModifiedSelector() throws Exception {
+ executeTarget("testModifiedSelector");
+
+ // Count number of files in test directory
+ File dir2 = new File(TEST_DIR);
+ assertTrue( dir2.exists() );
+ assertTrue( dir2.isDirectory() );
+ assertEquals(4, dir2.listFiles().length);
+
+ // Verify that the expected files are present
+ assertTrue( (new File(dir2, "modified1.txt")).exists() );
+ assertTrue( (new File(dir2, "modified2.txt")).exists() );
+ assertTrue( (new File(dir2, "conflicted1.txt")).exists() );
+ assertTrue( (new File(dir2, "conflicted2.txt")).exists() );
+ }
+
+ public void testIgnoredSelector() throws Exception {
+ executeTarget("testIgnoredSelector");
+
+ // Count number of files in test directory
+ File dir2 = new File(TEST_DIR);
+ assertTrue( dir2.exists() );
+ assertTrue( dir2.isDirectory() );
+ assertEquals(2, dir2.listFiles().length);
+
+ // Verify that the expected files are present
+ assertTrue( (new File(dir2, "ignored1.txt")).exists() );
+ assertTrue( (new File(dir2, "ignored2.txt")).exists() );
+ }
+
+ public void testConflictedSelector() throws Exception {
+ executeTarget("testConflictedSelector");
+
+ // Count number of files in test directory
+ File dir2 = new File(TEST_DIR);
+ assertTrue( dir2.exists() );
+ assertTrue( dir2.isDirectory() );
+ assertEquals(2, dir2.listFiles().length);
+
+ // Verify that the expected files are present
+ assertTrue( (new File(dir2, "conflicted1.txt")).exists() );
+ assertTrue( (new File(dir2, "conflicted2.txt")).exists() );
+ }
+
+ public void testReplacedSelector() throws Exception {
+ executeTarget("testReplacedSelector");
+
+ // Count number of files in test directory
+ File dir2 = new File(TEST_DIR);
+ assertTrue( dir2.exists() );
+ assertTrue( dir2.isDirectory() );
+ assertEquals(2, dir2.listFiles().length);
+
+ // Verify that the expected files are present
+ assertTrue( (new File(dir2, "replaced1.txt")).exists() );
+ assertTrue( (new File(dir2, "replaced2.txt")).exists() );
+ }
+
+ public void testEmbeddedSelector() throws Exception {
+ executeTarget("testEmbeddedSelector");
+
+ // Count number of files in test directory
+ File dir2 = new File(TEST_DIR);
+ assertTrue( dir2.exists() );
+ assertTrue( dir2.isDirectory() );
+ assertEquals(0, dir2.listFiles().length);
+
+ }
+
+ public void testAddSvnFileSet() throws Exception {
+ executeTarget("testAddSvnFileSet");
+
+ // Count number of files in test directory
+ File dir2 = new File(TEST_DIR);
+ assertTrue( dir2.exists() );
+ assertTrue( dir2.isDirectory() );
+ assertEquals(2, dir2.listFiles().length);
+
+ // Verify that the expected files are present
+ assertTrue( (new File(dir2, "added1.txt")).exists() );
+ assertTrue( (new File(dir2, "added2.txt")).exists() );
+ }
+
+ public void testCommitSvnFileSet() throws Exception {
+ executeTarget("testCommitSvnFileSet");
+
+ // Count number of files in test directory
+ File dir = new File(TEST_DIR);
+ assertTrue( dir.exists() );
+ assertTrue( dir.isDirectory() );
+ assertEquals(2, dir.listFiles().length);
+
+ // Verify that the expected files are present
+ assertTrue( (new File(dir, "file2.txt")).exists() );
+ assertTrue( (new File(dir, "dir1")).exists() );
+
+ File dir2 = new File(TEST_DIR, "dir1");
+ assertTrue( dir2.exists() );
+ assertTrue( dir2.isDirectory() );
+ assertEquals(1, dir2.listFiles().length);
+ assertTrue( (new File(dir2, "file1.txt")).exists() );
+ }
+
+ public void testDeleteSvnFileSet() throws Exception {
+ executeTarget("testDeleteSvnFileSet");
+
+ // Count number of files in test directory
+ File dir = new File(WORKINGCOPY2_DIR);
+ assertTrue( dir.exists() );
+ assertTrue( dir.isDirectory() );
+ File[] files = dir.listFiles();
+ assertEquals(3, files.length);
+
+ // Verify that the expected files are present
+ assertTrue( (new File(dir, "normal1.txt")).exists() );
+ assertTrue( (new File(dir, ".svn")).exists() );
+ assertTrue( (new File(dir, "dir1")).exists() );
+
+ File dir2 = new File(WORKINGCOPY2_DIR, "dir1");
+ assertTrue( dir2.exists() );
+ assertTrue( dir2.isDirectory() );
+ assertEquals(2, dir2.listFiles().length);
+ assertTrue( (new File(dir2, "normal2.txt")).exists() );
+ assertTrue( (new File(dir2, ".svn")).exists() );
+ }
+
+ public void testKeywordsSvnFileSet() throws Exception {
+ executeTarget("testKeywordsSvnFileSet");
+
+ // Test file1.txt
+ File dir = new File(WORKINGCOPY_DIR);
+ File file1 = new File(dir, "file1.txt");
+ BufferedReader br1 =
+ new BufferedReader(
+ new InputStreamReader(
+ new FileInputStream(file1)
+ )
+ );
+ String content1 = br1.readLine();
+ assertTrue( content1.matches(".*[0-9]+.*") );
+
+ // Test file2.txt
+ File dir2 = new File(WORKINGCOPY_DIR, "dir1");
+ File file2 = new File(dir2, "file2.txt");
+ BufferedReader br2 =
+ new BufferedReader(
+ new InputStreamReader(
+ new FileInputStream(file2)
+ )
+ );
+ String content2 = br2.readLine();
+ assertTrue( content2.matches(".*[0-9]+.*") );
+ }
+
+ public void testRevertSvnFileSet() throws Exception {
+ executeTarget("testRevertSvnFileSet");
+
+ // Test deleted1.txt
+ File dir = new File(WORKINGCOPY_DIR);
+ File deleted1 = new File(dir, "deleted1.txt");
+ assertTrue( deleted1.exists() );
+
+ // Test deleted2.txt
+ File dir2 = new File(WORKINGCOPY_DIR, "dir1");
+ File deleted2 = new File(dir2, "deleted2.txt");
+ assertTrue( deleted2.exists() );
+ }
+
+ public void testUpdateSvnFileSet() throws Exception {
+ executeTarget("testUpdateSvnFileSet");
+
+ // Test missing1.txt
+ File dir = new File(WORKINGCOPY_DIR);
+ File missing1 = new File(dir, "missing1.txt");
+ assertTrue( missing1.exists() );
+
+ // Test missing2.txt
+ File dir2 = new File(WORKINGCOPY_DIR, "dir1");
+ File missing2 = new File(dir2, "missing2.txt");
+ assertTrue( missing2.exists() );
+ }
+
+ public void testSvnFileSetAsRefId() throws Exception {
+ executeTarget("testSvnFileSetAsRefId");
+
+ // Count number of files in test directory
+ File dir = new File(TEST_DIR);
+ assertTrue( dir.exists() );
+ assertTrue( dir.isDirectory() );
+ assertEquals(2, dir.listFiles().length);
+
+ // Verify that the expected files are present
+ assertTrue( (new File(dir, "added1.txt")).exists() );
+ assertTrue( (new File(dir, "added2.txt")).exists() );
+ }
+
+ public void testSvnFileSetIncludes() throws Exception {
+ executeTarget("testSvnFileSetIncludes");
+
+ // Count number of files in test directory
+ File dir = new File(TEST_DIR);
+ assertTrue( dir.exists() );
+ assertTrue( dir.isDirectory() );
+ assertEquals(2, dir.listFiles().length);
+
+ // Verify that the expected files are present
+ assertTrue( (new File(dir, "file11.txt")).exists() );
+ assertTrue( (new File(dir, "dir")).exists() );
+
+ dir = new File(dir, "dir");
+ assertEquals(1, dir.listFiles().length);
+ assertTrue( (new File(dir, "file21.txt")).exists() );
+ }
+
+ public void testSvnFileSetExcludes() throws Exception {
+ executeTarget("testSvnFileSetExcludes");
+
+ // Count number of files in test directory
+ File dir = new File(TEST_DIR);
+ assertTrue( dir.exists() );
+ assertTrue( dir.isDirectory() );
+ assertEquals(2, dir.listFiles().length);
+
+ // Verify that the expected files are present
+ assertTrue( (new File(dir, "file12.txt")).exists() );
+ assertTrue( (new File(dir, "dir")).exists() );
+
+ dir = new File(dir, "dir");
+ assertEquals(1, dir.listFiles().length);
+ assertTrue( (new File(dir, "file22.txt")).exists() );
+ }
+
     public void testCleanupAfterTests() throws Exception {
             executeTarget("clean");
     }
Index: src/testcases/org/tigris/subversion/svnant/SvnJavaHLTest.java
===================================================================
--- src/testcases/org/tigris/subversion/svnant/SvnJavaHLTest.java (revision 1649)
+++ src/testcases/org/tigris/subversion/svnant/SvnJavaHLTest.java (working copy)
@@ -46,4 +46,5 @@
             super.executeTarget(targetName);
     }
 
+ public void testAddSvnFileSet() throws Exception { super.testAddSvnFileSet(); }
 }
Index: build.properties
===================================================================
--- build.properties (revision 1649)
+++ build.properties (working copy)
@@ -16,6 +16,7 @@
 # -----------------------------------------------------------------------------
 src.main.dir = src/main
 src.testcases.dir = src/testcases
+src.doc.dir = src/doc
 build.dir = build
 build.distrib.dir = ${build.dir}/distrib
 build.classes.dir = ${build.dir}/classes
Index: build.xml
===================================================================
--- build.xml (revision 1649)
+++ build.xml (working copy)
@@ -61,6 +61,21 @@
   </target>
 
   <!-- ================================================================= -->
+ <!-- compile docs -->
+ <!-- ================================================================= -->
+ <target name="docs" depends="" description="generate documentation">
+ <mkdir dir="${build.distrib.dir}/doc"/>
+ <style
+ basedir="${src.doc.dir}"
+ destdir="doc"
+ extension=".html"
+ style="${src.doc.dir}/ant-types.xsl"
+ processor="trax"
+ includes="*.xml"
+ />
+ </target>
+
+ <!-- ================================================================= -->
   <!-- compile junit test classes -->
   <!-- ================================================================= -->
   <target name="compileTests" description="compile junit sources files">
@@ -93,7 +108,7 @@
   <!-- ================================================================= -->
   <!-- make distribution -->
   <!-- ================================================================= -->
- <target name="makeDistrib" depends="clean,svnant.jar" description="make binary distribution">
+ <target name="makeDistrib" depends="clean,svnant.jar,docs" description="make binary distribution">
           <mkdir dir="${build.distrib.dir}"/>
                 <mkdir dir="${build.distrib.dir}/lib"/>
                 <mkdir dir="${build.distrib.dir}/doc"/>
@@ -109,7 +124,9 @@
                 <copy file="${ganymed.jar}" todir="${build.distrib.dir}/lib"/>
                 <copy file="GANYMED-LICENSE" todir="${build.distrib.dir}"/>
                 <copy file="${build.lib.dir}/svnant.jar" todir="${build.distrib.dir}/lib"/>
- <copy file="doc/svn.html" todir="${build.distrib.dir}/doc"/>
+ <copy todir="${build.distrib.dir}/doc">
+ <fileset dir="doc"/>
+ </copy>
                 <copy file="${distribfiles.dir}/build.xml" todir="${build.distrib.dir}"/>
     <copy file="${distribfiles.dir}/build.xml" todir="${build.distrib.dir}">
       <filterset>

Svn Selectors

Svn Selectors

Table of Content

svnAdded File selector that performs discrimination based on the 'added' subversion status.
svnModified File selector that performs discrimination based on the 'modified' subversion status.
svnUnversioned File selector that performs discrimination based on the 'unversioned' subversion status.
svnConflicted File selector that performs discrimination based on the 'conflicted' subversion status.
svnIgnored File selector that performs discrimination based on the 'ignored' subversion status.
svnLocked File selector that performs discrimination based on the 'locked' subversion status.
svnNormal File selector that performs discrimination based on the 'normal' subversion status.
svnReplaced File selector that performs discrimination based on the 'replaced' subversion status.
svnMissing File selector that performs discrimination based on the 'missing' subversion status.
svnDeleted File selector that performs discrimination based on the 'deleted' subversion status.

Introduction

This document describes the file selectors offered in svnAnt. To use those selectors, you must first obtain a copy of svnant.jar, add it to the classpath of your ant project and define the types. Fortunately, there is a resource file, within the distributed JAR file, and all those steps can be accomplished with the following code:

				
<path id="svnant.classpath">
  <pathelement location="${svnant.dir}/lib/svnant.jar" />
  <pathelement location="${svnant.dir}/lib/svnClientAdapter.jar" />
</path>  

<typedef resource="svntypes.xml" classpathref="project.classpath"/>
				
			

If you are upgrading from an earlier version of svnAnt, and the following line was used in your build.xml file, then replace it with the ones above.

				
<taskdef resource="svntask.properties" classpathref="svnant.classpath"/>
				
			

Bindings

All file selectors offer two parameters: javahl and javasvn. Those parameters are booleans, which means their values can be set to either true or false. If not specified, those parameters are assumed to be set (true). These two parameters are used to select which client is used to access Subversion.

There are three clients used by svnAnt to access Subversion:

  • JavaHL;
  • JavaSVN; and,
  • Command Line Interface.
To better understand the difference between those three clients, please refer to documentation on svnClientAdapter.jar.

The property javahl is considered only if the javahl libraries are available. Similarly, the property javasvn is considered only if JavaSVN is present. Finally, javahl takes precedence over javasvn.

To better illustrate the previous paragraph, use the following steps:

  1. If javahl is true and JavaHL bindings are available, then JavaHL is used.
  2. If javasvn is true and JavaSVN is present, then JavaSVN is used.
  3. If the two previous tests failed, for any reason, then the Command Line Interface is used.

svnAdded

File selector that performs discrimination based on the 'added' subversion status.

Implementation: org.tigris.subclipse.svnant.selectors.Added

Parameters

Attribute Description Required
javahl If set, instructs the use of JavaHL bindings, if available. Set to false to use command line client interface to subversion. Defaults to true. See note for more details. No
javasvn If set, instructs the use of JavaSvn bindings, if available. Set to false to use command line client interface to subversion. Defaults to true. See note for more details. No

Nested Types

No nested types defined for this type.

Description

This file selector is used to discriminate files within a fileset based on a Subversion status. In particular, this selector keeps files that are recognized as 'added'.

An 'added' file or directory is one that has been added to the repository, but not yet commited. In general, svn status displays those items with the letter A preceeding the name.

Example: to copy a number of files with the status 'added' from their location in workingcopy to a new directory called test, the following ant task can be used:


<copy todir="test">
	<fileset dir="workingcopy">
		<svnAdded/>
	</fileset>
</copy>
					
				

svnModified

File selector that performs discrimination based on the 'modified' subversion status.

Implementation: org.tigris.subclipse.svnant.selectors.Modified

Parameters

Attribute Description Required
javahl If set, instructs the use of JavaHL bindings, if available. Set to false to use command line client interface to subversion. Defaults to true. See note for more details. No
javasvn If set, instructs the use of JavaSvn bindings, if available. Set to false to use command line client interface to subversion. Defaults to true. See note for more details. No

Nested Types

No nested types defined for this type.

Description

This file selector is used to discriminate files within a fileset based on a Subversion status. In particular, this selector keeps files that are recognized as 'modified'.

A 'modified' file or directory is one that has been changed since the last update and where the changes have not yet been commited to the repository. In general, svn status display those items with the letter M preceeding the name. It is important to note that other items can also be considered modified, such as conflicted ones.

Example: to copy a number of files with the status 'modified' from their location in workingcopy to a new directory called test, the following ant task can be used:


<copy todir="test">
	<fileset dir="workingcopy">
		<svnModified/>
	</fileset>
</copy>
					
				

svnUnversioned

File selector that performs discrimination based on the 'unversioned' subversion status.

Implementation: org.tigris.subclipse.svnant.selectors.Unversioned

Parameters

Attribute Description Required
javahl If set, instructs the use of JavaHL bindings, if available. Set to false to use command line client interface to subversion. Defaults to true. See note for more details. No
javasvn If set, instructs the use of JavaSvn bindings, if available. Set to false to use command line client interface to subversion. Defaults to true. See note for more details. No

Nested Types

No nested types defined for this type.

Description

This file selector is used to discriminate files within a fileset based on a Subversion status. In particular, this selector keeps files that are recognized as 'unversioned'.

An 'unversioned' file or directory is one that is present in a working copy but is not yet known to the repository. In general, svn status display those items with a question mark (?) preceeding the name. Note that 'ignored' items are not considered 'unversioned'.

Eexample: to copy a number of files with the status 'unversioned' from their location in workingcopy to a new directory called test, the following ant task can be used:


<copy todir="test">
	<fileset dir="workingcopy">
		<svnUnversioned/>
	</fileset>
</copy>
		
				

svnConflicted

File selector that performs discrimination based on the 'conflicted' subversion status.

Implementation: org.tigris.subclipse.svnant.selectors.Conflicted

Parameters

Attribute Description Required
javahl If set, instructs the use of JavaHL bindings, if available. Set to false to use command line client interface to subversion. Defaults to true. See note for more details. No
javasvn If set, instructs the use of JavaSvn bindings, if available. Set to false to use command line client interface to subversion. Defaults to true. See note for more details. No

Nested Types

No nested types defined for this type.

Description

This file selector is used to discriminate files within a fileset based on a Subversion status. In particular, this selector keeps files that are recognized as 'conflicted'.

When updating a subversion item (file or directory), it is possible to have two sets of changes merged into the working item. This happens when the item was modified locally as well as remotely during the period since the last update. If the two sets of changes conflict (same lines of a file changes, same directory entries modified), then the item is marked as 'conflicted'. In general, svn status displays 'conflicted' items with the letter C preceeding the name. Note that 'conflicted' items are also considered 'modified'.

Example: to copy a number of files with the status 'conflicted' from their location in workingcopy to a new directory called test, the following ant task can be used:


<copy todir="test">
	<fileset dir="workingcopy">
		<svnConflicted/>
	</fileset>
</copy>
		
				

svnIgnored

File selector that performs discrimination based on the 'ignored' subversion status.

Implementation: org.tigris.subclipse.svnant.selectors.Ignored

Parameters

Attribute Description Required
javahl If set, instructs the use of JavaHL bindings, if available. Set to false to use command line client interface to subversion. Defaults to true. See note for more details. No
javasvn If set, instructs the use of JavaSvn bindings, if available. Set to false to use command line client interface to subversion. Defaults to true. See note for more details. No

Nested Types

No nested types defined for this type.

Description

This file selector is used to discriminate files within a fileset based on a Subversion status. In particular, this selector keeps files that are recognized as 'ignored'.

An 'ignored' file or directory is one which name match the patterns found in the parent directory's svn:ignore property. In general, svn status --no-ignore display those items with the letter I preceeding the name.

Example: to copy a number of files with the status 'ignored' from their location in workingcopy to a new directory called test, the following ant task can be used:


<copy todir="test">
	<fileset dir="workingcopy">
		<svnIgnored/>
	</fileset>
</copy>
		
				

svnLocked

File selector that performs discrimination based on the 'locked' subversion status.

Implementation: org.tigris.subclipse.svnant.selectors.Locked

Parameters

Attribute Description Required
javahl If set, instructs the use of JavaHL bindings, if available. Set to false to use command line client interface to subversion. Defaults to true. See note for more details. No
javasvn If set, instructs the use of JavaSvn bindings, if available. Set to false to use command line client interface to subversion. Defaults to true. See note for more details. No

Nested Types

No nested types defined for this type.

Description

This file selector is used to discriminate files within a fileset based on a Subversion status. In particular, this selector keeps files that are recognized as 'locked'.

A 'locked' file or directory is one where the repository has been informed of the intent of a user to prevent others from modifying the file. For a working copy to be aware of this fact, it must have been 'updated' since the lock status was changed. In general, svn status displays those items with one of the letters K, O or B in the sixth column. The 'lock' status is independent of most other conditions such as 'modified', 'conflicted', etc.

Example: to copy a number of files with the status 'locked' from their location in workingcopy to a new directory called test, the following ant task can be used:


<copy todir="test">
	<fileset dir="workingcopy">
		<svnLocked/>
	</fileset>
</copy>
		
				

svnNormal

File selector that performs discrimination based on the 'normal' subversion status.

Implementation: org.tigris.subclipse.svnant.selectors.Normal

Parameters

Attribute Description Required
javahl If set, instructs the use of JavaHL bindings, if available. Set to false to use command line client interface to subversion. Defaults to true. See note for more details. No
javasvn If set, instructs the use of JavaSvn bindings, if available. Set to false to use command line client interface to subversion. Defaults to true. See note for more details. No

Nested Types

No nested types defined for this type.

Description

This file selector is used to discriminate files within a fileset based on a Subversion status. In particular, this selector keeps files that are recognized as 'normal'.

A 'normal' file or directory is one that has not undergone any changes since the last update. In general, this is the great majority of the files in a working copy. svn status returns no special character for those items (a space in the first column).

Example: to copy a number of files with the status 'normal' from their location in workingcopy to a new directory called test, the following ant task can be used:


<copy todir="test">
	<fileset dir="workingcopy">
		<svnNormal/>
	</fileset>
</copy>
		
				

svnReplaced

File selector that performs discrimination based on the 'replaced' subversion status.

Implementation: org.tigris.subclipse.svnant.selectors.Replaced

Parameters

Attribute Description Required
javahl If set, instructs the use of JavaHL bindings, if available. Set to false to use command line client interface to subversion. Defaults to true. See note for more details. No
javasvn If set, instructs the use of JavaSvn bindings, if available. Set to false to use command line client interface to subversion. Defaults to true. See note for more details. No

Nested Types

No nested types defined for this type.

Description

This file selector is used to discriminate files within a fileset based on a Subversion status. In particular, this selector keeps files that are recognized as 'replaced'.

A 'replaced' file or directory is one that has been deleted, then created anew and finally added back to the repository. Also, those changes must not have been comitted. In general, svn status displays those items with the letter R preceeding the name.

Example: to copy a number of files with the status 'replaced' from their location in workingcopy to a new directory called test, the following ant task can be used:


<copy todir="test">
	<fileset dir="workingcopy">
		<svnReplaced/>
	</fileset>
</copy>
		
				

svnMissing

File selector that performs discrimination based on the 'missing' subversion status.

Implementation: org.tigris.subclipse.svnant.selectors.Missing

Parameters

Attribute Description Required
javahl If set, instructs the use of JavaHL bindings, if available. Set to false to use command line client interface to subversion. Defaults to true. See note for more details. No
javasvn If set, instructs the use of JavaSvn bindings, if available. Set to false to use command line client interface to subversion. Defaults to true. See note for more details. No

Nested Types

No nested types defined for this type.

Description

This file selector is used to discriminate files within a fileset based on a Subversion status. In particular, this selector keeps files that are recognized as 'missing'.

A 'missing' file or directory is one that is managed by Subversion and has been deleted without using the remove command. In general, svn status displays those items with the exclamation point (!) preceeding the name.

It is important to note that a regular FileSet (the one supplied by ANT) can not detect a missing item, since it does not exist on the file system. To detect Subversion missing items, use the FileSet provided by svn-ant (svnFileSet).

Example: to delete missing files from the repository associated with a workingcopy:


<svn>
	<delete>
		<svnFileSet dir="workingcopy">
			<svnMissing/>
		</svnFileSet>
	</delete>
</svn>
		
				

svnDeleted

File selector that performs discrimination based on the 'deleted' subversion status.

Implementation: org.tigris.subclipse.svnant.selectors.Deleted

Parameters

Attribute Description Required
javahl If set, instructs the use of JavaHL bindings, if available. Set to false to use command line client interface to subversion. Defaults to true. See note for more details. No
javasvn If set, instructs the use of JavaSvn bindings, if available. Set to false to use command line client interface to subversion. Defaults to true. See note for more details. No

Nested Types

No nested types defined for this type.

Description

This file selector is used to discriminate files within a fileset based on a Subversion status. In particular, this selector keeps files that are recognized as 'deleted'.

A 'deleted' file or directory is one that has been erased using Subversion's 'remove' command. In general, svn status displays those items with the letter D preceeding the name.

It is important to note that a regular FileSet (the one supplied by ANT) can not detect a deleted item, since it does not exist on the file system. To detect Subversion deleted items, use the FileSet provided by svn-ant (svnFileSet).

Example: to revert deleted files from a workingcopy:


<svn>
	<revert>
		<svnFileSet dir="workingcopy">
			<svnDeleted/>
		</svnFileSet>
	</revert>
</svn>
		
				

Svn Types

Svn Types

Table of Content

svnFileSet FileSet replacement that operates on list of files obtained from Subversion.

Introduction

This document describes the type extensions that svn-ant brings to Ant. To use those types, you must first obtain a copy of svnant.jar, add it to the classpath of your ant project and define the types. Fortunately, there is a resource file, within the distributed JAR file, and all those steps can be accomplished with the following code:

				
<path id="svnant.classpath">
  <pathelement location="${svnant.dir}/lib/svnant.jar" />
  <pathelement location="${svnant.dir}/lib/svnClientAdapter.jar" />
</path>  

<typedef resource="svntypes.xml" classpathref="project.classpath"/>
				
			

If you are upgrading from an earlier version of svnAnt, and the following line was used in your build.xml file, then replace it with the ones above.

				
<taskdef resource="svntask.properties" classpathref="svnant.classpath"/>
				
			

Bindings

All types offer two parameters: javahl and javasvn. Those parameters are booleans, which means their values can be set to either true or false. If not specified, those parameters are assumed to be set (true). These two parameters are used to select which client is used to access Subversion.

There are three clients used by svnAnt to access Subversion:

  • JavaHL;
  • JavaSVN; and,
  • Command Line Interface.
To better understand the difference between those three clients, please refer to documentation on svnClientAdapter.jar.

The property javahl is considered only if the javahl libraries are available. Similarly, the property javasvn is considered only if JavaSVN is present. Finally, javahl takes precedence over javasvn.

To better illustrate the previous paragraph, use the following steps:

  1. If javahl is true and JavaHL bindings are available, then JavaHL is used.
  2. If javasvn is true and JavaSVN is present, then JavaSVN is used.
  3. If the two previous tests failed, for any reason, then the Command Line Interface is used.

svnFileSet

FileSet replacement that operates on list of files obtained from Subversion.

Implementation: org.tigris.subclipse.svnant.SvnFileSet

Parameters

Attribute Description Required
dir Specifies the root directory used by the file set. It should specify a directory managed by Subversion. Either dir or file must be specified
file If used, specifies a fileset that contains a single file. Either dir or file must be specified
includes Comma-seperated or space-separated list of patterns, which describe files that are included. If this attribute if not specified, then all files are included. No
excludes Comma-seperated or space-separated list of patterns, which describe files that are excluded. If this attribute if not specified, then no files are excluded. No
javahl If set, instructs the use of JavaHL bindings, if available. Set to false to use command line client interface to subversion. Defaults to true. See note for more details. No
javasvn If set, instructs the use of JavaSvn bindings, if available. Set to false to use command line client interface to subversion. Defaults to true. See note for more details. No

Nested Types

exclude

The type svnFileSet can include the nested type 'exclude', similar to a classic FileSet.

include

The type svnFileSet can include the nested type 'include', similar to a classic FileSet.

patternSet

The type svnFileSet can include the nested type 'patternSet', similar to a classic FileSet.

selector

The type svnFileSet can include the any file selector, such as contains, date size, or any file selector defined by svn-ant

Description

This type implements a FileSet. Instances of FileSet are used in tasks that operates on a number of files. The files selected by a FileSet can be tailored by a number of patterns and selectors. More information about file sets is available with the Ant documentation.

The motivation with creating a replacement FileSet that is based on Subversion was to have the ability of creating sets of files that include deleted and missing files. In fact, the classic fileset operates only on files that are reported by the file system and can not predict deleted and missing files. Furthermore, there are useful commands that can be performed on deleted and missing files, such as 'revert', 'delete', 'update' and others.

At the present time, svnFileSet is experimental. It supports selectors but it does not yet accept any patterns (include, exclude). Those enhancments are to come later.

svnFileSet can be used within any svn-ant task that supports a nested file sets. It can also be used in any task that is based on a file set. If you have a problem using svnFileSet within a task that works well with the classic fileset, then report the problem to the author of the task. However, for the time being, there is a work around your problem. Instead of using a svnFileSet directly in the targeted task, use it indirectly via a classic fileset and a reference. For example, if ANT complains about a task similar to the following:


<target name="example">
	<mkdir dir="test"/>
	<copy todir="test">
		<svnFileSet dir="workingcopy">
			<svnAdded/>
		</svnFileSet>
	</copy>
</target>
					
				
you can rewrite it, using a reference, as:

<target name="example">
	<svnFileSet id="svnFileSetId_1" dir="workingcopy">
		<svnAdded/>
	</svnFileSet>
	<mkdir dir="test"/>
	<copy todir="test">
		<fileset refid="svnFileSetId_1"/>
	</copy>
</target>
					
				

If you are the author of a fileset-based task and that you can not understand why your task does not accept svnFileSet while it works perfectly well with the classic fileset, here is a thing you can check. If your task accepts instances of FileSet with a method similar to:


public void addFileset(FileSet set) {
	...
}
					
				
then adding the following method should fix the problem:

public void add(FileSet set) {
	addFileSet(set);
}
					
				

Examples

The following ant script can be used to remove all missing files from the associated repository:


<svn>
	<delete>
		<svnFileSet dir="workingcopy">
			<svnMissing/>
		</svnFileSet>
	</delete>
	<commit 
		dir="workingcopy" 
		message="automatically removing missing files"/>
</svn>
					
				

The following ant script can be used to add all new files to the associated repository:


<svn>
	<add>
		<svnFileSet dir="workingcopy">
			<svnUnversioned/>
		</svnFileSet>
	</add>
	<commit
		dir="workingcopy" 
		message="automatically adding files"/>
</svn>
					
				

The following ant script can be used to restore all deleted files:


<svn>
	<revert>
		<svnFileSet dir="workingcopy">
			<svnDeleted/>
		</svnFileSet>
	</revert>
</svn>
					
				

If, in the previous example, you wanted svn-ant to use the command line adapter:


<svn javahl="false" javasvn="false">
	<revert>
		<svnFileSet 
			dir="workingcopy" 
			javahl="false" 
			javasvn="false">
			<svnDeleted 
				javahl="false" 
				javasvn="false"/>
		</svnFileSet>
	</revert>
</svn>
					
				

Received on Fri Nov 11 07:03:54 2005

This is an archived mail posted to the Subclipse Dev mailing list.

This site is subject to the Apache Privacy Policy and the Apache Public Forum Archive Policy.