Browse Source

cleanup

git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@278205 13f79535-47bb-0310-9956-ffa450edef68
master
Stefan Bodewig 20 years ago
parent
commit
5d6618cee3
63 changed files with 3 additions and 7624 deletions
  1. +1
    -0
      proposal/sandbox/antunit/README
  2. +0
    -93
      proposal/sandbox/antunit/build.xml
  3. +0
    -143
      proposal/sandbox/antunit/src/etc/testcases/assert.xml
  4. +0
    -70
      proposal/sandbox/antunit/src/main/org/apache/ant/antlib/antunit/AssertTask.java
  5. +0
    -32
      proposal/sandbox/antunit/src/main/org/apache/ant/antlib/antunit/AssertionFailedException.java
  6. +0
    -117
      proposal/sandbox/antunit/src/main/org/apache/ant/antlib/antunit/antlib.xml
  7. +0
    -138
      proposal/sandbox/antunit/src/testcases/org/apache/ant/antlib/antunit/AssertTest.java
  8. +1
    -38
      proposal/sandbox/dotnet/README
  9. +0
    -91
      proposal/sandbox/dotnet/build.xml
  10. +0
    -32
      proposal/sandbox/dotnet/docs/dotnetexec.html
  11. +0
    -142
      proposal/sandbox/dotnet/docs/index.html
  12. +0
    -109
      proposal/sandbox/dotnet/docs/msbuild.html
  13. +0
    -108
      proposal/sandbox/dotnet/docs/nant.html
  14. +0
    -177
      proposal/sandbox/dotnet/docs/nunit.html
  15. +0
    -177
      proposal/sandbox/dotnet/docs/wix.html
  16. +0
    -89
      proposal/sandbox/dotnet/src/etc/testcases/dotnetexec.xml
  17. +0
    -73
      proposal/sandbox/dotnet/src/etc/testcases/msbuild.xml
  18. +0
    -72
      proposal/sandbox/dotnet/src/etc/testcases/nant.xml
  19. +0
    -81
      proposal/sandbox/dotnet/src/etc/testcases/nunit.xml
  20. +0
    -25
      proposal/sandbox/dotnet/src/etc/testcases/src/example.cs
  21. +0
    -31
      proposal/sandbox/dotnet/src/etc/testcases/src/example2.cs
  22. +0
    -30
      proposal/sandbox/dotnet/src/etc/testcases/src/fail.cs
  23. +0
    -24
      proposal/sandbox/dotnet/src/etc/testcases/src/msbuild.proj
  24. +0
    -24
      proposal/sandbox/dotnet/src/etc/testcases/src/nant.build
  25. +0
    -30
      proposal/sandbox/dotnet/src/etc/testcases/src/pass.cs
  26. +0
    -259
      proposal/sandbox/dotnet/src/main/org/apache/tools/ant/taskdefs/optional/dotnet/AbstractBuildTask.java
  27. +0
    -150
      proposal/sandbox/dotnet/src/main/org/apache/tools/ant/taskdefs/optional/dotnet/DotNetExecTask.java
  28. +0
    -120
      proposal/sandbox/dotnet/src/main/org/apache/tools/ant/taskdefs/optional/dotnet/MSBuildTask.java
  29. +0
    -94
      proposal/sandbox/dotnet/src/main/org/apache/tools/ant/taskdefs/optional/dotnet/NAntTask.java
  30. +0
    -335
      proposal/sandbox/dotnet/src/main/org/apache/tools/ant/taskdefs/optional/dotnet/NUnitTask.java
  31. +0
    -296
      proposal/sandbox/dotnet/src/main/org/apache/tools/ant/taskdefs/optional/dotnet/WixTask.java
  32. +0
    -38
      proposal/sandbox/dotnet/src/main/org/apache/tools/ant/taskdefs/optional/dotnet/antlib.xml
  33. +0
    -65
      proposal/sandbox/dotnet/src/testcases/org/apache/tools/ant/taskdefs/optional/dotnet/DotNetExecTaskTest.java
  34. +0
    -64
      proposal/sandbox/dotnet/src/testcases/org/apache/tools/ant/taskdefs/optional/dotnet/MSBuildTaskTest.java
  35. +0
    -64
      proposal/sandbox/dotnet/src/testcases/org/apache/tools/ant/taskdefs/optional/dotnet/NAntTaskTest.java
  36. +0
    -79
      proposal/sandbox/dotnet/src/testcases/org/apache/tools/ant/taskdefs/optional/dotnet/NUnitTaskTest.java
  37. +1
    -20
      proposal/sandbox/svn/README
  38. +0
    -91
      proposal/sandbox/svn/build.xml
  39. +0
    -217
      proposal/sandbox/svn/docs/changelog.html
  40. +0
    -129
      proposal/sandbox/svn/docs/revisiondiff.html
  41. +0
    -157
      proposal/sandbox/svn/docs/svn.html
  42. +0
    -158
      proposal/sandbox/svn/docs/tagdiff.html
  43. +0
    -137
      proposal/sandbox/svn/src/etc/changelog.xsl
  44. +0
    -140
      proposal/sandbox/svn/src/etc/diff.xsl
  45. +0
    -64
      proposal/sandbox/svn/src/etc/testcases/abstractsvntask.xml
  46. +0
    -69
      proposal/sandbox/svn/src/etc/testcases/changelog.xml
  47. +0
    -58
      proposal/sandbox/svn/src/etc/testcases/revisiondiff.xml
  48. +0
    -63
      proposal/sandbox/svn/src/etc/testcases/tagdiff.xml
  49. +0
    -699
      proposal/sandbox/svn/src/main/org/apache/tools/ant/taskdefs/svn/AbstractSvnTask.java
  50. +0
    -134
      proposal/sandbox/svn/src/main/org/apache/tools/ant/taskdefs/svn/LineOrientedOutputStream.java
  51. +0
    -32
      proposal/sandbox/svn/src/main/org/apache/tools/ant/taskdefs/svn/Svn.java
  52. +0
    -188
      proposal/sandbox/svn/src/main/org/apache/tools/ant/taskdefs/svn/SvnChangeLogParser.java
  53. +0
    -399
      proposal/sandbox/svn/src/main/org/apache/tools/ant/taskdefs/svn/SvnChangeLogTask.java
  54. +0
    -96
      proposal/sandbox/svn/src/main/org/apache/tools/ant/taskdefs/svn/SvnChangeLogWriter.java
  55. +0
    -207
      proposal/sandbox/svn/src/main/org/apache/tools/ant/taskdefs/svn/SvnDiffHandler.java
  56. +0
    -171
      proposal/sandbox/svn/src/main/org/apache/tools/ant/taskdefs/svn/SvnEntry.java
  57. +0
    -162
      proposal/sandbox/svn/src/main/org/apache/tools/ant/taskdefs/svn/SvnRevisionDiff.java
  58. +0
    -210
      proposal/sandbox/svn/src/main/org/apache/tools/ant/taskdefs/svn/SvnTagDiff.java
  59. +0
    -34
      proposal/sandbox/svn/src/main/org/apache/tools/ant/taskdefs/svn/antlib.xml
  60. +0
    -53
      proposal/sandbox/svn/src/testcases/org/apache/tools/ant/taskdefs/svn/AbstractSvnTaskTest.java
  61. +0
    -146
      proposal/sandbox/svn/src/testcases/org/apache/tools/ant/taskdefs/svn/SvnChangeLogTaskTest.java
  62. +0
    -136
      proposal/sandbox/svn/src/testcases/org/apache/tools/ant/taskdefs/svn/SvnRevisionDiffTest.java
  63. +0
    -144
      proposal/sandbox/svn/src/testcases/org/apache/tools/ant/taskdefs/svn/SvnTagDiffTest.java

+ 1
- 0
proposal/sandbox/antunit/README View File

@@ -0,0 +1 @@
Moved to http://svn.apache.org/repos/asf/ant/sandbox/antlibs/antunit/trunk/

+ 0
- 93
proposal/sandbox/antunit/build.xml View File

@@ -1,93 +0,0 @@
<?xml version="1.0"?>
<!--
Copyright 2005 The Apache Software Foundation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<project default="compile">

<target name="setup">
<property name="build" value="build"/>
<property name="build.classes" value="${build}/classes"/>
<property name="build.testclasses" value="${build}/test-classes"/>
<property name="build.lib" value="${build}/lib"/>
<property name="jarname" value="${build.lib}/ant-antunit.jar"/>
<mkdir dir="${build.classes}"/>
<mkdir dir="${build.testclasses}"/>
<mkdir dir="${build.lib}"/>
</target>

<target name="compile" depends="setup">
<javac
srcdir="src/main"
destdir="${build.classes}"
debug="true"
/>
</target>

<target name="antlib" depends="compile">
<copy todir="${build.classes}">
<fileset dir="src/main" includes="**/antlib.xml"/>
</copy>
<jar
destfile="${jarname}"
basedir="${build.classes}"
/>
</target>

<target name="setup-for-tests" depends="setup">
<ant
antfile="../../../build.xml"
target="test-jar"
inheritall="false"
/>
</target>

<target name="compile-tests" depends="setup-for-tests, antlib">
<javac
srcdir="src/testcases"
destdir="${build.testclasses}"
debug="true"
>
<classpath>
<pathelement location="${jarname}"/>
<pathelement location="../../../build/lib/ant-testutil.jar"/>
</classpath>
</javac>
</target>

<target name="test" depends="compile-tests">
<junit
printsummary="false"
haltonfailure="false"
failureproperty="tests.failed"
filtertrace="false"
fork="true"
forkmode="once"
>
<classpath>
<pathelement location="${jarname}"/>
<pathelement location="../../../build/lib/ant-testutil.jar"/>
<pathelement location="${build.testclasses}"/>
</classpath>

<batchtest>
<fileset dir="src/testcases"/>
</batchtest>

<formatter type="plain" usefile="false"/>
</junit>

<fail if="tests.failed">At least one test has failed.</fail>
</target>
</project>

+ 0
- 143
proposal/sandbox/antunit/src/etc/testcases/assert.xml View File

@@ -1,143 +0,0 @@
<?xml version="1.0"?>

<!--
Copyright 2005 The Apache Software Foundation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->

<project name="assert-test"
default="all" xmlns:au="antlib:org.apache.ant.antlib.antunit">

<target name="all">
<fail>Only run via JUnit</fail>
</target>

<target name="assertTruePass">
<au:assertTrue>
<istrue value="true"/>
</au:assertTrue>
</target>

<target name="assertTrueFail">
<au:assertTrue>
<istrue value="false"/>
</au:assertTrue>
</target>

<target name="assertFalsePass">
<au:assertFalse>
<isfalse value="true"/>
</au:assertFalse>
</target>

<target name="assertFalseFail">
<au:assertFalse>
<isfalse value="false"/>
</au:assertFalse>
</target>

<target name="assertEqualsPass">
<au:assertEquals expected="bar" actual="bar"/>
</target>

<target name="assertEqualsCasePass">
<au:assertEquals expected="bar" actual="BAR" casesensitive="false"/>
</target>

<target name="assertEqualsFail1">
<au:assertEquals expected="bar" actual="baz"/>
</target>

<target name="assertEqualsFail2">
<au:assertEquals expected="bar" actual="BAR"/>
</target>

<target name="assertPropertySetPass">
<property name="foo" value="bar"/>
<au:assertPropertySet name="foo"/>
</target>

<target name="assertPropertySetFail">
<au:assertPropertySet name="foo"/>
</target>

<target name="assertPropertyEqualsPass">
<property name="foo" value="bar"/>
<au:assertPropertyEquals name="foo" value="bar"/>
</target>

<target name="assertPropertyEqualsCasePass">
<property name="foo" value="bar"/>
<au:assertPropertyEquals name="foo" value="BAR" casesensitive="false"/>
</target>

<target name="assertPropertyEqualsFail1">
<au:assertPropertyEquals name="foo" value="bar"/>
</target>

<target name="assertPropertyEqualsFail2">
<property name="foo" value="bar"/>
<au:assertPropertyEquals name="foo" value="baz"/>
</target>

<target name="assertPropertyEqualsFail3">
<property name="foo" value="bar"/>
<au:assertPropertyEquals name="foo" value="BAR"/>
</target>

<target name="assertFileExistsPass">
<au:assertFileExists file="assert.xml"/>
</target>

<target name="assertFileExistsFail">
<au:assertFileExists file="assert.txt"/>
</target>

<target name="assertFileDoesntExistPass">
<au:assertFileDoesntExist file="assert.txt"/>
</target>

<target name="assertFileDoesntExistFail">
<au:assertFileDoesntExist file="assert.xml"/>
</target>

<target name="assertDestIsUptodatePass">
<au:assertDestIsUptodate
src="../../main/org/apache/ant/antlib/antunit/AssertTask.java"

dest="../../../build/classes/org/apache/ant/antlib/antunit/AssertTask.class"/>
</target>

<target name="assertDestIsUptodateFail">
<au:assertDestIsUptodate
dest="../../main/org/apache/ant/antlib/antunit/AssertTask.java"

src="../../../build/classes/org/apache/ant/antlib/antunit/AssertTask.class"/>
</target>

<target name="assertDestIsOutofdatePass">
<au:assertDestIsOutofdate
dest="../../main/org/apache/ant/antlib/antunit/AssertTask.java"

src="../../../build/classes/org/apache/ant/antlib/antunit/AssertTask.class"/>
</target>

<target name="assertDestIsOutofdateFail">
<au:assertDestIsOutofdate
src="../../main/org/apache/ant/antlib/antunit/AssertTask.java"

dest="../../../build/classes/org/apache/ant/antlib/antunit/AssertTask.class"/>
</target>

</project>

+ 0
- 70
proposal/sandbox/antunit/src/main/org/apache/ant/antlib/antunit/AssertTask.java View File

@@ -1,70 +0,0 @@
/*
* Copyright 2005 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

package org.apache.ant.antlib.antunit;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.taskdefs.condition.Condition;
import org.apache.tools.ant.taskdefs.condition.ConditionBase;

/**
* Exits the active build, giving an additional message if the single
* nested condition fails.
*
* <p>This one could as well be implemented as
*
* <pre>
* &lt;macrodef name="assertTrue"&gt;
* &lt;attribute name="message" default="Assertion failed"/&gt;
* &lt;element name="assertion" implicit="true"/&gt;
* &lt;sequential&gt;
* &lt;fail message="@{message}"&gt;
* &lt;condition&gt;
* &lt;assertion/&gt;
* &lt;/condition&gt;
* &lt;/fail&gt;
* &lt;/sequential&gt;
* &lt;/macrodef&gt;
* </pre>
*
* but wouldn't be able to throw a specialized exception that way -
* and the macrodef would nest the exception in yet another
* BuildException.</p>
*/
public class AssertTask extends ConditionBase {

private String message = AssertionFailedException.DEFAULT_MESSAGE;

public void setMessage(String value) {
this.message = value;
}

public void execute() throws BuildException {
int count = countConditions();
if (count > 1) {
throw new BuildException("You must not specify more tha one "
+ "conditions");
}
if (count < 1) {
throw new BuildException("You must specify a condition");
}
if (!((Condition) getConditions().nextElement()).eval()) {
throw new AssertionFailedException(message);
}
}

}

+ 0
- 32
proposal/sandbox/antunit/src/main/org/apache/ant/antlib/antunit/AssertionFailedException.java View File

@@ -1,32 +0,0 @@
/*
* Copyright 2005 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

package org.apache.ant.antlib.antunit;

import org.apache.tools.ant.BuildException;

/**
* Specialized BuildException thrown by the AssertTask task.
*/
public class AssertionFailedException extends BuildException {

public static final String DEFAULT_MESSAGE = "Assertion failed";

public AssertionFailedException(String message) {
super(message);
}
}

+ 0
- 117
proposal/sandbox/antunit/src/main/org/apache/ant/antlib/antunit/antlib.xml View File

@@ -1,117 +0,0 @@
<?xml version="1.0"?>
<!--
Copyright 2005 The Apache Software Foundation

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<antlib xmlns:au="antlib:org.apache.ant.antlib.antunit">
<taskdef name="assertTrue"
classname="org.apache.ant.antlib.antunit.AssertTask"/>

<macrodef name="assertFalse">
<attribute name="message" default="Assertion failed"/>
<element name="assertion" implicit="true"/>
<sequential>
<au:assertTrue message="@{message}">
<not>
<assertion/>
</not>
</au:assertTrue>
</sequential>
</macrodef>

<macrodef name="assertEquals">
<attribute name="expected"/>
<attribute name="actual"/>
<attribute name="casesensitive" default="true"/>
<attribute name="message"
default="Expected '@{expected}' but was '@{actual}'"/>
<sequential>
<au:assertTrue message="@{message}">
<equals arg1="@{expected}" arg2="@{actual}"
casesensitive="@{casesensitive}"/>
</au:assertTrue>
</sequential>
</macrodef>

<macrodef name="assertPropertySet">
<attribute name="name"/>
<attribute name="message"
default="Expected property '@{name}'"/>
<sequential>
<au:assertTrue message="@{message}">
<isset property="@{name}"/>
</au:assertTrue>
</sequential>
</macrodef>

<macrodef name="assertPropertyEquals">
<attribute name="name"/>
<attribute name="value"/>
<attribute name="casesensitive" default="true"/>
<attribute name="message"
default="Expected property '@{name}' to have value '@{value}' but was '${@{name}}'"/>
<sequential>
<au:assertPropertySet message="@{message}" name="@{name}"/>
<au:assertEquals message="@{message}" expected="@{value}"
actual="${@{name}}" casesensitive="@{casesensitive}"/>
</sequential>
</macrodef>

<macrodef name="assertFileExists">
<attribute name="file"/>
<attribute name="message"
default="Expected file '@{file}' to exist"/>
<sequential>
<au:assertTrue message="@{message}">
<available file="@{file}"/>
</au:assertTrue>
</sequential>
</macrodef>

<macrodef name="assertFileDoesntExist">
<attribute name="file"/>
<attribute name="message"
default="Didn't expect file '@{file}' to exist"/>
<sequential>
<au:assertFalse message="@{message}">
<available file="@{file}"/>
</au:assertFalse>
</sequential>
</macrodef>

<macrodef name="assertDestIsUptodate">
<attribute name="src"/>
<attribute name="dest"/>
<attribute name="message"
default="Expected '@{dest}' to be more recent than '@{src}'"/>
<sequential>
<au:assertTrue message="@{message}">
<uptodate srcfile="@{src}" targetfile="@{dest}"/>
</au:assertTrue>
</sequential>
</macrodef>

<macrodef name="assertDestIsOutofdate">
<attribute name="src"/>
<attribute name="dest"/>
<attribute name="message"
default="Expected '@{src}' to be more recent than '@{dest}'"/>
<sequential>
<au:assertFalse message="@{message}">
<uptodate srcfile="@{src}" targetfile="@{dest}"/>
</au:assertFalse>
</sequential>
</macrodef>

</antlib>

+ 0
- 138
proposal/sandbox/antunit/src/testcases/org/apache/ant/antlib/antunit/AssertTest.java View File

@@ -1,138 +0,0 @@
/*
* Copyright 2005 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.ant.antlib.antunit;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.BuildFileTest;

public class AssertTest extends BuildFileTest {

public AssertTest(String name) {
super(name);
}

public void setUp() {
configureProject("src/etc/testcases/assert.xml");
}

public void testTruePass() {
testPass("assertTruePass");
}
public void testFalsePass() {
testPass("assertFalsePass");
}
public void testEqualsPass() {
testPass("assertEqualsPass");
}
public void testEqualsCasePass() {
testPass("assertEqualsCasePass");
}
public void testPropertySetPass() {
testPass("assertPropertySetPass");
}
public void testPropertyEqualsPass() {
testPass("assertPropertyEqualsPass");
}
public void testPropertyEqualsCasePass() {
testPass("assertPropertyEqualsCasePass");
}
public void testFileExistsPass() {
testPass("assertFileExistsPass");
}
public void testFileDoesntExistPass() {
testPass("assertFileDoesntExistPass");
}
public void testDestIsUptodatePass() {
testPass("assertDestIsUptodatePass");
}
public void testDestIsOutofdatePass() {
testPass("assertDestIsOutofdatePass");
}

public void testTrueFail() {
testFail("assertTrueFail");
}
public void testFalseFail() {
testFail("assertFalseFail");
}
public void testEqualsFail1() {
testFail("assertEqualsFail1", "Expected 'bar' but was 'baz'");
}
public void testEqualsFail2() {
testFail("assertEqualsFail2", "Expected 'bar' but was 'BAR'");
}
public void testPropertySetFail() {
testFail("assertPropertySetFail", "Expected property 'foo'");
}
public void testPropertyEqualsFail1() {
testFail("assertPropertyEqualsFail1", "Expected property 'foo' to have value 'bar' but was '${foo}'");
}
public void testPropertyEqualsFail2() {
testFail("assertPropertyEqualsFail2", "Expected property 'foo' to have value 'baz' but was 'bar'");
}
public void testPropertyEqualsFail3() {
testFail("assertPropertyEqualsFail3", "Expected property 'foo' to have value 'BAR' but was 'bar'");
}
public void testFileExistsFail() {
testFail("assertFileExistsFail",
"Expected file 'assert.txt' to exist");
}
public void testFileDoesntExistFail() {
testFail("assertFileDoesntExistFail",
"Didn't expect file 'assert.xml' to exist");
}
public void testDestIsUptodateFail() {
testFail("assertDestIsUptodateFail",
"Expected '../../main/org/apache/ant/antlib/antunit/AssertTask.java' to be more recent than '../../../build/classes/org/apache/ant/antlib/antunit/AssertTask.class'");
}
public void testDestIsOutofdateFail() {
testFail("assertDestIsOutofdateFail",
"Expected '../../main/org/apache/ant/antlib/antunit/AssertTask.java' to be more recent than '../../../build/classes/org/apache/ant/antlib/antunit/AssertTask.class'");
}


private void testPass(String target) {
executeTarget(target);
}

private void testFail(String target) {
testFail(target, "Assertion failed");
}

private void testFail(String target, String message) {
try {
executeTarget(target);
fail("Expected failed assetion");
} catch (AssertionFailedException e) {
assertEquals(message, e.getMessage());
} catch (BuildException e) {
// depending on the number of macrodef indirections, this
// can become arbitrarily deep
while (true) {
Throwable t = e.getCause();
assertNotNull(t);
assertTrue("nested is a BuildException",
t instanceof BuildException);
if (t instanceof AssertionFailedException) {
assertEquals(message, e.getMessage());
break;
}
e = (BuildException) t;
}
} // end of try-catch
}
}

+ 1
- 38
proposal/sandbox/dotnet/README View File

@@ -1,38 +1 @@
dotnet sandbox README
=====================

Author:
-------

Stefan Bodewig, but feel free to go ahead and modify to your liking.

Goal:
-----

Provide a simple infrastructure to execute .NET applications from
within Ant for different VMs so that the user doesn't have to change
the build file when she wants to run Mono on Linux and Microsoft's VM
on Windows.

This sounds far more ambitioned than it actually is.

Short term goals are:

* A <dotnetexec> task that can be used as

<dotnetexec executable="ExampleCsc.exe"/>

without testing for the environment (see the dotnet.xml build file
for Ant's tests as an example for what may become simpler with
this).

* A <nant> task.

* A <msbuild> task - if only for the fun of having it.

* A <wix> task.

* A <nunit> task.

Those tasks should end up in an antlib of their own in order to be
distributable independent of Ant.
Moved to http://svn.apache.org/repos/asf/ant/sandbox/antlibs/dotnet/trunk/

+ 0
- 91
proposal/sandbox/dotnet/build.xml View File

@@ -1,91 +0,0 @@
<?xml version="1.0"?>
<!--
Copyright 2003-2004 The Apache Software Foundation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<project default="compile">

<target name="setup">
<property name="build" value="build"/>
<property name="build.classes" value="${build}/classes"/>
<property name="build.testclasses" value="${build}/test-classes"/>
<property name="build.lib" value="${build}/lib"/>
<property name="jarname" value="${build.lib}/dotnet.jar"/>
<mkdir dir="${build.classes}"/>
<mkdir dir="${build.testclasses}"/>
<mkdir dir="${build.lib}"/>
</target>

<target name="compile" depends="setup">
<javac
srcdir="src/main"
destdir="${build.classes}"
debug="true"
/>
</target>

<target name="antlib" depends="compile">
<copy todir="${build.classes}">
<fileset dir="src/main" includes="**/antlib.xml"/>
</copy>
<jar
destfile="${jarname}"
basedir="${build.classes}"
/>
</target>

<target name="setup-for-tests" depends="setup">
<ant
antfile="../../../build.xml"
target="test-jar"
inheritall="false"
/>
</target>

<target name="compile-tests" depends="setup-for-tests, antlib">
<javac
srcdir="src/testcases"
destdir="${build.testclasses}"
debug="true"
>
<classpath>
<pathelement location="${jarname}"/>
<pathelement location="../../../build/lib/ant-testutil.jar"/>
</classpath>
</javac>
</target>

<target name="test" depends="compile-tests">
<junit
printsummary="false"
haltonfailure="false"
failureproperty="tests.failed"
filtertrace="false"
>
<classpath>
<pathelement location="${jarname}"/>
<pathelement location="../../../build/lib/ant-testutil.jar"/>
<pathelement location="${build.testclasses}"/>
</classpath>

<batchtest>
<fileset dir="src/testcases"/>
</batchtest>

<formatter type="plain" usefile="false"/>
</junit>

<fail if="tests.failed">At least one test has failed.</fail>
</target>
</project>

+ 0
- 32
proposal/sandbox/dotnet/docs/dotnetexec.html View File

@@ -1,32 +0,0 @@
<html>
<head>
<meta http-equiv="Content-Language" content="en-us"></meta>
<title>DotNetExec Task</title>
</head>

<body>
<h2><a name="dotnetexec">DotNetExec</a></h2>

<h3>Description</h3>

<p>Executes a .NET assembly that's on your PATH or pointed to
directly by the executable attribute.</p>

<p>This task is an extension of Ant's <a
href="http://ant.apache.org/manual/CoreTasks/exec.html">exec</a>
task and supports all attributes and nested child elements of that
task. Use the executable attribute to specify the name of the
assembly (including the extension).</p>

<p>This task allows you to choose the .NET framework via the
<code>vm</code> attribute. The default value is "microsoft" on
Windows and "mono" on all other platforms. "microsoft" is a magic
name that means "run the assembly as executable directly" - this
may also work for Mono on Linux systems with the binfmt feature
described in the <a
href="http://www.go-mono.org/faq.html#q86">Mono FAQ</a>.</p>

<hr/>
<p align="center">Copyright &copy; 2003-2004 The Apache Software Foundation. All rights Reserved.</p>
</body>
</html>

+ 0
- 142
proposal/sandbox/dotnet/docs/index.html View File

@@ -1,142 +0,0 @@
<html>
<head>
<meta http-equiv="Content-Language" content="en-us"></meta>
<title>Dotnet Ant Library</title>
</head>

<body>
<h2>Introduction</h2>

<p>This is a library of Ant tasks that support using .NET
executables accross different platforms and in particular support
using common .NET development tools like <a
href="http://nant.sourceforge.net/">NAnt</a> or <a
href="http://www.nunit.org/">NUnit</a> from within Ant.</p>

<h2>Requirements</h2>

<p>The current version requires Ant 1.6.2 or later and may even
work better for a CVS build of Ant created from CVS HEAD.</p>

<h2>Where is it?</h2>

<p>The source code for the library currently lives in the
developer sandbox in Ant's CVS - <a
href="http://cvs.apache.org/viewcvs.cgi/ant/proposal/sandbox/dotnet/">http://cvs.apache.org/viewcvs.cgi/ant/proposal/sandbox/dotnet/</a>.
A binary can be found at <a
href="http://cvs.apache.org/~bodewig/dotnet/dotnet.jar">http://cvs.apache.org/~bodewig/dotnet/dotnet.jar</a>.
A zip file containing the docs is also <a
href="http://cvs.apache.org/~bodewig/dotnet/docs.zip">available</a>.</p>

<p>Note that these are temporary locations and may change later.</p>

<h2>Feedback</h2>

<p>Right now direct any feedback either directly to <a
href="mailto:bodewig@apache.org">me</a> or the <a
href="http://ant.apache.org/mail.html#Developer List">Ant
developer list</a>.

<h2>Installation</h2>

<p>If you are building this from sources, run the antlib target
and you'll get a file <code>dotnet.jar</code>. If you've
downloaded <code>dotnet.jar</code>, you are already ready.</p>

<p>There are several ways to use the tasks:</p>

<ul>
<li>The traditional way:
<pre>
&lt;taskdef
resource="org/apache/tools/ant/taskdefs/optional/dotnet/antlib.xml"&gt;
&lt;classpath&gt;
&lt;pathelement location="YOUR-PATH-TO/dotnet.jar"/&gt;
&lt;/classpath&gt;
&lt;/taskdef&gt;
</pre>

With this you can use the tasks like plain Ant tasks, they'll
live in the default namespace. I.e. if you can run
&lt;exec&gt; without any namespace prefix, you can do so for
&lt;dotnetexec&gt; as well.
</li>

<li>Similar, but assigning a namespace URI
<pre>
&lt;taskdef
uri="antlib:org.apache.tools.ant.taskdefs.optional.dotnet"
resource="org/apache/tools/ant/taskdefs/optional/dotnet/antlib.xml"&gt;
&lt;classpath&gt;
&lt;pathelement location="YOUR-PATH-TO/dotnet.jar"/&gt;
&lt;/classpath&gt;
&lt;/taskdef&gt;
</pre>

This puts you task into a separate namespace than Ant's
namespace. You would use the tasks like

<pre>
&lt;project
xmlns:dn="antlib:org.apache.tools.ant.taskdefs.optional.dotnet"
xmlns="antlib:org.apache.tools.ant"&gt;
...
&lt;dn:nant&gt;
&lt;dn:target name="my-target"/&gt;
&lt;/dn:nant&gt;
</pre>

or

<pre>
&lt;nant xmlns="antlib:org.apache.tools.ant.taskdefs.optional.dotnet"&gt;
&lt;target name="my-target"/&gt;
&lt;/nant&gt;
</pre>

or a variation thereof.
</li>

<li>Using Ant's autodiscovery. Place <code>dotnet.jar</code>
into a directory and use <code>ant -lib
DIR-CONTAINING-THE-JAR</code> or copy it into
<code>ANT_HOME/lib</code> - and then in your build file, simply
declare the namespace on the <code>project</code> tag:

<pre>
&lt;project
xmlns:dn="antlib:org.apache.tools.ant.taskdefs.optional.dotnet"
xmlns="antlib:org.apache.tools.ant"&gt;
</pre>

And all tasks of this library will automatically be available
in the <code>dn</code> namespace without any
<code>taskdef</code>.
</li>
</ul>

<h2>Tasks</h2>

<ul>
<li><a href="dotnetexec.html">dotnetexec</a> - run a .NET
assembly that's in your PATH. You can chose the framework that
is going to be used - defaults to Mono on non-Windows platforms
and Microsoft's on Windows.</li>

<li><a href="nant.html">nant</a> - execute the NAnt build
tool.</li>

<li><a href="msbuild.html">msbuild</a> - execute the MSBuild build
tool, untested.</li>

<li><a href="wix.html">wix</a> - execute the WiX toolset, untested.</li>

<li><a href="nunit.html">nunit</a> - execute the
nunit-console.exe <a href="http://www.nunit.org/">NUnit</a>
test runner.</li>
</ul>

<hr/>
<p align="center">Copyright &copy; 2003-2004 The Apache Software Foundation. All rights Reserved.</p>
</body>
</html>

+ 0
- 109
proposal/sandbox/dotnet/docs/msbuild.html View File

@@ -1,109 +0,0 @@
<html>
<head>
<meta http-equiv="Content-Language" content="en-us"></meta>
<title>MSBuild Task</title>
</head>

<body>
<h2><a name="dotnetexec">MSBuild</a></h2>

<h3>Description</h3>

<p>Runs the MSBuild build tool presented at the 2003 PDC. This
task is completely untested as the developers have no access to
the tool, it has been implemented by looking at the docs only.</p>

<p>You can either use an existing build file or nest a build file
(snippet) as a child into the task. If you don't specify either,
MSBuild's default build file search algorithm will apply.</p>

<h3>Parameters</h3>
<table border="1" cellpadding="2" cellspacing="0">
<tr>
<td valign="top"><b>Attribute</b></td>
<td valign="top"><b>Description</b></td>
<td align="center" valign="top"><b>Required</b></td>
</tr>
<tr>
<td valign="top">buildfile</td>
<td valign="top">External build file to invoke MSBuild on.</td>
<td align="center">No.</td>
</tr>
<tr>
<td valign="top">vm</td>
<td valign="top">Same as <a
href="dotnetexec.html">dotnetexec</a>'s vm attribute.
Specify the framework to use.</td>
<td align="center">No.</td>
</tr>
</table>

<h3>Parameters specified as nested elements</h3>
<h4>target</h4>

<p><code>target</code> has a single required attribute name -
specifies a target to be run.</p>

<h4>property</h4>

<p><code>property</code> has two required attributes. name and
value that specify name and value of a property that is to be
defined in the MSBuild invocation.</p>

<h4>build</h4>

<p>This element allows no attributes. You can nest a MSBuild build
file into it and MSBuild will be executed on that. You can also nest
a build file snippet instead and Ant will wrap the necessary MSBuild
<code>&lt;Project&gt; around it.</code></p>

<h3>Examples</h3>

<p>Let MSBuild search for a *.proj file in the (Ant) project's base
directory and execute the default target in it:</p>

<pre>&lt;msbuild/&gt;</pre>
<p>Let MSBuild execute the targets named foo and bar in the build
file msbuild.proj in Ant's basedir and pass the property
<code>/property:test=testvalue</code> to it:</p>

<pre>
&lt;msbuild buildfile="msbuild.proj"&gt;
&lt;target name="foo"/&gt;
&lt;target name="bar"/&gt;
&lt;property name="test" value="testvalue"/&gt;
&lt;/msbuild&gt;
</pre>

<p>Define a build file embeded into the task, let MSBuild execute the
echo target of that build file.</p>

<pre>
&lt;msbuild&gt;
&lt;target name="echo"&gt;
&lt;build&gt;
&lt;Project DefaultTargets="empty"&gt;
&lt;Target Name="empty"/&gt;
&lt;Target Name="echo"&gt;
&lt;Task Name="Echo" Message="This is MSBuild"/&gt;
&lt;/Target&gt;
&lt;/Project&gt;
&lt;/build&gt;
&lt;/msbuild&gt;
</pre>

<p>Run MSBuild's Echo task (if there actually is one):</p>

<pre>
&lt;msbuild&gt;
&lt;build&gt;
&lt;Task Name="Echo" Message="This is MSBuild"/&gt;
&lt;/build&gt;
&lt;/msbuild&gt;
</pre>

<hr/>
<p align="center">Copyright &copy; 2003-2004 The Apache Software Foundation. All rights Reserved.</p>
</body>
</html>

+ 0
- 108
proposal/sandbox/dotnet/docs/nant.html View File

@@ -1,108 +0,0 @@
<html>
<head>
<meta http-equiv="Content-Language" content="en-us"></meta>
<title>NAnt Task</title>
</head>

<body>
<h2><a name="dotnetexec">NAnt</a></h2>

<h3>Description</h3>

<p>Runs the <a href="http://nant.sourceforge.net/">NAnt</a> build
tool.</p>

<p>You can either use an existing build file or nest a build file
(snippet) as a child into the task. If you don't specify either,
NAnt's default build file search algorithm will apply.</p>

<h3>Parameters</h3>
<table border="1" cellpadding="2" cellspacing="0">
<tr>
<td valign="top"><b>Attribute</b></td>
<td valign="top"><b>Description</b></td>
<td align="center" valign="top"><b>Required</b></td>
</tr>
<tr>
<td valign="top">buildfile</td>
<td valign="top">External build file to invoke NAnt on.</td>
<td align="center">No.</td>
</tr>
<tr>
<td valign="top">vm</td>
<td valign="top">Same as <a
href="dotnetexec.html">dotnetexec</a>'s vm attribute.
Specify the framework to use.</td>
<td align="center">No.</td>
</tr>
</table>

<h3>Parameters specified as nested elements</h3>
<h4>target</h4>

<p><code>target</code> has a single required attribute name -
specifies a target to be run.</p>

<h4>property</h4>

<p><code>property</code> has two required attributes. name and
value that specify name and value of a property that is to be
defined in the NAnt invocation.</p>

<h4>build</h4>

<p>This element allows no attributes. You can nest a NAnt build
file into it and NAnt will be executed on that. You can also nest
a build file snippet instead and Ant will wrap the necessary NAnt
<code>&lt;project&gt; around it.</code></p>

<h3>Examples</h3>

<p>Let NAnt search for a *.build file in the (Ant) project's base
directory and execute the default target in it:</p>

<pre>&lt;nant/&gt;</pre>
<p>Let NAnt execute the targets named foo and bar in the build
file nant.build in Ant's basedir and pass the property
<code>-D:test=testvalue</code> to it:</p>

<pre>
&lt;nant buildfile="nant.build"&gt;
&lt;target name="foo"/&gt;
&lt;target name="bar"/&gt;
&lt;property name="test" value="testvalue"/&gt;
&lt;/nant&gt;
</pre>

<p>Define a build file embeded into the task, let NAnt execute the
echo target of that build file.</p>

<pre>
&lt;nant&gt;
&lt;target name="echo"&gt;
&lt;build&gt;
&lt;project basedir="." default="empty"&gt;
&lt;target name="empty"/&gt;
&lt;target name="echo"&gt;
&lt;echo message="this is NAnt"/&gt;
&lt;/target&gt;
&lt;/project&gt;
&lt;/build&gt;
&lt;/nant&gt;
</pre>

<p>Run NAnt's echo task:</p>

<pre>
&lt;nant&gt;
&lt;build&gt;
&lt;echo message="this is NAnt"/&gt;
&lt;/build&gt;
&lt;/nant&gt;
</pre>

<hr/>
<p align="center">Copyright &copy; 2003-2004 The Apache Software Foundation. All rights Reserved.</p>
</body>
</html>

+ 0
- 177
proposal/sandbox/dotnet/docs/nunit.html View File

@@ -1,177 +0,0 @@
<html>
<head>
<meta http-equiv="Content-Language" content="en-us"></meta>
<title>NUnit Task</title>
</head>

<body>
<h2><a name="dotnetexec">NUnit</a></h2>

<h3>Description</h3>

<p>Runs the <a href="http://www.nunit.org/">NUnit</a> console
test runner.</p>

<h3>Parameters</h3>
<table border="1" cellpadding="2" cellspacing="0">
<tr>
<td valign="top"><b>Attribute</b></td>
<td valign="top"><b>Description</b></td>
<td align="center" valign="top"><b>Required</b></td>
</tr>
<tr>
<td valign="top">vm</td>
<td valign="top">Same as <a
href="dotnetexec.html">dotnetexec</a>'s vm attribute.
Specify the framework to use.</td>
<td align="center">No.</td>
</tr>
<tr>
<td valign="top">config</td>
<td valign="top">Config file to use</td>
<td align="center">No.</td>
</tr>
<tr>
<td valign="top">output</td>
<td valign="top">Where test output should go.</td>
<td align="center">No.</td>
</tr>
<tr>
<td valign="top">error</td>
<td valign="top">Where test error output should go.</td>
<td align="center">No.</td>
</tr>
<tr>
<td valign="top">xmlout</td>
<td valign="top">Where NUnit's XML output should go.</td>
<td align="center">No.</td>
</tr>
<tr>
<td valign="top">transform</td>
<td valign="top">The transformation to apply.</td>
<td align="center">No.</td>
</tr>
<tr>
<td valign="top">thread</td>
<td valign="top">Causes a separate thread to be created for
running the tests - see the NUnit documentation for
details.</td>
<td align="center">No - defaults to false.</td>
</tr>
<tr>
<td valign="top">noshadow</td>
<td valign="top">Disables shadow copying of the assembly in
order to provide improved performance..</td>
<td align="center">No - defaults to false.</td>
</tr>
<tr>
<td valign="top">fixture</td>
<td valign="top">Test fixture to run.</td>
<td align="center">No.</td>
</tr>
<tr>
<td valign="top">labels</td>
<td valign="top">Causes an identifying label to be displayed
at the start of each test case.</td>
<td align="center">No - defaults to false.</td>
</tr>
<tr>
<td valign="top">failOnError</td>
<td valign="top">Stops the build if NUnit returns with a code
indicating an error or failure.</td>
<td align="center">No - defaults to false.</td>
</tr>
</table>

<h3>Parameters specified as nested elements</h3>
<h4>testassembly</h4>

<p><code>testassembly</code> has a single required attribute name -
specifies an assembly or a project file holding tests.</p>

<h4>include/exclude</h4>

<p><code>in/exclude</code> have a single required attribute name -
specifies a category to include or exclude from the tests.</p>

<p><b>Note</b> that in current versions of NUnit (up to 2.2) you
may choose to either include or exclude categories in a run, but
not both. This task does <b>not</b> enforce this restriction
since future versions of NUnit may change behavior.</p>

<h4>redirector</h4>

<p>A nested <a
href="http://ant.apache.org/manual/CoreTypes/redirector.html">I/O
Redirector</a> can be specified. Any file mapping is done using a
<code>null</code> sourcefile; therefore not all <a
href="http://ant.apache.org/manual/CoreTypes/mapper.html">Mapper</a>
types will return results.</p>

<h4>env</h4> <p>It is possible to specify environment variables to
pass to the system command via nested <code>&lt;env&gt;</code>
elements. They support the same attributes as the nested <a
href="http://ant.apache.org/manual/CoreTasks/exec.html#env"><code>env</code>
element of the <code>&lt;exec&gt;</code> task</a>.</p>

<h3>Examples</h3>

<h4>Specify an assembly or project:</h4>

<pre>
&lt;nunit&gt;
&lt;testassembly name="nunit.tests.dll"/&gt;
&lt;/nunit&gt;
</pre>
<p>or</p>

<pre>
&lt;nunit&gt;
&lt;testassembly name="nunit.tests.csproj"/&gt;
&lt;/nunit&gt;
</pre>
<h4>Specifying an Assembly and a Fixture</h4>

<pre>
&lt;nunit fixture="NUnit.Tests.AssertionTests"&gt;
&lt;testassembly name="nunit.tests.dll"/&gt;
&lt;/nunit&gt;
</pre>

<h4>Specifying Test Categories to Include</h4>

<pre>
&lt;nunit&gt;
&lt;testassembly name="nunit.tests.dll"/&gt;
&lt;include name="Baseline"/&gt;
&lt;/nunit&gt;
</pre>

<h4>Specifying the XML file name</h4>

<pre>
&lt;nunit xmlout="console-test.xml"&gt;
&lt;testassembly name="nunit.tests.dll"/&gt;
&lt;/nunit&gt;
</pre>

<p>changes the name of the output file to "console-test.xml" -
note that this task will resolve file names relative to the
project's base directory, not the current working directory.</p>

<h4>Specifying Multiple Assemblies</h4>

<pre>
&lt;nunit&gt;
&lt;testassembly name="assembly1.dll"/&gt;
&lt;testassembly name="assembly2.dll"/&gt;
&lt;testassembly name="assembly3.dll"/&gt;
&lt;/nunit&gt;
</pre>

<hr/>
<p align="center">Copyright &copy; 2004 The Apache Software Foundation. All rights Reserved.</p>
</body>
</html>

+ 0
- 177
proposal/sandbox/dotnet/docs/wix.html View File

@@ -1,177 +0,0 @@
<html>
<head>
<meta http-equiv="Content-Language" content="en-us"></meta>
<title>Wix Task</title>
</head>

<body>
<h2>Wix</h2>

<h3>Description</h3>

<p>Runs the candle, light or both from the <a
href="http://sourceforge.net/projects/wix">Wix</a> toolset.</p>

<h3>Parameters</h3>
<table border="1" cellpadding="2" cellspacing="0">
<tr>
<td valign="top"><b>Attribute</b></td>
<td valign="top"><b>Description</b></td>
<td align="center" valign="top"><b>Required</b></td>
</tr>
<tr>
<td valign="top">source</td>
<td valign="top">The single source file to process.</td>
<td align="center">Either this or at least one nested
&lt;sources&gt; set.</td>
</tr>
<tr>
<td valign="top">target</td>
<td valign="top">The expected target file.</td>
<td align="center">Yes, unless you run candle without light.</td>
</tr>
<tr>
<td valign="top">mode</td>
<td valign="top">Which part of the toolset to run, one of
&quot;candle&quot;, &quot;light&quot; or
&quot;both&quot;.</td>
<td align="center">No, default is &quot;both&quot;.</td>
</tr>
<tr>
<td valign="top">vm</td>
<td valign="top">Same as <a
href="dotnetexec.html">dotnetexec</a>'s vm attribute.
Specify the framework to use.</td>
<td align="center">No.</td>
</tr>
</table>

<h3>Parameters specified as nested elements</h3>

<h4>sources</h4>

<p>Specify source files that shall be passed on the command line.
This is a <a
href="http://ant.apache.org/manual/CoreTypes/fileset.html">fileset</a>.</p>

<h4>moresources</h4>

<p>Specify source files that shall not be passed on the command
line. This is a <a
href="http://ant.apache.org/manual/CoreTypes/fileset.html">fileset</a>.</p>

<p>Typically this would list include files when running candle or
the files that vecome part of the MSI file when running light.
The files in this set are only used for timestamp comparisons. If
neither these files nor the given &quot;normal&quot; sources are
newer than the expected target, the task won't do anything.</p>


<h3>Examples</h3>

<p>Create <code>product.wixobj</code> from <code>product.wxs</code>:</p>

<pre>
&lt;wix mode="candle" source="product.wxs"/&gt;
</pre>

<p>The same but using a nested sources element:</p>

<pre>
&lt;wix mode="candle"&gt;
&lt;sources dir="."&gt;
&lt;include name="product.wxs"/&gt;
&lt;/sources&gt;
&lt;/wix&gt;
</pre>

<p>Create <code>product.msi</code> from <code>product.wixobj</code>:</p>

<pre>
&lt;wix mode="light" source="product.wixobj" target="product.msi"/&gt;
</pre>

<p>Combine the examples into a single step:</p>

<pre>
&lt;wix source="product.wxs" target="product.msi"/&gt;
</pre>

<p>Note that the task wouldn't do anything if
<code>product.wxs</code> was older than
<code>product.wixobj</code> and <code>product.wixobj</code> was
older than <code>product.msi</code>.</p>

<p>Compile multiple <code>.wxs</code> files at once:</p>

<pre>
&lt;wix mode="candle"&gt;
&lt;sources dir="."&gt;
&lt;include name="*.wxs"/&gt;
&lt;/sources&gt;
&lt;/wix&gt;
</pre>

<p>Compile multiple <code>.wxs</code> files at once, specify some
include files in addition to that:</p>

<pre>
&lt;wix mode="candle"&gt;
&lt;sources dir="."&gt;
&lt;include name="*.wxs"/&gt;
&lt;/sources&gt;
&lt;moresources dir="."&gt;
&lt;include name="*.wxi"/&gt;
&lt;/moresources&gt;
&lt;/wix&gt;
</pre>

<p>Link multiple <code>.wixobj</code> files at once:</p>

<pre>
&lt;wix mode="light" target="product.msi"&gt;
&lt;sources dir="."&gt;
&lt;include name="*.wixobj"/&gt;
&lt;/sources&gt;
&lt;/wix&gt;
</pre>

<p>Link multiple <code>.wixobj</code> files at once and specify
that the files in directory &quot;source&quot; will become part of
the package:</p>

<pre>
&lt;wix mode="light" target="product.msi"&gt;
&lt;sources dir="."&gt;
&lt;include name="*.wixobj"/&gt;
&lt;/sources&gt;
&lt;moresources dir="source"/&gt;
&lt;/wix&gt;
</pre>

<pre>Combine multiple <code>.wxs</code> files and include files
into a single package and specify that the package will contain
files from the source directory:</pre>

<pre>
&lt;wix target="product.msi"&gt;
&lt;sources dir="."&gt;
&lt;include name="*.wxs"/&gt;
&lt;/sources&gt;
&lt;moresources dir="."&gt;
&lt;include name="*.wxi"/&gt;
&lt;/moresources&gt;
&lt;moresources dir="source"/&gt;
&lt;/wix&gt;
</pre>

<p>Again, if the intermediate <code>.wixobj</code> files are newer
that the corresponding <code>.wxs</code> files (and all include
files) the candle step will be skipped. If
<code>product.msi</code> is newer than all files, the task won't
do anything.</p>

<hr/>
<p align="center">Copyright &copy; 2004 The Apache Software Foundation. All rights Reserved.</p>
</body>
</html>

+ 0
- 89
proposal/sandbox/dotnet/src/etc/testcases/dotnetexec.xml View File

@@ -1,89 +0,0 @@
<?xml version="1.0"?>
<!--
Copyright 2003-2004 The Apache Software Foundation

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->

<project name="dotnet" basedir="." default="testCSC"
xmlns:dn="antlib:org.apache.tools.ant.taskdefs.optional.dotnet">

<property environment="env"/>
<property name="build.dir" location="build"/>
<property name="src.dir" location="src"/>

<property name="out.csc" location="${src.dir}/out.cs"/>
<property name="out.app" location="${build.dir}/out.exe"/>
<property name="out.type" value="exe"/>

<taskdef
uri="antlib:org.apache.tools.ant.taskdefs.optional.dotnet"
resource="org/apache/tools/ant/taskdefs/optional/dotnet/antlib.xml">
<classpath>
<pathelement location="../../../build/lib/dotnet.jar"/>
</classpath>
</taskdef>

<target name="probe_for_apps" >
<condition property="csc.found">
<or>
<available file="csc" filepath="${env.PATH}" />
<available file="csc.exe" filepath="${env.PATH}" />
<available file="csc.exe" filepath="${env.Path}" />
</or>
</condition>
<echo> csc.found=${csc.found}</echo>

<!-- Mono C# compiler -->
<condition property="mcs.found">
<available file="mcs" filepath="${env.PATH}" />
</condition>
<echo> mcs.found=${mcs.found}</echo>

<!-- any C# compiler -->
<condition property="c#.found">
<or>
<isset property="csc.found"/>
<isset property="mcs.found"/>
</or>
</condition>
</target>

<target name="init" depends="probe_for_apps">
<mkdir dir="${build.dir}"/>
<property name="testCSC.exe"
location="${build.dir}/ExampleCsc.exe" />
</target>

<target name="teardown">
<delete dir="${build.dir}"/>
</target>

<target name="validate_csc" depends="init">
<fail unless="c#.found">Needed C# compiler is missing</fail>
</target>

<target name="testCSC" depends="validate_csc">
<csc
destFile="${testCSC.exe}"
targetType="exe">
<src dir="${src.dir}" includes="ex*.cs"/>
</csc>
<available property="app.created" file="${testCSC.exe}"/>
<fail unless="app.created">No app ${testCSC.exe} created</fail>
<dn:dotnetexec executable="${testCSC.exe}" failonerror="true" />
<delete file="${testCSC.exe}"/>
</target>

</project>


+ 0
- 73
proposal/sandbox/dotnet/src/etc/testcases/msbuild.xml View File

@@ -1,73 +0,0 @@
<?xml version="1.0"?>
<!--
Copyright 2003-2004 The Apache Software Foundation

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<project name="msbuild" basedir="." default="echo"
xmlns:dn="antlib:org.apache.tools.ant.taskdefs.optional.dotnet">

<taskdef
uri="antlib:org.apache.tools.ant.taskdefs.optional.dotnet"
resource="org/apache/tools/ant/taskdefs/optional/dotnet/antlib.xml">
<classpath>
<pathelement location="../../../build/lib/dotnet.jar"/>
</classpath>
</taskdef>

<property environment="env"/>
<condition property="msbuild.found">
<or>
<available file="MSBuild.exe" filepath="${env.PATH}"/>
<available file="MSBuild.exe" filepath="${env.Path}"/>
<available file="MSBuild.exe"/>
</or>
</condition>

<target name="echo">
<msbuild
buildfile="src/msbuild.proj"
xmlns="antlib:org.apache.tools.ant.taskdefs.optional.dotnet"
>
<target name="echo"/>
<property name="foo" value="bar"/>
</msbuild>
</target>

<target name="nested-file">
<property name="foo" value="bar"/>
<msbuild
xmlns="antlib:org.apache.tools.ant.taskdefs.optional.dotnet"
>
<build>
<Project DefaultTargets="echo">
<Target Name="echo">
<Task Name="Echo" Message="foo is ${foo}"/>
</Target>
</Project>
</build>
</msbuild>
</target>

<target name="nested-task">
<property name="foo" value="bar"/>
<msbuild
xmlns="antlib:org.apache.tools.ant.taskdefs.optional.dotnet"
>
<build>
<Task Name="Echo" Message="foo is ${foo}"/>
</build>
</msbuild>
</target>

</project>

+ 0
- 72
proposal/sandbox/dotnet/src/etc/testcases/nant.xml View File

@@ -1,72 +0,0 @@
<?xml version="1.0"?>
<!--
Copyright 2003-2004 The Apache Software Foundation

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<project name="nant" basedir="." default="echo"
xmlns:dn="antlib:org.apache.tools.ant.taskdefs.optional.dotnet">

<taskdef
uri="antlib:org.apache.tools.ant.taskdefs.optional.dotnet"
resource="org/apache/tools/ant/taskdefs/optional/dotnet/antlib.xml">
<classpath>
<pathelement location="../../../build/lib/dotnet.jar"/>
</classpath>
</taskdef>

<property environment="env"/>
<condition property="nant.found">
<or>
<available file="NAnt.exe" filepath="${env.PATH}"/>
<available file="NAnt.exe" filepath="${env.Path}"/>
<available file="NAnt.exe"/>
</or>
</condition>

<target name="echo">
<nant
buildfile="src/nant.build"
xmlns="antlib:org.apache.tools.ant.taskdefs.optional.dotnet"
>
<target name="echo"/>
<property name="foo" value="bar"/>
</nant>
</target>

<target name="nested-file">
<property name="foo" value="bar"/>
<nant
xmlns="antlib:org.apache.tools.ant.taskdefs.optional.dotnet"
>
<build>
<project basedir="." default="echo">
<target name="echo">
<echo message="foo is ${foo}"/>
</target>
</project>
</build>
</nant>
</target>

<target name="nested-task">
<property name="foo" value="bar"/>
<nant
xmlns="antlib:org.apache.tools.ant.taskdefs.optional.dotnet"
>
<build>
<echo message="foo is ${foo}"/>
</build>
</nant>
</target>
</project>

+ 0
- 81
proposal/sandbox/dotnet/src/etc/testcases/nunit.xml View File

@@ -1,81 +0,0 @@
<?xml version="1.0"?>
<!--
Copyright 2004 The Apache Software Foundation

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<project name="nunit" basedir="." default="echo"
xmlns:dn="antlib:org.apache.tools.ant.taskdefs.optional.dotnet">

<property name="build.dir" value="build"/>
<property name="src.dir" location="src"/>

<taskdef
uri="antlib:org.apache.tools.ant.taskdefs.optional.dotnet"
resource="org/apache/tools/ant/taskdefs/optional/dotnet/antlib.xml">
<classpath>
<pathelement location="../../../build/lib/dotnet.jar"/>
</classpath>
</taskdef>

<property environment="env"/>
<condition property="nunit.found">
<or>
<available file="nunit-console.exe" filepath="${env.PATH}"/>
<available file="nunit-console.exe" filepath="${env.Path}"/>
<available file="nunit-console.exe"/>
</or>
</condition>

<target name="no-assembly">
<dn:nunit/>
</target>

<target name="compile-pass">
<mkdir dir="${build.dir}"/>
<csc destFile="${build.dir}/Pass.dll"
targetType="library" references="nunit.framework.dll">
<src dir="${src.dir}" includes="pass.cs"/>
</csc>
</target>

<target name="compile-fail">
<mkdir dir="${build.dir}"/>
<csc destFile="${build.dir}/Fail.dll"
targetType="library" references="nunit.framework.dll">
<src dir="${src.dir}" includes="fail.cs"/>
</csc>
</target>

<target name="passing-test" depends="compile-pass">
<dn:nunit>
<testassembly name="${build.dir}/Pass.dll"/>
</dn:nunit>
</target>

<target name="failing-test" depends="compile-fail">
<dn:nunit>
<testassembly name="${build.dir}/Fail.dll"/>
</dn:nunit>
</target>

<target name="failing-test-with-fail" depends="compile-fail">
<dn:nunit failonerror="true">
<testassembly name="${build.dir}/Fail.dll"/>
</dn:nunit>
</target>

<target name="teardown">
<delete dir="${build.dir}"/>
</target>
</project>

+ 0
- 25
proposal/sandbox/dotnet/src/etc/testcases/src/example.cs View File

@@ -1,25 +0,0 @@
/*
* Copyright 2001-2004 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using System;

public class Example {

public static void Main(String[] args) {
Example2.echo();
}
}

+ 0
- 31
proposal/sandbox/dotnet/src/etc/testcases/src/example2.cs View File

@@ -1,31 +0,0 @@
/*
* Copyright 2001-2004 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
using System;

/**
* this is just here to create confusion
*/
public class Example2 {

public int some_variable=3;
public static void echo() {
Console.WriteLine("hello, I look like Java, but I'm really .NET");
}
}

+ 0
- 30
proposal/sandbox/dotnet/src/etc/testcases/src/fail.cs View File

@@ -1,30 +0,0 @@
/*
* Copyright 2004 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

using System;
using NUnit.Framework;

[TestFixture]
public class FailingTest
{

[Test]
public void Fail()
{
Assert.IsTrue(false);
}
}

+ 0
- 24
proposal/sandbox/dotnet/src/etc/testcases/src/msbuild.proj View File

@@ -1,24 +0,0 @@
<?xml version="1.0"?>
<!--
Copyright 2003-2004 The Apache Software Foundation

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<Project DefaultTargets="empty">

<Target Name="empty"/>

<Target Name="echo">
<Task Name="Echo" Message="foo is ${foo}"/>
</Target>
</Project>

+ 0
- 24
proposal/sandbox/dotnet/src/etc/testcases/src/nant.build View File

@@ -1,24 +0,0 @@
<?xml version="1.0"?>
<!--
Copyright 2003-2004 The Apache Software Foundation

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<project basedir="." default="empty">

<target name="empty"/>

<target name="echo">
<echo message="foo is ${foo}"/>
</target>
</project>

+ 0
- 30
proposal/sandbox/dotnet/src/etc/testcases/src/pass.cs View File

@@ -1,30 +0,0 @@
/*
* Copyright 2004 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

using System;
using NUnit.Framework;

[TestFixture]
public class PassingTest
{

[Test]
public void Pass()
{
Assert.IsTrue(true);
}
}

+ 0
- 259
proposal/sandbox/dotnet/src/main/org/apache/tools/ant/taskdefs/optional/dotnet/AbstractBuildTask.java View File

@@ -1,259 +0,0 @@
/*
* Copyright 2003-2004 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

package org.apache.tools.ant.taskdefs.optional.dotnet;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.util.DOMElementWriter;
import org.apache.tools.ant.util.FileUtils;
import org.apache.tools.ant.util.XMLFragment;

import org.w3c.dom.DocumentFragment;
import org.w3c.dom.Element;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
* Base class for NAntTask and MSBuildTask.
*/
public abstract class AbstractBuildTask extends Task {

/**
* The buildfile to invoke the build tool for.
*/
private File buildFile;

/**
* The targets to execute.
*/
private List targets = new ArrayList();

/**
* Properties to set.
*/
private List properties = new ArrayList(1);

/**
* Nested build file fragment.
*/
private XMLFragment buildSnippet;

/**
* The vm attribute - if given.
*/
private String vm;

/**
* Empty constructor.
*/
protected AbstractBuildTask() {
}

/**
* Sets the name of the build file.
*/
public final void setBuildfile(File f) {
buildFile = f;
}

/**
* Adds a build file fragment.
*/
public void addBuild(XMLFragment f) {
if (buildSnippet == null) {
buildSnippet = f;
} else {
throw new BuildException("You must not specify more than one "
+ "build element");
}
}

/**
* Set the name of the executable for the virtual machine.
*
* @param value the name of the executable for the virtual machine
*/
public void setVm(String value) {
this.vm = value;
}

/**
* A target.
*/
public static class Target {
private String name;

public void setName(String name) {
this.name = name;
}

public String getName() {
return name;
}

}

/**
* A target to execute.
*/
public final void addTarget(Target t) {
targets.add(t);
}

/**
* A property.
*/
// XXX, could have reused Property or Environment.Variable
// - not decided so far
public static class Property {
private String name;
private String value;

public void setName(String name) {
this.name = name;
}

public String getName() {
return name;
}

public void setValue(String value) {
this.value = value;
}

public String getValue() {
return value;
}
}

/**
* A target to execute.
*/
public final void addProperty(Property t) {
properties.add(t);
}

/**
* Must return the executable.
*
* @return must not return null
*/
protected abstract String getExecutable();

/**
* Must return buildfile argument(s).
*
* @param buildFile the absolute File for the buildfile or null if
* the user didn't specify a buildfile.
*
* @return must not return null
*/
protected abstract String[] getBuildfileArguments(File buildFile);

/**
* Must return target argument(s).
*
* @return must not return null
*/
protected abstract String[] getTargetArguments(List targets);

/**
* Must return property argument(s).
*
* @return must not return null
*/
protected abstract String[] getPropertyArguments(List properties);

/**
* Turn the DoucmentFragment into a DOM tree suitable as a build
* file when serialized.
*
* <p>Must throw a BuildException if the snippet can not be turned
* into a build file.</p>
*/
protected abstract Element makeTree(DocumentFragment f);

/**
* Perform the build.
*/
public void execute() {
if (buildFile != null && buildSnippet != null) {
throw new BuildException("You must not specify the build file"
+ " attribute and a nested build at the"
+ " same time");
}

DotNetExecTask exec = DotNetExecTask.getTask(this, vm,
getExecutable(), null);
String[] args = getPropertyArguments(properties);
for (int i = 0; i < args.length; i++) {
exec.createArg().setValue(args[i]);
}
args = getTargetArguments(targets);
for (int i = 0; i < args.length; i++) {
exec.createArg().setValue(args[i]);
}

File generatedFile = null;
if (buildSnippet != null) {
try {
generatedFile = getBuildFile();
} catch (IOException e) {
throw new BuildException(e);
}
args = getBuildfileArguments(generatedFile);
} else {
args = getBuildfileArguments(buildFile);
}

for (int i = 0; i < args.length; i++) {
exec.createArg().setValue(args[i]);
}

try {
exec.execute();
} finally {
if (generatedFile != null) {
generatedFile.delete();
}
}
}

private File getBuildFile() throws IOException {
File f = null;
if (buildSnippet != null) {
Element e = makeTree(buildSnippet.getFragment());
f = FileUtils.newFileUtils().createTempFile("build", ".xml", null);
f.deleteOnExit();
FileOutputStream out = null;
try {
out = new FileOutputStream(f);
(new DOMElementWriter()).write(e, out);
} finally {
if (out != null) {
out.close();
}
}
}
return f;
}
}

+ 0
- 150
proposal/sandbox/dotnet/src/main/org/apache/tools/ant/taskdefs/optional/dotnet/DotNetExecTask.java View File

@@ -1,150 +0,0 @@
/*
* Copyright 2003-2004 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

package org.apache.tools.ant.taskdefs.optional.dotnet;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.taskdefs.ExecTask;
import org.apache.tools.ant.taskdefs.condition.Os;
import org.apache.tools.ant.types.Environment;

/**
* Specialized <exec> that knows how to deal with Mono vs. Microsoft's
* VM - and maybe Rotor at some point.
*/
public class DotNetExecTask extends ExecTask {

/**
* "Magic" VM argument for Microsoft's VM.
*/
private static final String MS_VM = "microsoft";

/**
* The user supplied executable attribute.
*/
private String executable;

/**
* The .NET VM to use.
*
* <p>Defaults to Microsoft's on Windows and mono on any other
* platform.</p>
*/
private String vm = Os.isFamily("windows") ? MS_VM : "mono";

/**
* Empty Constructor.
*/
public DotNetExecTask() {
super();
}

/**
* Set the name of the executable program.
* @param value the name of the executable program
*/
public void setExecutable(String value) {
this.executable = value;
}

/**
* Set the name of the executable for the virtual machine or the
* magic name "microsoft" which implies that we can invoke the
* executable directly.
*
* @param value the name of the executable for the virtual machine
*/
public void setVm(String value) {
this.vm = value;
}

/**
* Do the work.
*
* @throws BuildException if executable is empty or &lt;exec&gt;
* throws an exception.
*/
public void execute() throws BuildException {
if (executable == null) {
throw new BuildException("The executable attribute is required");
}
setupCommandline();
super.execute();
}

/**
* If the inherited Commandline doesn't know about the executable
* yet, set it and deal with the vm attribute.
*
* <p>The inherited Commandline may know the executable already if
* this task instance is getting reused.</p>
*/
protected void setupCommandline() {
if (cmdl.getExecutable() == null) {
if (vm.equals(MS_VM)) {
// can invoke executable directly
super.setExecutable(executable);
} else {
boolean b = getResolveExecutable();
// Mono wants the absolte path of the assembly
setResolveExecutable(b || isMono(vm));
super.setExecutable(vm);
cmdl.createArgument(true)
.setValue(resolveExecutable(executable, isMono(vm)));
setResolveExecutable(b);
}
}
}

/**
* Whether the given vm looks like the Mono executable.
*/
protected final static boolean isMono(String vm) {
return "mono".equals(vm) || "mint".equals(vm);
}

/**
* Creates an instance of this task based on a different tasks settings.
*/
public static DotNetExecTask getTask(Task t, String vm,
String executable,
Environment env) {
DotNetExecTask exec = new DotNetExecTask();
if (vm != null) {
exec.setVm(vm);
}
exec.setProject(t.getProject());
exec.setExecutable(executable);
exec.setTaskName(t.getTaskName());
if (env != null) {
String[] environment = env.getVariables();
if (environment != null) {
for (int i = 0; i < environment.length; i++) {
int idx = environment[i].indexOf("=");
Environment.Variable v = new Environment.Variable();
v.setKey(environment[i].substring(0, idx));
v.setValue(environment[i].substring(idx + 1));
exec.addEnv(v);
}
}
}
return exec;
}

}

+ 0
- 120
proposal/sandbox/dotnet/src/main/org/apache/tools/ant/taskdefs/optional/dotnet/MSBuildTask.java View File

@@ -1,120 +0,0 @@
/*
* Copyright 2003-2004 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

package org.apache.tools.ant.taskdefs.optional.dotnet;

import java.io.File;
import java.util.Iterator;
import java.util.ArrayList;
import java.util.List;

import org.w3c.dom.DocumentFragment;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
* Runs a MSBuild build process.
*/
public class MSBuildTask extends AbstractBuildTask {

private static final String TARGET = "generated-by-ant";

public MSBuildTask() {
super();
}

protected String getExecutable() {
return "MSBuild.exe";
}

protected String[] getBuildfileArguments(File buildFile) {
if (buildFile != null) {
return new String[] {
buildFile.getAbsolutePath()
};
} else {
return new String[0];
}
}

protected String[] getTargetArguments(List targets) {
if (targets.size() > 0) {
StringBuffer sb = new StringBuffer("/targets:");
Iterator iter = targets.iterator();
boolean first = true;
while (iter.hasNext()) {
AbstractBuildTask.Target t =
(AbstractBuildTask.Target) iter.next();
if (!first) {
sb.append(";");
}
sb.append(t.getName());
}
return new String[]{sb.toString()};
} else {
return new String[0];
}
}

protected String[] getPropertyArguments(List properties) {
if (properties.size() > 0) {
StringBuffer sb = new StringBuffer("/property:");
Iterator iter = properties.iterator();
boolean first = true;
while (iter.hasNext()) {
AbstractBuildTask.Property p =
(AbstractBuildTask.Property) iter.next();
if (!first) {
sb.append(";");
}
sb.append(p.getName()).append("=").append(p.getValue());
}
return new String[]{sb.toString()};
} else {
return new String[0];
}
}

/**
* Turn the DocumentFragment into a DOM tree suitable as a build
* file when serialized.
*
* <p>If we have exactly one <Project> child, return that.
* Otherwise if we have only <Task> children, wrap them into a
* <Target> which in turn gets wrapped into a <Project>.
* Otherwise, fail.</p>
*/
protected Element makeTree(DocumentFragment f) {
NodeList nl = f.getChildNodes();
if (nl.getLength() == 1
&& nl.item(0).getNodeType() == Node.ELEMENT_NODE
&& nl.item(0).getNodeName().equals("Project")) {
return (Element) nl.item(0);
} else {
Element p = f.getOwnerDocument().createElement("Project");
p.setAttribute("DefaultTargets", TARGET);

Element t = f.getOwnerDocument().createElement("Target");
t.setAttribute("Name", TARGET);

p.appendChild(t);
t.appendChild(f);
return p;
}
}
}

+ 0
- 94
proposal/sandbox/dotnet/src/main/org/apache/tools/ant/taskdefs/optional/dotnet/NAntTask.java View File

@@ -1,94 +0,0 @@
/*
* Copyright 2003-2004 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

package org.apache.tools.ant.taskdefs.optional.dotnet;

import java.io.File;
import java.util.Iterator;
import java.util.ArrayList;
import java.util.List;

import org.w3c.dom.DocumentFragment;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
* Runs a NAnt build process.
*/
public class NAntTask extends AbstractBuildTask {

public NAntTask() {
super();
}

protected String getExecutable() {
return "NAnt.exe";
}

protected String[] getBuildfileArguments(File buildFile) {
if (buildFile != null) {
return new String[] {
"-buildfile:" + buildFile.getAbsolutePath()
};
} else {
return new String[0];
}
}

protected String[] getTargetArguments(List targets) {
ArrayList al = new ArrayList(targets.size());
Iterator iter = targets.iterator();
while (iter.hasNext()) {
AbstractBuildTask.Target t = (AbstractBuildTask.Target) iter.next();
al.add(t.getName());
}
return (String[]) al.toArray(new String[al.size()]);
}

protected String[] getPropertyArguments(List properties) {
ArrayList al = new ArrayList(properties.size());
Iterator iter = properties.iterator();
while (iter.hasNext()) {
AbstractBuildTask.Property p =
(AbstractBuildTask.Property) iter.next();
al.add("-D:" + p.getName() + "=" + p.getValue());
}
return (String[]) al.toArray(new String[al.size()]);
}

/**
* Turn the DocumentFragment into a DOM tree suitable as a build
* file when serialized.
*
* <p>If we have exactly one <project> child, return that.
* Otherwise assume that this is a valid build file snippet that
* just needs an empty project wrapped around it.</p>
*/
protected Element makeTree(DocumentFragment f) {
NodeList nl = f.getChildNodes();
if (nl.getLength() == 1
&& nl.item(0).getNodeType() == Node.ELEMENT_NODE
&& nl.item(0).getNodeName().equals("project")) {
return (Element) nl.item(0);
} else {
Element e = f.getOwnerDocument().createElement("project");
e.appendChild(f);
return e;
}
}
}

+ 0
- 335
proposal/sandbox/dotnet/src/main/org/apache/tools/ant/taskdefs/optional/dotnet/NUnitTask.java View File

@@ -1,335 +0,0 @@
/*
* Copyright 2004 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

package org.apache.tools.ant.taskdefs.optional.dotnet;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.types.Environment;
import org.apache.tools.ant.types.RedirectorElement;

import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;

/**
* Task to run the NUnit Console test runner.
*
* @see http://www.nunit.org/
*/
public class NUnitTask extends Task {

/**
* The vm attribute - if given.
*/
private String vm;

/**
* Test assemblies.
*/
private ArrayList testAssemblies = new ArrayList();

/**
* The /config argument.
*/
private File configFile;

/**
* The /output argument.
*/
private File out;

/**
* The /err argument.
*/
private File err;

/**
* The /xml argument.
*/
private File xmlOut;

/**
* The /transform argument.
*/
private File transform;

/**
* The /thread argument.
*/
private boolean thread = false;

/**
* The /fixture argument.
*/
private String fixture;

/**
* Categories to include.
*/
private ArrayList includes = new ArrayList();

/**
* Categories to exclude.
*/
private ArrayList excludes = new ArrayList();

/**
* The /noshadow argument.
*/
private boolean noshadow = false;

/**
* The /labels argument.
*/
private boolean labels = false;

/**
* Redirects everything that NUnit wants to send to the console.
*/
private RedirectorElement redirectorElement;

/**
* Whether a failure should stop the build.
*/
private boolean failOnError = false;

/**
* Support for nested environment variables.
*/
private Environment env = new Environment();

public NUnitTask() {
super();
}

/**
* Set the name of the executable for the virtual machine.
*
* @param value the name of the executable for the virtual machine
*/
public void setVm(String value) {
this.vm = value;
}

/**
* Sets the name of the config file.
*/
public void setConfig(File c) {
configFile = c;
}

/**
* The /output argument.
*/
public void setOut(File out) {
this.out = out;
}

/**
* The /err argument.
*/
public void setError(File err) {
this.err = err;
}

/**
* The /xml argument.
*/
public void setXmlOut(File out) {
this.xmlOut = out;
}

/**
* The /transform argument.
*/
public void setTransform(File transform) {
this.transform = transform;
}

/**
* The /thread argument.
*/
public void setThread(boolean thread) {
this.thread = thread;
}

/**
* The /fixture argument.
*/
public void setFixture(String fixture) {
this.fixture = fixture;
}

/**
* The /noshadow argument.
*/
public void setNoshadow(boolean noshadow) {
this.noshadow = noshadow;
}

/**
* The /labels argument.
*/
public void setLabels(boolean labels) {
this.labels = labels;
}

/**
* Whether a failure should stop the build.
*/
public void setFailOnError(boolean b) {
failOnError = b;
}

/**
* Adds a test assembly by name.
*/
public void addTestAssembly(NamedElement a) {
testAssemblies.add(a);
}

/**
* Adds a category to the include list.
*/
public void addInclude(NamedElement a) {
includes.add(a);
}

/**
* Adds a category to the exclude list.
*/
public void addExclude(NamedElement a) {
excludes.add(a);
}

/**
* Add an environment variable to the launched process.
*
* @param var new environment variable
*/
public void addEnv(Environment.Variable var) {
env.addVariable(var);
}

/**
* Add a <code>RedirectorElement</code> to this task.
*
* <p>This does not use the <code>out</code> and
* <code>error</code> attributes, it only captures NUnits output
* that has not been redirected by those attributes.</p>
*/
public void addConfiguredRedirector(RedirectorElement redirectorElement) {
if (this.redirectorElement != null) {
throw new BuildException("cannot have > 1 nested <redirector>s");
} else {
this.redirectorElement = redirectorElement;
}
}

public void execute() {
if (testAssemblies.size() == 0) {
throw new BuildException("You must specify at least one test "
+ "assembly.");
}
DotNetExecTask exec = DotNetExecTask.getTask(this, vm,
"nunit-console.exe",
env);
Iterator iter = testAssemblies.iterator();
while (iter.hasNext()) {
NamedElement a = (NamedElement) iter.next();
exec.createArg().setValue(a.getName());
}
if (configFile != null) {
exec.createArg().setValue("/config="
+ configFile.getAbsolutePath());
}
exec.createArg().setValue("/nologo");

if (out != null) {
exec.createArg().setValue("/output=" + out.getAbsolutePath());
}
if (err != null) {
exec.createArg().setValue("/err=" + err.getAbsolutePath());
}
if (xmlOut != null) {
exec.createArg().setValue("/xml=" + xmlOut.getAbsolutePath());
}
if (transform != null) {
exec.createArg().setValue("/transform="
+ transform.getAbsolutePath());
}

if (thread) {
exec.createArg().setValue("/thread");
}
if (noshadow) {
exec.createArg().setValue("/noshadow");
}
if (labels) {
exec.createArg().setValue("/labels");
}
if (fixture != null) {
exec.createArg().setValue("/fixture=" + fixture);
}
if (includes.size() > 0) {
StringBuffer sb = new StringBuffer("/include=");
iter = includes.iterator();
boolean first = false;
while (iter.hasNext()) {
if (first) {
first = false;
} else {
sb.append(",");
}
NamedElement a = (NamedElement) iter.next();
sb.append(a.getName());
}
exec.createArg().setValue(sb.toString());
}
if (excludes.size() > 0) {
StringBuffer sb = new StringBuffer("/exclude=");
iter = excludes.iterator();
boolean first = false;
while (iter.hasNext()) {
if (first) {
first = false;
} else {
sb.append(",");
}
NamedElement a = (NamedElement) iter.next();
sb.append(a.getName());
}
exec.createArg().setValue(sb.toString());
}

if (redirectorElement != null) {
exec.addConfiguredRedirector(redirectorElement);
}
exec.setFailonerror(failOnError);

exec.execute();
}

public static class NamedElement {
private String name;
public String getName() {return name;}
public void setName(String s) {name = s;}
}
}

+ 0
- 296
proposal/sandbox/dotnet/src/main/org/apache/tools/ant/taskdefs/optional/dotnet/WixTask.java View File

@@ -1,296 +0,0 @@
/*
* Copyright 2004 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

package org.apache.tools.ant.taskdefs.optional.dotnet;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.types.EnumeratedAttribute;
import org.apache.tools.ant.types.FileSet;

import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
* Task to run the WiX utility to create MSI files from an XML description.
*
* @see http://sf.net/projects/wix
*/
public class WixTask extends Task {

/**
* The vm attribute - if given.
*/
private String vm;

/**
* The source files.
*/
private ArrayList sources = new ArrayList();

/**
* Additional source files (include files in the case of candle,
* or media/files/whatever in the case of light).
*/
private ArrayList moreSources = new ArrayList();

/**
* A single source file.
*/
private File source;

/**
* The target file.
*/
private File target;

/**
* What to do.
*/
private Mode mode;

public WixTask() {
super();
}

/**
* Set the name of the executable for the virtual machine.
*
* @param value the name of the executable for the virtual machine
*/
public void setVm(String value) {
this.vm = value;
}

/**
* The main source file.
*
* <p><code>candle</code> may include more files than this one,
* the main source is the one passed on the command line.</p>
*
* @param File object of the main source file.
*/
public void setSource(File f) {
source = f;
}

/**
* A set of source files.
*/
public void addSources(FileSet fs) {
sources.add(fs);
}

/**
* A set of additional source files (include files in the case of
* candle, or media/files/whatever in the case of light).
*
* <p>Unlike the files specified as sources, these will not be
* passed on the command line, they only help Ant to determine
* whether the target is out-of-date.</p>
*/
public void addMoreSources(FileSet fs) {
moreSources.add(fs);
}

public void execute() {
if (source == null && sources.size() == 0) {
throw new BuildException("You must specify at least one source"
+ " file.");
}
String m = Mode.BOTH;
if (mode != null) {
m = mode.getValue();
}

if (target == null && !m.equals(Mode.CANDLE)) {
throw new BuildException("You must specify the target if you want"
+ " to run light.");
}

List lightSources = new ArrayList();
if (!m.equals(Mode.LIGHT)) {
doCandle(lightSources);
} else {
if (source != null) {
lightSources.add(source);
}
if (sources.size() > 0) {
lightSources.addAll(grabFiles(sources));
}
}
List moreLightSources = new ArrayList();
if (moreSources.size() > 0) {
moreLightSources = grabFiles(moreSources);
}
if (!m.equals(Mode.CANDLE)) {
doLight(lightSources, moreLightSources);
}
}

/**
* Invoke candle on all sources that are newer than their targets.
*
* @param lightSources list that will be filled with File objects
* pointing to the generated object files.
*/
private void doCandle(List lightSources) {
List s = new ArrayList();
if (source != null) {
s.add(source);
}
if (sources != null) {
s.addAll(grabFiles(sources));
}
List ms = new ArrayList();
if (moreSources != null) {
ms.addAll(grabFiles(moreSources));
}
Iterator iter = s.iterator();
List toProcess = new ArrayList();
while (iter.hasNext()) {
File thisSource = (File) iter.next();
File t = target;
if (t == null) {
t = getTarget(thisSource);
}
if (isOutOfDate(t, thisSource, ms)) {
toProcess.add(thisSource);
lightSources.add(t);
}
}
if (toProcess.size() != 0) {
runCandle(toProcess);
}
}

/**
* Invoke light on all sources that are newer than their targets.
*/
private void doLight(List lightSources, List moreLightSources) {
List tmp = new ArrayList(lightSources);
tmp.addAll(moreLightSources);
if (isOutOfDate(target, tmp)) {
runLight(lightSources);
}
}

/**
* Run candle passing all files in list on the command line.
*/
private void runCandle(List s) {
run("candle.exe", s, null);
}

/**
* Run light passing all files in list on the command line.
*/
private void runLight(List s) {
run("light.exe", s, target);
}

/**
* Runs the specified command passing list on the command line an
* potentially adding an /out parameter.
*/
private void run(String executable, List s, File target) {
DotNetExecTask exec = DotNetExecTask.getTask(this, vm,
executable, null);
Iterator iter = s.iterator();
while (iter.hasNext()) {
File f = (File) iter.next();
exec.createArg().setValue(f.getAbsolutePath());
}
if (target != null) {
exec.createArg().setValue("/out");
exec.createArg().setValue(target.getAbsolutePath());
}
exec.execute();
}

/**
* Is t older than s or any of the files in list?
*/
private boolean isOutOfDate(File t, File s, List l) {
return t.lastModified() < s.lastModified() || isOutOfDate(t, l);
}

/**
* Is t older than any of the files in list?
*/
private boolean isOutOfDate(File t, List l) {
Iterator iter = l.iterator();
while (iter.hasNext()) {
File f = (File) iter.next();
if (t.lastModified() < f.lastModified()) {
return true;
}
}
return false;
}

/**
* Turn the fileset collection into a list of Files.
*/
private List grabFiles(List s) {
List r = new ArrayList();
Iterator iter = s.iterator();
while (iter.hasNext()) {
FileSet fs = (FileSet) iter.next();
DirectoryScanner ds = fs.getDirectoryScanner(getProject());
String[] f = ds.getIncludedFiles();
File base = fs.getDir(getProject());
for (int i = 0; i < f.length; i++) {
r.add(new File(base, f[i]));
}
}
return r;
}

/**
* Generates the name of a candle target from the source file.
*
* <p>Simply chops of the extension and adds .wixobj.</p>
*/
private File getTarget(File s) {
String name = s.getAbsolutePath();
int dot = name.lastIndexOf(".");
if (dot > -1) {
return new File(name.substring(0, dot) + ".wixobj");
} else {
return new File(name + ".wixobj");
}
}

public static class Mode extends EnumeratedAttribute {
private final static String CANDLE = "candle";
private final static String LIGHT = "light";
private final static String BOTH = "both";

public Mode() {
super();
}

public String[] getValues() {
return new String[] {CANDLE, LIGHT, BOTH,};
}
}
}

+ 0
- 38
proposal/sandbox/dotnet/src/main/org/apache/tools/ant/taskdefs/optional/dotnet/antlib.xml View File

@@ -1,38 +0,0 @@
<?xml version="1.0"?>
<!--
Copyright 2003-2004 The Apache Software Foundation

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<antlib>
<taskdef
name="dotnetexec"
classname="org.apache.tools.ant.taskdefs.optional.dotnet.DotNetExecTask"
/>
<taskdef
name="msbuild"
classname="org.apache.tools.ant.taskdefs.optional.dotnet.MSBuildTask"
/>
<taskdef
name="nant"
classname="org.apache.tools.ant.taskdefs.optional.dotnet.NAntTask"
/>
<taskdef
name="wix"
classname="org.apache.tools.ant.taskdefs.optional.dotnet.WixTask"
/>
<taskdef
name="nunit"
classname="org.apache.tools.ant.taskdefs.optional.dotnet.NUnitTask"
/>
</antlib>

+ 0
- 65
proposal/sandbox/dotnet/src/testcases/org/apache/tools/ant/taskdefs/optional/dotnet/DotNetExecTaskTest.java View File

@@ -1,65 +0,0 @@
/*
* Copyright 2003-2004 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.tools.ant.taskdefs.optional.dotnet;

import org.apache.tools.ant.BuildFileTest;

/**
* Tests the DotNetExecTask task, based off Ant's DotnetTest.
*
*/
public class DotNetExecTaskTest extends BuildFileTest {

/**
* Description of the Field
*/
private final static String TASKDEFS_DIR = "src/etc/testcases/";


/**
* Constructor
*
* @param name testname
*/
public DotNetExecTaskTest(String name) {
super(name);
}


/**
* The JUnit setup method
*/
public void setUp() {
configureProject(TASKDEFS_DIR + "dotnetexec.xml");
}


/**
* The teardown method for JUnit
*/
public void tearDown() {
executeTarget("teardown");
}


/**
* A unit test for JUnit
*/
public void testCSC() throws Exception {
executeTarget("testCSC");
}
}

+ 0
- 64
proposal/sandbox/dotnet/src/testcases/org/apache/tools/ant/taskdefs/optional/dotnet/MSBuildTaskTest.java View File

@@ -1,64 +0,0 @@
/*
* Copyright 2003-2004 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.tools.ant.taskdefs.optional.dotnet;

import org.apache.tools.ant.BuildFileTest;

/**
* Tests the MSBuildTask task.
*/
public class MSBuildTaskTest extends BuildFileTest {

/**
* Description of the Field
*/
private final static String TASKDEFS_DIR = "src/etc/testcases/";

/**
* Constructor
*
* @param name testname
*/
public MSBuildTaskTest(String name) {
super(name);
}

/**
* The JUnit setup method
*/
public void setUp() {
configureProject(TASKDEFS_DIR + "msbuild.xml");
}

public void testEcho() throws Exception {
if (getProject().getProperty("msbuild.found") != null) {
expectLogContaining("echo", "foo is bar");
}
}

public void testNestedFile() throws Exception {
if (getProject().getProperty("msbuild.found") != null) {
expectLogContaining("nested-file", "foo is bar");
}
}

public void testNestedTask() throws Exception {
if (getProject().getProperty("msbuild.found") != null) {
expectLogContaining("nested-task", "foo is bar");
}
}
}

+ 0
- 64
proposal/sandbox/dotnet/src/testcases/org/apache/tools/ant/taskdefs/optional/dotnet/NAntTaskTest.java View File

@@ -1,64 +0,0 @@
/*
* Copyright 2003-2004 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.tools.ant.taskdefs.optional.dotnet;

import org.apache.tools.ant.BuildFileTest;

/**
* Tests the NAntTask task.
*/
public class NAntTaskTest extends BuildFileTest {

/**
* Description of the Field
*/
private final static String TASKDEFS_DIR = "src/etc/testcases/";

/**
* Constructor
*
* @param name testname
*/
public NAntTaskTest(String name) {
super(name);
}

/**
* The JUnit setup method
*/
public void setUp() {
configureProject(TASKDEFS_DIR + "nant.xml");
}

public void testEcho() throws Exception {
if (getProject().getProperty("nant.found") != null) {
expectLogContaining("echo", "foo is bar");
}
}

public void testNestedFile() throws Exception {
if (getProject().getProperty("nant.found") != null) {
expectLogContaining("nested-file", "foo is bar");
}
}

public void testNestedTask() throws Exception {
if (getProject().getProperty("nant.found") != null) {
expectLogContaining("nested-task", "foo is bar");
}
}
}

+ 0
- 79
proposal/sandbox/dotnet/src/testcases/org/apache/tools/ant/taskdefs/optional/dotnet/NUnitTaskTest.java View File

@@ -1,79 +0,0 @@
/*
* Copyright 2004 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.tools.ant.taskdefs.optional.dotnet;

import org.apache.tools.ant.BuildFileTest;

/**
* Tests the NUnitTask task.
*/
public class NUnitTaskTest extends BuildFileTest {

/**
* Description of the Field
*/
private final static String TASKDEFS_DIR = "src/etc/testcases/";

/**
* Constructor
*
* @param name testname
*/
public NUnitTaskTest(String name) {
super(name);
}

/**
* The JUnit setup method
*/
public void setUp() {
configureProject(TASKDEFS_DIR + "nunit.xml");
}

/**
* The teardown method for JUnit
*/
public void tearDown() {
executeTarget("teardown");
}

public void testNoAssembly() {
expectSpecificBuildException("no-assembly", "no assembly",
"You must specify at least one test assembly.");
}

public void testPass() {
if (getProject().getProperty("nunit.found") != null) {
expectLogContaining("passing-test",
"Tests run: 1, Failures: 0, Not run: 0");
}
}

public void testFail() {
if (getProject().getProperty("nunit.found") != null) {
expectLogContaining("failing-test",
"Tests run: 1, Failures: 1, Not run: 0");
}
}

public void testFailOnFail() {
if (getProject().getProperty("nunit.found") != null) {
expectBuildException("failing-test-with-fail", "test should fail");
}
}

}

+ 1
- 20
proposal/sandbox/svn/README View File

@@ -1,20 +1 @@
This library provides Ant task(s) as wrapper(s) over the svn command
line utility.

Alternative approaches like JNI or even a native Java SVN client exist
and have been taken by other teams. In particular we know (this list
is certainly incomplete):

* <http://subclipse.tigris.org/svnant.html> using javahl JNI bindings
of subversion

* <http://tmate.org/svn/ant.html> using a pure Java SVN client

each of which provides Ant tasks.

The task(s) of this library only provides very rudimentary support for
SVN, matching what the traditional Ant task(s) for CVS could do.

If you need more than what this libary provides, we encourage you to
check out the existing alternatives.

Moved to http://svn.apache.org/repos/asf/ant/sandbox/antlibs/svn/trunk/

+ 0
- 91
proposal/sandbox/svn/build.xml View File

@@ -1,91 +0,0 @@
<?xml version="1.0"?>
<!--
Copyright 2005 The Apache Software Foundation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<project default="compile">

<target name="setup">
<property name="build" value="build"/>
<property name="build.classes" value="${build}/classes"/>
<property name="build.testclasses" value="${build}/test-classes"/>
<property name="build.lib" value="${build}/lib"/>
<property name="jarname" value="${build.lib}/ant-svn.jar"/>
<mkdir dir="${build.classes}"/>
<mkdir dir="${build.testclasses}"/>
<mkdir dir="${build.lib}"/>
</target>

<target name="compile" depends="setup">
<javac
srcdir="src/main"
destdir="${build.classes}"
debug="true"
/>
</target>

<target name="antlib" depends="compile">
<copy todir="${build.classes}">
<fileset dir="src/main" includes="**/antlib.xml"/>
</copy>
<jar
destfile="${jarname}"
basedir="${build.classes}"
/>
</target>

<target name="setup-for-tests" depends="setup">
<ant
antfile="../../../build.xml"
target="test-jar"
inheritall="false"
/>
</target>

<target name="compile-tests" depends="setup-for-tests, antlib">
<javac
srcdir="src/testcases"
destdir="${build.testclasses}"
debug="true"
>
<classpath>
<pathelement location="${jarname}"/>
<pathelement location="../../../build/lib/ant-testutil.jar"/>
</classpath>
</javac>
</target>

<target name="test" depends="compile-tests">
<junit
printsummary="false"
haltonfailure="false"
failureproperty="tests.failed"
filtertrace="false"
>
<classpath>
<pathelement location="${jarname}"/>
<pathelement location="../../../build/lib/ant-testutil.jar"/>
<pathelement location="${build.testclasses}"/>
</classpath>

<batchtest>
<fileset dir="src/testcases"/>
</batchtest>

<formatter type="plain" usefile="false"/>
</junit>

<fail if="tests.failed">At least one test has failed.</fail>
</target>
</project>

+ 0
- 217
proposal/sandbox/svn/docs/changelog.html View File

@@ -1,217 +0,0 @@
<html>

<head>
<meta http-equiv="Content-Language" content="en-us">
<title>ChangeLog Task</title>
</head>

<body>

<h2><a name="changelog">ChangeLog</a></h2>
<h3>Description</h3>

<p>Generates an XML-formatted report file of the change logs recorded
in a <a href="http://subversion.tigris.org/"
target="_top">Subversion</a> repository. </p>

<p><b>Important:</b> This task needs "svn" on the path. If it isn't,
you will get an error (such as error 2 on windows). If
<code>&lt;svn&gt;</code> doesn't work, try to execute svn.exe from the
command line in the target directory in which you are working.</p>

<h3>Parameters</h3>
<table border="1" cellpadding="2" cellspacing="0">
<tr>
<td valign="top"><b>Attribute</b></td>
<td valign="top"><b>Description</b></td>
<td align="center" valign="top"><b>Required</b></td>
</tr>
<tr>
<td colspan="3">Attributes from parent <a href="svn.html">svn
task</a> which are meaningful here<br/>
</tr>
<tr>
<td valign="top">svnURL</td>
<td valign="top">the URL the subcommand should apply to.</td>
<td align="center" valign="top">No</td>
</tr>
<tr>
<td valign="top">dest</td>
<td valign="top">the directory where the checked out files are.</td>
<td align="center" valign="top">No, default is project's basedir.</td>
</tr>
<tr>
<td valign="top">failonerror</td>
<td valign="top">Stop the build process if the command exits with a
return code other than <code>0</code>. Defaults to false</td>
<td align="center" valign="top">No</td>
</tr>
<tr>
<td colspan="3">Specific attributes</td>
</tr>
<tr>
<td valign="top">dir</td>
<td valign="top">The directory from which to run the CVS <em>log</em>
command.</td>
<td align="center" valign="top">No; defaults to ${basedir}.</td>
</tr>
<tr>
<td valign="top">destfile</td>
<td valign="top">The file in which to write the change log report.</td>
<td align="center" valign="top">Yes</td>
</tr>
<tr>
<td valign="top">usersfile</td>
<td valign="top">Property file that contains name-value pairs mapping
user IDs and names that should be used in the report in place of
the user ID.</td>
<td align="center" valign="top">No</td>
</tr>
<tr>
<td valign="top">daysinpast</td>
<td valign="top">Sets the number of days into the past for which the
change log information should be retrieved.</td>
<td align="center" valign="top">No</td>
</tr>
<tr>
<td valign="top">start</td>
<td valign="top">The earliest revision/date from which change logs
are to be included in the report.</td>
<td align="center" valign="top">No</td>
</tr>
<tr>
<td valign="top">end</td>
<td valign="top">The latest revision/date to which change logs are to be
included in the report.</td>
<td align="center" valign="top">No</td>
</tr>
</table>

<h3>Parameters specified as nested elements</h3>
<h4><a name="user">user</a></h4>

<p>The nested <code>&lt;user&gt;</code> element allows you to specify
a mapping between a user ID as it appears on the Subversion server and
a name to include in the formatted report. Anytime the specified user
ID has made a change in the repository, the
<code>&lt;author&gt;</code> tag in the report file will include the
name specified in <code>displayname</code> rather than the user
ID.</p>

<table border="1" cellpadding="2" cellspacing="0">
<tr>
<td valign="top"><b>Attribute</b></td>
<td valign="top"><b>Description</b></td>
<td align="center" valign="top"><b>Required</b></td>
</tr>
<tr>
<td valign="top">displayname</td>
<td valign="top">The name to be used in the Subversion change log
report.</td>
<td valign="top" align="center">Yes</td>
</tr>
<tr>
<td valign="top">userid</td>
<td valign="top">The userid of the person as it exists on the
Subversion server.
</td>
<td valign="top" align="center">Yes</td>
</tr>
</table>


<h3>Examples</h3>
<pre> &lt;changelog dir=&quot;dve/network&quot;
destfile=&quot;changelog.xml&quot;
/&gt;</pre>

<p>Generates a change log report for all the changes that have been made
under the <code>dve/network</code> directory.
It writes these changes into the file <code>changelog.xml</code>.</p>

<pre> &lt;changelog dir=&quot;dve/network&quot;
destfile=&quot;changelog.xml&quot;
daysinpast=&quot;10&quot;
/&gt;</pre>

<p>Generates a change log report for any changes that were made
under the <code>dve/network</code> directory in the past 10 days.
It writes these changes into the file <code>changelog.xml</code>.</p>

<pre> &lt;changelog dir=&quot;dve/network&quot;
destfile=&quot;changelog.xml&quot;
start=&quot;{2002-02-20}&quot;
end=&quot;{2002-03-20}&quot;
/&gt;</pre>

<p>Generates a change log report for any changes that were made
between February 20, 2002 and March 20, 2002
under the <code>dve/network</code> directory.
It writes these changes into the file <code>changelog.xml</code>.</p>

<pre> &lt;changelog dir=&quot;dve/network&quot;
destfile=&quot;changelog.xml&quot;
start=&quot;{2002-02-20}&quot;
/&gt;</pre>

<p>Generates a change log report for any changes that were made
after February 20, 2002 under the <code>dve/network</code> directory.
It writes these changes into the file <code>changelog.xml</code>.</p>

<pre> &lt;changelog dir=&quot;dve/network&quot;
destfile=&quot;changelog.xml&quot;
start=&quot;1000&quot;
end=&quot;1500&quot;
/&gt;</pre>

<p>Generates a change log report for any changes that were made
between Subversion revisions 1000 and 1500 under the
<code>dve/network</code> directory. It writes these changes into the
file <code>changelog.xml</code>.</p>

<pre> &lt;changelog dir=&quot;dve/network&quot;
destfile=&quot;changelog.xml&quot;&gt;
&lt;user displayname=&quot;Esmerelda Weatherwax&quot; userid=&quot;granny&quot;/&gt;
&lt;/changelog&gt;</pre>

<p>Generates a change log report for all the changes that were made
under the <code>dve/network</code> directory, substituting the name
&quot;Esmerelda Weatherwax&quot; in the <code>&lt;author&gt;</code> tags
anytime it encounters a change made by the user ID &quot;granny&quot;.
It writes these changes into the file <code>changelog.xml</code>.</p>

<h4>Generate Report</h4>
<p>This antlib includes a basic XSLT stylesheet that you can use to
generate a HTML report based on the xml output. The following example
illustrates how to generate a HTML report from the XML report.</p>

<pre>
&lt;style in="changelog.xml"
out="changelog.html"
style="your-path-to/etc/changelog.xsl"&gt;
&lt;param name="title" expression="Jakarta BCEL ChangeLog"/&gt;
&lt;param name="repo" expression="http://svn.apache.org/repos/asf"/&gt;
&lt;/style&gt;
</pre>

<h4>Sample Output</h4>
<pre>
&lt;entry&gt;
&lt;date&gt;2005-02-14&lt;/date&gt;
&lt;time&gt;01:55&lt;/time&gt;
&lt;author&gt;&lt;![CDATA[dbrosius]]&gt;&lt;/author&gt;
&lt;revision&gt;153687&lt;/revision&gt;
&lt;path&gt;
&lt;name&gt;&lt;![CDATA[/jakarta/bcel/trunk/src/java/org/apache/bcel/util/BCELifier.java]]&gt;&lt;/name&gt;
&lt;action&gt;modified&lt;/action&gt;
&lt;/path&gt;
&lt;message&gt;&lt;![CDATA[Update BCELifier to handle the new method access flags (ACC_BRIDGE, ACC_VARARGS)]]&gt;&lt;/message&gt;
&lt;/entry&gt;
</pre>

<hr><p align="center">Copyright &copy; 2005 The Apache Software Foundation. All rights
Reserved.</p>

</body>
</html>


+ 0
- 129
proposal/sandbox/svn/docs/revisiondiff.html View File

@@ -1,129 +0,0 @@
<html>
<head>
<meta http-equiv="Content-Language" content="en-us">
<title>RevisionDiff Task</title>
</head>
<body>
<h2><a name="revisiondiff">RevisionDiff</a></h2>
<h3>Description</h3>

<p>Generates an XML-formatted report file of the changes between two
revisions recorded in a <a href="http://subversion.tigris.org/"
target="_top">Subversion</a> repository. </p>

<p><b>Important:</b> This task needs "svn" on the path. If it isn't,
you will get an error (such as error 2 on windows). If
<code>&lt;svn&gt;</code> doesn't work, try to execute
<code>svn.exe</code> from the command line in the target directory in
which you are working.</p>

<h3>Parameters</h3>
<table border="1" cellpadding="2" cellspacing="0">
<tr>
<td valign="top"><b>Attribute</b></td>
<td valign="top"><b>Description</b></td>
<td align="center" valign="top"><b>Required</b></td>
</tr>
<tr>
<td valign="top">start</td>
<td valign="top">The earliest revision from which diffs are to be
included in the report.</td>
<td align="center" valign="top">Yes.</td>
</tr>
<tr>
<td valign="top">end</td>
<td valign="top">The latest revision from which diffs are to be
included in the report.</td>
<td align="center" valign="top">Yes.</td>
</tr>
<tr>
<td valign="top">destfile</td>
<td valign="top">The file in which to write the diff report.</td>
<td align="center" valign="top">Yes</td>
</tr>
</table>

<h3>Parameters inherited from the <code>svn</code> task</h3>
<table border="1" cellpadding="2" cellspacing="0">
<tr>
<td valign="top"><b>Attribute</b></td>
<td valign="top"><b>Description</b></td>
<td align="center" valign="top"><b>Required</b></td>
</tr>
<tr>
<td valign="top">svnURL</td>
<td valign="top">the svn URL to diff.</td>
<td align="center" valign="top">No</td>
</tr>
<tr>
<td valign="top">failonerror</td>
<td valign="top">Stop the buildprocess if the command exits with a
returncode other than 0. Defaults to false</td>
<td align="center" valign="top">No</td>
</tr>
</table>

<h3>Examples</h3>
<pre> &lt;revisiondiff
svnURL=&quot;http://svn.apache.org/repos/asf/jakarta/bcel/trunk&quot;
destfile=&quot;diff.xml&quot;
start=&quot;152904&quot;
end=&quot;153682&quot;
/&gt;</pre>

<p>Generates a revisiondiff report for all the changes that have been
made in the <code>Apache BCEL</code> module between the revisions
<code>152904</code> and <code>153682</code>. It writes these changes
into the file <code>diff.xml</code>.</p>

<pre> &lt;revisiondiff
destfile=&quot;diff.xml&quot;
package=&quot;ant&quot;
start=&quot;{2002-01-01}&quot;
end=&quot;{2002-02-01}&quot;
dest=&quot;my-working-copy-of-BCEL&quot;
/&gt;</pre>

<p>Generates a diff report for all the changes that have been made in
the <code>Apache BCEL</code> module in january 2002. In this example
<code>svnURL</code> has not been set, it is assumed that
<code>my-working-copy-of-BCEL</code> contains a checked out copy of
the BCEL module. It writes these changes into the file
<code>diff.xml</code>.</p>

<h4>Generate Report</h4>

<p>This antlib includes a basic XSLT stylesheet that you can use to
generate a HTML report based on the xml output. The following example
illustrates how to generate a HTML report from the XML report.</p>

<pre>
&lt;style in="diff.xml"
out="diff.html"
style="your-path-to/etc/diff.xsl"&gt;
&lt;param name="title" expression="Jakarta BCEL diff"/&gt;
&lt;param name="repo" expression="http://svn.apache.org/repos/asf/jakarta/bcel/trunk"/&gt;
&lt;/style&gt;
</pre>

<h4>(Shortened) Example Output</h4>
<pre>
&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;revisiondiff start="153872" end="152873" svnurl="http://svn.apache.org/repos/asf/jakarta/bcel/trunk" &gt;
&lt;path&gt;
&lt;name&gt;&lt;![CDATA[LICENSE.txt]]&gt;&lt;/name&gt;
&lt;action&gt;modified&lt;/action&gt;
&lt;/path&gt;
&lt;path&gt;
&lt;name&gt;&lt;![CDATA[NOTICE.txt]]&gt;&lt;/name&gt;
&lt;action&gt;deleted&lt;/action&gt;
&lt;/path&gt;
&lt;/revisiondiff&gt;
</pre>

<hr><p align="center">Copyright &copy; 2005 The Apache Software Foundation. All rights
Reserved.</p>

</body>
</html>


+ 0
- 157
proposal/sandbox/svn/docs/svn.html View File

@@ -1,157 +0,0 @@
<html>

<head>
<meta http-equiv="Content-Language" content="en-us">
<title>Subversion Task</title>
<link rel="stylesheet" type="text/css" href="../stylesheets/antmanual.css">
</head>

<body>

<h2><a name="svn">SVN</a></h2>
<h3>Description</h3>
<p>Handles packages/modules retrieved from a
<a href="http://subversion.tigris.org/" target="_top">Subversion</a> repository.</p>
<p><b>Important:</b> This task needs &quot;<code>svn</code>&quot; on the path. If it isn't, you will get
an error (such as error <code>2</code> on windows). If <code>&lt;svn&gt;</code> doesn't work, try to execute <code>svn.exe</code>
from the command line in the target directory in which you are working.
<h3>Parameters</h3>
<table border="1" cellpadding="2" cellspacing="0">
<tr>
<td valign="top"><b>Attribute</b></td>
<td valign="top"><b>Description</b></td>
<td align="center" valign="top"><b>Required</b></td>
</tr>
<tr>
<td valign="top">subcommand</td>
<td valign="top">the SVN subcommand to execute.</td>
<td align="center" valign="top">No, default &quot;checkout&quot;.</td>
</tr>
<tr>
<td valign="top">svnURL</td>
<td valign="top">the URL the subcommand should apply to.</td>
<td align="center" valign="top">No</td>
</tr>
<tr>
<td valign="top">dest</td>
<td valign="top">the directory where the checked out files should
be placed. Note that this is different from SVN's <code>-d</code> command line
switch as Ant will never shorten pathnames to avoid empty
directories.</td>
<td align="center" valign="top">No, default is project's basedir.</td>
</tr>
<tr>
<td valign="top">revision</td>
<td valign="top">the revision or date of the subcommand should apply to</td>
<td align="center" valign="top">No</td>
</tr>
<tr>
<td valign="top">quiet</td>
<td valign="top">suppress informational messages. This is the same as <code>--quiet</code> on the command line.</td>
<td align="center" valign="top">No, default &quot;false&quot;</td>
</tr>
<tr>
<td valign="top">verbose</td>
<td valign="top">Be verbose. This is the same as <code>--verbose</code> on the command line.</td>
<td align="center" valign="top">No, default &quot;false&quot;</td>
</tr>
<tr>
<td valign="top">dryrun</td>
<td valign="top">report only, don't change any files.</td>
<td align="center" valign="top">No, default to &quot;false&quot;</td>
</tr>
<tr>
<td valign="top">file</td>
<td valign="top">Uses the contents of the file passed as an
argument to this switch for the specified subcommand.</td>
<td align="center" valign="top">No.</td>
</tr>
<tr>
<td valign="top">force</td>
<td valign="top">Forces a particular command or operation to run.</td>
<td align="center" valign="top">No, defaults to false.</td>
</tr>
<tr>
<td valign="top">recursive</td>
<td valign="top">Makes a subcommand recurse into
subdirectories. Most subcommands recurse by default.</td>
<td align="center" valign="top">No.</td>
</tr>
<tr>
<td valign="top">targets</td>
<td valign="top">Tells Subversion to get the list of files that you wish to
operate on from the filename you provide instead of listing all
the files on the command line.</td>
<td align="center" valign="top">No.</td>
</tr>
<tr>
<td valign="top">output</td>
<td valign="top">the file to direct standard output from the command.</td>
<td align="center" valign="top">No, default output to ANT Log as <code>MSG_INFO</code>.</td>
</tr>
<tr>
<td valign="top">error</td>
<td valign="top">the file to direct standard error from the command.</td>
<td align="center" valign="top">No, default error to ANT Log as <code>MSG_WARN</code>.</td>
</tr>
<tr>
<td valign="top">append</td>
<td valign="top">whether to append output/error when redirecting to a file.</td>
<td align="center" valign="top">No, default to &quot;false&quot;.</td>
</tr>
<tr>
<td valign="top">failonerror</td>
<td valign="top">Stop the build process if the command exits with a
return code other than <code>0</code>. Defaults to &quot;false&quot;</td>
<td align="center" valign="top">No</td>
</tr>
</table>
<h3>Examples</h3>
<pre> &lt;svn svnURL=&quot;http://svn.apache.org/repos/asf/httpd/httpd/trunk/&quot;
dest=&quot;${ws.dir}&quot;
/&gt;</pre>
<p>checks out the URL
&quot;http://svn.apache.org/repos/asf/httpd/httpd/trunk/&quot; and
stores the files in &quot;<code>${ws.dir}</code>&quot;.</p>
<pre> &lt;svn dest=&quot;${ws.dir}&quot; command=&quot;update&quot;/&gt;</pre>
<p>updates the working copy that has previously been checked out into
&quot;<code>${ws.dir}</code>&quot;.</p>

<pre> &lt;svn command=&quot;-q diff&quot; output=&quot;patch.txt&quot;/&gt;</pre>

<p>silently (<code>-q</code>) creates a file called <code>patch.txt</code> which contains a unified diff which can be used as input to patch.
The equivalent, using <code>&lt;commandline&gt;</code> elements, is:
</p>
<pre>
&lt;svn output=&quot;patch&quot;&gt;
&lt;commandline&gt;
&lt;argument value=&quot;-q&quot;/&gt;
&lt;argument value=&quot;diff&quot;/&gt;
&lt;/commandline&gt;
&lt;/svn&gt;
</pre>
or:
<pre>
&lt;svn output=&quot;patch&quot;&gt;
&lt;commandline&gt;
&lt;argument line=&quot;-q diff -u -N&quot;/&gt;
&lt;/commandline&gt;
&lt;/svn&gt;
</pre>
<p>
You may include as many <code>&lt;commandline&gt;</code> elements as you like.
Each will inherit the <code>failonerror</code> and other &quot;global&quot; parameters
from the <code>&lt;svn&gt;</code> element.
</p>

<pre> &lt;svn command=&quot;update&quot;/&gt;</pre>
<p>Updates from the head of repository creating any new directories as necessary.</p>
<p>See <a href="http://svnbook.red-bean.com/en/1.1/ch09.html#svn-ch-9-sect-1" target="_top">Version Control with Subversion</a> for details,
specifically the <a href="http://svnbook.red-bean.com/en/1.1/ch09.html#svn-ch-9-sect-1" target="_top">The Subversion Command Line Client: svn</a></p>
<hr>
<p align="center">Copyright &copy; 2005 The Apache Software
Foundation. All rights Reserved.</p>

</body>
</html>


+ 0
- 158
proposal/sandbox/svn/docs/tagdiff.html View File

@@ -1,158 +0,0 @@
<html>
<head>
<meta http-equiv="Content-Language" content="en-us">
<title>RevisionDiff Task</title>
</head>
<body>
<h2><a name="tagdiff">TagDiff</a></h2>
<h3>Description</h3>

<p>Generates an XML-formatted report file of the changes between two
tags recorded in a <a href="http://subversion.tigris.org/"
target="_top">Subversion</a> repository. </p>

<p><b>Important:</b> This task needs "svn" on the path. If it isn't,
you will get an error (such as error 2 on windows). If
<code>&lt;svn&gt;</code> doesn't work, try to execute
<code>svn.exe</code> from the command line in the target directory in
which you are working.</p>

<p>This task assumes that your repository follows the best-practice
layout of</p>
<pre>
BASEURL
|
|
-----&gt; trunk
-----&gt; tags
|
|
----------&gt; tag1
----------&gt; tag2
</pre>

<h3>Parameters</h3>
<table border="1" cellpadding="2" cellspacing="0">
<tr>
<td valign="top"><b>Attribute</b></td>
<td valign="top"><b>Description</b></td>
<td align="center" valign="top"><b>Required</b></td>
</tr>
<tr>
<td valign="top">tag1</td>
<td valign="top">The first tag.</td>
<td align="center" valign="top">Yes.</td>
</tr>
<tr>
<td valign="top">tag2</td>
<td valign="top">The second tag.</td>
<td align="center" valign="top">No, defaults to "trunk/"</td>
</tr>
<tr>
<td valign="top">destfile</td>
<td valign="top">The file in which to write the diff report.</td>
<td align="center" valign="top">Yes</td>
</tr>
<tr>
<td valign="top">baseURL</td>
<td valign="top">The baseURL of the repository, used to calculate
the two URLs to compare.</td>
<td align="center" valign="top">Yes</td>
</tr>
</table>

<h3>Parameters inherited from the <code>svn</code> task</h3>
<table border="1" cellpadding="2" cellspacing="0">
<tr>
<td valign="top"><b>Attribute</b></td>
<td valign="top"><b>Description</b></td>
<td align="center" valign="top"><b>Required</b></td>
</tr>
<tr>
<td valign="top">failonerror</td>
<td valign="top">Stop the buildprocess if the command exits with a
returncode other than 0. Defaults to false</td>
<td align="center" valign="top">No</td>
</tr>
</table>

<h3>Examples</h3>
<pre>
&lt;tagdiff failonerror="true"
baseURL="http://svn.apache.org/repos/asf/jakarta/bcel/"
destfile="diff.xml"
tag1="initial"
tag2="BCEL_5_0"
/&gt;
</pre>

<p>Generates a tagdiff report for all the changes that have been
made in the <code>Apache BCEL</code> module between the tags
<code>initial</code> and <code>BCEL_5_0</code>. It writes these changes
into the file <code>diff.xml</code>.</p>

<pre>
&lt;tagdiff failonerror="true"
baseURL="http://svn.apache.org/repos/asf/jakarta/bcel/"
destfile="diff.xml"
tag1="BCEL_5_0"
tag2="trunk"
/&gt;
</pre>

<p>Generates a tagdiff report for all the changes that have been made
in the <code>Apache BCEL</code> module between the tag
<code>BCEL_5_0</code> and the <code>trunk</code>. It writes these
changes into the file <code>diff.xml</code>.</p>

<pre>
&lt;tagdiff failonerror="true"
baseURL="http://svn.apache.org/repos/asf/jakarta/bcel/"
destfile="diff.xml"
tag1="BCEL_5_0"
/&gt;
</pre>

<p>Does the same, using <code>trunk</code> as <code>tag2</code>
implicitly.</p>

<h4>Generate Report</h4>

<p>This antlib includes a basic XSLT stylesheet that you can use to
generate a HTML report based on the xml output. The following example
illustrates how to generate a HTML report from the XML report.</p>

<pre>
&lt;style in="diff.xml"
out="diff.html"
style="your-path-to/etc/diff.xsl"&gt;
&lt;param name="title" expression="Jakarta BCEL diff"/&gt;
&lt;param name="repo" expression="http://svn.apache.org/repos/asf/jakarta/bcel/trunk"/&gt;
&lt;/style&gt;
</pre>

<h4>(Shortened) Example Output</h4>
<pre>
&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;tagdiff tag1="BCEL_5_0" svnurl="http://svn.apache.org/repos/asf/jakarta/bcel/" &gt;
&lt;path&gt;
&lt;name&gt;&lt;![CDATA[default.properties]]&gt;&lt;/name&gt;
&lt;action&gt;added&lt;/action&gt;
&lt;/path&gt;
&lt;path&gt;
&lt;name&gt;&lt;![CDATA[xdocs/images/classloader.gif]]&gt;&lt;/name&gt;
&lt;action&gt;modified&lt;/action&gt;
&lt;/path&gt;
&lt;path&gt;
&lt;name&gt;&lt;![CDATA[README]]&gt;&lt;/name&gt;
&lt;action&gt;deleted&lt;/action&gt;
&lt;/path&gt;
&lt;/tagdiff&gt;
</pre>

<hr><p align="center">Copyright &copy; 2005 The Apache Software Foundation. All rights
Reserved.</p>

</body>
</html>


+ 0
- 137
proposal/sandbox/svn/src/etc/changelog.xsl View File

@@ -1,137 +0,0 @@
<?xml version="1.0" encoding="ISO-8859-1"?>

<xsl:stylesheet
xmlns:xsl='http://www.w3.org/1999/XSL/Transform'
version='1.0'>

<!--
Copyright 2005 The Apache Software Foundation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<xsl:param name="title"/>
<xsl:param name="repo"/>

<xsl:output method="html" indent="yes" encoding="US-ASCII"
doctype-public="-//W3C//DTD HTML 4.01//EN"
doctype-system="http://www.w3.org/TR/html401/strict.dtd"/>

<!-- Copy standard document elements. Elements that
should be ignored must be filtered by apply-templates
tags. -->
<xsl:template match="*">
<xsl:copy>
<xsl:copy-of select="attribute::*[. != '']"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>

<xsl:template match="changelog">
<html>
<head>
<title><xsl:value-of select="$title"/></title>
<style type="text/css">
body, p {
font-family: Verdana, Arial, Helvetica, sans-serif;
font-size: 80%;
color: #000000;
background-color: #ffffff;
}
tr, td {
font-family: Verdana, Arial, Helvetica, sans-serif;
background: #eeeee0;
}
td {
padding-left: 20px;
}
.dateAndAuthor {
font-family: Verdana, Arial, Helvetica, sans-serif;
font-weight: bold;
text-align: left;
background: #a6caf0;
padding-left: 3px;
}
a {
color: #000000;
}
pre {
font-weight: bold;
}
</style>
</head>
<body>
<h1>
<a name="top"><xsl:value-of select="$title"/></a>
</h1>
<p style="text-align: right">Designed for use with <a href="http://ant.apache.org/">Apache Ant</a>.</p>
<hr/>
<table border="0" width="100%" cellspacing="1">
<xsl:apply-templates select=".//entry">
<xsl:sort select="date" data-type="text" order="descending"/>
<xsl:sort select="time" data-type="text" order="descending"/>
</xsl:apply-templates>
</table>
</body>
</html>
</xsl:template>
<xsl:template match="entry">
<tr>
<td class="dateAndAuthor">
<xsl:value-of select="date"/><xsl:text> </xsl:text><xsl:value-of select="time"/><xsl:text> </xsl:text><xsl:value-of select="author"/>
</td>
</tr>
<tr>
<td>
<pre>
<xsl:apply-templates select="message"/></pre>
<ul>
<xsl:apply-templates select="path"/>
</ul>
</td>
</tr>
</xsl:template>

<xsl:template match="date">
<i><xsl:value-of select="."/></i>
</xsl:template>

<xsl:template match="time">
<i><xsl:value-of select="."/></i>
</xsl:template>

<xsl:template match="author">
<i>
<xsl:value-of select="."/>
</i>
</xsl:template>

<xsl:template match="path">
<li>
<a>
<xsl:attribute name="href"><xsl:value-of select="$repo"/><xsl:value-of select="name"/></xsl:attribute><xsl:value-of select="$repo"/><xsl:value-of select="name"/></a>
(<xsl:value-of select="action"/>)
</li>
</xsl:template>

<!-- Any elements within a message are processed,
so that we can preserve HTML tags. -->
<xsl:template match="message">
<xsl:apply-templates/>
</xsl:template>
</xsl:stylesheet>

+ 0
- 140
proposal/sandbox/svn/src/etc/diff.xsl View File

@@ -1,140 +0,0 @@
<!--
Copyright 2005 The Apache Software Foundation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:param name="title"/>
<xsl:param name="repo"/>

<xsl:output method="html" indent="yes"/>

<!-- Copy standard document elements. Elements that
should be ignored must be filtered by apply-templates
tags. -->
<xsl:template match="*">
<xsl:copy>
<xsl:copy-of select="attribute::*[. != '']"/>
<xsl:apply-templates/>
</xsl:copy>
</xsl:template>

<xsl:template match="revisiondiff|tagdiff">
<HTML>
<HEAD>
<TITLE><xsl:value-of select="$title"/></TITLE>
</HEAD>
<BODY link="#000000" alink="#000000" vlink="#000000" text="#000000">
<style type="text/css">
body, p {
font-family: verdana,arial,helvetica;
font-size: 80%;
color:#000000;
}
.dateAndAuthor {
font-family: verdana,arial,helvetica;
font-size: 80%;
font-weight: bold;
text-align:left;
background:#a6caf0;
}
tr, td{
font-family: verdana,arial,helvetica;
font-size: 80%;
background:#eeeee0;
}
</style>
<h1>
<a name="top"><xsl:value-of select="$title"/></a>
</h1>
diff between <xsl:value-of select="@start"/><xsl:value-of select="@tag1"/> and <xsl:value-of select="@end"/><xsl:value-of select="@tag2"/>
<p align="right">Designed for use with <a href="http://ant.apache.org/">Apache Ant</a>.</p>
<hr size="2"/>
<a name="TOP"/>
<table width="100%">
<tr>
<td align="right">
<a href="#New">New Files</a> |
<a href="#Modified">Modified Files</a> |
<a href="#Removed">Removed Files</a>
</td>
</tr>
</table>
<TABLE BORDER="0" WIDTH="100%" CELLPADDING="3" CELLSPACING="1">
<xsl:call-template name="show-paths">
<xsl:with-param name="title">New Files</xsl:with-param>
<xsl:with-param name="anchor">New</xsl:with-param>
<xsl:with-param name="paths" select=".//path[action='added']"/>
</xsl:call-template>

<xsl:call-template name="show-paths">
<xsl:with-param name="title">Modified Files</xsl:with-param>
<xsl:with-param name="anchor">Modified</xsl:with-param>
<xsl:with-param name="paths" select=".//path[action='modified']"/>
</xsl:call-template>

<xsl:call-template name="show-paths">
<xsl:with-param name="title">Removed Files</xsl:with-param>
<xsl:with-param name="anchor">Removed</xsl:with-param>
<xsl:with-param name="paths" select=".//path[action='deleted']"/>
</xsl:call-template>
</TABLE>
</BODY>
</HTML>
</xsl:template>

<xsl:template name="show-paths">
<xsl:param name="title"/>
<xsl:param name="anchor"/>
<xsl:param name="paths"/>
<TR>
<TD colspan="2" class="dateAndAuthor">
<a>
<xsl:attribute name="name"><xsl:value-of select="$anchor"/></xsl:attribute>
<xsl:value-of select="$title"/> - <xsl:value-of select="count($paths)"/> entries
</a>
<a href="#TOP">(back to top)</a>
</TD>
</TR>
<TR>
<TD width="20">
<xsl:text> </xsl:text>
</TD>
<TD>
<ul>
<xsl:apply-templates select="$paths"/>
</ul>
</TD>
</TR>
</xsl:template>

<xsl:template match="path">
<li>
<a target="_new">
<xsl:attribute name="href"><xsl:value-of select="$repo"/>/<xsl:value-of select="name" /></xsl:attribute>
<xsl:value-of select="name" />
</a>
</li>
</xsl:template>

<!-- Any elements within a msg are processed,
so that we can preserve HTML tags. -->
<xsl:template match="msg">
<b><xsl:apply-templates/></b>
</xsl:template>
</xsl:stylesheet>

+ 0
- 64
proposal/sandbox/svn/src/etc/testcases/abstractsvntask.xml View File

@@ -1,64 +0,0 @@
<?xml version="1.0"?>

<!--
Copyright 2005 The Apache Software Foundation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->

<project name="abstractsvntask-test" basedir="../../../"
default="all" xmlns:svn="antlib:org.apache.tools.ant.taskdefs.svn">

<property name="tmpdir" value="tmpdir"/>
<property name="tpfdir" value="${tmpdir}/tpf"/>
<property name="file" value="ebcdic.h"/>

<target name="setup">
<mkdir dir="${tmpdir}"/>
<svn:svn
svnURL="http://svn.apache.org/repos/asf/httpd/httpd/trunk/os/tpf/"
dest="${tmpdir}"/>
</target>

<target name="all" depends="setup">
<svn:svn failonerror="true" subcommand="status ${file}" dest="${tpfdir}"/>
<svn:svn failonerror="true" dest="${tpfdir}">
<commandline>
<argument value="up"/>
<argument value="-r"/>
<argument value="83750"/>
<argument value="${file}"/>
</commandline>
</svn:svn>
<svn:svn failonerror="true" subcommand="status ${file}" dest="${tpfdir}"/>
<svn:svn failonerror="true" dest="${tpfdir}">
<commandline>
<argument line="up -r HEAD ${file}" />
</commandline>
</svn:svn>
<svn:svn failonerror="true" subcommand="status ${file}" dest="${tpfdir}"/>
</target>

<target name="revision-attribute">
<mkdir dir="${tmpdir}" />
<svn:svn
svnURL="http://svn.apache.org/repos/asf/httpd/httpd/trunk/os/tpf"
dest="${tmpdir}"
quiet="false"
revision="83750"/>
</target>

<target name="cleanup">
<delete dir="${tmpdir}" />
</target>
</project>

+ 0
- 69
proposal/sandbox/svn/src/etc/testcases/changelog.xml View File

@@ -1,69 +0,0 @@
<?xml version="1.0"?>

<!--
Copyright 2005 The Apache Software Foundation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->

<project name="changelog-test" basedir="../../../"
default="log" xmlns:svn="antlib:org.apache.tools.ant.taskdefs.svn">

<property name="tmpdir" value="tmpdir"/>
<property name="trunkdir" value="${tmpdir}/trunk"/>

<target name="setup">
<mkdir dir="${tmpdir}"/>
<svn:svn
svnURL="http://svn.apache.org/repos/asf/jakarta/bcel/trunk"
dest="${tmpdir}"/>
</target>

<target name="log" depends="setup">
<svn:changelog failonerror="true" dest="${trunkdir}"
destfile="${tmpdir}/log.xml" />
</target>

<target name="start" depends="setup">
<svn:changelog failonerror="true" dest="${trunkdir}"
destfile="${tmpdir}/log.xml" start="153000"/>
</target>

<target name="startDate" depends="setup">
<svn:changelog failonerror="true" dest="${trunkdir}"
destfile="${tmpdir}/log.xml" start="{2005-02-10}"/>
</target>

<target name="end" depends="setup">
<svn:changelog failonerror="true" dest="${trunkdir}"
destfile="${tmpdir}/log.xml" end="153000"/>
</target>

<target name="endDate" depends="setup">
<svn:changelog failonerror="true" dest="${trunkdir}"
destfile="${tmpdir}/log.xml" end="{2005-02-10}"/>
</target>

<target name="report" depends="start">
<style in="${tmpdir}/log.xml"
out="${tmpdir}/log.html"
style="src/etc/changelog.xsl">
<param name="title" expression="Jakarta BCEL ChangeLog"/>
<param name="repo" expression="http://svn.apache.org/repos/asf"/>
</style>
</target>

<target name="cleanup">
<delete dir="${tmpdir}" />
</target>
</project>

+ 0
- 58
proposal/sandbox/svn/src/etc/testcases/revisiondiff.xml View File

@@ -1,58 +0,0 @@
<?xml version="1.0"?>

<!--
Copyright 2005 The Apache Software Foundation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->

<project name="revisiondiff-test" basedir="../../../"
default="diff" xmlns:svn="antlib:org.apache.tools.ant.taskdefs.svn">

<property name="tmpdir" value="tmpdir"/>
<property name="trunkdir" value="${tmpdir}/trunk"/>

<target name="dir-prep">
<mkdir dir="${tmpdir}"/>
</target>

<target name="setup" depends="dir-prep">
<svn:svn
svnURL="http://svn.apache.org/repos/asf/jakarta/bcel/trunk"
dest="${tmpdir}"/>
</target>

<target name="diff" depends="setup">
<svn:revisiondiff failonerror="true" dest="${trunkdir}"
destfile="${tmpdir}/diff.xml" start="152904" end="153682"/>
</target>

<target name="diff-using-url" depends="dir-prep">
<svn:revisiondiff failonerror="true"
svnURL="http://svn.apache.org/repos/asf/jakarta/bcel/trunk"
destfile="${tmpdir}/diff.xml" start="152904" end="153682"/>
</target>

<target name="report" depends="diff-using-url">
<style in="${tmpdir}/diff.xml"
out="${tmpdir}/diff.html"
style="src/etc/diff.xsl">
<param name="title" expression="Jakarta BCEL diff"/>
<param name="repo" expression="http://svn.apache.org/repos/asf/jakarta/bcel/trunk"/>
</style>
</target>

<target name="cleanup">
<delete dir="${tmpdir}" />
</target>
</project>

+ 0
- 63
proposal/sandbox/svn/src/etc/testcases/tagdiff.xml View File

@@ -1,63 +0,0 @@
<?xml version="1.0"?>

<!--
Copyright 2005 The Apache Software Foundation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->

<project name="revisiondiff-test" basedir="../../../"
default="diff-with-implicit-trunk"
xmlns:svn="antlib:org.apache.tools.ant.taskdefs.svn">

<property name="tmpdir" value="tmpdir"/>

<target name="dir-prep">
<mkdir dir="${tmpdir}"/>
</target>

<target name="diff-with-two-tags" depends="dir-prep">
<svn:tagdiff failonerror="true"
baseURL="http://svn.apache.org/repos/asf/jakarta/bcel/"
destfile="${tmpdir}/diff.xml"
tag2="BCEL_5_0" tag1="initial"/>
</target>

<target name="diff-with-explicit-trunk" depends="dir-prep">
<svn:tagdiff failonerror="true"
baseURL="http://svn.apache.org/repos/asf/jakarta/bcel/"
destfile="${tmpdir}/diff.xml"
tag1="BCEL_5_0" tag2="trunk"/>
</target>

<target name="diff-with-implicit-trunk" depends="dir-prep">
<svn:tagdiff failonerror="true"
baseURL="http://svn.apache.org/repos/asf/jakarta/bcel/"
destfile="${tmpdir}/diff.xml"
tag1="BCEL_5_0"/>
</target>

<!--target name="report" depends="diff-with-implicit-trunk"-->
<target name="report">
<style in="/tmp/diff.xml"
out="/tmp/diff.html"
style="src/etc/diff.xsl">
<param name="title" expression="Jakarta BCEL diff"/>
<param name="repo" expression="http://svn.apache.org/repos/asf/jakarta/bcel/trunk"/>
</style>
</target>

<target name="cleanup">
<delete dir="${tmpdir}" />
</target>
</project>

+ 0
- 699
proposal/sandbox/svn/src/main/org/apache/tools/ant/taskdefs/svn/AbstractSvnTask.java View File

@@ -1,699 +0,0 @@
/*
* Copyright 2005 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

package org.apache.tools.ant.taskdefs.svn;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.Vector;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.taskdefs.Execute;
import org.apache.tools.ant.taskdefs.ExecuteStreamHandler;
import org.apache.tools.ant.taskdefs.LogOutputStream;
import org.apache.tools.ant.taskdefs.PumpStreamHandler;
import org.apache.tools.ant.types.Commandline;
import org.apache.tools.ant.types.Environment;
import org.apache.tools.ant.util.StringUtils;

/**
* Just like Ant's built-in CVS task, the main loginc lives in this
* abstract task.
*/
public abstract class AbstractSvnTask extends Task {

private Commandline cmd = new Commandline();

/** list of Commandline children */
private Vector vecCommandlines = new Vector();

/**
* the URL the subcommand should apply to.
*/
private String svnURL;

/**
* the revision
*/
private String revision;
/**
* the default command.
*/
private static final String DEFAULT_SUBCOMMAND = "checkout";
/**
* the SVN command to execute.
*/
private String subCommand = null;

/**
* suppress information messages.
*/
private boolean quiet = false;

/**
* be verbose
*/
private boolean verbose = false;

/**
* report only, don't change any files.
*/
private boolean dryrun = false;

/**
* the directory where the checked out files should be placed.
*/
private File dest;

/** whether or not to append stdout/stderr to existing files */
private boolean append = false;

/**
* the file to direct standard output from the command.
*/
private File output;

/**
* the file to direct standard error from the command.
*/
private File error;

/**
* If true it will stop the build if svn exits with error.
* Default is false. (Iulian)
*/
private boolean failOnError = false;

/**
* Uses the contents of the file passed as an argument to this
* switch for the specified subcommand.
*/
private File file;

/**
* Forces a particular command or operation to run.
*/
private boolean force;

/**
* Makes a subcommand recurse into subdirectories.
*/
private Boolean recursive = null;

/**
* Tells Subversion to get the list of files that you wish to
* operate on from the filename you provide instead of listing all
* the files on the command line.
*/
private File targets;

/**
* Create accessors for the following, to allow different handling of
* the output.
*/
private ExecuteStreamHandler executeStreamHandler;
private OutputStream outputStream;
private OutputStream errorStream;

/** empty no-arg constructor*/
public AbstractSvnTask() {
super();
}

/**
* sets the handler
* @param handler a handler able of processing the output and error streams from the svn exe
*/
public void setExecuteStreamHandler(ExecuteStreamHandler handler) {
this.executeStreamHandler = handler;
}

/**
* find the handler and instantiate it if it does not exist yet
* @return handler for output and error streams
*/
protected ExecuteStreamHandler getExecuteStreamHandler() {

if (this.executeStreamHandler == null) {
setExecuteStreamHandler(new PumpStreamHandler(getOutputStream(),
getErrorStream()));
}

return this.executeStreamHandler;
}

/**
* sets a stream to which the output from the svn executable should be sent
* @param outputStream stream to which the stdout from svn should go
*/
protected void setOutputStream(OutputStream outputStream) {

this.outputStream = outputStream;
}

/**
* access the stream to which the stdout from svn should go
* if this stream has already been set, it will be returned
* if the stream has not yet been set, if the attribute output
* has been set, the output stream will go to the output file
* otherwise the output will go to ant's logging system
* @return output stream to which svn' stdout should go to
*/
protected OutputStream getOutputStream() {

if (this.outputStream == null) {

if (output != null) {
try {
setOutputStream(new PrintStream(
new BufferedOutputStream(
new FileOutputStream(output
.getPath(),
append))));
} catch (IOException e) {
throw new BuildException(e, getLocation());
}
} else {
setOutputStream(new LogOutputStream(this, Project.MSG_INFO));
}
}

return this.outputStream;
}

/**
* sets a stream to which the stderr from the svn exe should go
* @param errorStream an output stream willing to process stderr
*/
protected void setErrorStream(OutputStream errorStream) {

this.errorStream = errorStream;
}

/**
* access the stream to which the stderr from svn should go
* if this stream has already been set, it will be returned
* if the stream has not yet been set, if the attribute error
* has been set, the output stream will go to the file denoted by the error attribute
* otherwise the stderr output will go to ant's logging system
* @return output stream to which svn' stderr should go to
*/
protected OutputStream getErrorStream() {

if (this.errorStream == null) {

if (error != null) {

try {
setErrorStream(new PrintStream(
new BufferedOutputStream(
new FileOutputStream(error.getPath(),
append))));
} catch (IOException e) {
throw new BuildException(e, getLocation());
}
} else {
setErrorStream(new LogOutputStream(this, Project.MSG_WARN));
}
}

return this.errorStream;
}

/**
* Sets up the environment for toExecute and then runs it.
* @param toExecute the command line to execute
* @throws BuildException if failonError is set to true and the svn command fails
*/
protected void runCommand(Commandline toExecute) throws BuildException {
Environment env = new Environment();

//
// Just call the getExecuteStreamHandler() and let it handle
// the semantics of instantiation or retrieval.
//
Execute exe = new Execute(getExecuteStreamHandler(), null);

exe.setAntRun(getProject());
if (dest == null) {
dest = getProject().getBaseDir();
}

if (!dest.exists()) {
dest.mkdirs();
}

exe.setWorkingDirectory(dest);
exe.setCommandline(toExecute.getCommandline());
exe.setEnvironment(env.getVariables());

try {
String actualCommandLine = executeToString(exe);
log(actualCommandLine, Project.MSG_VERBOSE);
int retCode = exe.execute();
log("retCode=" + retCode, Project.MSG_DEBUG);
/*Throw an exception if svn exited with error. (Iulian)*/
if (failOnError && Execute.isFailure(retCode)) {
throw new BuildException("svn exited with error code "
+ retCode
+ StringUtils.LINE_SEP
+ "Command line was ["
+ actualCommandLine + "]", getLocation());
}
} catch (IOException e) {
if (failOnError) {
throw new BuildException(e, getLocation());
} else {
log("Caught exception: " + e.getMessage(), Project.MSG_WARN);
}
} catch (BuildException e) {
if (failOnError) {
throw(e);
} else {
Throwable t = e.getException();
if (t == null) {
t = e;
}
log("Caught exception: " + t.getMessage(), Project.MSG_WARN);
}
} catch (Exception e) {
if (failOnError) {
throw new BuildException(e, getLocation());
} else {
log("Caught exception: " + e.getMessage(), Project.MSG_WARN);
}
}
}

/**
* do the work
* @throws BuildException if failonerror is set to true and the svn command fails.
*/
public void execute() throws BuildException {

String savedCommand = getSubCommand();

if (this.getSubCommand() == null && vecCommandlines.size() == 0) {
// re-implement legacy behaviour:
this.setSubCommand(AbstractSvnTask.DEFAULT_SUBCOMMAND);
}

String c = this.getSubCommand();
Commandline cloned = null;
if (c != null) {
cloned = (Commandline) cmd.clone();
cloned.createArgument(true).setLine(c);
if (svnURL != null) {
cloned.createArgument().setValue(svnURL);
}
this.addConfiguredCommandline(cloned, true);
}

try {
for (int i = 0; i < vecCommandlines.size(); i++) {
this.runCommand((Commandline) vecCommandlines.elementAt(i));
}
} finally {
if (cloned != null) {
removeCommandline(cloned);
}
setSubCommand(savedCommand);

if (outputStream != null) {
try {
outputStream.close();
} catch (IOException e) {
//ignore
}
}
if (errorStream != null) {
try {
errorStream.close();
} catch (IOException e) {
//ignore
}
}
}
}

private String executeToString(Execute execute) {

StringBuffer stringBuffer =
new StringBuffer(Commandline.describeCommand(execute
.getCommandline()));

String newLine = StringUtils.LINE_SEP;
String[] variableArray = execute.getEnvironment();

if (variableArray != null) {
stringBuffer.append(newLine);
stringBuffer.append(newLine);
stringBuffer.append("environment:");
stringBuffer.append(newLine);
for (int z = 0; z < variableArray.length; z++) {
stringBuffer.append(newLine);
stringBuffer.append("\t");
stringBuffer.append(variableArray[z]);
}
}

return stringBuffer.toString();
}

/**
* The URL the subcommand should apply to.
*
* @param url the URL the subcommand should apply to.
*/
public void setSvnURL(String url) {

// Check if not real svnroot => set it to null
if (url != null) {
if (url.trim().equals("")) {
url = null;
}
}

this.svnURL = url;
}

/**
* access the svnURL variable
* @return svnURL
*/
public String getSvnURL() {

return this.svnURL;
}

/**
* The directory where the checked out files should be placed.
*
* <p>Note that this is different from SVN's -d command line
* switch as Ant will never shorten pathnames to avoid empty
* directories.</p>
*
* @param dest directory where the checked out files should be placed
*/
public void setDest(File dest) {
this.dest = dest;
}

/**
* get the file where the checked out files should be placed
*
* @return directory where the checked out files should be placed
*/
public File getDest() {

return this.dest;
}

/**
* revision
* @return revision
*/
public String getRevision() {
return revision;
}

/**
* The revision to operate upon.
* @param p revision
*/
public void setRevision(String p) {
// Check if not real revision => set it to null
if (p != null && p.trim().length() > 0) {
revision = p;
addSubCommandArgument("--revision");
addSubCommandArgument(p);
}
}

/**
* Uses the contents of the file passed as an argument to this
* switch for the specified subcommand.
*/
public void setFile(File file) {
this.file = file;
}

/**
* Uses the contents of the file passed as an argument to this
* switch for the specified subcommand.
*/
public File getFile() {
return file;
}

/**
* Forces a particular command or operation to run.
*/
public void setForce(boolean force) {
this.force = force;
}

/**
* Forces a particular command or operation to run.
*/
public boolean getForce() {
return force;
}

/**
* Makes a subcommand recurse into subdirectories. Most
* subcommands recurse by default.
*/
public void setRecursive(Boolean recursive) {
this.recursive = recursive;
}

/**
* Makes a subcommand recurse into subdirectories. Most
* subcommands recurse by default.
*/
public Boolean getRecursive() {
return recursive;
}

/**
* Tells Subversion to get the list of files that you wish to
* operate on from the filename you provide instead of listing all
* the files on the command line.
*/
public void setTargets(File targets) {
this.targets = targets;
}

/**
* Tells Subversion to get the list of files that you wish to
* operate on from the filename you provide instead of listing all
* the files on the command line.
*/
public File getTargets() {
return targets;
}

/**
* This needs to be public to allow configuration
* of commands externally.
* @param arg command argument
*/
public void addSubCommandArgument(String arg) {
this.addSubCommandArgument(cmd, arg);
}

/**
* This method adds a command line argument to an external subcommand.
*
* @param c command line to which one argument should be added
* @param arg argument to add
*/
protected void addSubCommandArgument(Commandline c, String arg) {
c.createArgument().setValue(arg);
}


/**
* The SVN command to execute.
*
* @param c a command as string
*/
public void setSubCommand(String c) {
this.subCommand = c;
}
/**
* accessor to a command line as string
*
* @return command line as string
*/
public String getSubCommand() {
return this.subCommand;
}

/**
* If true, suppress informational messages.
* @param q if true, suppress informational messages
*/
public void setQuiet(boolean q) {
quiet = q;
}

/**
* If true, be verbose.
* @param q if true, be verbose.
*/
public void setVerbose(boolean v) {
verbose = v;
}

/**
* If true, report only and don't change any files.
*
* @param ne if true, report only and do not change any files.
*/
public void setDryrun(boolean ne) {
dryrun = ne;
}

/**
* The file to direct standard output from the command.
* @param output a file to which stdout should go
*/
public void setOutput(File output) {
this.output = output;
}

/**
* The file to direct standard error from the command.
*
* @param error a file to which stderr should go
*/
public void setError(File error) {
this.error = error;
}

/**
* Whether to append output/error when redirecting to a file.
* @param value true indicated you want to append
*/
public void setAppend(boolean value) {
this.append = value;
}

/**
* Stop the build process if the command exits with
* a return code other than 0.
* Defaults to false.
* @param failOnError stop the build process if the command exits with
* a return code other than 0
*/
public void setFailOnError(boolean failOnError) {
this.failOnError = failOnError;
}

/**
* Configure a commandline element for things like quiet, etc.
* @param c the command line which will be configured
* if the commandline is initially null, the function is a noop
* otherwise the function append to the commandline arguments concerning
* <ul>
* <li>
* svn
* </li>
* <li>
* quiet
* </li>
* <li>verbose</li>
* <li>dryrun</li>
* </ul>
*/
protected void configureCommandline(Commandline c) {
if (c == null) {
return;
}
c.setExecutable("svn");
if (quiet) {
c.createArgument(true).setValue("--quiet");
}
if (verbose) {
c.createArgument(true).setValue("--verbose");
}
if (dryrun) {
c.createArgument(true).setValue("--dry-run");
}
if (file != null) {
c.createArgument(true).setValue("--file");
c.createArgument(true).setFile(file);
}
if (force) {
c.createArgument(true).setValue("--force");
}
if (recursive != null) {
if (recursive.booleanValue()) {
c.createArgument(true).setValue("--recursive");
} else {
c.createArgument(true).setValue("--non-recursive");
}
}
if (targets != null) {
c.createArgument(true).setValue("--targets");
c.createArgument(true).setFile(targets);
}
}

/**
* remove a particular command from a vector of command lines
* @param c command line which should be removed
*/
protected void removeCommandline(Commandline c) {
vecCommandlines.removeElement(c);
}

/**
* Adds direct command-line to execute.
* @param c command line to execute
*/
public void addConfiguredCommandline(Commandline c) {
this.addConfiguredCommandline(c, false);
}

/**
* Configures and adds the given Commandline.
* @param c commandline to insert
* @param insertAtStart If true, c is
* inserted at the beginning of the vector of command lines
*/
public void addConfiguredCommandline(Commandline c,
boolean insertAtStart) {
if (c == null) {
return;
}
this.configureCommandline(c);
if (insertAtStart) {
vecCommandlines.insertElementAt(c, 0);
} else {
vecCommandlines.addElement(c);
}
}

}

+ 0
- 134
proposal/sandbox/svn/src/main/org/apache/tools/ant/taskdefs/svn/LineOrientedOutputStream.java View File

@@ -1,134 +0,0 @@
/*
* Copyright 2005 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

package org.apache.tools.ant.taskdefs.svn;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;

/**
* Invokes {@link #processLine processLine} whenever a full line has
* been written to this stream.
*
* <p>Tries to be smart about line separators.</p>
*/
public abstract class LineOrientedOutputStream extends OutputStream {

/** Initial buffer size. */
private static final int INTIAL_SIZE = 132;

/** Carriage return */
private static final int CR = 0x0d;

/** Linefeed */
private static final int LF = 0x0a;

private ByteArrayOutputStream buffer
= new ByteArrayOutputStream(INTIAL_SIZE);
private boolean skip = false;

/**
* Write the data to the buffer and flush the buffer, if a line
* separator is detected.
*
* @param cc data to log (byte).
*/
public final void write(int cc) throws IOException {
final byte c = (byte) cc;
if ((c == '\n') || (c == '\r')) {
if (!skip) {
processBuffer();
}
} else {
buffer.write(cc);
}
skip = (c == '\r');
}

/**
* Flush this log stream
*/
public final void flush() throws IOException {
if (buffer.size() > 0) {
processBuffer();
}
}

/**
* Converts the buffer to a string and sends it to
* <code>processLine</code>
*/
private void processBuffer() throws IOException {
try {
processLine(buffer.toString());
} finally {
buffer.reset();
}
}

/**
* Processes a line.
*
* @param line the line to log.
*/
protected abstract void processLine(String line) throws IOException;

/**
* Writes all remaining
*/
public final void close() throws IOException {
if (buffer.size() > 0) {
processBuffer();
}
super.close();
}

/**
* Write a block of characters to the output stream
*
* @param b the array containing the data
* @param off the offset into the array where data starts
* @param len the length of block
*
* @throws IOException if the data cannot be written into the stream.
*/
public final void write(byte[] b, int off, int len) throws IOException {
// find the line breaks and pass other chars through in blocks
int offset = off;
int blockStartOffset = offset;
int remaining = len;
while (remaining > 0) {
while (remaining > 0 && b[offset] != LF && b[offset] != CR) {
offset++;
remaining--;
}
// either end of buffer or a line separator char
int blockLength = offset - blockStartOffset;
if (blockLength > 0) {
buffer.write(b, blockStartOffset, blockLength);
}
while (remaining > 0 && (b[offset] == LF || b[offset] == CR)) {
write(b[offset]);
offset++;
remaining--;
}
blockStartOffset = offset;
}
}

}

+ 0
- 32
proposal/sandbox/svn/src/main/org/apache/tools/ant/taskdefs/svn/Svn.java View File

@@ -1,32 +0,0 @@
/*
* Copyright 2005 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

package org.apache.tools.ant.taskdefs.svn;

/**
* Performs operations on a SVN repository.
*
* @ant.task category="scm"
*/
public class Svn extends AbstractSvnTask {

/**
* SVN Task - now implemented by the Abstract SVN Task base class
*/
public Svn() {
}
}

+ 0
- 188
proposal/sandbox/svn/src/main/org/apache/tools/ant/taskdefs/svn/SvnChangeLogParser.java View File

@@ -1,188 +0,0 @@
/*
* Copyright 2005 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.tools.ant.taskdefs.svn;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.ArrayList;

/**
* A class used to parse the output of the svn log command.
*
*/
class SvnChangeLogParser extends LineOrientedOutputStream {

private final static int GET_ENTRY_LINE = 0;
private final static int GET_REVISION_LINE = 1;
private final static int GET_PATHS = 2;
private final static int GET_MESSAGE = 3;

private String message = "";
private Date date = null;
private String author = null;
private String revision = null;
private ArrayList paths = new ArrayList();

/** input format for dates read in from cvs log */
private static final String PATTERN = "yyyy-MM-dd HH:mm:ss";
private static final SimpleDateFormat INPUT_DATE
= new SimpleDateFormat(PATTERN);

private final ArrayList entries = new ArrayList();
private int status = GET_ENTRY_LINE;

/**
* Get a list of rcs entries as an array.
*
* @return a list of rcs entries as an array
*/
public SvnEntry[] getEntrySetAsArray() {
return (SvnEntry[]) entries.toArray(new SvnEntry[entries.size()]);
}

/**
* Receive notification about the process writing
* to standard output.
* @param line the line to process
*/
public void processLine(final String line) {
switch(status) {
case GET_ENTRY_LINE:
// make sure attributes are reset when
// working on a 'new' file.
reset();
processEntryStart(line);
break;
case GET_REVISION_LINE:
processRevision(line);
break;

case GET_MESSAGE:
processMessage(line);
break;

case GET_PATHS:
processPath(line);
break;

default:
// Do nothing
break;
}
}

/**
* Process a line while in "GET_MESSAGE" state.
*
* @param line the line
*/
private void processMessage(final String line) {
final String lineSeparator = System.getProperty("line.separator");
if (line.equals("------------------------------------------------------------------------")) {
//We have ended changelog for that particular revision
//so we can save it
final int end
= message.length() - lineSeparator.length();
message = message.substring(0, end);
saveEntry();
status = GET_REVISION_LINE;
} else {
message += line + lineSeparator;
}
}

/**
* Process a line while in "GET_ENTRY_LINE" state.
*
* @param line the line to process
*/
private void processEntryStart(final String line) {
if (line.equals("------------------------------------------------------------------------")) {
status = GET_REVISION_LINE;
}
}

/**
* Process a line while in "REVISION" state.
*
* @param line the line to process
*/
private void processRevision(final String line) {
int index = line.indexOf(" |");
if (line.startsWith("r")
&& (line.endsWith("lines") || line.endsWith("line"))
&& index > -1) {
revision = line.substring(1, index);
int end = line.indexOf(" |", index + 1);
author = line.substring(index + 3, end);
String d = line.substring(end + 3, end + 3 + PATTERN.length());
date = parseDate(d);
status = GET_PATHS;
}
}

/**
* Process a line while in "GET_PATHS" state.
*
* @param line the line to process
*/
private void processPath(final String line) {
if (line.startsWith("Changed paths:")) {
// ignore
} else if (line.equals("")) {
status = GET_MESSAGE;
} else if (line.length() > 5) {
paths.add(new SvnEntry.Path(line.substring(5), line.charAt(3)));
}
}

/**
* Utility method that saves the current entry.
*/
private void saveEntry() {
SvnEntry entry = new SvnEntry(date, revision, author, message,
paths);
entries.add(entry);
reset();
}

/**
* Parse date out from expected format.
*
* @param date the string holding date
* @return the date object or null if unknown date format
*/
private Date parseDate(final String date) {
try {
return INPUT_DATE.parse(date);
} catch (ParseException e) {
return null;
}
}

/**
* Reset all internal attributes except status.
*/
public void reset() {
this.date = null;
this.author = null;
this.message = "";
this.revision = null;
this.paths.clear();
}
}

+ 0
- 399
proposal/sandbox/svn/src/main/org/apache/tools/ant/taskdefs/svn/SvnChangeLogTask.java View File

@@ -1,399 +0,0 @@
/*
* Copyright 2005 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.tools.ant.taskdefs.svn;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Enumeration;
import java.util.Properties;
import java.util.Vector;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.taskdefs.LogOutputStream;
import org.apache.tools.ant.taskdefs.PumpStreamHandler;
import org.apache.tools.ant.taskdefs.cvslib.CvsUser;
import org.apache.tools.ant.types.FileSet;
import org.apache.tools.ant.util.FileUtils;

/**
* Examines the output of svn log and group related changes together.
*
* It produces an XML output representing the list of changes.
* <pre>
* <font color=#0000ff>&lt;!-- Root element --&gt;</font>
* <font color=#6a5acd>&lt;!ELEMENT</font> changelog <font color=#ff00ff>(entry</font><font color=#ff00ff>+</font><font color=#ff00ff>)</font><font color=#6a5acd>&gt;</font>
* <font color=#0000ff>&lt;!-- SVN Entry --&gt;</font>
* <font color=#6a5acd>&lt;!ELEMENT</font> entry <font color=#ff00ff>(date,time,revision,author,path</font><font color=#ff00ff>+,msg</font><font color=#ff00ff>,msg)</font><font color=#6a5acd>&gt;</font>
* <font color=#0000ff>&lt;!-- Date of svn entry --&gt;</font>
* <font color=#6a5acd>&lt;!ELEMENT</font> date <font color=#ff00ff>(#PCDATA)</font><font color=#6a5acd>&gt;</font>
* <font color=#0000ff>&lt;!-- Time of svn entry --&gt;</font>
* <font color=#6a5acd>&lt;!ELEMENT</font> time <font color=#ff00ff>(#PCDATA)</font><font color=#6a5acd>&gt;</font>
* <font color=#0000ff>&lt;!-- Author of change --&gt;</font>
* <font color=#6a5acd>&lt;!ELEMENT</font> author <font color=#ff00ff>(#PCDATA)</font><font color=#6a5acd>&gt;</font>
* <font color=#0000ff>&lt;!-- commit message --&gt;</font>
* <font color=#6a5acd>&lt;!ELEMENT</font> msg <font color=#ff00ff>(#PCDATA)</font><font color=#6a5acd>&gt;</font>
* <font color=#0000ff>&lt;!-- List of paths affected --&gt;</font>
* <font color=#6a5acd>&lt;!ELEMENT</font> path <font color=#ff00ff>(name,action)</font><font color=#ff00ff></font><font color=#ff00ff>)</font><font color=#6a5acd>&gt;</font>
* <font color=#0000ff>&lt;!-- Name of the path --&gt;</font>
* <font color=#6a5acd>&lt;!ELEMENT</font> name <font color=#ff00ff>(#PCDATA)</font><font color=#6a5acd>&gt;</font>
* <font color=#6a5acd>&lt;!ELEMENT</font> action <font color=#ff00ff>(added|modified|deleted)</font><font color=#6a5acd>&gt;</font>
* <font color=#0000ff>&lt;!-- Revision number --&gt;</font>
* <font color=#6a5acd>&lt;!ELEMENT</font> revision <font color=#ff00ff>(#PCDATA)</font><font color=#6a5acd>&gt;</font>
* </pre>
*
* @ant.task name="svnchangelog" category="scm"
*/
public class SvnChangeLogTask extends AbstractSvnTask {
/** User list */
private File usersFile;

/** User list */
private Vector svnUsers = new Vector();

/** Input dir */
private File inputDir;

/** Output file */
private File destFile;

/** The earliest revision at which to start processing entries. */
private String startRevision;

/** The latest revision at which to stop processing entries. */
private String endRevision;

/**
* Filesets containing list of files against which the svn log will be
* performed. If empty then all files in the working directory will
* be checked.
*/
private final Vector filesets = new Vector();


/**
* Set the base dir for svn.
*
* @param inputDir The new dir value
*/
public void setDir(final File inputDir) {
this.inputDir = inputDir;
}


/**
* Set the output file for the log.
*
* @param destFile The new destfile value
*/
public void setDestfile(final File destFile) {
this.destFile = destFile;
}


/**
* Set a lookup list of user names & addresses
*
* @param usersFile The file containing the users info.
*/
public void setUsersfile(final File usersFile) {
this.usersFile = usersFile;
}


/**
* Add a user to list changelog knows about.
*
* @param user the user
*/
public void addUser(final CvsUser user) {
svnUsers.addElement(user);
}


/**
* Set the revision at which the changelog should start.
*
* @param start The revision at which the changelog should start.
*/
public void setStart(final String start) {
this.startRevision = start;
}


/**
* Set the revision at which the changelog should stop.
*
* @param endRevision The revision at which the changelog should stop.
*/
public void setEnd(final String endRevision) {
this.endRevision = endRevision;
}


/**
* Set the number of days worth of log entries to process.
*
* @param days the number of days of log to process.
*/
public void setDaysinpast(final int days) {
final long time = System.currentTimeMillis()
- (long) days * 24 * 60 * 60 * 1000;

final SimpleDateFormat outputDate =
new SimpleDateFormat("{yyyy-MM-dd}");
setStart(outputDate.format(new Date(time)));
}


/**
* Adds a set of files about which svn logs will be generated.
*
* @param fileSet a set of files about which svn logs will be generated.
*/
public void addFileset(final FileSet fileSet) {
filesets.addElement(fileSet);
}


/**
* Execute task
*
* @exception BuildException if something goes wrong executing the
* svn command
*/
public void execute() throws BuildException {
File savedDir = inputDir; // may be altered in validate

try {

validate();
final Properties userList = new Properties();

loadUserlist(userList);

for (int i = 0, size = svnUsers.size(); i < size; i++) {
final CvsUser user = (CvsUser) svnUsers.get(i);
user.validate();
userList.put(user.getUserID(), user.getDisplayname());
}

setSubCommand("log");
setVerbose(true);

if (null != startRevision) {
if (null != endRevision) {
setRevision(startRevision + ":" + endRevision);
} else {
setRevision(startRevision + ":HEAD");
}
}

// Check if list of files to check has been specified
if (!filesets.isEmpty()) {
final Enumeration e = filesets.elements();

while (e.hasMoreElements()) {
final FileSet fileSet = (FileSet) e.nextElement();
final DirectoryScanner scanner =
fileSet.getDirectoryScanner(getProject());
final String[] files = scanner.getIncludedFiles();

for (int i = 0; i < files.length; i++) {
addSubCommandArgument(files[i]);
}
}
}

final SvnChangeLogParser parser = new SvnChangeLogParser();
final PumpStreamHandler handler =
new PumpStreamHandler(parser,
new LogOutputStream(this,
Project.MSG_ERR));

log(getSubCommand(), Project.MSG_VERBOSE);

setDest(inputDir);
setExecuteStreamHandler(handler);
super.execute();

final SvnEntry[] entrySet = parser.getEntrySetAsArray();
final SvnEntry[] filteredEntrySet = filterEntrySet(entrySet);

replaceAuthorIdWithName(userList, filteredEntrySet);

writeChangeLog(filteredEntrySet);

} finally {
inputDir = savedDir;
}
}

/**
* Validate the parameters specified for task.
*
* @throws BuildException if fails validation checks
*/
private void validate()
throws BuildException {
if (null == inputDir) {
inputDir = getDest();
}
if (null == destFile) {
final String message = "Destfile must be set.";

throw new BuildException(message);
}
if (!inputDir.exists()) {
final String message = "Cannot find base dir "
+ inputDir.getAbsolutePath();

throw new BuildException(message);
}
if (null != usersFile && !usersFile.exists()) {
final String message = "Cannot find user lookup list "
+ usersFile.getAbsolutePath();

throw new BuildException(message);
}
}

/**
* Load the userlist from the userList file (if specified) and add to
* list of users.
*
* @param userList the file of users
* @throws BuildException if file can not be loaded for some reason
*/
private void loadUserlist(final Properties userList)
throws BuildException {
if (null != usersFile) {
try {
userList.load(new FileInputStream(usersFile));
} catch (final IOException ioe) {
throw new BuildException(ioe.toString(), ioe);
}
}
}

/**
* Filter the specified entries according to an appropriate rule.
*
* @param entrySet the entry set to filter
* @return the filtered entry set
*/
private SvnEntry[] filterEntrySet(final SvnEntry[] entrySet) {
final Vector results = new Vector();

for (int i = 0; i < entrySet.length; i++) {
final SvnEntry svnEntry = entrySet[i];

if (null != endRevision && !isBeforeEndRevision(svnEntry)) {
//Skip revisions that are too late
continue;
}
results.addElement(svnEntry);
}

final SvnEntry[] resultArray = new SvnEntry[results.size()];

results.copyInto(resultArray);
return resultArray;
}

/**
* replace all known author's id's with their maven specified names
*/
private void replaceAuthorIdWithName(final Properties userList,
final SvnEntry[] entrySet) {
for (int i = 0; i < entrySet.length; i++) {

final SvnEntry entry = entrySet[ i ];
if (userList.containsKey(entry.getAuthor())) {
entry.setAuthor(userList.getProperty(entry.getAuthor()));
}
}
}

/**
* Print changelog to file specified in task.
*
* @param entrySet the entry set to write.
* @throws BuildException if there is an error writing changelog.
*/
private void writeChangeLog(final SvnEntry[] entrySet)
throws BuildException {
FileOutputStream output = null;

try {
output = new FileOutputStream(destFile);

final PrintWriter writer =
new PrintWriter(new OutputStreamWriter(output, "UTF-8"));

final SvnChangeLogWriter serializer = new SvnChangeLogWriter();

serializer.printChangeLog(writer, entrySet);
} catch (final UnsupportedEncodingException uee) {
getProject().log(uee.toString(), Project.MSG_ERR);
} catch (final IOException ioe) {
throw new BuildException(ioe.toString(), ioe);
} finally {
FileUtils.close(output);
}
}

private static final String PATTERN = "yyyy-MM-dd";
private static final SimpleDateFormat INPUT_DATE
= new SimpleDateFormat(PATTERN);

/**
* Checks whether a given entry is before the given end revision,
* using revision numbers or date information as appropriate.
*/
private boolean isBeforeEndRevision(SvnEntry entry) {
if (endRevision.startsWith("{")
&& endRevision.length() >= 2 + PATTERN.length() ) {
try {
Date endDate =
INPUT_DATE.parse(endRevision.substring(1,
PATTERN.length()
+ 1));
return entry.getDate().before(endDate);
} catch (ParseException e) {
}
} else {
try {
int endRev = Integer.parseInt(endRevision);
int entryRev = Integer.parseInt(entry.getRevision());
return endRev >= entryRev;
} catch (NumberFormatException e) {
} // end of try-catch
}
// failed to parse revision, use a save fallback
return true;
}
}


+ 0
- 96
proposal/sandbox/svn/src/main/org/apache/tools/ant/taskdefs/svn/SvnChangeLogWriter.java View File

@@ -1,96 +0,0 @@
/*
* Copyright 2005 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.tools.ant.taskdefs.svn;

import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import javax.xml.parsers.DocumentBuilder;

import org.apache.tools.ant.util.DOMElementWriter;
import org.apache.tools.ant.util.DOMUtils;

import org.w3c.dom.Document;
import org.w3c.dom.Element;

/**
* Class used to generate an XML changelog.
*/
public class SvnChangeLogWriter {
/** output format for dates written to xml file */
private static final SimpleDateFormat OUTPUT_DATE
= new SimpleDateFormat("yyyy-MM-dd");
/** output format for times written to xml file */
private static final SimpleDateFormat OUTPUT_TIME
= new SimpleDateFormat("HH:mm");
/** stateless helper for writing the XML document */
private static final DOMElementWriter DOM_WRITER = new DOMElementWriter();

/**
* Print out the specified entries.
*
* @param output writer to which to send output.
* @param entries the entries to be written.
*/
public void printChangeLog(final PrintWriter output,
final SvnEntry[] entries) throws IOException {
output.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
Document doc = DOMUtils.newDocument();
Element root = doc.createElement("changelog");
DOM_WRITER.openElement(root, output, 0, "\t");
output.println();
for (int i = 0; i < entries.length; i++) {
final SvnEntry entry = entries[i];

printEntry(output, entry, root);
}
DOM_WRITER.closeElement(root, output, 0, "\t", entries.length > 0);
output.flush();
output.close();
}


/**
* Print out an individual entry in changelog.
*
* @param entry the entry to print
* @param output writer to which to send output.
*/
private void printEntry(final PrintWriter output, final SvnEntry entry,
final Element element) throws IOException {
Document doc = element.getOwnerDocument();

Element ent = doc.createElement("entry");
DOMUtils.appendTextElement(ent, "date",
OUTPUT_DATE.format(entry.getDate()));
DOMUtils.appendTextElement(ent, "time",
OUTPUT_TIME.format(entry.getDate()));
DOMUtils.appendCDATAElement(ent, "author", entry.getAuthor());
DOMUtils.appendTextElement(ent, "revision", entry.getRevision());

SvnEntry.Path[] paths = entry.getPaths();
for (int i = 0; i < paths.length; i++) {
Element path = DOMUtils.createChildElement(ent, "path");
DOMUtils.appendCDATAElement(path, "name", paths[i].getName());
DOMUtils.appendTextElement(path, "action",
paths[i].getActionDescription());
}
DOMUtils.appendCDATAElement(ent, "message", entry.getMessage());
DOM_WRITER.write(ent, output, 1, "\t");
}
}


+ 0
- 207
proposal/sandbox/svn/src/main/org/apache/tools/ant/taskdefs/svn/SvnDiffHandler.java View File

@@ -1,207 +0,0 @@
/*
* Copyright 2005 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.tools.ant.taskdefs.svn;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.StringTokenizer;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.util.DOMElementWriter;
import org.apache.tools.ant.util.DOMUtils;
import org.apache.tools.ant.util.FileUtils;

import org.w3c.dom.Document;
import org.w3c.dom.Element;

/**
* Parses the output of a svn diff command and/or writes an XML report
* based on such a diff output.
*
* It produces an XML output representing the list of changes.
*/
final class SvnDiffHandler {

/**
* Token to identify the word file in the rdiff log
*/
private static final String INDEX = "Index: ";
/**
* Token to identify a deleted file based on the Index line.
*/
private static final String DELETED = " (deleted)";

/**
* Token to identify added files based on the diff line.
*/
private static final String IS_NEW = "\t(revision 0)";

/**
* Token that starts diff line of old revision.
*/
private static final String DASHES = "--- ";

/** stateless helper for writing the XML document */
private static final DOMElementWriter DOM_WRITER = new DOMElementWriter();

/**
* Parse the tmpFile and return and array of entries to be written
* in the output.
*
* @param tmpFile the File containing the output of the svn rdiff command
* @return the entries in the output
* @exception BuildException if an error occurs
*/
static SvnEntry.Path[] parseDiff(File tmpFile) throws BuildException {
// parse the output of the command
BufferedReader reader = null;

try {
reader = new BufferedReader(new FileReader(tmpFile));
ArrayList entries = new ArrayList();

String line = reader.readLine();
String name = null;
String currDiffLine = null;
boolean deleted = false;
boolean added = false;

while (null != line) {
if (line.length() > INDEX.length()) {
if (line.startsWith(INDEX)) {
if (name != null) {
SvnEntry.Path p =
new SvnEntry.Path(name,
deleted
? SvnEntry.Path.DELETED
: (added
? SvnEntry.Path.ADDED
: SvnEntry.Path.MODIFIED)
);
entries.add(p);
deleted = added = false;
}

name = line.substring(INDEX.length());
if (line.endsWith(DELETED)) {
name = name.substring(0, name.length()
- DELETED.length());
deleted = true;
}

currDiffLine = DASHES + name;
} else if (currDiffLine != null
&& line.startsWith(currDiffLine)
&& line.endsWith(IS_NEW)) {
added = true;
}
}
line = reader.readLine();
}
if (name != null) {
SvnEntry.Path p = new SvnEntry.Path(name,
deleted
? SvnEntry.Path.DELETED
: (added
? SvnEntry.Path.ADDED
: SvnEntry.Path.MODIFIED)
);
entries.add(p);
}

SvnEntry.Path[] array = (SvnEntry.Path[])
entries.toArray(new SvnEntry.Path[entries.size()]);
return array;
} catch (IOException e) {
throw new BuildException("Error in parsing", e);
} finally {
FileUtils.close(reader);
}
}

/**
* Write the diff log.
*
* @param entries a <code>SvnRevisionEntry[]</code> value
* @exception BuildException if an error occurs
*/
static void writeDiff(File destFile, SvnEntry.Path[] entries,
String rootElementName,
String tag1Name, String tag1Value,
String tag2Name, String tag2Value,
String svnURL) throws BuildException {
FileOutputStream output = null;
try {
output = new FileOutputStream(destFile);
PrintWriter writer = new PrintWriter(
new OutputStreamWriter(output, "UTF-8"));
writer.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
Document doc = DOMUtils.newDocument();
Element root = doc.createElement(rootElementName);
if (tag1Name != null && tag1Value != null) {
root.setAttribute(tag1Name, tag1Value);
}
if (tag2Name != null && tag2Value != null) {
root.setAttribute(tag2Name, tag2Value);
}

if (svnURL != null) {
root.setAttribute("svnurl", svnURL);
}
DOM_WRITER.openElement(root, writer, 0, "\t");
writer.println();
for (int i = 0, c = entries.length; i < c; i++) {
writeRevisionEntry(doc, writer, entries[i]);
}
DOM_WRITER.closeElement(root, writer, 0, "\t", true);
writer.flush();
writer.close();
} catch (UnsupportedEncodingException uee) {
throw new BuildException(uee);
} catch (IOException ioe) {
throw new BuildException(ioe.toString(), ioe);
} finally {
FileUtils.close(output);
}
}

/**
* Write a single entry to the given writer.
*
* @param doc Document used to create elements.
* @param writer a <code>PrintWriter</code> value
* @param entry a <code>SvnRevisionEntry</code> value
*/
private static void writeRevisionEntry(Document doc,
PrintWriter writer,
SvnEntry.Path entry)
throws IOException {
Element e = doc.createElement("path");
DOMUtils.appendCDATAElement(e, "name", entry.getName());
DOMUtils.appendTextElement(e, "action", entry.getActionDescription());
DOM_WRITER.write(e, writer, 1, "\t");
}

}

+ 0
- 171
proposal/sandbox/svn/src/main/org/apache/tools/ant/taskdefs/svn/SvnEntry.java View File

@@ -1,171 +0,0 @@
/*
* Copyright 2005 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.tools.ant.taskdefs.svn;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;

public class SvnEntry {
private final Date date;
private final String revision;
private String author;
private final String message;
private final ArrayList paths = new ArrayList();

/**
* Creates a new instance of a SvnEntry
* @param date the date
* @param author the author
* @param message a message to be added to the revision
*/
public SvnEntry(final Date date, final String revision,
final String author, final String message) {
this(date, revision, author, message, Collections.EMPTY_LIST);
}

/**
* Creates a new instance of a SvnEntry
* @param date the date
* @param author the author
* @param message a message to be added to the revision
*/
public SvnEntry(final Date date, final String revision,
final String author, final String message,
final Collection paths) {
this.date = date;
this.revision = revision;
this.author = author;
this.message = message;
this.paths.addAll(paths);
}

/**
* Adds a path to the SvnEntry
* @param path the path to add
* @param revision the revision
*/
public void addPath(final String name, final char action) {
paths.add(new Path(name, action));
}

/**
* Gets the date of the SvnEntry
* @return the date
*/
public Date getDate() {
return date;
}

/**
* Gets the revision of the SvnEntry
* @return the date
*/
public String getRevision() {
return revision;
}

/**
* Sets the author of the SvnEntry
* @param author the author
*/
public void setAuthor(final String author) {
this.author = author;
}

/**
* Gets the author of the SvnEntry
* @return the author
*/
public String getAuthor() {
return author;
}

/**
* Gets the message for the SvnEntry
* @return the message
*/
public String getMessage() {
return message;
}

/**
* Gets the paths in this SvnEntry
* @return the files
*/
public Path[] getPaths() {
return (Path[]) paths.toArray(new Path[paths.size()]);
}

public static class Path {

private static final char ADDED_MARKER = 'A';
private static final char MODIFIED_MARKER = 'M';
private static final char DELETED_MARKER = 'D';

public static final int ADDED = 0;
public static final int MODIFIED = 1;
public static final int DELETED = 2;

private static final String[] ACTIONS = {
"added", "modified", "deleted",
};

private final String name;
private final int action;

public Path(final String name, final char actionChar) {
this.name = name;
switch (actionChar) {
case ADDED_MARKER:
action = ADDED;
break;
case MODIFIED_MARKER:
action = MODIFIED;
break;
case DELETED_MARKER:
action = DELETED;
break;
default:
throw new IllegalArgumentException("Unkown action; "
+ actionChar);
}
}

public Path(final String name, final int action) {
this.name = name;
if (action != ADDED && action != DELETED && action != MODIFIED) {
throw new IllegalArgumentException("Unkown action; " + action);
}
this.action = action;
}

public String getName() {
return name;
}

public int getAction() {
return action;
}

public String getActionDescription() {
return ACTIONS[action];
}
}

}

+ 0
- 162
proposal/sandbox/svn/src/main/org/apache/tools/ant/taskdefs/svn/SvnRevisionDiff.java View File

@@ -1,162 +0,0 @@
/*
* Copyright 2005 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.tools.ant.taskdefs.svn;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.StringTokenizer;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.util.FileUtils;

/**
* Examines the output of svn diff between two revisions.
*
* It produces an XML output representing the list of changes.
* <PRE>
* &lt;!-- Root element --&gt;
* &lt;!ELEMENT revisiondiff ( paths? ) &gt;
* &lt;!-- Start revision of the report --&gt;
* &lt;!ATTLIST revisiondiff start NMTOKEN #IMPLIED &gt;
* &lt;!-- End revision of the report --&gt;
* &lt;!ATTLIST revisiondiff end NMTOKEN #IMPLIED &gt;
* &lt;!-- Subversion URL if known --&gt;
* &lt;!ATTLIST revisiondiff svnurl NMTOKEN #IMPLIED &gt;
*
* &lt;!-- Path added, changed or removed --&gt;
* &lt;!ELEMENT path ( name,action ) &gt;
* &lt;!-- Name of the file --&gt;
* &lt;!ELEMENT name ( #PCDATA ) &gt;
* &lt;!ELEMENT action (added|modified|deleted)&gt;
* </PRE>
*
* @ant.task name="svnrevisiondiff"
*/
public class SvnRevisionDiff extends AbstractSvnTask {

/**
* Used to create the temp file for svn log
*/
private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();

/**
* The earliest revision from which diffs are to be included in the report.
*/
private String mystartRevision;

/**
* The latest revision from which diffs are to be included in the report.
*/
private String myendRevision;

/**
* The file in which to write the diff report.
*/
private File mydestfile;

/**
* Set the start revision.
*
* @param s the start revision.
*/
public void setStart(String s) {
mystartRevision = s;
}

/**
* Set the end revision.
*
* @param s the end revision.
*/
public void setEnd(String s) {
myendRevision = s;
}

/**
* Set the output file for the diff.
*
* @param f the output file for the diff.
*/
public void setDestFile(File f) {
mydestfile = f;
}

/**
* Execute task.
*
* @exception BuildException if an error occurs
*/
public void execute() throws BuildException {
// validate the input parameters
validate();

// build the rdiff command
setSubCommand("diff");
setRevision(mystartRevision + ":" + myendRevision);
addSubCommandArgument("--no-diff-deleted");

File tmpFile = null;
try {
tmpFile =
FILE_UTILS.createTempFile("svnrevisiondiff", ".log", null);
tmpFile.deleteOnExit();
setOutput(tmpFile);

// run the svn command
super.execute();

// parse the diff
SvnEntry.Path[] entries = SvnDiffHandler.parseDiff(tmpFile);

// write the revision diff
SvnDiffHandler.writeDiff(mydestfile, entries, "revisiondiff",
"start", mystartRevision,
"end", myendRevision, getSvnURL());
} finally {
if (tmpFile != null) {
tmpFile.delete();
}
}
}

/**
* Validate the parameters specified for task.
*
* @exception BuildException if a parameter is not correctly set
*/
private void validate() throws BuildException {
if (null == mydestfile) {
throw new BuildException("Destfile must be set.");
}

if (null == mystartRevision) {
throw new BuildException("Start revision or start date must be set.");
}

if (null == myendRevision) {
throw new BuildException("End revision or end date must be set.");
}
}
}

+ 0
- 210
proposal/sandbox/svn/src/main/org/apache/tools/ant/taskdefs/svn/SvnTagDiff.java View File

@@ -1,210 +0,0 @@
/*
* Copyright 2005 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.tools.ant.taskdefs.svn;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.StringTokenizer;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.util.FileUtils;

/**
* Examines the output of svn diff between two tags or a tag and trunk.
*
* <p>This task only works if you follow the best-practice structure of
* <pre>
* BASEURL
* |
* |
* -----&gt; trunk
* -----&gt; tags
* |
* |
* ----------&gt; tag1
* ----------&gt; tag2
* </pre>
*
* It produces an XML output representing the list of changes.
* <PRE>
* &lt;!-- Root element --&gt;
* &lt;!ELEMENT tagdiff ( paths? ) &gt;
* &lt;!-- First tag --&gt;
* &lt;!ATTLIST tagdiff tag1 NMTOKEN #IMPLIED &gt;
* &lt;!-- Second tag --&gt;
* &lt;!ATTLIST tagdiff tag2 NMTOKEN #IMPLIED &gt;
* &lt;!-- Subversion BaseURL --&gt;
* &lt;!ATTLIST tagdiff svnurl NMTOKEN #IMPLIED &gt;
*
* &lt;!-- Path added, changed or removed --&gt;
* &lt;!ELEMENT path ( name,action ) &gt;
* &lt;!-- Name of the file --&gt;
* &lt;!ELEMENT name ( #PCDATA ) &gt;
* &lt;!ELEMENT action (added|modified|deleted)&gt;
* </PRE>
*
* @ant.task name="svntagdiff"
*/
public class SvnTagDiff extends AbstractSvnTask {

/**
* Used to create the temp file for svn log
*/
private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();

/**
* The earliest revision from which diffs are to be included in the report.
*/
private String tag1;

/**
* The latest revision from which diffs are to be included in the report.
*/
private String tag2;

/**
* The file in which to write the diff report.
*/
private File mydestfile;

/**
* Base URL.
*/
private String baseURL;

/**
* Set the first tag.
*
* @param s the first tag.
*/
public void setTag1(String s) {
tag1 = s;
}

/**
* Set the second tag.
*
* @param s the second tag.
*/
public void setTag2(String s) {
tag2 = s;
}

/**
* Set the output file for the diff.
*
* @param f the output file for the diff.
*/
public void setDestFile(File f) {
mydestfile = f;
}

/**
* Set the base URL from which to calculate tag URLs.
*
* @param u the base URL from which to calculate tag URLs.
*/
public void setBaseURL(String u) {
baseURL = u;
if (!u.endsWith("/")) {
baseURL += "/";
}
}

/**
* Execute task.
*
* @exception BuildException if an error occurs
*/
public void execute() throws BuildException {
// validate the input parameters
validate();

// build the rdiff command
setSubCommand("diff");
addSubCommandArgument("--no-diff-deleted");
if (tag1.equals("trunk") || tag1.equals("trunk/")) {
addSubCommandArgument(baseURL + "trunk/");
} else {
if (tag1.endsWith("/")) {
addSubCommandArgument(baseURL + "tags/" + tag1);
} else {
addSubCommandArgument(baseURL + "tags/" + tag1 + "/");
}
}
if (tag2 == null || tag2.equals("trunk") || tag2.equals("trunk/")) {
addSubCommandArgument(baseURL + "trunk/");
} else {
if (tag2.endsWith("/")) {
addSubCommandArgument(baseURL + "tags/" + tag2);
} else {
addSubCommandArgument(baseURL + "tags/" + tag2 + "/");
}
}
File tmpFile = null;
try {
tmpFile =
FILE_UTILS.createTempFile("svntagdiff", ".log", null);
tmpFile.deleteOnExit();
setOutput(tmpFile);

// run the svn command
super.execute();

// parse the diff
SvnEntry.Path[] entries = SvnDiffHandler.parseDiff(tmpFile);

// write the revision diff
SvnDiffHandler.writeDiff(mydestfile, entries, "tagdiff",
"tag1", tag1, "tag2",
tag2 == null ? "trunk" : tag2,
baseURL);
} finally {
if (tmpFile != null) {
tmpFile.delete();
}
}
}

/**
* Validate the parameters specified for task.
*
* @exception BuildException if a parameter is not correctly set
*/
private void validate() throws BuildException {
if (null == mydestfile) {
throw new BuildException("Destfile must be set.");
}

if (null == tag1) {
throw new BuildException("tag1 must be set.");
}

if (null == baseURL) {
throw new BuildException("baseURL must be set.");
}
}
}

+ 0
- 34
proposal/sandbox/svn/src/main/org/apache/tools/ant/taskdefs/svn/antlib.xml View File

@@ -1,34 +0,0 @@
<?xml version="1.0"?>
<!--
Copyright 2005 The Apache Software Foundation

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<antlib>
<taskdef
name="svn"
classname="org.apache.tools.ant.taskdefs.svn.Svn"
/>
<taskdef
name="changelog"
classname="org.apache.tools.ant.taskdefs.svn.SvnChangeLogTask"
/>
<taskdef
name="revisiondiff"
classname="org.apache.tools.ant.taskdefs.svn.SvnRevisionDiff"
/>
<taskdef
name="tagdiff"
classname="org.apache.tools.ant.taskdefs.svn.SvnTagDiff"
/>
</antlib>

+ 0
- 53
proposal/sandbox/svn/src/testcases/org/apache/tools/ant/taskdefs/svn/AbstractSvnTaskTest.java View File

@@ -1,53 +0,0 @@
/*
* Copyright 2005 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.tools.ant.taskdefs.svn;

import java.io.File;

import org.apache.tools.ant.BuildFileTest;

/**
*/
public class AbstractSvnTaskTest extends BuildFileTest {

public AbstractSvnTaskTest() {
this( "AbstractSvnTaskTest" );
}

public AbstractSvnTaskTest(String name) {
super(name);
}

public void setUp() {
configureProject("src/etc/testcases/abstractsvntask.xml");
}

public void tearDown() {
executeTarget("cleanup");
}

public void testAbstractSvnTask() {
executeTarget("all");
}

public void testRevisionAttribute() {
File f = getProject().resolveFile("tmpdir/tpf/ebcdic.h");
assertTrue("starting empty", !f.exists());
expectLogContaining("revision-attribute", "A tpf/ebcdic.h");
assertTrue("now it is there", f.exists());
}
}

+ 0
- 146
proposal/sandbox/svn/src/testcases/org/apache/tools/ant/taskdefs/svn/SvnChangeLogTaskTest.java View File

@@ -1,146 +0,0 @@
/*
* Copyright 2005 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.tools.ant.taskdefs.svn;

import java.io.IOException;
import java.io.FileReader;

import org.apache.tools.ant.BuildFileTest;
import org.apache.tools.ant.util.FileUtils;

import junit.framework.Assert;

/**
*/
public class SvnChangeLogTaskTest extends BuildFileTest {

public SvnChangeLogTaskTest(String name) {
super(name);
}

public void setUp() {
configureProject("src/etc/testcases/changelog.xml");
}

public void tearDown() {
executeTarget("cleanup");
}

public void testLog() throws IOException {
String log = executeTargetAndReadLogFully("log");
assertRev153687(log);
assertRev152685(log);
}

public void testStart() throws IOException {
String log = executeTargetAndReadLogFully("start");
assertRev153687(log);
assertNoRev152685(log);
}

public void testStartDate() throws IOException {
String log = executeTargetAndReadLogFully("startDate");
assertRev153687(log);
assertNoRev152685(log);
}

public void testEnd() throws IOException {
String log = executeTargetAndReadLogFully("end");
assertNoRev153687(log);
assertRev152685(log);
}

public void testEndDate() throws IOException {
String log = executeTargetAndReadLogFully("endDate");
assertNoRev153687(log);
assertRev152685(log);
}

private String executeTargetAndReadLogFully(String target)
throws IOException {
executeTarget(target);
FileReader r = new FileReader(getProject()
.resolveFile("tmpdir/log.xml"));
try {
return FileUtils.readFully(r);
} finally {
r.close();
}
}

private static final void assertRev153687(String log) {
int rev = log.indexOf("<revision>153687</revision>");
Assert.assertTrue(rev > -1);
int entryBeforeRev = log.lastIndexOf("<entry>", rev);
int entryAfterRev = log.indexOf("</entry>", rev);

Assert.assertTrue(entryBeforeRev > -1);
Assert.assertTrue(entryAfterRev > -1);

Assert
.assertTrue(log.lastIndexOf("<author><![CDATA[dbrosius]]></author>",
rev) > entryBeforeRev);
Assert
.assertTrue(log.indexOf("<name><![CDATA[/jakarta/bcel/trunk/src"
+ "/java/org/apache/bcel/util/BCELifier."
+ "java]]></name>", rev) < entryAfterRev);
Assert
.assertTrue(log.indexOf("<action>modified</action>", rev)
< entryAfterRev);
Assert
.assertTrue(log.indexOf("<message><![CDATA[Update BCELifier to "
+ "handle the new method access flags "
+ "(ACC_BRIDGE, ACC_VARARGS)]]></message>",
rev)
< entryAfterRev);
}

private static final void assertRev152685(String log) {
int rev = log.indexOf("<revision>152685</revision>");
Assert.assertTrue(rev > -1);
int entryBeforeRev = log.lastIndexOf("<entry>", rev);
int entryAfterRev = log.indexOf("</entry>", rev);

Assert.assertTrue(entryBeforeRev > -1);
Assert.assertTrue(entryAfterRev > -1);

Assert
.assertTrue(log.lastIndexOf("<![CDATA[(no author)]]>", rev)
> entryBeforeRev);
Assert
.assertTrue(log.indexOf("<name><![CDATA[/jakarta/bcel/branches]]>"
+ "</name>", rev) < entryAfterRev);
Assert
.assertTrue(log.indexOf("<action>added</action>", rev)
< entryAfterRev);
Assert
.assertTrue(log.indexOf("<message><![CDATA[New repository "
+ "initialized by cvs2svn.]]></message>",
rev)
< entryAfterRev);
}

private static final void assertNoRev153687(String log) {
int rev = log.indexOf("<revision>153687</revision>");
Assert.assertEquals(-1, rev);
}

private static final void assertNoRev152685(String log) {
int rev = log.indexOf("<revision>152685</revision>");
Assert.assertEquals(-1, rev);
}
}

+ 0
- 136
proposal/sandbox/svn/src/testcases/org/apache/tools/ant/taskdefs/svn/SvnRevisionDiffTest.java View File

@@ -1,136 +0,0 @@
/*
* Copyright 2005 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.tools.ant.taskdefs.svn;

import java.io.IOException;
import java.io.FileReader;

import org.apache.tools.ant.BuildFileTest;
import org.apache.tools.ant.util.FileUtils;

import junit.framework.Assert;

/**
*/
public class SvnRevisionDiffTest extends BuildFileTest {

public SvnRevisionDiffTest(String name) {
super(name);
}

public void setUp() {
configureProject("src/etc/testcases/revisiondiff.xml");
}

public void tearDown() {
executeTarget("cleanup");
}

public void testDiff() throws IOException {
String log = executeTargetAndReadLogFully("diff");
assertAttributesNoURL(log);
assertAdded(log);
assertModified(log);
assertDeleted(log);
}

public void testDiffUrl() throws IOException {
String log = executeTargetAndReadLogFully("diff-using-url");
assertAttributesWithURL(log);
assertAdded(log);
assertModified(log);
assertDeleted(log);
}

private String executeTargetAndReadLogFully(String target)
throws IOException {
executeTarget(target);
FileReader r = new FileReader(getProject()
.resolveFile("tmpdir/diff.xml"));
try {
return FileUtils.readFully(r);
} finally {
r.close();
}
}

private static final void assertAttributes(String log) {
int start = log.indexOf("<revisiondiff");
Assert.assertTrue(start > -1);
int end = log.indexOf(">", start);
Assert.assertTrue(end > -1);
Assert.assertTrue(log.indexOf("start=\"152904\"", start) > -1);
Assert.assertTrue(log.indexOf("start=\"152904\"", start) < end);
Assert.assertTrue(log.indexOf("end=\"153682\"", start) > -1);
Assert.assertTrue(log.indexOf("end=\"153682\"", start) < end);
}

private static final void assertAttributesNoURL(String log) {
assertAttributes(log);
Assert.assertEquals(-1, log.indexOf("svnurl="));
}

private static final void assertAttributesWithURL(String log) {
assertAttributes(log);
int start = log.indexOf("<revisiondiff");
int end = log.indexOf(">", start);
Assert.assertTrue(log.indexOf("svnurl=\"http://svn.apache.org/repos/"
+ "asf/jakarta/bcel/trunk\"", start)
> -1);
Assert.assertTrue(log.indexOf("svnurl=\"http://svn.apache.org/repos/"
+ "asf/jakarta/bcel/trunk\"", start)
< end);
}

private static final void assertAdded(String log) {
int name = log.indexOf("<![CDATA[src/java/org/apache/bcel/classfile/"
+ "ElementValuePair.java]]>");
Assert.assertTrue(name > -1);

int pathAfterName = log.indexOf("</path>", name);
Assert.assertTrue(pathAfterName > -1);

Assert.assertTrue(log.indexOf("<action>added</action>", name) > -1);
Assert.assertTrue(log.indexOf("<action>added</action>", name)
< pathAfterName);
}

private static final void assertModified(String log) {
int name = log.indexOf("<name><![CDATA[xdocs/stylesheets/project."
+ "xml]]></name>");
Assert.assertTrue(name > -1);

int pathAfterName = log.indexOf("</path>", name);
Assert.assertTrue(pathAfterName > -1);

Assert.assertTrue(log.indexOf("<action>modified</action>", name) > -1);
Assert.assertTrue(log.indexOf("<action>modified</action>", name)
< pathAfterName);
}

private static final void assertDeleted(String log) {
int name = log.indexOf("<name><![CDATA[lib/CCK.jar]]></name>");
Assert.assertTrue(name > -1);

int pathAfterName = log.indexOf("</path>", name);
Assert.assertTrue(pathAfterName > -1);

Assert.assertTrue(log.indexOf("<action>deleted</action>", name) > -1);
Assert.assertTrue(log.indexOf("<action>deleted</action>", name)
< pathAfterName);
}
}

+ 0
- 144
proposal/sandbox/svn/src/testcases/org/apache/tools/ant/taskdefs/svn/SvnTagDiffTest.java View File

@@ -1,144 +0,0 @@
/*
* Copyright 2005 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.tools.ant.taskdefs.svn;

import java.io.IOException;
import java.io.FileReader;

import org.apache.tools.ant.BuildFileTest;
import org.apache.tools.ant.util.FileUtils;

import junit.framework.Assert;

/**
*/
public class SvnTagDiffTest extends BuildFileTest {

public SvnTagDiffTest(String name) {
super(name);
}

public void setUp() {
configureProject("src/etc/testcases/tagdiff.xml");
}

public void tearDown() {
executeTarget("cleanup");
}

public void testDiffWithTwoTags() throws IOException {
String log = executeTargetAndReadLogFully("diff-with-two-tags");
assertAttributes(log, "initial", "BCEL_5_0");
assertAdded1(log);
}

public void testDiffWithExplicitTrunk() throws IOException {
String log = executeTargetAndReadLogFully("diff-with-explicit-trunk");
assertDiffWithTrunk(log);
}

public void testDiffWithImplicitTrunk() throws IOException {
String log = executeTargetAndReadLogFully("diff-with-implicit-trunk");
assertDiffWithTrunk(log);
}

private static void assertDiffWithTrunk(String log) {
assertAttributes(log, "BCEL_5_0", "trunk");
assertAdded(log);
assertModified(log);
assertDeleted(log);
}

private String executeTargetAndReadLogFully(String target)
throws IOException {
executeTarget(target);
FileReader r = new FileReader(getProject()
.resolveFile("tmpdir/diff.xml"));
try {
return FileUtils.readFully(r);
} finally {
r.close();
}
}

private static final void assertAttributes(String log, String tag1,
String tag2) {
int start = log.indexOf("<tagdiff");
Assert.assertTrue(start > -1);
int end = log.indexOf(">", start);
Assert.assertTrue(end > -1);
Assert.assertTrue(log.indexOf("tag1=\"" + tag1 + "\"", start) > -1);
Assert.assertTrue(log.indexOf("tag1=\"" + tag1 + "\"", start) < end);
Assert.assertTrue(log.indexOf("tag2=\"" + tag2 + "\"", start) > -1);
Assert.assertTrue(log.indexOf("tag2=\"" + tag2 + "\"", start) < end);
Assert.assertTrue(log.indexOf("svnurl=\"http://svn.apache.org/repos/"
+ "asf/jakarta/bcel/\"", start) > -1);
Assert.assertTrue(log.indexOf("svnurl=\"http://svn.apache.org/repos/"
+ "asf/jakarta/bcel/\"", start) < end);
}

private static final void assertAdded(String log) {
int name = log.indexOf("<![CDATA[LICENSE.txt]]>");
Assert.assertTrue(name > -1);

int pathAfterName = log.indexOf("</path>", name);
Assert.assertTrue(pathAfterName > -1);

Assert.assertTrue(log.indexOf("<action>added</action>", name) > -1);
Assert.assertTrue(log.indexOf("<action>added</action>", name)
< pathAfterName);
}

private static final void assertModified(String log) {
int name = log.indexOf("<name><![CDATA[src/java/org/apache/bcel/"
+ "Repository.java]]></name>");
Assert.assertTrue(name > -1);

int pathAfterName = log.indexOf("</path>", name);
Assert.assertTrue(pathAfterName > -1);

Assert.assertTrue(log.indexOf("<action>modified</action>", name) > -1);
Assert.assertTrue(log.indexOf("<action>modified</action>", name)
< pathAfterName);
}

private static final void assertDeleted(String log) {
int name = log.indexOf("<name><![CDATA[LICENSE]]></name>");
Assert.assertTrue(name > -1);

int pathAfterName = log.indexOf("</path>", name);
Assert.assertTrue(pathAfterName > -1);

Assert.assertTrue(log.indexOf("<action>deleted</action>", name) > -1);
Assert.assertTrue(log.indexOf("<action>deleted</action>", name)
< pathAfterName);
}

private static final void assertAdded1(String log) {
int name = log.indexOf("<name><![CDATA[src/java/org/apache/bcel/"
+ "Repository.java]]></name>");
Assert.assertTrue(name > -1);

int pathAfterName = log.indexOf("</path>", name);
Assert.assertTrue(pathAfterName > -1);

Assert.assertTrue(log.indexOf("<action>added</action>", name) > -1);
Assert.assertTrue(log.indexOf("<action>added</action>", name)
< pathAfterName);
}

}

Loading…
Cancel
Save