From 6d649a05c988af85d215a83bdcf1aecaead1ef87 Mon Sep 17 00:00:00 2001 From: Ben Maurer Date: Mon, 6 Jun 2005 20:09:58 +0000 Subject: [PATCH] depreciated svn path=/trunk/old-code/; revision=45535 --- nant/.cvsignore | 2 + nant/ChangeLog | 17 + nant/README-nant.txt | 62 ++++ nant/doc/arrow.gif | Bin 0 -> 58 bytes nant/doc/authors.html | 43 +++ nant/doc/changelog.html | 121 +++++++ nant/doc/index.html | 43 +++ nant/doc/license.html | 48 +++ nant/doc/style.css | 71 ++++ nant/doc/todo.html | 55 +++ nant/readme.txt | 4 + nant/src/AssemblyInfo.cs | 37 ++ .../Attributes/BooleanValidatorAttribute.cs | 42 +++ .../src/Attributes/Int32ValidatorAttribute.cs | 63 ++++ nant/src/Attributes/TaskAttributeAttribute.cs | 78 ++++ nant/src/Attributes/TaskFileSetAttribute.cs | 40 +++ nant/src/Attributes/TaskNameAttribute.cs | 45 +++ nant/src/Attributes/ValidatorAttribute.cs | 28 ++ nant/src/BuildException.cs | 85 +++++ nant/src/DirectoryScanner.cs | 226 ++++++++++++ nant/src/FileSet.cs | 132 +++++++ nant/src/Location.cs | 89 +++++ nant/src/NAnt.cs | 107 ++++++ nant/src/NAnt.exe | Bin 0 -> 61440 bytes nant/src/Project.cs | 332 ++++++++++++++++++ nant/src/PropertyDictionary.cs | 72 ++++ nant/src/Target.cs | 115 ++++++ nant/src/TargetCollection.cs | 35 ++ nant/src/Task.cs | 192 ++++++++++ nant/src/TaskBuilder.cs | 84 +++++ nant/src/TaskBuilderCollection.cs | 46 +++ nant/src/TaskCollection.cs | 26 ++ nant/src/TaskFactory.cs | 57 +++ nant/src/Tasks/CallTask.cs | 41 +++ nant/src/Tasks/ChangeLog | 13 + nant/src/Tasks/CompilerBase.cs | 195 ++++++++++ nant/src/Tasks/CopyTask.cs | 196 +++++++++++ nant/src/Tasks/CscTask.cs | 45 +++ nant/src/Tasks/DeleteTask.cs | 173 +++++++++ nant/src/Tasks/EchoTask.cs | 34 ++ nant/src/Tasks/ExecTask.cs | 58 +++ nant/src/Tasks/ExternalProgramBase.cs | 130 +++++++ nant/src/Tasks/FailTask.cs | 38 ++ nant/src/Tasks/IncludeTask.cs | 134 +++++++ nant/src/Tasks/JscTask.cs | 40 +++ nant/src/Tasks/McsTask.cs | 47 +++ nant/src/Tasks/MkDirTask.cs | 49 +++ nant/src/Tasks/MoveTask.cs | 71 ++++ nant/src/Tasks/NantTask.cs | 65 ++++ nant/src/Tasks/PropertyTask.cs | 37 ++ nant/src/Tasks/SleepTask.cs | 91 +++++ nant/src/Tasks/StyleTask.cs | 171 +++++++++ nant/src/Tasks/TStampTask.cs | 43 +++ nant/src/Tasks/TaskDefTask.cs | 42 +++ nant/src/Tasks/VbcTask.cs | 40 +++ nant/src/Util/Log.cs | 155 ++++++++ nant/src/Util/XmlNodeTextPositionMap.cs | 187 ++++++++++ 57 files changed, 4492 insertions(+) create mode 100755 nant/.cvsignore create mode 100644 nant/ChangeLog create mode 100644 nant/README-nant.txt create mode 100755 nant/doc/arrow.gif create mode 100755 nant/doc/authors.html create mode 100755 nant/doc/changelog.html create mode 100755 nant/doc/index.html create mode 100755 nant/doc/license.html create mode 100755 nant/doc/style.css create mode 100755 nant/doc/todo.html create mode 100644 nant/readme.txt create mode 100755 nant/src/AssemblyInfo.cs create mode 100755 nant/src/Attributes/BooleanValidatorAttribute.cs create mode 100755 nant/src/Attributes/Int32ValidatorAttribute.cs create mode 100755 nant/src/Attributes/TaskAttributeAttribute.cs create mode 100755 nant/src/Attributes/TaskFileSetAttribute.cs create mode 100755 nant/src/Attributes/TaskNameAttribute.cs create mode 100755 nant/src/Attributes/ValidatorAttribute.cs create mode 100755 nant/src/BuildException.cs create mode 100755 nant/src/DirectoryScanner.cs create mode 100755 nant/src/FileSet.cs create mode 100755 nant/src/Location.cs create mode 100755 nant/src/NAnt.cs create mode 100755 nant/src/NAnt.exe create mode 100755 nant/src/Project.cs create mode 100755 nant/src/PropertyDictionary.cs create mode 100755 nant/src/Target.cs create mode 100755 nant/src/TargetCollection.cs create mode 100755 nant/src/Task.cs create mode 100755 nant/src/TaskBuilder.cs create mode 100755 nant/src/TaskBuilderCollection.cs create mode 100755 nant/src/TaskCollection.cs create mode 100755 nant/src/TaskFactory.cs create mode 100755 nant/src/Tasks/CallTask.cs create mode 100644 nant/src/Tasks/ChangeLog create mode 100755 nant/src/Tasks/CompilerBase.cs create mode 100755 nant/src/Tasks/CopyTask.cs create mode 100755 nant/src/Tasks/CscTask.cs create mode 100755 nant/src/Tasks/DeleteTask.cs create mode 100755 nant/src/Tasks/EchoTask.cs create mode 100755 nant/src/Tasks/ExecTask.cs create mode 100755 nant/src/Tasks/ExternalProgramBase.cs create mode 100755 nant/src/Tasks/FailTask.cs create mode 100755 nant/src/Tasks/IncludeTask.cs create mode 100755 nant/src/Tasks/JscTask.cs create mode 100644 nant/src/Tasks/McsTask.cs create mode 100755 nant/src/Tasks/MkDirTask.cs create mode 100755 nant/src/Tasks/MoveTask.cs create mode 100755 nant/src/Tasks/NantTask.cs create mode 100755 nant/src/Tasks/PropertyTask.cs create mode 100755 nant/src/Tasks/SleepTask.cs create mode 100755 nant/src/Tasks/StyleTask.cs create mode 100755 nant/src/Tasks/TStampTask.cs create mode 100755 nant/src/Tasks/TaskDefTask.cs create mode 100755 nant/src/Tasks/VbcTask.cs create mode 100755 nant/src/Util/Log.cs create mode 100755 nant/src/Util/XmlNodeTextPositionMap.cs diff --git a/nant/.cvsignore b/nant/.cvsignore new file mode 100755 index 00000000..6e955671 --- /dev/null +++ b/nant/.cvsignore @@ -0,0 +1,2 @@ +NAnt.exe +nant.exe diff --git a/nant/ChangeLog b/nant/ChangeLog new file mode 100644 index 00000000..b8cf5a0b --- /dev/null +++ b/nant/ChangeLog @@ -0,0 +1,17 @@ +2002-04-28 Nick Drochak + + * makefile: Make NAnt.exe dependant on all the *.cs in src and each sub + dir. Since we don't remove it on a 'make clean' it doesn't get rebuilt + when a new file is added or an existing one changed. + +2002-03-17 Nick Drochak + + * makefile: Do not remove the NAnt.exe on a 'make clean'. This would + prevent other cleans from happening that need nant. + +2002/03/15 Nick Drochak + + * makefile: Compile a version of NAnt with Mono's libs. It only does + this if you 'make NAnt_mono.exe'. Of course, right now the resulting + exe probably is not going to work yet becuase of the immature class + libs. diff --git a/nant/README-nant.txt b/nant/README-nant.txt new file mode 100644 index 00000000..66c04bef --- /dev/null +++ b/nant/README-nant.txt @@ -0,0 +1,62 @@ +NAnt + +What is it? +----------- +NAnt is a .NET based build tool. In theory it is kind of like make without +make's wrinkles. In practice it's a lot like Ant. + +If you are not familiar with Jakarta Ant you can get more information at the +Jakarta project web site. +http://jakarta.apache.org/ + + +Why NAnt? +--------- +Because Ant was too Java specific. +Because Ant needed the Java runtime. NAnt only needs the .NET runtime. + + +The Latest Version +------------------ +Details of the latest version can be found on the NAnt project web site +http://nant.sourceforge.net/ + + +Documentation +------------- +Documentation is available in HTML format, in the doc/ directory. + + +License +------- +Copyright (C) 2001 Gerry Shaw + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +In addition, as a special exception, Gerry Shaw gives permission to link the +code of this program with the Microsoft .NET library (or with modified versions +of Microsoft .NET library that use the same license as the Microsoft .NET +library), and distribute linked combinations including the two. You must obey +the GNU General Public License in all respects for all of the code used other +than the Microsoft .NET library. If you modify this file, you may extend this +exception to your version of the file, but you are not obligated to do so. If +you do not wish to do so, delete this exception statement from your version. + +A copy of the GNU General Public License is available in the COPYING.txt file +included with all NAnt distributions. + +For more licensing information refer to the GNU General Public License on the +GNU Project web site. +http://www.gnu.org/copyleft/gpl.html diff --git a/nant/doc/arrow.gif b/nant/doc/arrow.gif new file mode 100755 index 0000000000000000000000000000000000000000..d5e5f8e771dc7a54fa6087761659cf2eba98b0bc GIT binary patch literal 58 zcmZ?wbhEHbjEB<5wG8q|kKzxu41CwA+|4PQ$7v?lhyrsP|#V|jV Hfx#L8hD{FA literal 0 HcmV?d00001 diff --git a/nant/doc/authors.html b/nant/doc/authors.html new file mode 100755 index 00000000..3b8ce57e --- /dev/null +++ b/nant/doc/authors.html @@ -0,0 +1,43 @@ + + + + + + + NAnt Authors + + + + + + + +

NAnt Authors

+ +

Lead Developer

+
    +
  • Gerry Shaw (gerry_shaw@yahoo.com)
  • +
+ +

Developers

+
    +
  • Ian MacLean (ian_maclean@another.com)
  • +
+ +

Code Contributions (sorted by name)

+
    +
  • Mike Krueger (mike@icsharpcode.net)
  • +
  • Sergey Chaban (serge@wildwestsoftware.com)
  • +
+ +

Special Thanks To

+
    +
  • The Ant team on the Jakarta project.
  • +
  • Hazware for the original XBuild source.
  • +
  • Philip Craig for NUnit.
  • +
  • Microsoft for making .NET and C#.
  • +
  • Ximian for working on the Mono project ot make .NET a true open standard.
  • +
+ + + diff --git a/nant/doc/changelog.html b/nant/doc/changelog.html new file mode 100755 index 00000000..a5f3ac7e --- /dev/null +++ b/nant/doc/changelog.html @@ -0,0 +1,121 @@ + + + + + + + NAnt Change Log + + + + + + + +

NAnt Change Log

+ +

0.6.0 September 18, 2001

+
    +
  • report build file xml errors in a useful way
  • +
  • report error location when tasks are missing required attributes
  • +
  • copy task updated - thanks to Ian MacLean
  • +
  • **/*.cs type pattern matching now available in file sets via DirectoryScanner class
  • +
  • Ian MacLean added as a project developer
  • +
  • added all the environment variables to properites, ie, <echo message="path=${nant.env.PATH}"/>
  • +
  • move task updated - thanks to Ian MacLean
  • +
  • sleep task added - thanks to Ian MacLean
  • +
  • DirectoryScanner and FileSet's scan for files AND directories now
  • +
  • FileSet's cache scan results, use Scan() to rescan
  • +
  • FileSet's auto initialize to their containing Task, this helps clean up the code
  • +
  • copy task can now copy full directory trees
  • +
  • added verbose attribute to copy task, default off, message gives number of files processed
  • +
  • fixed bug with any ExternalBase tasks hanging - thanks to Sergey Chaban for reporting
  • +
  • include task added
  • +
  • call task added
  • +
  • -verbose command line option added
  • +
  • build file can now build complete distribution, try 'nant dist'
  • +
+ +

0.5.0 August 22, 2001

+
    +
  • complete overhaul of the web site and doc folder (all html files)
  • +
  • made src a parent folder to be able to hold multiple assemblies in anticipation of the NAnt.Tests.dll assembly
  • +
  • licensed changed to GNU General Public License
  • +
  • source code placed under CVS
  • +
  • tasks can now have attributes in base classes, see CompilerBase as an example - thanks to Mike Krueger
  • +
  • coding conventions posted on SourceForge in the document manager
  • +
  • task manager in SourceForge is now being used to track currently active tasks
  • +
  • namespace changed to SourceForge.NAnt
  • +
  • added basic command line parsing
  • +
  • added version resource
  • +
  • support for multiple build targets (try 'nant clean test')
  • +
  • BuildException added to report text position in the build file where errors occur - thanks to Ian MacLean
  • +
  • style task (xslt processing) added - thanks to Serge
  • +
  • executable is now signed with the NAnt.key
  • +
  • converted all public/protected fields to properties
  • +
  • added support for user define properties
  • +
  • added -set option (try 'nant -set:debug=true clean build')
  • +
  • changed verions number to 0.5 to reflect the number of changes in the code base
  • +
+ +

0.1.5 July 22, 2001

+
    +
  • only compiles program if source file last write time > output last write time
  • +
  • refactored compiler code into common CompilerBase class
  • +
  • refactored compiler and exec task into common ExternalProgramBase class
  • +
  • added <arg value="/win32res:filename"/> element to all external program tasks
  • +
  • added Int32ValidatorAttribute and BooleanValidatorAttribute classes to perform error checking on task attributes after macro expansion but before task execution. Search for BooleanValidator or Int32Validator in Tasks for examples.
  • +
  • changed Task attribute names to TaskAttributeAttribute and FileSetAttribute
  • +
  • removed default value for task attributes (set with initial value)
  • +
  • changes to Project class on how to initialize a project and run it
  • +
  • right aligned task prefixes to clean up output
  • +
  • added or enhanced these tasks +
      +
    • vbc, jsc, csc
    • +
    • move
    • +
    • nant
    • +
    • taskdef
    • +
    • tstamp
    • +
    • exec (failonerror attribute)
    • +
    +
  • +
+ +

0.1.4 July 19, 2001

+
    +
  • added or enhanced these tasks +
      +
    • echo
    • +
    • fail
    • +
    • property
    • +
    • copy (respects basedir)
    • +
    • delete (respects basedir)
    • +
    • mkdir (respects basedir)
    • +
    • exec
    • +
    +
  • +
+ +

0.1.3 July 18, 2001

+
    +
  • dependices working via depends attribute on targets
  • +
  • changed name from NBuild to NAnt
  • +
  • using the name "Parameter" to refer to the xml attributes in tasks because it was conflicting badly with .NET Attributes
  • +
  • added FileSetParameterAttribute so that fileset parameters would autoinit
  • +
  • renamed TaskAttributeAttribute to StringParameterAttribute
  • +
  • broke into seperate source files (one per class)
  • +
  • changed default build file from Project.xml to the first file with a .build extension
  • +
+ +

0.1.2 July 16, 2001

+
    +
  • basic functionality to have NAnt build itself (csc task)
  • +
+ +

0.1.1 July 5, 2001

+
    +
  • initial test version
  • +
+ + + diff --git a/nant/doc/index.html b/nant/doc/index.html new file mode 100755 index 00000000..635c2ca1 --- /dev/null +++ b/nant/doc/index.html @@ -0,0 +1,43 @@ + + + + + + + NAnt - A .NET Build Tool + + + + + + + +

NAnt Home Page

+ +

September 18, 2001 Gerry Shaw -- gerry_shaw@yahoo.com

+

NAnt is a .NET based build tool. In theory it is kind of like make without make's wrinkles. In practice it's a lot like Ant. NAnt has only been tested with Beta 2 .NET SDK, build 2914.

+

The idea for NAnt came from Hazware's XBuild project. After emailing the author for a beta 2 version of the tool and getting no response I decided to port the code to .NET beta 2. Due to the number of changes from .NET beta 1 to beta 2 the result was a total rewrite.

+ + +

Getting Started

+

Since the software is still in heavy development you are going to be on your own. You can see NAnt build itself by doing the following:

+
    +
  1. Download the latest released version.
  2. +
  3. Unzip the distribution into a new folder.
  4. +
  5. Using a command prompt (so you can see the build output) cd into the + folder where NAnt was unzipped.
  6. +
  7. Type bin\nant at the command prompt to build NAnt.
  8. +
+ +

SourceForge logo (link to home page)

+ + + diff --git a/nant/doc/license.html b/nant/doc/license.html new file mode 100755 index 00000000..86d993bb --- /dev/null +++ b/nant/doc/license.html @@ -0,0 +1,48 @@ + + + + + + + NAnt License + + + + + + + +

NAnt License

+

Copyright © 2001 Gerry Shaw

+

+ This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. +

+

+ This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. +

+

+ You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +

+

+ In addition, as a special exception, Gerry Shaw gives permission to link the + code of this program with the Microsoft .NET library (or with modified versions + of Microsoft .NET library that use the same license as the Microsoft .NET + library), and distribute linked combinations including the two. You must obey + the GNU General Public License in all respects for all of the code used other + than the Microsoft .NET library. If you modify this file, you may extend this + exception to your version of the file, but you are not obligated to do so. If + you do not wish to do so, delete this exception statement from your version. +

+

A copy of the GNU General Public License is available in the COPYING.txt file included with all NAnt distributions.

+

The GNU Project has more information on the GNU General Public License.

+ + + diff --git a/nant/doc/style.css b/nant/doc/style.css new file mode 100755 index 00000000..32613372 --- /dev/null +++ b/nant/doc/style.css @@ -0,0 +1,71 @@ +body { + font-family: Georgia, "Times New Roman", Times, "New York", serif; + background: white; + color: black +} + +h1, h2, h3, h4, h5, h6 { + font-family: Verdana, Arial, Helvetica, Geneva, SunSans-Regular, sans-serif +} + +h1.LinkHeader, h2.LinkHeader, h3.LinkHeader { margin-bottom: -18 } + +h4 { + margin-bottom: 0.5em +} + +h5 { + margin-bottom: -.8em; +} + + +hr { + color: gray +} + +input { + font-family: Verdana, Arial, Helvetica, Geneva, SunSans-Regular, sans-serif; +} + +a:link { color: #0000cc; } +a:visited { color: purple } +a:active { color: #cc0000 } +a:hover { color: #cc0000; } + +/* + +Because HTML 4.0 strict does not include the border attribute for images we turn it off with a style +but this totally messes up Navigator 4.7 so we can't use it. + +a:link img, a:visited img, a:active img { + border: none +} +*/ + +/* have list items flush left against lists in a side bar use this style */ +ul.FlushLeft { + margin-left: 1.25em; + list-style-position: outside +} + +.NavBar { + background-color: #dfff80; + border-color: #999966; + border-style: none none solid none; + border-width: 2px; +} + +.NavBar-Cell { + font-family: Verdana, Arial, Helvetica, Geneva, SunSans-Regular, sans-serif; + font-size: 79%; +} + +.SideBar { + font-size: 80%; + font-family: Verdana, Arial, Helvetica, Geneva, SunSans-Regular, sans-serif; + padding: 8px; +} + +/* color scheme */ +.N { color: #99cc00; } +.Ant { color: #ff9900; } diff --git a/nant/doc/todo.html b/nant/doc/todo.html new file mode 100755 index 00000000..20cd3ba1 --- /dev/null +++ b/nant/doc/todo.html @@ -0,0 +1,55 @@ + + + + + + + NAnt To Do + + + + + + + +

NAnt To Do

+

The following is a rough guide to what features are being worked on and when they will be worked on in the future.

+

For a list of what is actively being worked refer to the NAnt Task Manager on SourceForge.

+ +

0.7

+
    +
  • command line parsing using clippy (another tool I'm working on that will be posted soon)
  • +
  • clippy task (for command line parsing)
  • +
  • nunit tests
  • +
  • nunit task
  • +
  • validate build file for valid xml and against a schema before starting build
  • +
  • code xml docs for all non private members
  • +
  • developer docs (code conventions, high level design)
  • +
  • post newsgroup announcment
  • +
  • request code review and project help
  • +
+ +

0.8

+
    +
  • task documentation for users
  • +
  • zip task
  • +
  • ftp task
  • +
  • standard input support for tasks that require input (ie, passwords when copying files via scp to SourceForge)
  • +
+ +

1.0

+
    +
  • official release
  • +
  • general cleanup
  • +
  • xml documentation
  • +
  • user documentation
  • +
  • post newsgroup announcment
  • +
+ +

1.1

+
    +
  • additional optional but useful tasks (sql, touch, email, grep)
  • +
+ + + \ No newline at end of file diff --git a/nant/readme.txt b/nant/readme.txt new file mode 100644 index 00000000..816b000c --- /dev/null +++ b/nant/readme.txt @@ -0,0 +1,4 @@ +This is an import of the Nant sources version 0.6.0 into the +tree. We are doing this because the binaries were not compatible +across versions of .NET. + diff --git a/nant/src/AssemblyInfo.cs b/nant/src/AssemblyInfo.cs new file mode 100755 index 00000000..1bd25d5d --- /dev/null +++ b/nant/src/AssemblyInfo.cs @@ -0,0 +1,37 @@ +// NAnt - A .NET build tool +// Copyright (C) 2001 Gerry Shaw +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Gerry Shaw (gerry_shaw@yahoo.com) + +using System.Reflection; +using System.Runtime.CompilerServices; + +[assembly: AssemblyTitle("NAnt")] +[assembly: AssemblyDescription("A .NET Build Tool")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("http://nant.sourceforge.net/")] +[assembly: AssemblyProduct("NAnt")] +[assembly: AssemblyCopyright("Copyright (C) 2001 Gerry Shaw")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] +[assembly: AssemblyVersion("0.6.0.*")] + +// This will not compile with Visual Studio. If you want to build a signed +// executable use the NAnt build file. To build under Visual Studio just +// exclude this file from the build. +[assembly: AssemblyDelaySign(false)] +[assembly: AssemblyKeyName("")] diff --git a/nant/src/Attributes/BooleanValidatorAttribute.cs b/nant/src/Attributes/BooleanValidatorAttribute.cs new file mode 100755 index 00000000..932b027d --- /dev/null +++ b/nant/src/Attributes/BooleanValidatorAttribute.cs @@ -0,0 +1,42 @@ +// NAnt - A .NET build tool +// Copyright (C) 2001 Gerry Shaw +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Gerry Shaw (gerry_shaw@yahoo.com) + +namespace SourceForge.NAnt { + + using System; + using System.Reflection; + + /// Indicates that field should be able to be converted into a Boolean. + [AttributeUsage(AttributeTargets.Field, Inherited=true)] + public class BooleanValidatorAttribute : ValidatorAttribute { + + public BooleanValidatorAttribute() { + } + + public override string Validate(object value) { + string errorMessage = null; + try { + Convert.ToBoolean(value); + } catch (Exception) { + errorMessage = String.Format("Cannot resolve to '{0}' to Boolean value.", value.ToString()); + } + return errorMessage; + } + } +} \ No newline at end of file diff --git a/nant/src/Attributes/Int32ValidatorAttribute.cs b/nant/src/Attributes/Int32ValidatorAttribute.cs new file mode 100755 index 00000000..51d967d7 --- /dev/null +++ b/nant/src/Attributes/Int32ValidatorAttribute.cs @@ -0,0 +1,63 @@ +// NAnt - A .NET build tool +// Copyright (C) 2001 Gerry Shaw +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Gerry Shaw (gerry_shaw@yahoo.com) + +namespace SourceForge.NAnt { + + using System; + using System.Reflection; + + /// Indicates that field should be able to be converted into a Int32 within the given range. + [AttributeUsage(AttributeTargets.Field, Inherited=true)] + public class Int32ValidatorAttribute : ValidatorAttribute { + + int _minValue = Int32.MinValue; + int _maxValue = Int32.MaxValue; + + public Int32ValidatorAttribute() { + } + + public Int32ValidatorAttribute(int minValue, int maxValue) { + MinValue = minValue; + MaxValue = maxValue; + } + + public int MinValue { + get { return _minValue; } + set { _minValue = value; } + } + + public int MaxValue { + get { return _maxValue; } + set { _maxValue = value; } + } + + public override string Validate(object value) { + string errorMessage = null; + try { + Int32 intValue = Convert.ToInt32(value); + if (intValue < MinValue || intValue > MaxValue) { + errorMessage = String.Format("Cannot resolve '{0}' to integer between '{1}' and '{2}'.", value.ToString(), MinValue, MaxValue); + } + } catch (Exception) { + errorMessage = String.Format("Cannot resolve '{0}' to integer value.", value.ToString()); + } + return errorMessage; + } + } +} \ No newline at end of file diff --git a/nant/src/Attributes/TaskAttributeAttribute.cs b/nant/src/Attributes/TaskAttributeAttribute.cs new file mode 100755 index 00000000..060e25c3 --- /dev/null +++ b/nant/src/Attributes/TaskAttributeAttribute.cs @@ -0,0 +1,78 @@ +// NAnt - A .NET build tool +// Copyright (C) 2001 Gerry Shaw +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Gerry Shaw (gerry_shaw@yahoo.com) + +namespace SourceForge.NAnt { + + using System; + using System.Reflection; + + /// Indicates that field should be treated as a xml attribute for the task. + /// + /// Examples of how to specify task attributes + /// + /// // task XmlType default is string + /// [TaskAttribute("out", Required=true)] + /// string _out = null; // assign default value here + /// + /// [TaskAttribute("optimize")] + /// [BooleanValidator()] + /// // during ExecuteTask you can safely use Convert.ToBoolean(_optimize) + /// string _optimize = Boolean.FalseString; + /// + /// [TaskAttribute("warnlevel")] + /// [Int32Validator(0,4)] // limit values to 0-4 + /// // during ExecuteTask you can safely use Convert.ToInt32(_optimize) + /// string _warnlevel = "0"; + /// + /// [TaskFileSet("sources")] + /// FileSet _sources = new FileSet(); + /// + /// NOTE: Attribute values must be of type of string if you want + /// to be able to have macros. The field stores the exact value during + /// InitializeTask. Just before ExecuteTask is called NAnt will expand + /// all the macros with the current values. + [AttributeUsage(AttributeTargets.Field, Inherited=true)] + public class TaskAttributeAttribute : Attribute { + + string _name; + bool _required; + bool _expandText; + + public TaskAttributeAttribute(string name) { + Name = name; + Required = false; + ExpandText = true; + } + + public string Name { + get { return _name; } + set { _name = value; } + } + + public bool Required { + get { return _required; } + set { _required = value; } + } + + public bool ExpandText { + get { return _expandText; } + set { _expandText = value; } + } + } +} diff --git a/nant/src/Attributes/TaskFileSetAttribute.cs b/nant/src/Attributes/TaskFileSetAttribute.cs new file mode 100755 index 00000000..607f59fc --- /dev/null +++ b/nant/src/Attributes/TaskFileSetAttribute.cs @@ -0,0 +1,40 @@ +// NAnt - A .NET build tool +// Copyright (C) 2001 Gerry Shaw +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Gerry Shaw (gerry_shaw@yahoo.com) + +namespace SourceForge.NAnt { + + using System; + using System.Reflection; + + /// Indicates that field should be treated as a xml file set for the task. + [AttributeUsage(AttributeTargets.Field, Inherited=true)] + public class TaskFileSetAttribute : Attribute { + + string _name; + + public TaskFileSetAttribute(string name) { + Name = name; + } + + public string Name { + get { return _name; } + set { _name = value; } + } + } +} \ No newline at end of file diff --git a/nant/src/Attributes/TaskNameAttribute.cs b/nant/src/Attributes/TaskNameAttribute.cs new file mode 100755 index 00000000..bc7ffde1 --- /dev/null +++ b/nant/src/Attributes/TaskNameAttribute.cs @@ -0,0 +1,45 @@ +// NAnt - A .NET build tool +// Copyright (C) 2001 Gerry Shaw +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Gerry Shaw (gerry_shaw@yahoo.com) + +namespace SourceForge.NAnt { + + using System; + using System.Reflection; + + /// Indicates that class should be treated as a task. + /// + /// Attach this attribute to a subclass of Task to have NAnt be able + /// to reconize it. The name should be short but must not confict + /// with any other task already in use. + /// + [AttributeUsage(AttributeTargets.Class, Inherited=false, AllowMultiple=false)] + public class TaskNameAttribute : Attribute { + + string _name; + + public TaskNameAttribute(string name) { + _name = name; + } + + public string Name { + get { return _name; } + set { _name = value; } + } + } +} \ No newline at end of file diff --git a/nant/src/Attributes/ValidatorAttribute.cs b/nant/src/Attributes/ValidatorAttribute.cs new file mode 100755 index 00000000..053089cc --- /dev/null +++ b/nant/src/Attributes/ValidatorAttribute.cs @@ -0,0 +1,28 @@ +// NAnt - A .NET build tool +// Copyright (C) 2001 Gerry Shaw +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Gerry Shaw (gerry_shaw@yahoo.com) + +namespace SourceForge.NAnt { + + using System; + using System.Reflection; + + public abstract class ValidatorAttribute : Attribute { + public abstract string Validate(object value); + } +} \ No newline at end of file diff --git a/nant/src/BuildException.cs b/nant/src/BuildException.cs new file mode 100755 index 00000000..7940496d --- /dev/null +++ b/nant/src/BuildException.cs @@ -0,0 +1,85 @@ +// NAnt - A .NET build tool +// Copyright (C) 2001 Gerry Shaw +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Gerry Shaw (gerry_shaw@yahoo.com) +// Ian MacLean (ian_maclean@another.com) + +namespace SourceForge.NAnt { + + using System; + + /// + /// Thrown whenever an error occurs during the build. + /// + public class BuildException : ApplicationException { + + private Location _location = Location.UnknownLocation; + + /// + /// Constructs a build exception with no descriptive information. + /// + public BuildException() : base() { + } + + /// + /// Constructs an exception with a descriptive message. + /// + public BuildException(String message) : base(message) { + } + + /// + /// Constructs an exception with a descriptive message and an + /// instance of the Exception that is the cause of the current Exception. + /// + public BuildException(String message, Exception e) : base(message, e) { + } + + /// + /// Constructs an exception with a descriptive message and location + /// in the build file that caused the exception. + /// + /// Location in the build file where the exception occured. + public BuildException(String message, Location location) : base(message) { + _location = location; + } + + /// + /// Constructs an exception with the given descriptive message, the + /// location in the build file and an instance of the Exception that + /// is the cause of the current Exception. + /// + /// The error message that explains the reason for the exception. + /// Location in the build file where the exception occured. + /// An instance of Exception that is the cause of the current Exception. + public BuildException(String message, Location location, Exception e) : base(message, e) { + _location = location; + } + + public override string Message { + get { + string message = base.Message; + + // only include location string if not empty + string locationString = _location.ToString(); + if (locationString != String.Empty) { + message = locationString + " " + message; + } + return message; + } + } + } +} diff --git a/nant/src/DirectoryScanner.cs b/nant/src/DirectoryScanner.cs new file mode 100755 index 00000000..a2baa303 --- /dev/null +++ b/nant/src/DirectoryScanner.cs @@ -0,0 +1,226 @@ +// NAnt - A .NET build tool +// Copyright (C) 2001 Gerry Shaw +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Gerry Shaw (gerry_shaw@yahoo.com) + +/* +Examples: +"**\*.class" matches all .class files/dirs in a directory tree. + +"test\a??.java" matches all files/dirs which start with an 'a', then two +more characters and then ".java", in a directory called test. + +"**" matches everything in a directory tree. + +"**\test\**\XYZ*" matches all files/dirs that start with "XYZ" and where +there is a parent directory called test (e.g. "abc\test\def\ghi\XYZ123"). + +Example of usage: + +DirectoryScanner scanner = DirectoryScanner(); +scanner.Includes.Add("**\\*.class"); +scanner.Exlucdes.Add("modules\\*\\**"); +scanner.BaseDirectory = "test"; +scanner.Scan(); +foreach (string filename in GetIncludedFiles()) { + Console.WriteLine(filename); +} +*/ + +namespace SourceForge.NAnt { + + using System; + using System.Collections.Specialized; + using System.IO; + using System.Text; + using System.Text.RegularExpressions; + + public class DirectoryScanner { + + string _baseDirectory = Environment.CurrentDirectory; + + // holds the nant patterns + StringCollection _includes = new StringCollection(); + StringCollection _excludes = new StringCollection(); + + // holds the nant patterns converted to regular expression patterns + StringCollection _includePatterns = null; + StringCollection _excludePatterns = null; + + // holds the result from a scan + StringCollection _fileNames = null; + StringCollection _directoryNames = null; + + public StringCollection Includes { + get { return _includes; } + } + + public StringCollection Excludes { + get { return _excludes; } + } + + public string BaseDirectory { + get { return _baseDirectory; } + set { _baseDirectory = value; } + } + + public StringCollection FileNames { + get { + if (_fileNames == null) { + Scan(); + } + return _fileNames; + } + } + + public StringCollection DirectoryNames { + get { + if (_directoryNames == null) { + Scan(); + } + return _directoryNames; + } + } + + public void Scan() { + _includePatterns = new StringCollection(); + foreach (string pattern in Includes) { + _includePatterns.Add(ToRegexPattern(pattern)); + } + + _excludePatterns = new StringCollection(); + foreach (string pattern in Excludes) { + _excludePatterns.Add(ToRegexPattern(pattern)); + } + + _fileNames = new StringCollection(); + _directoryNames = new StringCollection(); + + ScanDirectory(Path.GetFullPath(BaseDirectory)); + } + + void ScanDirectory(string path) { + // get info for the current directory + DirectoryInfo currentDirectoryInfo = new DirectoryInfo(path); + + // scan subfolders + foreach (DirectoryInfo directoryInfo in currentDirectoryInfo.GetDirectories()) { + ScanDirectory(directoryInfo.FullName); + } + + // scan files + foreach (FileInfo fileInfo in currentDirectoryInfo.GetFiles()) { + string filename = Path.Combine(path, fileInfo.Name); + if (IsPathIncluded(filename)) { + _fileNames.Add(filename); + } + } + + // Check current path last so that delete task will correctly + // delete empty directories. This may *seem* like a special case + // but it is more like formalizing something in a way that makes + // writing the delete task easier :) + if (IsPathIncluded(path)) { + _directoryNames.Add(path); + } + } + + bool IsPathIncluded(string path) { + bool included = false; + + // check path against includes + foreach (string pattern in _includePatterns) { + Match m = Regex.Match(path, pattern); + if (m.Success) { + included = true; + break; + } + } + + // check path against excludes + if (included) { + foreach (string pattern in _excludePatterns) { + Match m = Regex.Match(path, pattern); + if (m.Success) { + included = false; + break; + } + } + } + + return included; + } + + string ToRegexPattern(string nantPattern) { + + StringBuilder pattern = new StringBuilder(nantPattern); + + // NAnt patterns can use either / \ as a directory seperator. + // We must replace both of these characters with Path.DirectorySeperatorChar + pattern.Replace('/', Path.DirectorySeparatorChar); + pattern.Replace('\\', Path.DirectorySeparatorChar); + + // Patterns MUST be full paths. + if (!Path.IsPathRooted(pattern.ToString())) { + pattern = new StringBuilder(Path.Combine(BaseDirectory, pattern.ToString())); + } + + // The '\' character is a special character in regular expressions + // and must be escaped before doing anything else. + pattern.Replace(@"\", @"\\"); + + // Escape the rest of the regular expression special characters. + // NOTE: Characters other than . $ ^ { [ ( | ) * + ? \ match themselves. + // TODO: Decide if ] and } are missing from this list, the above + // list of characters was taking from the .NET SDK docs. + pattern.Replace(".", @"\."); + pattern.Replace("$", @"\$"); + pattern.Replace("^", @"\^"); + pattern.Replace("{", @"\{"); + pattern.Replace("[", @"\["); + pattern.Replace("(", @"\("); + pattern.Replace(")", @"\)"); + pattern.Replace("+", @"\+"); + + // Special case directory seperator string under Windows. + string seperator = Path.DirectorySeparatorChar.ToString(); + if (seperator == @"\") { + seperator = @"\\"; + } + + // Convert NAnt pattern characters to regular expression patterns. + + // SPECIAL CASE: to match subdirectory OR current directory. If + // we don't do this then we can write something like 'src/**/*.cs' + // to match all the files ending in .cs in the src directory OR + // subdirectories of src. + pattern.Replace(seperator + "**", "(" + seperator + ".|)|"); + + // | is a place holder for * to prevent it from being replaced in next line + pattern.Replace("**", ".|"); + pattern.Replace("*", "[^" + seperator + "]*"); + pattern.Replace("?", "[^" + seperator + "]?"); + pattern.Replace('|', '*'); // replace place holder string + + // Help speed up the search + pattern.Insert(0, '^'); // start of line + pattern.Append('$'); // end of line + + return pattern.ToString(); + } + } +} diff --git a/nant/src/FileSet.cs b/nant/src/FileSet.cs new file mode 100755 index 00000000..4e934fc8 --- /dev/null +++ b/nant/src/FileSet.cs @@ -0,0 +1,132 @@ +// NAnt - A .NET build tool +// Copyright (C) 2001 Gerry Shaw +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Gerry Shaw (gerry_shaw@yahoo.com) + +namespace SourceForge.NAnt { + + using System; + using System.Collections.Specialized; + using System.IO; + + public class FileSet { + + /// + /// Used to determine if a file has a more recent last write time then the specified write time. + /// + /// A collection of filenames to check last write times against. + /// The datetime to compare against. + /// True if at least one file in fileNames has a last write time greater than targetLastWriteTime. + public static bool MoreRecentLastWriteTime(StringCollection fileNames, DateTime targetLastWriteTime) { + foreach (string fileName in fileNames) { + FileInfo fileInfo = new FileInfo(fileName); + if (!fileInfo.Exists) { + return true; + } + if (fileInfo.LastWriteTime > targetLastWriteTime) { + return true; + } + } + return false; + } + + // We can't just use the DirectoryScanner's includes/excludes collections + // because when we do a Scan() we need to first expand any macros. + + StringCollection _includes = new StringCollection(); + StringCollection _excludes = new StringCollection(); + DirectoryScanner _scanner = null; + string _baseDirectory; + bool _includeAllByDefault; + Task _task = null; + + public FileSet(bool includeAllByDefault) { + IncludeAllByDefault = includeAllByDefault; + Excludes.Add("**/CVS/*"); + Excludes.Add("**/.cvsignore"); + } + + /// + /// Will be automagically set in Task.AutoInitializeAttributes() if + /// file set has TaskFileSetAttribute set on it. + /// + // TODO: change this to IMacroExpander + public Task Task { + get { return _task; } + set { _task = value; } + } + + public string BaseDirectory { + get { return _baseDirectory; } + set { _baseDirectory = value; } + } + + /// Determines if scan should produce everything or nothing + /// if there are no Includes set. Default false. + public bool IncludeAllByDefault { + get { return _includeAllByDefault; } + set { _includeAllByDefault = value; } + } + + public StringCollection Includes { + get { return _includes; } + } + + public StringCollection Excludes { + get { return _excludes; } + } + + public void Scan() { + // get project (only for expanding macros) + Project expander = Task.Project; + + _scanner = new DirectoryScanner(); + _scanner.BaseDirectory = expander.GetFullPath(BaseDirectory);; + + foreach (string path in Includes) { + _scanner.Includes.Add(expander.ExpandText(path)); + } + if (Includes.Count <= 0 && IncludeAllByDefault) { + _scanner.Includes.Add("**"); + } + + foreach (string path in Excludes) { + _scanner.Excludes.Add(expander.ExpandText(path)); + } + + _scanner.Scan(); + } + + public StringCollection DirectoryNames { + get { + if (_scanner == null) { + Scan(); + } + return _scanner.DirectoryNames; + } + } + + public StringCollection FileNames { + get { + if (_scanner == null) { + Scan(); + } + return _scanner.FileNames; + } + } + } +} \ No newline at end of file diff --git a/nant/src/Location.cs b/nant/src/Location.cs new file mode 100755 index 00000000..3a51279d --- /dev/null +++ b/nant/src/Location.cs @@ -0,0 +1,89 @@ +// NAnt - A .NET build tool +// Copyright (C) 2001 Gerry Shaw +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Ian MacLean (ian_maclean@another.com) +// Gerry Shaw (gerry_shaw@yahoo.com) + +namespace SourceForge.NAnt { + using System; + using System.IO; + + /// + /// Stores the file name and line number in a file. + /// + public class Location { + string _fileName; + int _lineNumber; + int _columnNumber; + + public static readonly Location UnknownLocation = new Location(); + + /// + /// Creates a location consisting of a file name and line number. + /// + public Location(string fileName, int lineNumber, int columnNumber) { + Uri uri = new Uri(fileName); + string strfileName = uri.LocalPath; // convert from URI syntax to local path + Init(strfileName, lineNumber, columnNumber); + } + + /// + /// Creates a location consisting of a file name but no line number. + /// + public Location(string fileName) { + Init(fileName, 0, 0); + } + + /// + /// Creates an "unknown" location. + /// + private Location() { + Init(null, 0, 0); + } + + /// + /// Private Init function. + /// + private void Init(string fileName, int lineNumber, int columnNumber) { + _fileName = fileName; + _lineNumber = lineNumber; + _columnNumber = columnNumber; + } + + /// + /// Returns the file name, line number and a trailing space. An error + /// message can be appended easily. For unknown locations, returns + /// an empty string. + /// + public override string ToString() { + string message = ""; + + if (_fileName != null) { + message += _fileName; + + if (_lineNumber != 0) { + message += ":"; + message += _lineNumber.ToString(); + } + + message += ":"; + } + + return message; + } + } +} diff --git a/nant/src/NAnt.cs b/nant/src/NAnt.cs new file mode 100755 index 00000000..7a192036 --- /dev/null +++ b/nant/src/NAnt.cs @@ -0,0 +1,107 @@ +// NAnt - A .NET build tool +// Copyright (C) 2001 Gerry Shaw +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Gerry Shaw (gerry_shaw@yahoo.com) + +namespace SourceForge.NAnt { + + using System; + using System.Diagnostics; + using System.IO; + using System.Text.RegularExpressions; + + public class NAnt { + public static int Main(string[] args) { + int returnCode = 0; + + Log.IndentSize = 12; + + Project project = new Project(); + + const string buildfileOption = "-buildfile:"; + const string basedirOption = "-basedir:"; + const string setOption = "-set:"; + const string helpOption = "-h"; // allow -h and -help + const string verboseOption = "-verbose"; + + bool showHelp = false; + + foreach (string arg in args) { + if (arg.StartsWith(buildfileOption)) { + project.BuildFileName = arg.Substring(buildfileOption.Length); + } else if (arg.StartsWith(basedirOption)) { + project.BaseDirectory = arg.Substring(basedirOption.Length); + } else if (arg.StartsWith(basedirOption)) { + project.BaseDirectory = arg.Substring(basedirOption.Length); + } else if (arg.StartsWith(setOption)) { + // TODO: implement user defined properties + // user defined properties from command line or file should be + // marked so that they cannot be overwritten by the build file + // ie, once set they are set for the rest of the build. + Match match = Regex.Match(arg, @"-set:(\w+)=(\w*)"); + if (match.Success) { + string name = match.Groups[1].Value; + string value = match.Groups[2].Value; + project.Properties.AddReadOnly(name, value); + } + } else if (arg.StartsWith(helpOption)) { + showHelp = true; + } else if (arg.StartsWith(verboseOption)) { + project.Verbose = true; + } else if (arg.Length > 0) { + // must be a target (or mistake ;) + project.BuildTargets.Add(arg); + } + } + + // Get version information directly from assembly. This takes more + // work but prevents the version numbers from getting out of sync. + ProcessModule module = Process.GetCurrentProcess().MainModule; + FileVersionInfo info = FileVersionInfo.GetVersionInfo(module.FileName); + string programName = Path.GetFileNameWithoutExtension(info.FileName); // in case the user has renamed the program + + if (showHelp) { + const int optionPadding = 23; + + Console.WriteLine("NAnt Version {0} Copyright (C) 2001 Gerry Shaw", info.FileMajorPart + "." + info.FileMinorPart + "." + info.FileBuildPart); + Console.WriteLine("http://nant.sourceforge.net/"); + Console.WriteLine(); + Console.WriteLine("NAnt comes with ABSOLUTELY NO WARRANTY."); + Console.WriteLine("This is free software, and you are welcome to redistribute it under certain"); + Console.WriteLine("conditions set out by the GNU General Public License. A copy of the license"); + Console.WriteLine("is available in the distribution package and from the NAnt web site."); + Console.WriteLine(); + Console.WriteLine("usage: {0} [options] [target]", programName); + Console.WriteLine(); + Console.WriteLine("options:"); + Console.WriteLine(" {0} use given buildfile", (buildfileOption + "").PadRight(optionPadding)); + Console.WriteLine(" {0} set project base directory", (basedirOption + "").PadRight(optionPadding)); + Console.WriteLine(" {0} use value for given property", (setOption + "=").PadRight(optionPadding)); + Console.WriteLine(" {0} print this message", helpOption.PadRight(optionPadding)); + Console.WriteLine(); + Console.WriteLine("If no buildfile is specified the first file ending in .build will be used."); + } else { + if (!project.Run()) { + Console.WriteLine("Try `{0} -help' for more information.", programName); + returnCode = 1; // set return code to indicate an error occurred + } + } + Log.Close(); + return returnCode; + } + } +} diff --git a/nant/src/NAnt.exe b/nant/src/NAnt.exe new file mode 100755 index 0000000000000000000000000000000000000000..a7a82b71366d39506c5c6a32f4a1b55ac1dc0573 GIT binary patch literal 61440 zcmeFadwg8Qkv81t%*>gaG}36~k!4GGjExyvl8uc4+t^^)7DnJ3whV>C;8LvI#Iu%e#1@ZUx+e&>2-~23>^qrGY6ep&AIiVhj zK0EzO)|zLhckRp8PYt5Ki_9L6f(Dv>vKVk3=OaQEbSo+`??LZr;5`kzr-Ao0@SXG7Rc6sa@OAZSp^^l11@&Cv1}4aY_D?SEh;>R zw6Z_8RWz>ZK~E7&pA`5t8_3QeGdhCupq+X9?YG}Qf;NM8R=2DmkF8qX1+5*(Vhius z!E8)qWaM*1?r(%v7KJ+c1W}z;uFIkvmsX;qC6$FJwWV0ZR#hgoEi$QlX z@@C?AvH=g-V9OKB#)8rqKv2-a+9#%Ef!OW;KoC?+>R!Yay$INuHq&in^WjugI#s>s zvlO-}S$%U=B z(n&hD`vf=!k|7u4;%GU-$?)P=q4i|Aa2ABn$Vf8Mnn*gyh&1Xx32KzPET7J%F*{?a zM9UG$gbUs>q*f}Lj26Z`7E&=4OFHh;tQ>P^f^HV*55srcxA#s;CWc{$R;ngh(;80J zxU+zN8I4>szLD07M&jW39deA1Ypb$>?;fmy>V_?;>ST4Y>e~GAE8lwiZO1(v4ac14 z;I1q&(&dwZhG@!y!fn-PEj!hM@iKpjwfKuVPk5qF>WH9npm`Wk$!=Z)q0eq2=~Q&l zw}4AVlF@_O&EijhBI?2zoYq<1I70VU3f>+g@4z5l$5$#SwxMkSeK59=MW==!$5h%v zDwa;gTRM`lWc+5DfnkT?M172Z>&(KZpmlAcdeSAs;&ChNFb>tllksHi+WdmgC8K~a z;>idUxd1EC1d0p;4MlQZW6sIP4%BC133O$$w!qBg6KoCJ!4Xge;p@;%#}3dU44tJg zdE{efVS2D*44Nr}N=%vNsr@5S*;_y~N{^w}v5cX!FWCm1ZmfPJ#y0CmIP2}~Y^bf| zC$x{nsdLFs1QZqt`RFmQvuM+Cf2oD3@Z0qxtSB6{-?kOkAK@wE*P75g+#jQMtR+}4 z4w(K763IF&>$`T#;`bfk;Z%|hC7i7?24{Hf1+TVhdk@qVq-?PkOH*?lz8$m>Dj6t* zZU02BZgHdKX&iG3H7ur+f|qW#_h2nDHW$|JfOe;+n^S1^XsaTvSwF3o$T$$G@kXgy zRC|Fd_tr>69{T20J&u?w^dT@xmv+hReq@F4xrGi_Q08zAqi%9*qz7ksCxvy+V(l_e0+Or5B1XwLqcDZ#RWp|9*HlTTpV{HvW`Y% zk$2pqN{9yc=u$rI9#hKOY|e2P0byss(P>>{XJGM zSe_N*R*p?6R=s2;>W^TUf_8Bgv)Ym{$x8DY(@xKcJ&3|e^UNRPzytd5pprRY@4-ye zCSIC1WnKsteRaxsn9?{rWJW9i_dX#W;mU+~^mal#0+SNnmUvpvcg!VBarT<};bKC( z#0B;qh!7NWFw+_|<9%9C;v(TCR^@pgSeqlOKo;{MmOTMU$u|U40qsCvScfnUPH{C$ z9rr|hwFMjEEnDm?ti^GkMdG-fWbin$tt?w=XJK9wmu2iMjBVnwVA{lGoKFL=Zj2u0 zC{?nrhVOa*FXx{XWWr=8nnKUlZj?KoCc0l_%1!&S`a#gmyorynA(oJP7wbs z2&!2Sb`}%aX-zwYP@q&PexgeKKqu zT;Y5WhlLI}*iNkNXTBjCU!lq=dg&fZ4DP}knbf_ky4 zm*Jr3pI~e1Q2Z@GrVD>woWWS+Y~cAp6-*B<{`4`n_EvN&z|e!>iw?t17r%)%N9ZKH zJRO6Vr!%k{Gz}eqoyCHn*L=Spg9Iht;Kxrn2p&GeM-M@b-$Uod`Mq)(Jnuov4ta;N z%sZ4pi{p6GpK8B34P|A&1}<7giErG!&;nzT=^g_w7V-9MP&It-j1rHjM>y&MtR>Jr zoB&4KaW`RP-7X|CCw<&UP-bW0sGQd2#)N(b6B6I)o7awSB11s94_0v*eRy-aWwxn5 zDQN09l>I`fzMlR*K{i8>RCp1>J?xfr#DvaSaV>1vJr(6c#8ibN+0y{D&aksEWq1P9 z-eR;Dmc6VP^`cwB%8+;>^?M@ux)i2cig?mTvRlBrI+{HlUu{Q5vuEIYmSHo~wDb{= zjjv}>k3%@pkbNI2?aicug>O)%NcK#?oN|@xJ^FbV3YJtMl*g7Ttiv^K55w3T&O*`4 zbGT1Z>UA};)5^eQS+@Fw`pXS}f1mUXj3*`-#(LZ^!BJ=omMlGR@vtmkRdyE3m($kh zTyhqgzIrKIi@2E2vFuhP)h%^iO_IrwS4X8LcTMEh+82=(u=QBDC=kV3>m#!E0hA^1 z9N=K6Dd+(n%xMcIL#@?jfTM0VOFb3;dYp=}H%eoq;$k<8VE!0d-48fF$K?toBBfxG z<9eLJNth6EG1mUHYSDGzkgO6fpMu7*9S^(PAON;q5v`7-*E!RvWq+qrP^{@xthGjW zikr~?MYkZ&5fEWXFYLi~;dmvc38-Pn$`5=d9UZ>t*YHI*W?U;hm&wvmnJoR1=RTno z51lDzF{3;zosnJafdnJ;8>Q_PVy1wcxl)EeVP43ry7r!#AZx{zrvoSr$vVb3*7HLl zu|dWtWnYF!RX*qeIoOP?4)p1m8YTbd_vx4yK783fXMvY(nKZ=q%Vo0sp)c%yFM#!u?<>inA(H3kM#>Ug9vP z+#E93=G#)pZr52Hr-Y?>kLkB*E854ksQTko25TR*I;`riR5NuR1QUFy|EqvUu#gOh zvu^FOvv6Ea>vZF#<4(o;Qx!=E?udy02*_4$T5Nta(2(5$(OODth*u|&-ATMt%;W2# zy@z4suo5_}Qwm=PNkEj#vvy2K$I;`oSD`cdoLs5iUUk@b`6)A6GcunG#;xUJJ9?t6(Mz@%YoN)N!{4(x?R&QU@hXzMDy9}0- z$&1g>TydXMIt|12&!8rH{n`p$9eJutAKo+z@#EBTcm z=iMGys&DR&uRC{wy7URQ)P+$8v;FAX1pZ+=_Rj$YvDIYsGab7GLI>SJv>tD1 zuzew!j=q98`-)*5Sj3}I75hfO#x zMc5S8VUs3yi@Fui=vE>adpUbSWuCtakDnfdN1$-OC$Q|6CKB0;Hi~b8Ay0d8fc{rx zwearG*i87{iA>*tNyev}tMYP;f&4$JLm%|=FRE2d?;Q7G=t>{XZLpM&w^YE`^-@7A zg;Wp_0|*|l)1`)g03lV;%8i<1L(j+e z^i2G0HX%KOlIuq(TB+kaM_P>e3XcZaPeDK3-Oyh8xWj=o2-zfV1~wI1^lR|JQGrZY zjG2WoW+kV*H;X%A?H#6?9$zIrf#cLC5R2{y3$2va1%~A7o>F{!GHxatxG~e331=?? zhnACdYyks15nx+YSoUh(4o&>>@81oxJ*d5RMs;CI6lxA@jmi@l4v2p~ptE!lOZcn> zULvGD4Ik>@uY8`~4s+rME3^6s{QVdHpd_vt*stk4qZ&Mi)RP%F+E^Ih{MgwpXoYth zg6bB)2;fV$w5ViD_MT&qhkb;d><>VXow0Oz+)`8>#Xc$8VDDKB>N}#M!0hdyFa8io zRm5>$!Z$qkf8a|~wbn)4eI-age2BQO0MiyPoC+nGb89Di2XNSv)^ftmP=${jc+Z3D z4#biV?2RJhi@m@XMKab$|Ac;OI&t;xPelYQkT|}C>Vod?fY9?1PYONS`VpbH{-q-i0j1+0fhx#%aVORdNOV4 z8FqFQnJtnVV=nW{fKotzfIuk@@$4dy9RWM~u>k#xeC+IHpiR$97M{Vt_>GlxK?TpJ zun2)?*mVmf6{KPvkPZHoWj|Z=@N9XB~;jke9UQ`??_HuNZU+DNL=VH)|Svf zK#q4>!cIVfua?Py*4lutP9R{I$w@imk(p?B8rls6vsY3f^>L@MI0}|U3_vWtH#Dn0 zzE_3iQI+XMWGwr=20qk{6uXA)g~D1bn0ynMg?(RD^855E$wE{w)dO&N^ z0vJaC9Q&B^RlsRf$Q+vBkXj!Ng_9wj!4Zpg+wsCq$f#WkVlZ*#@xr}jTv%|eb5NlZ zvcS{wD|-%-HimNJkvvgC^tZUhg4uc^vA5Z)Fyg6L2`6F-E)JaT$Ul+@ss?jTKo-s72)e+xbF}vUcn3=ISZ3STn#2e;~7*Z<1P#^ zw)aq8%8*4oSyTKhcwdyNP1b5etwv0}1|x2z>XLP4TY5*buAy)=_#!hoDy)%fEUeS0 zDTp9o9eB7|$1WR@tCNX(oG77#vAxMuGMUtEBy}4thz=QVD)kL3{v9j1M(iE=m#n0= z{rPs{c-!Pj_s$>sefl1L;OWI~>PM(byRZdfj?fBGz%jrVhX-Gfy6h%o{ToC5Luv2& zcw^6MQ0Q1nV;uMA(3!XPZ3AcDHjHcE)u?S@0d&mTxA!P-bU*45>%BFIJ(>w3R!mJZ zH|x~mlhsk<{lU2X6~*-VyP&!l^=F_T*{h*{~YlI9mq*Jm#_}|33mHa*gA<54l$Dj@1 zrUD0j$tU|MG`klECD)+{k-v@|aEC2i3V#fxj)`J`LeSeK@C#;JTG_@Z3v|1rwMh$) zFflC)#?hX1Fj^LnR^RcQNxmlo)i$O0F?3;+c|l~a=jg~bRA9X~;Js9sIL}Fw*-xT^ zY(C>HQ_RLW3bn@^sXG@D^Lp?wo9DfI&B;Gj5XU?AH+qVzS@ZdrxAMcb5cwR?R$WC~ z?uW~5y!wu995VaBHmHYc)2v*0XxJi`9OeMWvW&kheMG!)D6Fse5j1&`CO=)1r?AIB zn80W3$xGm5f~`kOd3t`<-k`6RIO)P2H0qn7HMv%FhWk z>8e2SCP-af{18&cIiwSchK3^9U5%L1mPb2_eq-@2A&fV6^(n9$ntiNr4-NVQ$SwZ2 ziHg5kDt>69;_sD;ub-&+tx_>>y+_?!D5MUeQ?PD=k$K%t!!=7G4{sHwr_H++@yD&C z3riPM5yVU_jmd~~3g=eQn}t*B(w*wf@^Fr*Vwp$PCBN?RZ;hD6fX($Dl2_qJ?8Cf+EgI>8Q4Y)+o^xX zx9mZ<_ra+q*ILBzG^2nEdynC1k%3MHw43I1J`&(5t;aKQCe9cOya6$_EjLnKV?mywXHINKewbUhp7>1x97j+*%aT_j=NJWQ- zuCc3e4q*)VIH*SqxGfNA3q~5YREZuVG8Updc`BR=X?xP!5j^3Jw7a(KTmJaS{;_P z&M{Z+^$kgHO=uGv!HHYxJYJvEYdpqg96l)Y8-4hS_eoeF_icH0qIsMKR2xpGzY4kR zJ%n`hqGPWz-IfYELS?#uf+J9K*|xrTxEaNE_6xK{XaKi9r$potB9tISPWBrtn~Abn z5&bN2uc->#N7XMLP!-!%DGDFFDup*(D4%U-zXUdV+x0c%%=p29t9g($Q0(QnIPxSi z6-=i>E#eSvj^okBXHk@8CAujd_9uh5hP}^`CzvUR#Pe`NAarw8z}$%FK#giVO8q)2 z@!15WiJDvT9uEgRo`z5GXeeet)95(!LdbRmWJ?=O>8GhqOA~g!7_V475YB!M-#GAm z1Yfv37;A~540U2{FFCD8Yb|-z4l&iL15v3aPdaqPw6Efi9CQcgxRfEJK86)!zUT)Y z2Kt#cPi}v>p9eI{nRcchl5mUz9c#k_E~;BcXmUZ)#By?GQ#cXc!^NcJ|9C8R5J(mQP<{vUCsFQOk_0ACcKp zKY|VtNz2nwj`%+AQx z6Z3l}?fEW7z4~J$IlU~@8M^)V>94a(VqjK01@p19-$7b<66(?O!XREOA;f>h!Tw0f zyN4XKC!$^=Ub}%27L;hUUp(_*v@9smhJ^1~2cu;{iB|hicF&W+@1NOM49nXe4Pk!LGdwsjfgh(FogpCg{5yWffWFLnpwKh>XvEdmc1>sF6Nzs=b^8YKzykg zi65CtYfveD#36R}+n~UuxNlj*n6C~tpc6EpS#i;TE^MAJoArd9;Ck|1 z6d5jGLDno5f0q{KT&4{Q-=jolh^AtJB3RL5qum(1bTE{Co)U1a3VJ`uggHT4JCIK6 z(h17y%Vqk00nG;chOH1DYxp_*3XOE*OL*G~vr5jYB~pfOCSmLG=pZxVAb@1G)wXmaJIo)Ubh$2jqU8$$y~kqSw$uv{0My(+O0jdx><9 zze~ECgl=Yu-}-3b2ms@jnq#mP_y%NXa37;2V9tw=8aLU8gC+kItz)Tm+}|M6vMgHI zSmF&&1FuxrQbI(-4en1!mX4a&Fsj4uJ|MhBw+ah)6uTlu;alA z@)O8#uIY?rz;HW;KwX8u=4<88+8m!7T4Y+`a&e!17mmp72;Om)wcBf8atA{S>G{bL=|)7 zsR-+yAl$$&J+c#Z%+ivVtUSU$SF&%z1V+x2?0+*mz^rx&b}`OJ{r$kmy!PLD=>^jB z)fMXq3rhYzNME#P`@v{gFphS|!Dv}fqSb2-yEUNT7y-b}!pH zq!6ngM@5-DD!GWlE0e4$w^8;^t}ZM<6^)XsdQtt zy_-cBp-4{VL^I*+zd__wP?z0YDNS843qKyq%g)#nsv)))8wpMS9gi0dKURQJKT!&~ zSj}RsNg$aim+YOEGD5sks_1YhsVm}l4e*8v?#Rzk?O5{pfpe30+Cjs+TYLutBa69% zzs<;Znu^-;Vr2G5GDKpbX_OvPSt_;}C@inQj^rSQU7!6qs?IWl zz6}(17D72@(0|JDzFe?m?#JFi>>e@^EJa{I0(um0&H7- zS{?Uu?~dFw>x7&&N!$28Scl%{p0qEb|1u(_u1Ou00|iDm`TN& z;#TBw3Z~y6<5}P@L1*3_`xX4U>pOUBHjs4Y+S1#SPA6;m0r)eYIG-N5}meicm+N zY0Dl6?|A=;^!hq1)>%jPhsTqjOuInPt-(CQRe?5b6#+4dxD(KZRcGy42V23{dVCeJ z7|VXbDc|9|8S*U$zd$Uo_$uTBgQvrQ`5ycIX4zyTnwFI16D&I-+;v{1jW{#7L3;31AF9yK*<5#QjO>3F>CxUS5-GDxfAm-!tXx#iI!^-&-WP5wq z!bEs-@$k018w}?P`2vuk6inhC4q+WpdOyy^dv!;l{S$o4#$0|OO#rK33f#@@|%VV`GFm9?D&au z7}FwH>x|8t)F02(KV?2+_2y2@0Tnq*sRyvo%~;XL5JEl{ru}J??ueqlO8wb7k{cf2 z6w9$LD0EaIM3VgudZ>2d5B-(3_iTK_nuVTq0{DXxjPwrfbT#49^W%~}Y<&{HHva-# zj05Xny2<{e6;sCt7X}mR^w5%!qwaP-;W+9OVNwQTES(u!7>ucfai;5#I_jA!)_tX# z>E7CBY8};?WV%h#5lL^5^fQuvN7A25`j(^(b)-L9(oK?%)SX-BsE^l?=Vv5+Ow#X3 z`e#W)DVEkrdUT2$`Xs#oX-s`TMcH0YQSvGEr0lKVQlC(T`X!-+x~l%%x`g^LQb#SG z#6F%b>4ztg@UUGgp{#&DwDrj}zi5aPS5 zrvQo|7ZB(?1F^hTT`H6T%qBuN3*_M4enOuSC=6>J1N0Q2DEKr=*|UH$s5M8*ejrda z+9l<$0A+C&aEws?LCPB8H_203%W<21rrIn}1W*RI&$bAZ5~u~Ui z`IjYqR(QT5`PU`=Z%N+@-3ywS!*r6Qhe$dn%(_QQdYq&uOM0rLTO~a|%vu*oUbp)} z$=@CR2JkOM$YGzPuS%+EUYER|!>v(L-XrN}B>k$S-<9-5Nj1%W$^SO`Ea?9h{T?hJ z7W*Ocn*W9v`RKa3zgllw1;1U=en~Ho^!<|RR{kh?6(@&?q;--`m2`%rJCP>UMe$ao zAB?Avepu2^#{Z1`(N&x`S5+;97rnVE1wZyFr07=_wV}sL%l4}(j?SBsz9nf*H8B}U zTO{?HYm(P>wSN9JNDhBZ zutn++qhIq+;HI^js(A?cOwH$!{;GyFnvb@zwp!NJwU*Sf^dD*|12to*4@-V_awY;r z((BKYq3_sSsW)T@UpD#sc-CU8UV$z*&@O?VRHU@kQ@*l*db0$j;dNW5D|{}G{2D8J zNUbu^pY05wEd~k)xQYxKs6LPZbeTZ9g|MnRRJfq^dGNvuH56GNSO`zC#z0#F^8lS= zpzgpTtQ@-xG!R${=xPJ)L0MegWuU827FS==khD;xUNB{Bp<2CRAhuAAAgL@%LN#ef zWT{aL4MfTsb)rC*MfL`^zzu(0zF|}0ZN36@_8ckagdERwfi72r;L@mC8P=nWvNWn8IhfIQ-KcI8=<>+n4k^E6palXwXP}kNB9y&h zptVwlNr}(pku3r>8ECunASf3aXjq^%2D((BUITqdpo;~1GD1x>s*f6ont&_gdA=B0Jc2as}T>|O;O;?jw_{)|HK5}3Vv&#E%E=x+YG(fyL(!it!hssq`AyiT>|Oe!tHhX%bEo8%I>Nt`;sZ+ zteUN!G7!gTj@sv=oTJ{XfFj)F8~-v#H3{^Dx-VXXdR+qD5czEUEkJz+dMs{Ra}-}c zQ0j)rzsAE>i@MQ3d*g9H4;bh-C~H+u80c>(YgI2AsH&>gYE!i*3l}w|>RRl$E;dj` zpnV3KCD30D)Fx1N4eMR6j<1>oE<*y{pw?GSwdSftYcXA~}Jj8pEQ^@mj^-ooctYZ}4{@2j) z)*`i2pfUB8st#+hI&-6xi62~|E-pdy)Dm?|2|C$2R(-VuZM2rDS4z+s*72%JLc1p; zKd4%Wlj$`AT^>2My4PBvdJS}h7%@3Kx%ku6@? zQtTpkYA7;0ai!I%Mh&zeaV?;a8i-P#q#iI3r9MeLW}ssei`2>LMFVY0ECuw2SB5^U zQNh!ty$Ch2Mm1?jdbCFU(Uh^bYt+m$G$l2$Ms3g##^@$M7nh)UYQ4HqpfMT04eAjM zsm~>DvNos}1$t6_DX|cDQwCx*x>>z!AZqDU^`?QSrBhX8tL{;2%|dmW${6Ulnt6a08i=dm z7PZDe8)}vUI>$g~*7RDZt6c`_ulX{d>kM>Z&0~P>HPGcXPXc;OL+Zmdi|{)s&vi@d z>V}$UP}a3gL&L#+>J0VEUJWreeVQP-9iX>_Wteo0qpazs}SGNiD zgv!*`;Oz5Dx=hAsr+Tpj?Lt}YPT?t|l2^Q9hWQ@hsN~gB12LXIS9KYP@%*`Jr-4qa zU4*lrQ3FxC=cyYFw57He&_f!M=>9zQTweEqI_py}pR1t{)V^)?sWs;bBy#qvb4t)W z)vtDypf{}n^_+$xx703FgX)(Cx?do$#pm+KHw2n2(3tu~tz!?W6Lp#TR81Vvy#|Wa zrtN}y!9WekX1l0X^_OKCQd=sZz7n(xXImfDP~^zuYTFoOs3Ele zqICh-Tk86{a=H(BTfOGP_)Gb-o|W{v)Q|V){dIM|M>v#ITdl7r&oTz*3zLY^>6>Zh zb=rx|mZjE7s_8Y&g+9zJ$lK~R!5l2FYaJ-tftX)UCbu_{TFRea(@6X&NG-KR(yvJR zm@mI<3QL*dm(G28-CvDoK4409>;C@sNv(T?!$XpPLec}}d{JojBMqoGgoYSP9f*%l zCH@zZ9>_;ymf+d6r{{l`e0g+i^{8MTlT=H~5x0#Mjn7+nhOL&hDWh2e?if11;Azi9&m;8N_J}l{@l0Gi!(~>?f>5nAcFX?MY zkFujkYt-+M9&20HQ+21=Nm+rS){pAW1m?f$&a;^x1U{DfoZV>6Og)NP?Wu19-<5g+ z>HAVI0e@-g4Z*yMTXENUpG+-O^R0VP%d)a>#ei_|IBEc}~7jn>@y&!Mej>rVpqwYdrF0KD&fa%k~ki+Q~*U>yEYmnYq|5D(5>*4x&>U`_#l0Jit&H2_ZB>jtE zY9}oOhC9Xct;3MdTSrb>g!F_-`vYTEFECMS0MB9a*6vBa2;{8~BEMTPhPu+adD3ji z!?v!sK0E1Er1#g{W8EZj-fn#ld~Ub?W74kR_11q*x-58~k-rL0V>;F5s(F%L5$r@1 zTcaMfrlzkAj#)ZCGdI12ED*KUq&q^_TU*liSWjEU^h@e# z>x%Trp@*#-(;Gt^wbN00U%D8&-IB90jMoLBG4(I$k34Lr5Lm^zJuIbEII@N1`A+Uiz44fC+l?`&uaoGzGC6npoy)z`2%{IH}^>wNOJ zZ)k{HQTv57E$urEc`Ipu-@Y|69qHYXsP)%|j?jGMKac$M$xk9}nfzU($4q`M(hhu$ z>O}ejKW#n(2{L{#o`s(D3(J`@hrUO=^NRpJj%WKvXlXKBdmBEPQ!2!}* zuTH)QnDrR1^Mx}td_#0M^0!7Q57+OVjdw+_x5f6GUzYS4q_n817Sn6NfA7?nY+BuS zV`J*iQ-2qG&5kzxCAM2lX?hzeHF>34-83bBr8=`|8q!?TVev+5ps5wEk&Idh+vae3JOZPQph8c5XsLp&MKo}|7xZ_QWD z&G&%==f$7w2Bht(wYdgIUDR#V>S(4UvD9xULvx^NvErPXi&*{Ys=2C1-HG&Mbqvz? zsdJFVC7+VCMbabHGT@Ju(v|AmsvcET?e?XT-YMy~B>frE%k3G~XVq?ao^9&Vz@^B4 zI(WM^Mco^?9hgr9?gZwJ(6^9268ag^8ppD?slNmQ_Gi@sXFBqi24*0CmD6ssRy#1M z;7VX_ce;^3B-n%epPez}=L9cBJ`ld$zF92}-iiFY@Z-pL2ET>;rtp5`w*-HN{0G8T z;AWKz1_GZ|UkgtUY*P;hXCNPnv?KqO;7a7v(Qf3w9qd8=gy zKM~k3r9TU%!k>y;A#$)n+tkyc>5`w0{BMHoA-2+ue4{glbg6SY(#_7}NVhxtkv<*T zuj@M7RMD|;2LzHJ|50bA^SK~2iTpo1y^?<%`9yd>(zC)=m>i}f?F+Xfy)N91^q%k- z(x<|=BmI8(aisgg`;q=SY(?0X6_K7IUmIyhIy=&hbVXzg=~;rYEVv|ePUs&)zYK+)4?0gc&pZF+ z%m^PJ-W7g3{6OSuk>5m?MNf;K8+D_XMz4&1Gy0?GE77;2Rk6BQLu^`XSu7VDi0zJD z61y_?Q0)7$pTvG1dp#D69~nO}o{ta4uZ@2u{@wUb;{Ox>Ydl(2SJhB8tE#msh$tt7 zSj@qH`~jK>{)^(tNDR;O@s9)I$@nzn=HMyE5qK(b6wc$1##!RAI2$`&9jcb&tgA!K zQfqLo)rF_rn?ZR7&T`H|v_3s>7}7bC-h}z6)F%TSNIxy9#^`jJ{bAsB{{A2-hwU4Y zo@{>->9+*){t)pWlJqu7|2ahdUkH)sHzobCLz?}P{>CBxP09a7(opzOU}`0uBI%)$ z`Z@PR$YDUzVM)g#iVezZD@*-TJ>po?6#*kMRtlJsYizAmZexwYzW3$0Y~2fl_S9j%&&{7KdkvB(x2A+25GkT&q#GG zJ$Ct8^4FBZwXF5uwe7(CP0~b?`Q^!ZwjOI6_Q$&&5v2IHDPfoV*Qr9tSEIy&9fpyI zKS#b6DgVW$IP!H!`I{5f$WKDb-vX{delk+t6H6jL1*wfw{uI(CQ1KU48-PDV(hR6< zSUOYuS`*SXl-pP#rXigNYqw$lGmy^5d9ICjg%3x14AyH~Ey6ER*od3kkS+l&e~D;5 z(xrGq*T$P0Myjj_fv=irRHcq)Zke-YZ8?&kt=~_Ux zT8D4!K=GfgHXz2po(`**jdPpLNKePvj*XdjI@0&yKU>9{e%!*~fjDenz0cCMZtrkk?l`rsePC#AZdXqA7kk`7 zUw)g~w7WQz>sReVxF)!5cqpe%?e5F>b`QCQGHR1MT$jbo>lqSiwX(afkJVJiuAy9E zpu2BF!QD~l?qAVe%&C=b{~*{E3^2G`C|4GHmC>q4B8*e6^3+EoBDFOK|yaC+TEuq39ia*7i`z2 zq3(W7aOyVQupWWAE8V_6bTaP_AVe$_x_7V17t!V1uA$QkdGxeguGY9aI84L2uHAz< zA=%&-^Q@}2Z0H`^$x0q(ZTFyR9~|t<_jHq>V^>dZP$*Xn=lgogAo_>a-NNooJ>3HX zxq>pog2r@Bu^olZ%22Gzi>Td&-J)tw2W2z{3+BQx0D$9JJR4&o_3NXSO3c2n1T^qW4dvSeNZSC`h zVe61q?AAdu6l|h2NNk`4=n}(8#5RLMDw8FRH>gB=d1IAZ`ulJ!+qcf`&8ha`A-8h? zb_Ne|QF(U4Tv4EfFHPB^DpO*n=6dK_$|#u&1}*uyJu;xBe*2^qC246TyY+%xVVjG| zZbawgr?Hks0$m`ky|81rKQ}N`6hfM5$;LJJe1C5JupUlM{`CVLg#wI^!95^@U zZW_$>Xbto#eYe_Yt6MQPMYWm+-`@{=S(6{gan4l8cz}GBvUM4`{4#m+z#xl*@DRCD zhqt=JLxbqW*52HEX~zO3^Gob351jJe?AUw_eL)Smc{dlwy~rHPb5zqqYG+RZ5?vG@3P@+-Jb7* zGnOg2y{~&{C#^?1s)BLUAp%I05wy!K3t1NM1S8x5f|Z4uP$0iBenGbO zx;F+qSt?7Va4eMybTHnP ze7E-JipB07Vj$ut)YcyDJo;oJZ>w-z(mxmLGdclYb}XxX64WGg}8uI6zav zdQm(N12oj#b6&|*iyG`K8X0@(p;xK)F+AA&a0|VH>FdjT5H)+EP%?*=SBRP4Wau^CS7mi>NXJ#^u3F_vUTGd)eXs7?ysw^7 zo$AdMhcGk>i+66I$S`SFv2RF*u2|@iZ<0s`ZHc3SJ~rmMdl96pEabX}a%C7f9g&qw z47|0wSj_cr>yv3CCa|>|OXCTB!^NFceJ@s{HMt9NeIBq0>nN6X1bR6PX%U8mc$PS- zfUBym%5}L6v8>a_i=}?JTrTX(#R9UFk)>{MWgiz(-HPU+HVer%ZnPiPx;i)Hk6sB&NP9xT z?Ux{=9I>(|Yt7v8zCBkAqs#4*Fdn(QcF!1AZWzi%WyE&lBv97t#laju?FY;x&;Z)! z?w}~aU**D0foMbJnic*4a}c4mBqhA+EYjM%X$If9F}EX!s82-2L^O?+S}pT0@zBk! zf{ikAP;1>nZey;8riO(^#!B#8izcx5^wHkew_-Pz$?oAkco2FCF*^yzXf%>xpNte0 z^xCRKx(fV6w6e14=|Fp0H{8Ds(+XaW!)~C>1LqC67Y>v{SB8qvh7PdQ+V1>-l1&5q z?`a3KrMHCC{1N@IJN{@>*bnp-%}@mDfsR}aK^5g8RErCt+6 zP<7f|5bOCldqf+D2UL4+ucp%uM%2AJH*~^qUmtCv++XQhMH{-FkGIDc@m+WC`hmXP zzB05!Pev@;ltJ#~o?ph0ne_uJv7Ij{!EW8zT{Mw7wmrSM!5n=}kEa_1ETvL*b(NpM zUszGVp~8sw!9nVQ8iIx-M;+w1{x0@VFyPZ-2miF%5oANsb4lIJfaOpX) zU?mK8xG({;t^(Gd{_aBg;H1%w;K^*f6vnN;dq^ST&?{5v5TFYiRUAaYfifN7W?jxoFy!)$`N!Ca z`4h2CLkwq1xXu{NS}f(cLg&DCmxU{bi$iXISxCr)a}kC8`I_AJAtmN0-V#a)76BYW^$cx7304Z$ps8u`nG-6JaplhLfgSpYXH#xSQ$P@%K@h^q zTv-iAg4lI;3?PQXP$E18u@55imBR&W1c$IjT##GGqm0f~dF&^PvH{UqEe{tqPhsPF zUR0%{2s7GpD55>JnKEX4e68aM3VwuJVa5^OH=@wOkSL4Nl_7ej(tIUQ-pdo(nA58? zDh%{?7kbSukVTt|xlKEBeSO}M197Lhh4Y~9(t;@(pAcDYMr2_(a^3y(o>;Jqi2fGY zb5qK%F1G`HB;A_azz(?Z)4KCRu+ffPSj>oKW+lhmv*Q!G`yjBqp{*{IV?J0EDq^l~ zWAslYh<=#S>Mp4Z%!=l4qjIHR%^0eGu%tlU3lpPKjFm3TUwA8Q;Ra;<^rl30`VKQl z3Qt!yDsEHV!L1$V4h+D!v1DOEgb3Br+&2vU{Ab1@#n z1HN-l(b56fuEMZ4Ea+rOld{d?j+3h49NE0FQ*B^$zsBu`b>m-oIrMEG?*q3Za2TEixsksOOhx@u=H#{@os!>FL5f>`hSMjtw41^--ag{92 z6LQ?b`3%yOLT#M`IGWTWW=M=JbPV+190JEE><*P&RJ0^U?z`4+SDS{n6}4%aiH_QH zw-j+8SnR{vG*H|Q_v^_mWn#M$ua`EAodT}wz927a0P7BU(@eZqnG=ij(N3;x5)^Hn zd!dMkc@B?$0e29kqlYqOCyvFiNKhy^X2f}zN^%T{v-GmxHeE3bz+5a4IfQ7Na4?hS z0U5N0#dA&fZfvW|l{9=ZgBaNn>CjaT7fOet;w-hScyz#Hc{)Fl8i5c7Y!i;)hcJr$ zu#b&&>{7=4kBNX;nP6#eM315dIIuWB7N0OMggCf}DXEY7wNmNn^~CbQeK;ZzQ|xk~ z1kdI3WTsFYTDcQJ4t5@!uq>8Zljj<)EDCzW(6IEwJD$)2Gdh*2zP5X)XQx_SaEHxl z)o_n^_5nN=ff;b8Wi~e(U3Um4T^$1#d>9wddHDwl%brFjxpBYp-wY=U6 zRctmmZ$ud1wxV)ZQOIjGZ-5vNVpp9+#9>O#F9R3?H z?aw#uQ`%mGTOc^Jxc2{Tixu(*@S;oTEVQ8l%klG?y6+j>F(?ApjX!GXeDpRiIZD$F zd4~YyA^WiOWiEbYXE~s5)XG6((yAnT+9R6k1-7VEd^s@PxU+!aNW!mHmhR|4Ed(0) z%iw(n=6a-F5&STDfc0zhKq)9SHMkTbNDUr`JXRvKd>-z2WPqg(t#CJZZ%XDpyb<4zo-ey#PTBS zM;)~iCH?3xF%C=b3IC2ffu>pryECVgg$o(#Ho)?o+ZTQQC;D@8N3WzL%n z{`5TS0fsYye2u=^D(8KV>8V#f&O+MRK6Og2p2ySUM~r7#<7<0dVVRTWfr=dZ&~Hk( z6Pl()^@4Lxc^utJxe)uKFFokTc9H(@Qd{(>WsjzNN*r}c>35r{OF|{i~>9co`d8danYcgb0NAG zlo&Rsml-|a<2%D^Tr^xRDh1T$Kx;*ik_!?!4nk;79Q**}F_mhr6r-MyFFYelFV7DVJKj(}+H^oQC}_ zOknM1@IMcKtWR?-yMB)TyWvz`ysUS0D0GLqPui&&hjNU@|9x4Uct2uoT(?h9C)p~(_+aG0WYqA zx2{PCK*x_D=oGfP!;GHR7EZ>1%VExN>T`VZpzcMT18t!Q$3}Nf7po;#$Cm4Ry7Crn zum5x{v?0!1S~X=Me-)UAzcYC|FaXDSJZ+^LODyH_`dN0p{v|Dg9`=K-?2zA0{ULY@ z@-B+Yq=T%ee^?iKMMqnNuGvHF5*dcDXL@wi;cHOF1=#B?$M8VDszC=m<3lkO^?IhF zJ5iIpQ1jctkKTh;bdqb@=%`hHER^-nA4LAkaa9YD}V*lVvfdPEgK2s7z4@XCWD$CpbOHLoUh z2yKUqdudH*nP_a-2lkn-=5p?E77QrWyam1JLx4xi?E_!hNV&8}T4lJf1pm>`Q8G$} z4MG5~21GXk#}!S5&csD!rm)q(Ovxd|k17#|G_XfSlsky4CsT#vqf-XSMapoZMbA(i2 z39O;b7m|Cc*%JKRJn^(mZ_5H)yiH&R%+~aBK8qe-h%4i>v0~}`9OSJ~8?#TJMoM}TDNJ)F3R2+r!tY8qsu#sMB2e^tXww z5&n1J`*dK}0h7UH^>%CsxFuMJveP;GqaW`=H66(4loMRW0ziMYp_EQ1-Go2lm}FBJCE=Lwyc#S+8aH>NQ>-aO!v)XlaUcE*QRJ>C`k2 zy+5X#&0xZ_BW1Pmbl`n}%Rw64L9&tt)9gqp!gKoMOv!ejH9ArDtGv{ElTgi=cxo<% z<>+waIAyi_`FaCb86c9kp2!pJpj7jL6Md;zRsm-OR)?RzCwKXbgo_pz(aOH)_H~%S zWmC;7JBy{z9+!Y}>2YuyOJ%(Exe;2O?{Ag#9DAB3M^0Oao}S(asnL&hLKGd(PNYn4 zPvYNz<)L~V(do?<)k<%~hCCHBmgTgh0A7rcfq9gNOM3{eUTl}cs@2p>BRZMU24~SZ zrNO6H@-gPfjpunEK$*m*voY%kyZ6Hyi!@PJs6zZ*o)3o#LH4;HNqD z*MJ}M8{xq>Vx_E{HuLaW6Xj-WYWjg?-lU>!;6QHz3dRVG@;PRR3}%$IP|1yJkZEUX zna1NkSF8^$`07`3_SH|7>(g#8pbgIEQsCd6`JGkeIGu@~|2-3Sl7&k<8@UneH@TKG zr)uU@*u7d=$)_9zawXQg4%(#GH#*|+N25F#WnbtFILk14XN{NEUrs9R2FmW%--Gh% zGQQkcepI_)IOLA;?XWkD#Pty=ojs38_1vlKY553MDRth__b#m-T)pa+PtQ8%ikIhi zs>l~FI`h=Vh5N1yW~@XLf>z6RBB6|JMIrzqz*-RmeG%J9*p5vw0X+W%!0*)q$O3Tc zMz3RX8+zepb)mY^j{$PPw5|zb7QkqWvLjOEHc4-cW-KV=rsU|Y5WTKBfiY-m zLN#`$sR`O^YLXt`jsb-Y-VGaXnjNkM1*`G@dT4Yq3=v=W4`a@P2uSNj?~5zD*%Ktt zTo*YcT;;Es0IDv66cv!gk7=kNo}^-<-GG0vKtCL#5+mL_OjZ^C)dk$ulJ|4)mLv3& z2#0jbx zb>SF%6Zqo~4ZKGCP*AxoX;U~HKuL2GwVT8HocKrkIDq;}c%^v=3Eo1}BzU^Z7qTiz zD2xBa3(+v&Admr~Y4FA%Y!Cms2b@9zs?<%h1A553s}fSx3>i*NARaFcRW=9VVMlj! zJ&H6<4ae$6Z?9{Hch2BHX5rAZ=0RYwtBJb#b<3#EbE#L_PXBo#T0K>qFI2LRheOmD zRHudHwG$j*PJwk3IZ?K4=pj{!3d!w+JeY;LN?>-Ny1 zy!WbmIDlu|l_I1eBJS!8k3&=PBHxnLozO3hh{kY@Q{Dv;zaBH#^3wM@_+e!$m9oHb`Y1id`h%3bd87l${@_#8LAwhzg{V zr8GHK4c}(fjZKPh0a@K-C>ae=!upJUdJqVf z8KRB^W+VHZ9D{pM$*~Rq&57m!df9~jAwI+U%FrYoMt>sIOEs1kWFyUire-X#b|QH( zsO=`W+2qB^i|MPz)`E?VFX4GgbvTSXYp;b?xF%!Sgq+hkNuZ>MCxL*@0{=hDwd*yk zU8B#!Z`F-$P9$o=XoNZZVFo^oaY2^?0sWmw=H2i`@P6u4CsXri3Bw=#9ErwA)W4A|zOGSeEx^6LD$eH42I@ zVL^FF(px0GE2`||*f6~=miOu)bh2zxI0`ompD?x?MRlW>)h&bT4WjW5sJN~JQ4(G0 zHKMxFYq*SdK!|Ioi)%#4v5`!;x^8TQJvoT)LI0>w*l=BjzDaaA2BmXUJ}4c|M{40t zM6+bXpn|?cUL{aMH!>B?F!C@B)n#ZBCICr=!>Dx|o!-OVT9csW;r)yQWHaahb=^@% zyTDfmjHxMMi(mjVh}W>1vEIG%KgAH$Js_h8?)M^4WjLY^wN!KI`g|t4a&~6H5l76= zti~&KyEB`1cH?}L9gyESP}42dv~y@^aLK%R^p10NK!7WT_$7pa+z?JQ;VzQxnYrsa zx-xPlE7OJFM!-)v=m-;Q-HU8ge-2?jV}NmAwIw=S&&72tTmr*8FY+@Dx!l}d#$5Qk zeVEEDm)v{Fdm4C81Mg|zJq^64f%i1<{}m1J7s}+{o*%935&tDSg-5dL06ghV#NU>E z_!k)hg!JdKz(QpBhH(IA^mzB%5TN@I{e#|>xJ-Z!T)@VCt==iPI=#W&@CTC zl+v~VsQI-DMtGG%A6Vm98;=_@I6hy8-gY5ZegKmJ%&P;8 zq0YoFw0U*;6!ZVIcLpg4!$1_Jp2P!)6cMS=g@SAK2p&LP)Q!jVNWMQqTOtbLQhrKE z+jQEQmu$)(k}HDCo;D;1`hS+Tv0d_mT@7*U@a%>ttN2DWlgId8it{>eSSxX~DaCsA z*F?0Us$H-i+?u1|zV^MUg1WTSjyNRVjFI%;nA3Zws+?H2u0oQ@#HDi(EK>lqS8s~Q zKcoequuqEj=M0dzAepU;6dd_6rMBV!A?Qe>P5=AZq^lf}cX7;u^ATGmiDZ(=7u? cn1BhGfC-p@37CKhn1BhGfC-p@3H&92CuM~&{{R30 literal 0 HcmV?d00001 diff --git a/nant/src/Project.cs b/nant/src/Project.cs new file mode 100755 index 00000000..9746dadc --- /dev/null +++ b/nant/src/Project.cs @@ -0,0 +1,332 @@ +// NAnt - A .NET build tool +// Copyright (C) 2001 Gerry Shaw +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Gerry Shaw (gerry_shaw@yahoo.com) +// Ian MacLean (ian_maclean@another.com) + +namespace SourceForge.NAnt { + + using System; + using System.IO; + using System.Reflection; + using System.Text.RegularExpressions; + using System.Xml; + using System.Xml.XPath; + using System.Collections; + using System.Collections.Specialized; + + /// + /// Central representation of an NAnt project. + /// + public class Project { + + public static readonly string BuildFilePattern = "*.build"; + + /// + /// Finds the file name for the build file in the specified directory. + /// + /// The directory to look for a build file. When in doubt use Environment.CurrentDirectory for directory. + /// The path to the build file or null if no build file could be found. + public static string FindBuildFileName(string directory) { + string buildFileName = null; + + // find first file ending in .build + DirectoryInfo directoryInfo = new DirectoryInfo(directory); + FileInfo[] files = directoryInfo.GetFiles(BuildFilePattern); + if (files.Length > 0) { + buildFileName = Path.Combine(directory, files[0].Name); + } + return buildFileName; + } + + string _name; + string _defaultTargetName; + string _baseDirectory; + string _buildFileName; + bool _verbose = false; + + StringCollection _buildTargets = new StringCollection(); + TaskCollection _tasks = new TaskCollection(); + TargetCollection _targets = new TargetCollection(); + XPathTextPositionMap _positionMap; // created when Xml document is loaded + TaskFactory _taskFactory; // created in constructor + PropertyDictionary _properties = new PropertyDictionary(); + + public Project() { + _taskFactory = new TaskFactory(this); + } + + /// + /// The name of the project. + /// + public string Name { + get { return _name; } + set { _name = value; } + } + + public string BaseDirectory { + get { return _baseDirectory; } + set { _baseDirectory = value; } + } + + public string BuildFileName { + get { return _buildFileName; } + set { _buildFileName = value; } + } + + /// + /// When true tasks should output more output. + /// + public bool Verbose { + get { return _verbose; } + set { _verbose = value; } + } + + /// + /// The list of targets to built. + /// + /// + /// Targets are built in the order they appear in the collection. If + /// the collection is empty the default target will be built. + /// + public StringCollection BuildTargets { + get { return _buildTargets; } + } + + /// + /// The list of tasks to perform before any targets executed. + /// + /// + /// Tasks are executed in the order they appear in the collection. + /// + public TaskCollection Tasks { + get { return _tasks; } + } + + public PropertyDictionary Properties { + get { return _properties; } + } + + public TargetCollection Targets { + get { return _targets; } + } + + public bool Run() { + bool buildResult = false; + try { + DateTime startTime = DateTime.Now; + + if (BaseDirectory == null) { + BaseDirectory = Environment.CurrentDirectory; + } + BaseDirectory = Path.GetFullPath(BaseDirectory); + + if (BuildFileName == null || BuildFileName == String.Empty) { + BuildFileName = FindBuildFileName(BaseDirectory); + if (BuildFileName == null) { + throw new BuildException(String.Format("Could not find a '{0}' file in '{1}'", BuildFilePattern, BaseDirectory)); + } + } + + Log.WriteLine("Buildfile: {0}", BuildFileName); + if (Verbose) { + Log.WriteLine("Base Directory: {0}", BaseDirectory); + } + + XmlDocument doc = new XmlDocument(); + try { + doc.Load(BuildFileName); + // TODO: validate against xsd schema + } catch (XmlException e) { + throw new BuildException(String.Format("Could not load '{0}'", BuildFileName), e); + } + + Initialize(doc); + Properties.Add("nant.buildfile", BuildFileName); + + Execute(); + + Log.WriteLine(); + Log.WriteLine("BUILD SUCCEEDED"); + + TimeSpan buildTime = DateTime.Now - startTime; + Log.WriteLine(); + Log.WriteLine("Total time: {0} seconds", (int) buildTime.TotalSeconds); + + buildResult = true; + } catch (BuildException e) { + Log.WriteLine(); + Log.WriteLine("BUILD FAILED"); + Log.WriteLine(e.Message); + if (e.InnerException != null) { + Log.WriteLine(e.InnerException.Message); + } + } catch (Exception e) { + // all other exceptions should have been caught + Log.WriteLine(); + Log.WriteLine("INTERNAL ERROR"); + Log.WriteLine(e.ToString()); + } + return buildResult; + } + + public int AddTasks(string assemblyPath) { + + Assembly assembly; + if (assemblyPath == null) { + assembly = Assembly.GetExecutingAssembly(); + } else { + assembly = Assembly.LoadFrom(assemblyPath); + } + + int taskCount = 0; + foreach(Type type in assembly.GetTypes()) { + if (type.IsSubclassOf(typeof(Task)) && !type.IsAbstract) { + if (_taskFactory.Builders.Add(new TaskBuilder(type.FullName, assemblyPath))) { + taskCount++; + } + } + } + return taskCount; + } + + public void Initialize(XmlDocument doc) { + + Name = doc.SelectSingleNode("project/@name").Value; + + // make it possible for user to override this value + if (BaseDirectory == null) { + BaseDirectory = doc.SelectSingleNode("project/@basedir").Value; + } + + // used only if BuildTargets collection is empty + _defaultTargetName = doc.SelectSingleNode("project/@default").Value; + + // initialize builtin tasks + AddTasks(null); + + // init static built in properties + Properties.Add("nant.project.name", Name); + Properties.Add("nant.base.dir", BaseDirectory); + Properties.Add("nant.default.name", _defaultTargetName); + + // add all environment variables + IDictionary variables = Environment.GetEnvironmentVariables(); + foreach (string name in variables.Keys) { + string value = (string) variables[name]; + Properties.Add("nant.env." + name, value); + } + + // Load line Xpath to linenumber array + _positionMap = new XPathTextPositionMap(doc.BaseURI); + + // process all the non-target nodes (these are global tasks for the project) + XmlNodeList taskList = doc.SelectNodes("project/*[name() != 'target']"); + foreach (XmlNode taskNode in taskList) { + + // TODO: do somethiing like Project.CreateTask(taskNode) and have the project set the location + TextPosition textPosition = _positionMap.GetTextPosition(taskNode); + + Task task = CreateTask(taskNode); + if (task != null) { + Tasks.Add(task); + } + } + + // execute global tasks now - before anything else + // this lets us include tasks that do things like add more tasks + foreach (Task task in Tasks) { + task.Execute(); + } + + // process all the targets + XmlNodeList targetList = doc.SelectNodes("project/target"); + foreach (XmlNode targetNode in targetList) { + Target target = new Target(this); + target.Initialize(targetNode); + Targets.Add(target); + } + } + + public void Execute() { + if (BuildTargets.Count == 0) { + BuildTargets.Add(_defaultTargetName); + } + + foreach(string targetName in BuildTargets) { + Execute(targetName); + } + } + + public void Execute(string targetName) { + Target target = Targets.Find(targetName); + if (target == null) { + throw new BuildException(String.Format("unknown target '{0}'", targetName)); + } + target.Execute(); + } + + public Task CreateTask(XmlNode taskNode) { + return CreateTask(taskNode, null); + } + + public Task CreateTask(XmlNode taskNode, Target target) { + Task task = _taskFactory.CreateTask(taskNode, target); + if (task != null) { + // save task location in case of error + TextPosition pos = _positionMap.GetTextPosition(taskNode); + + // initialize the task + task.Initialize(taskNode, new Location(taskNode.BaseURI, pos.Line, pos.Column)); + } + return task; + } + + public string ExpandText(string input) { + string output = input; + if (input != null) { + const string pattern = @"\$\{([^\}]*)\}"; + foreach (Match m in Regex.Matches(input, pattern)) { + if (m.Length > 0) { + + string token = m.ToString(); + string propertyName = m.Groups[1].Captures[0].Value; + string propertyValue = Properties[propertyName]; + + if (propertyValue != null) { + output = output.Replace(token, propertyValue); + } + } + } + } + return output; + } + + public string GetFullPath(string path) { + string baseDir = ExpandText(BaseDirectory); + + if (path != null) { + if (!Path.IsPathRooted(path)) { + path = Path.Combine(baseDir, path); + } + } else { + path = baseDir; + } + return Path.GetFullPath(path); + } + } +} diff --git a/nant/src/PropertyDictionary.cs b/nant/src/PropertyDictionary.cs new file mode 100755 index 00000000..072ba46c --- /dev/null +++ b/nant/src/PropertyDictionary.cs @@ -0,0 +1,72 @@ +// NAnt - A .NET build tool +// Copyright (C) 2001 Gerry Shaw +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Gerry Shaw (gerry_shaw@yahoo.com) + +namespace SourceForge.NAnt { + + using System.Collections; + using System.Collections.Specialized; + + public class PropertyDictionary : DictionaryBase { + + /// + /// Maintains a list of the property names that are readonly. + /// + StringCollection _readOnlyProperties = new StringCollection(); + + /// + /// Adds a property that cannot be changed. + /// + /// + /// Properties added with this method can never be changed. Note that + /// they are removed if the Clear method is called. + /// + /// Name of property + /// Value of property + public void AddReadOnly(string name, string value) { + if (!_readOnlyProperties.Contains(name)) { + _readOnlyProperties.Add(name); + Dictionary.Add(name, value); + } + } + + /// + /// Adds a property to the collection. + /// + /// Name of property + /// Value of property + public void Add(string name, string value) { + if (!_readOnlyProperties.Contains(name)) { + Dictionary.Add(name, value); + } + } + + public string this[string name] { + get { return (string) Dictionary[(object) name]; } + set { + if (!_readOnlyProperties.Contains(name)) { + Dictionary[name] = value; + } + } + } + + protected override void OnClear() { + _readOnlyProperties.Clear(); + } + } +} \ No newline at end of file diff --git a/nant/src/Target.cs b/nant/src/Target.cs new file mode 100755 index 00000000..3e0de022 --- /dev/null +++ b/nant/src/Target.cs @@ -0,0 +1,115 @@ +// NAnt - A .NET build tool +// Copyright (C) 2001 Gerry Shaw +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Gerry Shaw (gerry_shaw@yahoo.com) +// Ian MacLean (ian_maclean@another.com) + +namespace SourceForge.NAnt { + + using System; + using System.Collections.Specialized; + using System.Xml; + + public class Target { + + string _name; + Project _project; + bool _hasExecuted = false; + TaskCollection _tasks = new TaskCollection(); + StringCollection _dependencies = new StringCollection(); + + public Target(Project project) { + Project = project; + } + + public string Name { + get { return _name; } + set { _name = value; } + } + + public Project Project { + get { return _project; } + set { _project = value; } + } + + public bool HasExecuted { + get { return _hasExecuted; } + } + + public TaskCollection Tasks { + get { return _tasks; } + } + + public StringCollection Dependencies { + get { return _dependencies; } + } + + public void Initialize(XmlNode targetNode) { + // get target name + XmlNode nameNode = targetNode.SelectSingleNode("@name"); + if (nameNode == null) { + // TODO: add Location to exception + throw new BuildException("target must have a name attribute"); + } + Name = nameNode.Value; + + // add dependicies + XmlNode dependsNode = targetNode.SelectSingleNode("@depends"); + if (dependsNode != null) { + string depends = dependsNode.Value; + foreach (string str in depends.Split(new char[]{','})) { + string dependency = str.Trim(); + if (dependency.Length > 0) { + Dependencies.Add(dependency); + } + } + } + + // select all the non-target nodes (these are global tasks for the project) + XmlNodeList taskList = targetNode.SelectNodes("*"); + foreach (XmlNode taskNode in taskList) { + Task task = Project.CreateTask(taskNode, this); + if (task != null) { + Tasks.Add(task); + } + } + } + + public void Execute() { + if (!HasExecuted) { + try { + foreach (string targetName in Dependencies) { + Target target = Project.Targets.Find(targetName); + if (target == null) { + // TODO: add Location to exception + throw new BuildException(String.Format("unknown dependent target '{0}' of target '{1}'", targetName, Name)); + } + target.Execute(); + } + + Log.WriteLine(); + Log.WriteLine("{0}:", Name); + foreach (Task task in Tasks) { + task.Execute(); + } + } finally { + _hasExecuted = true; + } + } + } + } +} diff --git a/nant/src/TargetCollection.cs b/nant/src/TargetCollection.cs new file mode 100755 index 00000000..c4f486b1 --- /dev/null +++ b/nant/src/TargetCollection.cs @@ -0,0 +1,35 @@ +// NAnt - A .NET build tool +// Copyright (C) 2001 Gerry Shaw +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Gerry Shaw (gerry_shaw@yahoo.com) + +namespace SourceForge.NAnt { + + using System; + using System.Collections; + + public class TargetCollection : ArrayList { + + public Target Find(string targetName) { + foreach(Target target in this) { + if (target.Name == targetName) + return target; + } + return null; + } + } +} \ No newline at end of file diff --git a/nant/src/Task.cs b/nant/src/Task.cs new file mode 100755 index 00000000..2a4eafae --- /dev/null +++ b/nant/src/Task.cs @@ -0,0 +1,192 @@ +// NAnt - A .NET build tool +// Copyright (C) 2001 Gerry Shaw +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Gerry Shaw (gerry_shaw@yahoo.com) +// Mike Krueger (mike@icsharpcode.net) +// Ian MacLean (ian_maclean@another.com) + +namespace SourceForge.NAnt { + + using System; + using System.Reflection; + using System.Xml; + + public abstract class Task { + + /// Gets and sets how much spacing log prefix names will be padded. + /// + /// Includes characters for a space after the name and the [ ] brackets. Default is 12. + /// + public static int LogPrefixPadding = Log.IndentSize; + + Location _location = Location.UnknownLocation; + Target _target = null; + Project _project = null; + + /// + /// Location in build file where task is defined. + /// + protected Location Location { + get { return _location; } + set { _location = value; } + } + + public string Name { + get { + string name = null; + TaskNameAttribute taskName = (TaskNameAttribute) Attribute.GetCustomAttribute(GetType(), typeof(TaskNameAttribute)); + if (taskName != null) { + name = taskName.Name; + } + return name; + } + } + + public string LogPrefix { + get { + string prefix = "[" + Name + "] "; + return prefix.PadLeft(LogPrefixPadding); + } + } + + public Target Target { + get { return _target; } + set { _target = value; } + } + + public Project Project { + get { return _project; } + set { _project = value; } + } + + protected void AutoInitializeAttributes(XmlNode taskNode) { + + // TODO: BooleanValidatorAttribute and Int32ValidatorAttribute implementation in Task + + // Go down the inheritance tree to find the private fields in the object. + // We are looking for task attributes to initialize. + Type currentType = GetType(); + while (currentType != typeof(object)) { + FieldInfo[] fieldInfoArray = currentType.GetFields(BindingFlags.NonPublic|BindingFlags.Instance); + foreach (FieldInfo fieldInfo in fieldInfoArray) { + + // process TaskAttribute attributes + TaskAttributeAttribute taskAttribute = (TaskAttributeAttribute) Attribute.GetCustomAttribute(fieldInfo, typeof(TaskAttributeAttribute)); + if (taskAttribute != null) { + + // get value from xml file + XmlNode node = taskNode.SelectSingleNode("@" + taskAttribute.Name); + + // check if its required + if (node == null && taskAttribute.Required) { + // TODO: add Location to exception + throw new BuildException(String.Format("{0} is a required attribute.", taskAttribute.Name), Location); + } + + if (node != null) { + fieldInfo.SetValue(this, Convert.ChangeType(node.Value, fieldInfo.FieldType)); + } + } + + // process TaskFileSet attributes + TaskFileSetAttribute fileSetAttribute = (TaskFileSetAttribute) Attribute.GetCustomAttribute(fieldInfo, typeof(TaskFileSetAttribute)); + if (fileSetAttribute != null) { + // have file set initialize itself + FileSet fileSet = (FileSet) fieldInfo.GetValue(this); + + // set task fileset belongs to + fileSet.Task = this; + + // load values from build file + XmlNode fileSetNode = taskNode.SelectSingleNode(fileSetAttribute.Name); + if (fileSetNode != null) { + + XmlNode baseDirectoryNode = fileSetNode.SelectSingleNode("@basedir"); + if (baseDirectoryNode != null) { + fileSet.BaseDirectory = baseDirectoryNode.Value; + } + + foreach (XmlNode node in fileSetNode.SelectNodes("includes")) { + string pathname = node.SelectSingleNode("@name").Value; + fileSet.Includes.Add(pathname); + } + + foreach (XmlNode node in fileSetNode.SelectNodes("excludes")) { + fileSet.Excludes.Add(node.SelectSingleNode("@name").Value); + } + } + } + } + currentType = currentType.BaseType; + } + } + + protected void AutoExpandAttributes() { + + // Go down the inheritance tree to find the private fields in the object. + // We are looking for task attributes to initialize. + Type currentType = GetType(); + while (currentType != typeof(object)) { + FieldInfo[] fieldInfoArray = currentType.GetFields(BindingFlags.NonPublic|BindingFlags.Instance); + foreach (FieldInfo fieldInfo in fieldInfoArray) { + + // proces string parameters + TaskAttributeAttribute taskAttribute = (TaskAttributeAttribute) Attribute.GetCustomAttribute(fieldInfo, typeof(TaskAttributeAttribute)); + if (taskAttribute != null) { + if (taskAttribute.ExpandText) { + string value = (string) fieldInfo.GetValue(this); + value = Project.ExpandText(value); + fieldInfo.SetValue(this, value); + } + + // if a field also has a validator attribute then ensure that value is correct + ValidatorAttribute[] validators = (ValidatorAttribute[]) Attribute.GetCustomAttributes(fieldInfo, typeof(ValidatorAttribute)); + foreach (ValidatorAttribute validator in validators) { + string errorMessage = validator.Validate(fieldInfo.GetValue(this)); + if (errorMessage != null) { + throw new BuildException(String.Format("Error processing '{0}' attribute in <{1}> task: {2}", taskAttribute.Name, Name, errorMessage), Location); + } + } + } + } + currentType = currentType.BaseType; + } + } + + public void Initialize(XmlNode taskNode) { + Initialize(taskNode, null); + } + + public void Initialize(XmlNode taskNode, Location location) { + if (location != null) { + _location = location; + } + AutoInitializeAttributes(taskNode); + InitializeTask(taskNode); + } + + public void Execute() { + AutoExpandAttributes(); + ExecuteTask(); + } + + protected virtual void InitializeTask(XmlNode taskNode) { + } + + protected abstract void ExecuteTask(); + } +} diff --git a/nant/src/TaskBuilder.cs b/nant/src/TaskBuilder.cs new file mode 100755 index 00000000..97b602b4 --- /dev/null +++ b/nant/src/TaskBuilder.cs @@ -0,0 +1,84 @@ +// NAnt - A .NET build tool +// Copyright (C) 2001 Gerry Shaw +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Gerry Shaw (gerry_shaw@yahoo.com) + +namespace SourceForge.NAnt { + + using System; + using System.Reflection; + + public class TaskBuilder { + + string _className; + string _assemblyFileName; + string _taskName; + + public TaskBuilder(string className) + : this(className, null) { + } + + public TaskBuilder(string className, string assemblyFileName) { + _className = className; + _assemblyFileName = assemblyFileName; + + // get task name from attribute + Assembly assembly = GetAssembly(); + TaskNameAttribute taskNameAttribute = (TaskNameAttribute) Attribute.GetCustomAttribute(assembly.GetType(ClassName), typeof(TaskNameAttribute)); + _taskName = taskNameAttribute.Name; + } + + public string ClassName { + get { return _className; } + } + + public string AssemblyFileName { + get { return _assemblyFileName; } + } + + public string TaskName { + get { return _taskName; } + } + + private Assembly GetAssembly() { + Assembly assembly; + if (AssemblyFileName == null) { + assembly = Assembly.GetExecutingAssembly(); + } else { + assembly = Assembly.LoadFrom(AssemblyFileName); + } + return assembly; + } + + public Task CreateTask(Project project, Target target) { + Task task; + try { + Assembly assembly = GetAssembly(); + + // create instance (ignore case) + task = (Task) assembly.CreateInstance(ClassName, true); + + // set default values + task.Project = project; + task.Target = target; + } catch (Exception) { + task = null; + } + return task; + } + } +} \ No newline at end of file diff --git a/nant/src/TaskBuilderCollection.cs b/nant/src/TaskBuilderCollection.cs new file mode 100755 index 00000000..bb61c317 --- /dev/null +++ b/nant/src/TaskBuilderCollection.cs @@ -0,0 +1,46 @@ +// NAnt - A .NET build tool +// Copyright (C) 2001 Gerry Shaw +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Gerry Shaw (gerry_shaw@yahoo.com) + +namespace SourceForge.NAnt { + + using System; + using System.Collections; + + public class TaskBuilderCollection : ArrayList { + + public bool Add(TaskBuilder builder) { + // prevent adding duplicate builders with the name task name + bool taskAdded = false; + if (GetBuilderForTask(builder.TaskName) == null) { + base.Add(builder); + taskAdded = true; + } + return taskAdded; + } + + public TaskBuilder GetBuilderForTask(string taskName) { + foreach (TaskBuilder builder in this) { + if (builder.TaskName == taskName) { + return builder; + } + } + return null; + } + } +} \ No newline at end of file diff --git a/nant/src/TaskCollection.cs b/nant/src/TaskCollection.cs new file mode 100755 index 00000000..94d7afc4 --- /dev/null +++ b/nant/src/TaskCollection.cs @@ -0,0 +1,26 @@ +// NAnt - A .NET build tool +// Copyright (C) 2001 Gerry Shaw +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Gerry Shaw (gerry_shaw@yahoo.com) + +namespace SourceForge.NAnt { + + using System.Collections; + + public class TaskCollection : ArrayList { + } +} \ No newline at end of file diff --git a/nant/src/TaskFactory.cs b/nant/src/TaskFactory.cs new file mode 100755 index 00000000..f1e4f7f7 --- /dev/null +++ b/nant/src/TaskFactory.cs @@ -0,0 +1,57 @@ +// NAnt - A .NET build tool +// Copyright (C) 2001 Gerry Shaw +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Gerry Shaw (gerry_shaw@yahoo.com) + +namespace SourceForge.NAnt { + + using System; + using System.Xml; + + internal class TaskFactory { + + TaskBuilderCollection _builders = new TaskBuilderCollection(); + Project _project; + + public TaskFactory(Project project) { + Project = project; + } + + public TaskBuilderCollection Builders { + get { return _builders; } + } + + public Project Project { + get { return _project; } + set { _project = value; } + } + + public Task CreateTask(XmlNode taskNode, Target target) { + string taskName = taskNode.Name; + Task task = null; + + TaskBuilder builder = Builders.GetBuilderForTask(taskName); + if (builder != null) { + task = builder.CreateTask(Project, target); + } else { + throw new BuildException(String.Format("unknown task <{0}> in target <{1}>", taskName, target.Name)); + } + + return task; + } + } +} \ No newline at end of file diff --git a/nant/src/Tasks/CallTask.cs b/nant/src/Tasks/CallTask.cs new file mode 100755 index 00000000..08e24711 --- /dev/null +++ b/nant/src/Tasks/CallTask.cs @@ -0,0 +1,41 @@ +// NAnt - A .NET build tool +// Copyright (C) 2001 Gerry Shaw +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Gerry Shaw (gerry_shaw@yahoo.com) + +namespace SourceForge.NAnt { + + using System; + using System.Collections.Specialized; + using System.Diagnostics; + using System.IO; + using System.Xml; + + [TaskName("call")] + public class CallTask : Task { + + [TaskAttribute("target", Required=true)] + string _target = null; + + // Attribute properties + public string TargetName { get { return _target; } } + + protected override void ExecuteTask() { + Project.Execute(TargetName); + } + } +} \ No newline at end of file diff --git a/nant/src/Tasks/ChangeLog b/nant/src/Tasks/ChangeLog new file mode 100644 index 00000000..68de36bb --- /dev/null +++ b/nant/src/Tasks/ChangeLog @@ -0,0 +1,13 @@ +2002-04-26 Martin Baulig + + * CompilerBase.cs (WriteOption): New virtual method. The default + implementation writes CSC-style command line options, but it can + be overridden in derived class to write mcs-style command line + arguments. + (ExecuteTask): Use the new virtual `WriteOption' method to write + options. + + * CscTask.cs (WriteOptions): Use the new `WriteOption' method. + + * McsTask.cs: New file. + diff --git a/nant/src/Tasks/CompilerBase.cs b/nant/src/Tasks/CompilerBase.cs new file mode 100755 index 00000000..39ffb297 --- /dev/null +++ b/nant/src/Tasks/CompilerBase.cs @@ -0,0 +1,195 @@ +// NAnt - A .NET build tool +// Copyright (C) 2001 Gerry Shaw +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Gerry Shaw (gerry_shaw@yahoo.com) +// Mike Krueger (mike@icsharpcode.net) + +namespace SourceForge.NAnt { + + using System; + using System.Collections.Specialized; + using System.Diagnostics; + using System.IO; + + public abstract class CompilerBase : ExternalProgramBase { + + string _responseFileName; + + // Microsoft common compiler options + [TaskAttribute("output", Required=true)] + string _output = null; + + [TaskAttribute("target", Required=true)] + string _target = null; + + [TaskAttribute("debug")] + [BooleanValidator()] + string _debug = Boolean.FalseString; + + [TaskAttribute("define")] + string _define = null; + + [TaskAttribute("win32icon")] + string _win32icon = null; + + [TaskFileSet("references")] + FileSet _references = new FileSet(false); + + [TaskFileSet("resources")] + FileSet _resources = new FileSet(false); + + [TaskFileSet("modules")] + FileSet _modules = new FileSet(false); + + [TaskFileSet("sources")] + FileSet _sources = new FileSet(true); // include all by default + + public string Output { get { return _output; } } + public string OutputTarget { get { return _target; } } + public bool Debug { get { return Convert.ToBoolean(_debug); } } + public string Define { get { return _define; } } + public string Win32Icon { get { return _win32icon; } } + public FileSet References { get { return _references; } } + public FileSet Resources { get { return _resources; } } + public FileSet Modules { get { return _modules; } } + public FileSet Sources { get { return _sources; } } + + public override string ProgramFileName { get { return Name; } } + public override string ProgramArguments { get { return "@" + _responseFileName; } } + + protected virtual void WriteOptions(TextWriter writer) { + } + + protected virtual void WriteOption(TextWriter writer, string name) { + writer.WriteLine("/{0}", name); + } + + protected virtual void WriteOption(TextWriter writer, string name, string arg) { + writer.WriteLine("/{0}:{1}", name, arg); + } + + protected string GetOutputPath() { + return Path.GetFullPath(Path.Combine(BaseDirectory, Project.ExpandText(Output))); + } + + protected virtual bool NeedsCompiling() { + // return true as soon as we know we need to compile + + FileInfo outputFileInfo = new FileInfo(GetOutputPath()); + if (!outputFileInfo.Exists) { + return true; + } + + if (FileSet.MoreRecentLastWriteTime(Sources.FileNames, outputFileInfo.LastWriteTime)) { + return true; + } + if (FileSet.MoreRecentLastWriteTime(References.FileNames, outputFileInfo.LastWriteTime)) { + return true; + } + if (FileSet.MoreRecentLastWriteTime(Modules.FileNames, outputFileInfo.LastWriteTime)) { + return true; + } + + // if we made it here then we don't have to recompile + return false; + } + + protected override void ExecuteTask() { + if (NeedsCompiling()) { + // create temp response file to hold compiler options + _responseFileName = Path.GetTempFileName(); + StreamWriter writer = new StreamWriter(_responseFileName); + + try { + if (References.BaseDirectory == null) { + References.BaseDirectory = BaseDirectory; + } + if (Modules.BaseDirectory == null) { + Modules.BaseDirectory = BaseDirectory; + } + if (Sources.BaseDirectory == null) { + Sources.BaseDirectory = BaseDirectory; + } + + Log.WriteLine(LogPrefix + "Compiling {0} files to {1}", Sources.FileNames.Count, GetOutputPath()); + + // specific compiler options + WriteOptions(writer); + + // Microsoft common compiler options + WriteOption(writer, "nologo"); + WriteOption(writer, "target", OutputTarget); + WriteOption(writer, "out", GetOutputPath()); + if (Debug) { + WriteOption(writer, "debug"); + WriteOption(writer, "define", "DEBUG"); + WriteOption(writer, "define", "TRACE"); + } + if (Define != null) { + WriteOption(writer, "define", Define); + } + if (Win32Icon != null) { + WriteOption(writer, "win32icon", Win32Icon); + } + foreach (string fileName in References.FileNames) { + WriteOption(writer, "reference", fileName); + } + foreach (string fileName in Modules.FileNames) { + WriteOption(writer, "addmodule", fileName); + } + foreach (string fileName in Resources.FileNames) { + WriteOption(writer, "resource", fileName); + } + foreach (string fileName in Sources.FileNames) { + writer.WriteLine(fileName); + } + // Make sure to close the response file otherwise contents + // will not be written to disc and EXecuteTask() will fail. + writer.Close(); + + if (Verbose) { + // display response file contents + Log.WriteLine(LogPrefix + "Contents of " + _responseFileName); + /* + StreamReader reader = File.OpenText(_responseFileName); + string line = reader.ReadLine(); + while (line != null) { + Log.WriteLine(LogPrefix + " " + line); + line = reader.ReadLine(); + } + reader.Close(); + */ + + StreamReader reader = File.OpenText(_responseFileName); + Log.WriteLine(reader.ReadToEnd()); + reader.Close(); + + } + + // call base class to do the work + base.ExecuteTask(); + + } finally { + // make sure we delete response file even if an exception is thrown + writer.Close(); // make sure stream is closed or file cannot be deleted + File.Delete(_responseFileName); + _responseFileName = null; + } + } + } + } +} diff --git a/nant/src/Tasks/CopyTask.cs b/nant/src/Tasks/CopyTask.cs new file mode 100755 index 00000000..849eb023 --- /dev/null +++ b/nant/src/Tasks/CopyTask.cs @@ -0,0 +1,196 @@ +// NAnt - A .NET build tool +// Copyright (C) 2001 Gerry Shaw +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Gerry Shaw (gerry_shaw@yahoo.com) +// Ian MacLean (ian_maclean@another.com) + +namespace SourceForge.NAnt { + + using System; + using System.IO; + using System.Xml; + using System.Text; + using System.Collections; + using System.Collections.Specialized; + + [TaskName("copy")] + public class CopyTask : Task { + + [TaskAttribute("file")] + string _sourceFile = null; + + [TaskAttribute("tofile")] + string _toFile = null; + + [TaskAttribute("todir")] + string _toDirectory = null; + + [TaskAttribute("filtering")] + [BooleanValidator()] + string _filtering = Boolean.FalseString; + + [TaskAttribute("flatten")] + [BooleanValidator()] + string _flatten = Boolean.FalseString; + + [TaskAttribute("includeEmptyDirs")] + [BooleanValidator()] + string _includeEmptyDirs = Boolean.FalseString; + + [TaskFileSet("fileset")] + FileSet _fileset = new FileSet(true); // include all by default + + [TaskAttribute("overwrite")] + [BooleanValidator()] + string _overwrite = Boolean.FalseString; + + [TaskAttribute("verbose")] + [BooleanValidator()] + string _verbose = Boolean.FalseString; + + [TaskAttribute("preserveLastModified")] + [BooleanValidator()] + string _preserveLastModified = Boolean.FalseString; + + Hashtable _fileCopyMap = new Hashtable(); + + public string SourceFile { get { return _sourceFile; } } + public string ToFile { get { return _toFile; } } + public string ToDirectory { get { return _toDirectory; } } + public bool Filtering { get { return Convert.ToBoolean(_filtering); } } + public bool Flatten { get { return Convert.ToBoolean(_flatten); } } + public bool IncludeEmptyDirs { get { return Convert.ToBoolean(_includeEmptyDirs); } } + public bool Overwrite { get { return Convert.ToBoolean(_overwrite); } } + public bool PreserveLastModified{ get { return Convert.ToBoolean(_preserveLastModified); } } + public FileSet CopyFileSet { get { return _fileset; } } + + public bool Verbose { + get { + return (Project.Verbose || Convert.ToBoolean(_verbose)); + } + } + + protected Hashtable FileCopyMap { + get { return _fileCopyMap; } + } + + /// + /// Actually does the file (and possibly empty directory) copies. + /// + protected virtual void DoFileOperations() { + int fileCount = FileCopyMap.Keys.Count; + if (fileCount > 0) { + if (ToDirectory != null) { + Log.WriteLine(LogPrefix + "Copying {0} files to {1}", fileCount, Project.GetFullPath(ToDirectory)); + } else { + Log.WriteLine(LogPrefix + "Copying {0} files", fileCount); + } + + // loop thru our file list + foreach (string sourcePath in FileCopyMap.Keys) { + string dstPath = (string)FileCopyMap[sourcePath]; + if (sourcePath == dstPath) { + if (Verbose) { + Log.WriteLine(LogPrefix + "Skipping self-copy of {0}" + sourcePath); + } + continue; + } + + try { + if (Verbose) { + Log.WriteLine(LogPrefix + "Copying {0} to {1}", sourcePath, dstPath); + } + + // create directory if not present + string dstDirectory = Path.GetDirectoryName(dstPath); + if (!Directory.Exists(dstDirectory)) { + Directory.CreateDirectory(dstDirectory); + if (Verbose) { + Log.WriteLine(LogPrefix + "Created directory {0}", dstDirectory); + } + } + + File.Copy(sourcePath, dstPath, true); + } catch (IOException ioe) { + string msg = String.Format("Cannot copy {0} to {1}", sourcePath, dstPath); + throw new BuildException(msg, Location, ioe); + } + } + } + + // TODO: handle empty directories in the fileset, refer to includeEmptyDirs attribute at + // http://jakarta.apache.org/ant/manual/CoreTasks/copy.html + } + + protected override void ExecuteTask() { + + string dstDirectoryPath = Project.GetFullPath(ToDirectory); + string srcFilePath = Project.GetFullPath(SourceFile); + FileInfo srcInfo = new FileInfo(srcFilePath); + + string dstFilePath; + if (ToFile == null) { + dstFilePath = dstDirectoryPath + Path.DirectorySeparatorChar + srcInfo.Name; + } else { + dstFilePath = Project.GetFullPath(ToFile); + } + + FileInfo dstInfo = new FileInfo(dstFilePath); + if (SourceFile != null) { + if (srcInfo.Exists) { + // do the outdated check + bool outdated = (!dstInfo.Exists) || (srcInfo.LastWriteTime > dstInfo.LastWriteTime); + + if (Overwrite || outdated) { + // add to a copy map of absolute verified paths + FileCopyMap.Add(srcFilePath, dstFilePath); + } + } else { + Log.WriteLine(LogPrefix + "Could not find file {0} to copy.", srcFilePath); + } + } else { + // get the complete path of the base directory of the fileset, ie, c:\work\nant\src + string srcBasePath = Project.GetFullPath(CopyFileSet.BaseDirectory); + string dstBasePath = Project.GetFullPath(ToDirectory); + + // if source file not specified use fileset + foreach (string pathname in CopyFileSet.FileNames) { + // replace the fileset path with the destination path + // NOTE: big problems could occur if the file set base dir is rooted on a different drive + string dstPath = pathname.Replace(srcBasePath, dstBasePath); + + srcInfo = new FileInfo(pathname); + dstInfo = new FileInfo(dstPath); + + if (srcInfo.Exists) { + // do the outdated check + bool outdated = (!dstInfo.Exists) || (srcInfo.LastWriteTime > dstInfo.LastWriteTime); + + if (Overwrite || outdated) { + FileCopyMap.Add(pathname, dstPath); + } + } else { + Log.WriteLine(LogPrefix + "Could not find file {0} to copy.", srcFilePath); + } + } + } + + // do all the actual copy operations now... + DoFileOperations(); + } + } +} diff --git a/nant/src/Tasks/CscTask.cs b/nant/src/Tasks/CscTask.cs new file mode 100755 index 00000000..202082bc --- /dev/null +++ b/nant/src/Tasks/CscTask.cs @@ -0,0 +1,45 @@ +// NAnt - A .NET build tool +// Copyright (C) 2001 Gerry Shaw +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Gerry Shaw (gerry_shaw@yahoo.com) +// Mike Krueger (mike@icsharpcode.net) + +namespace SourceForge.NAnt { + + using System; + using System.IO; + + [TaskName("csc")] + public class CscTask : CompilerBase { + + // C# specific compiler options + [TaskAttribute("doc")] + string _doc = null; + + protected override void WriteOptions(TextWriter writer) { + WriteOption(writer, "fullpaths"); + if (_doc != null) { + WriteOption(writer, "doc", _doc); + } + } + + protected override bool NeedsCompiling() { + // TODO: add checks for any referenced files OR return false to always compile + return base.NeedsCompiling(); + } + } +} diff --git a/nant/src/Tasks/DeleteTask.cs b/nant/src/Tasks/DeleteTask.cs new file mode 100755 index 00000000..4d4abf25 --- /dev/null +++ b/nant/src/Tasks/DeleteTask.cs @@ -0,0 +1,173 @@ +// NAnt - A .NET build tool +// Copyright (C) 2001 Gerry Shaw +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Gerry Shaw (gerry_shaw@yahoo.com) + + +// TODO: move this into the task documentation (once we figure out how tasks +// should be documented - xml?? +/* + +verbose: Show name of each deleted file ("true"/"false"). Default is "false" +when omitted. + +quiet: If the file does not exist, do not display a diagnostic message or +modify the exit status to reflect an error (unless Ant has been invoked with +the -verbose or -debug switches). This means that if a file or directory cannot +be deleted, then no error is reported. This setting emulates the -f option to +the Unix "rm" command. ("true"/"false"). Default is "false" meaning things are +"noisy". Setting this to true, implies setting failonerror to false. + +failonerror: This flag (which is only of relevance if 'quiet' is false), +controls whether an error -such as a failure to delete a file- stops the build +task, or is merely reported to the screen. The default is "true" + +*/ + +namespace SourceForge.NAnt { + + using System; + using System.IO; + + [TaskName("delete")] + public class DeleteTask : Task { + + [TaskAttribute("file")] + string _file = null; + + [TaskAttribute("dir")] + string _dir = null; + + [TaskAttribute("verbose")] + [BooleanValidator()] + string _verbose = Boolean.FalseString; + + [TaskAttribute("failonerror")] + [BooleanValidator()] + string _failOnError = Boolean.TrueString; + + /// If true then delete empty directories when using filesets. + [TaskAttribute("includeEmptyDirs")] + [BooleanValidator()] + string _includeEmptyDirs = Boolean.FalseString; + + [TaskFileSet("fileset")] + FileSet _fileset = new FileSet(false); + + public string FileName { get { return _file; } } + public string DirectoryName { get { return _dir; } } + public bool FailOnError { get { return Convert.ToBoolean(_failOnError); } } + public bool IncludeEmptyDirectories { get { return Convert.ToBoolean(_includeEmptyDirs); } } + public FileSet DeleteFileSet { get { return _fileset; } } + + public bool Verbose { + get { + return (Project.Verbose || Convert.ToBoolean(_verbose)); + } + } + + protected override void ExecuteTask() { + + // limit task to deleting either a file or a directory or a file set + if (FileName != null && DirectoryName != null) { + throw new BuildException("Cannot specify 'file' and 'dir' in the same delete task", Location); + } + + // try to delete specified file + if (FileName != null) { + string path = null; + try { + path = Project.GetFullPath(FileName); + } catch (Exception e) { + string msg = String.Format("Could not determine path from {0}", FileName); + throw new BuildException(msg, Location, e); + } + DeleteFile(path); + + // try to delete specified directory + } else if (DirectoryName != null) { + string path = null; + try { + path = Project.GetFullPath(DirectoryName); + } catch (Exception e) { + string msg = String.Format("Could not determine path from {0}", DirectoryName); + throw new BuildException(msg, Location, e); + } + DeleteDirectory(path); + + // delete files/directories in fileset + } else { + // only use the file set if file and dir attributes have NOT been set + foreach (string path in DeleteFileSet.FileNames) { + DeleteFile(path); + } + + if (IncludeEmptyDirectories) { + foreach (string path in DeleteFileSet.DirectoryNames) { + // only delete EMPTY directories (no files, no directories) + DirectoryInfo dirInfo = new DirectoryInfo(path); + + if ((dirInfo.GetFiles().Length == 0) && (dirInfo.GetDirectories().Length == 0)) { + DeleteDirectory(path); + } + } + } + } + } + + void DeleteDirectory(string path) { + try { + if (Directory.Exists(path)) { + if (Verbose) { + Log.WriteLine(LogPrefix + "Deleting directory {0}", path); + } + if (path.Length > 10) { + Directory.Delete(path, true); + } else { + // TODO: remove this once this task is fully tested and NAnt is at 1.0 + Console.WriteLine(LogPrefix + "Path {0} is too close to root to delete this early in development", path); + } + } else { + throw new DirectoryNotFoundException(); + } + } catch (Exception e) { + if (FailOnError) { + string msg = String.Format("Cannot delete directory {0}", path); + throw new BuildException(msg, Location, e); + } + } + } + + void DeleteFile(string path) { + try { + if (File.Exists(path)) { + if (Verbose) { + Log.WriteLine(LogPrefix + "Deleting file {0}", path); + } + File.Delete(path); + } else { + throw new FileNotFoundException(); + } + } catch (Exception e) { + if (FailOnError) { + string msg = String.Format("Cannot delete file {0}", path); + throw new BuildException(msg, Location, e); + } + } + } + } +} diff --git a/nant/src/Tasks/EchoTask.cs b/nant/src/Tasks/EchoTask.cs new file mode 100755 index 00000000..871a4385 --- /dev/null +++ b/nant/src/Tasks/EchoTask.cs @@ -0,0 +1,34 @@ +// NAnt - A .NET build tool +// Copyright (C) 2001 Gerry Shaw +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Gerry Shaw (gerry_shaw@yahoo.com) + +namespace SourceForge.NAnt { + + using System; + + [TaskName("echo")] + public class EchoTask : Task { + + [TaskAttribute("message", Required=true)] + string _message = null; + + protected override void ExecuteTask() { + Log.WriteLine(LogPrefix + _message); + } + } +} diff --git a/nant/src/Tasks/ExecTask.cs b/nant/src/Tasks/ExecTask.cs new file mode 100755 index 00000000..747c8ab5 --- /dev/null +++ b/nant/src/Tasks/ExecTask.cs @@ -0,0 +1,58 @@ +// NAnt - A .NET build tool +// Copyright (C) 2001 Gerry Shaw +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Gerry Shaw (gerry_shaw@yahoo.com) + +namespace SourceForge.NAnt { + + using System; + using System.IO; + + [TaskName("exec")] + public class ExecTask : ExternalProgramBase { + + [TaskAttribute("program", Required=true)] + string _program = null; + + [TaskAttribute("commandline")] + string _commandline = null; + + [TaskAttribute("basedir")] + string _baseDirectory = null; + + // Stop the buildprocess if the command exits with a returncode other than 0. + [TaskAttribute("failonerror")] + [BooleanValidator()] + string _failonerror = Boolean.TrueString; + + // TODO: change this to Int32Parameter to ensure value is a valid Int32 type after text expansion + [TaskAttribute("timeout")] + [Int32Validator()] + string _timeout = Int32.MaxValue.ToString(); + + public override string ProgramFileName { get { return Project.GetFullPath(_program); } } + public override string ProgramArguments { get { return _commandline; } } + public override string BaseDirectory { get { return Project.GetFullPath(_baseDirectory); } } + public override int TimeOut { get { return Convert.ToInt32(_timeout); } } + public override bool FailOnError { get { return Convert.ToBoolean(_failonerror); } } + + protected override void ExecuteTask() { + Log.WriteLine(LogPrefix + "{0} {1}", Path.GetFileName(ProgramFileName), GetCommandLine()); + base.ExecuteTask(); + } + } +} \ No newline at end of file diff --git a/nant/src/Tasks/ExternalProgramBase.cs b/nant/src/Tasks/ExternalProgramBase.cs new file mode 100755 index 00000000..0bc93817 --- /dev/null +++ b/nant/src/Tasks/ExternalProgramBase.cs @@ -0,0 +1,130 @@ +// NAnt - A .NET build tool +// Copyright (C) 2001 Gerry Shaw +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Gerry Shaw (gerry_shaw@yahoo.com) + +namespace SourceForge.NAnt { + + using System; + using System.Collections.Specialized; + using System.Diagnostics; + using System.IO; + using System.Text; + using System.Xml; + + public abstract class ExternalProgramBase : Task { + + [TaskAttribute("verbose")] + [BooleanValidator()] + string _verbose = Boolean.FalseString; + + public abstract string ProgramFileName { get; } + public abstract string ProgramArguments { get; } + + public virtual string BaseDirectory { + get { + if (Project != null) { + return Project.BaseDirectory; + } else { + return null; + } + } + } + + public virtual int TimeOut { + get { return Int32.MaxValue; } + } + + public virtual bool FailOnError { + get { return true; } + } + + public bool Verbose { + get { + return (Project.Verbose || Convert.ToBoolean(_verbose)); + } + } + + StringCollection _args = new StringCollection(); + + protected override void InitializeTask(XmlNode taskNode) { + // initialize the _args collection + foreach (XmlNode optionNode in taskNode.SelectNodes("arg")) { + + // TODO: decide if we should enforce arg elements not being able + // to accept a file and value attribute on the same element. + // Ideally this would be down via schema and since it doesn't + // really hurt for now I'll leave it in. + + XmlNode valueNode = optionNode.SelectSingleNode("@value"); + if (valueNode != null) { + _args.Add(Project.ExpandText(valueNode.Value)); + } + + XmlNode fileNode = optionNode.SelectSingleNode("@file"); + if (fileNode != null) { + _args.Add(Project.GetFullPath(Project.ExpandText(fileNode.Value))); + } + } + } + + public string GetCommandLine() { + // append any nested arguments to command line + StringBuilder arguments = new StringBuilder(ProgramArguments); + foreach (string arg in _args) { + arguments = arguments.Append(' '); + arguments = arguments.Append(arg); + } + return arguments.ToString(); + } + + protected override void ExecuteTask() { + try { + // create process to launch compiler (redirect standard output to temp buffer) + Process process = new Process(); + process.StartInfo.FileName = ProgramFileName; + process.StartInfo.Arguments = GetCommandLine(); + process.StartInfo.RedirectStandardOutput = true; + process.StartInfo.UseShellExecute = false; + process.StartInfo.WorkingDirectory = BaseDirectory; + if (Verbose) { + Log.WriteLine(LogPrefix + "{0}>{1} {2}", process.StartInfo.WorkingDirectory, process.StartInfo.FileName, process.StartInfo.Arguments); + } + process.Start(); + + // display standard output + StreamReader reader = process.StandardOutput; + string output = reader.ReadToEnd(); + if (output.Length > 0) { + int indentLevel = Log.IndentLevel; + Log.IndentLevel = 0; + Log.WriteLine(output); + Log.IndentLevel = indentLevel; + } + + // wait for program to exit + process.WaitForExit(TimeOut); + + if (FailOnError && process.ExitCode != 0) { + throw new BuildException("Program error, see build log for details."); + } + } catch (Exception e) { + throw new BuildException(e.Message, Location, e); + } + } + } +} \ No newline at end of file diff --git a/nant/src/Tasks/FailTask.cs b/nant/src/Tasks/FailTask.cs new file mode 100755 index 00000000..2e6b7161 --- /dev/null +++ b/nant/src/Tasks/FailTask.cs @@ -0,0 +1,38 @@ +// NAnt - A .NET build tool +// Copyright (C) 2001 Gerry Shaw +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Gerry Shaw (gerry_shaw@yahoo.com) + +namespace SourceForge.NAnt { + + using System; + + [TaskName("fail")] + public class FailTask : Task { + + [TaskAttribute("message")] + string _message = null; + + protected override void ExecuteTask() { + string message = _message; + if (message == null) { + message = "No message"; + } + throw new BuildException(message); + } + } +} diff --git a/nant/src/Tasks/IncludeTask.cs b/nant/src/Tasks/IncludeTask.cs new file mode 100755 index 00000000..637c3dab --- /dev/null +++ b/nant/src/Tasks/IncludeTask.cs @@ -0,0 +1,134 @@ +// NAnt - A .NET build tool +// Copyright (C) 2001 Gerry Shaw +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Ian MacLean (ian_maclean@another.com) + + +namespace SourceForge.NAnt { + + using System; + using System.Xml; + using System.Collections; + using System.Collections.Specialized; + + /// + /// Summary description for IncludeTask. + /// + + [TaskName("include")] // TODO make into ant:include + public class IncludeTask : Task { + + /// hours to to add to the sleep time + [TaskAttribute("href", Required=true)] + string _href = null; + + // Attribute properties + public string Href { get { return _href; } } + + XPathTextPositionMap _positionMap; // created when Xml document is loaded + TaskCollection _tasks = new TaskCollection(); + + // static members + static System.Collections.Stack _includesStack = new Stack(); + static bool IsIncluded( string href ) { + bool result = false; + IEnumerator stackenum = _includesStack.GetEnumerator(); + while ( stackenum.MoveNext()) { + if ( href == (string)stackenum.Current ) { + result = true; break; + } + } + return result; + } + + protected void InitializeIncludedDocument(XmlDocument doc) { + + // Load line Xpath to linenumber array + _positionMap = new XPathTextPositionMap(doc.BaseURI); + + // process all the non-target nodes (these are global tasks for the project) + XmlNodeList taskList = doc.SelectNodes("project/*[name() != 'target']"); + foreach (XmlNode taskNode in taskList) { + + // TODO: do somethiing like Project.CreateTask(taskNode) and have the project set the location + TextPosition textPosition = _positionMap.GetTextPosition(taskNode); + + Task task = Project.CreateTask(taskNode); + if (task != null) { + // Store a local copy also so we can execute only those + _tasks.Add(task); + } + } + + // execute global tasks now - before anything else + // this lets us include tasks that do things like add more tasks + // Here is where we should check for recursive dependencies + // + foreach (Task task in _tasks ) { + task.Execute(); + } + + // process all the targets + XmlNodeList targetList = doc.SelectNodes("project/target"); + foreach (XmlNode targetNode in targetList) { + Target target = new Target(Project); + target.Initialize(targetNode); + Project.Targets.Add(target); + } + } + + /// + /// verify parameters + /// + /// taskNode used to define this task instance + protected override void InitializeTask(XmlNode taskNode) { + + //TODO check where we are in document - if not at top level then bail out on error ... + // basic recursion check + if (IsIncluded( Project.GetFullPath(Href) )) { + throw new BuildException("Recursive includes are not allowed", Location); + } + } + + protected override void ExecuteTask() { + + string fullpath = Project.GetFullPath(Href); + // push ourselves onto the stack + _includesStack.Push(fullpath); + try { + + XmlDocument doc = new XmlDocument(); + + // Handle local file case + doc.Load(fullpath); + + InitializeIncludedDocument(doc); + } + // Handling the case where a nested include causes an exception during initialization + catch ( BuildException ) { + throw; + } + catch ( Exception e) { + throw new BuildException(e.Message, Location, e); + } + finally { + // Pop off the stack + _includesStack.Pop(); + } + } + } +} diff --git a/nant/src/Tasks/JscTask.cs b/nant/src/Tasks/JscTask.cs new file mode 100755 index 00000000..e2944122 --- /dev/null +++ b/nant/src/Tasks/JscTask.cs @@ -0,0 +1,40 @@ +// NAnt - A .NET build tool +// Copyright (C) 2001 Gerry Shaw +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Gerry Shaw (gerry_shaw@yahoo.com) +// Mike Krueger (mike@icsharpcode.net) + +namespace SourceForge.NAnt { + + using System; + using System.IO; + + [TaskName("jsc")] + public class JscTask : CompilerBase { + + // TODO: add JScript.NET specific compiler options here (see CscTask) + + protected override void WriteOptions(TextWriter writer) { + // TODO: add support for compiler specific options + } + + protected override bool NeedsCompiling() { + // TODO: add checks for any referenced files OR return false to always compile + return base.NeedsCompiling(); + } + } +} diff --git a/nant/src/Tasks/McsTask.cs b/nant/src/Tasks/McsTask.cs new file mode 100644 index 00000000..3c5a0ee3 --- /dev/null +++ b/nant/src/Tasks/McsTask.cs @@ -0,0 +1,47 @@ +// NAnt - A .NET build tool +// Copyright (C) 2002 Ximian, Inc. +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Martin Baulig (martin@gnome.org) + +using System; +using System.IO; + +namespace SourceForge.NAnt +{ + + [TaskName("mcs")] + public class McsTask : CompilerBase + { + protected override void WriteOption(TextWriter writer, string name) { + if (name.Equals("nologo")) { + return; + } else { + writer.WriteLine("--{0}", name); + } + } + + protected override void WriteOption(TextWriter writer, string name, string arg) { + if (name.Equals("out")) { + writer.WriteLine("-o {0}", arg); + } else if (name.Equals("reference")) { + writer.WriteLine("-r {0}", arg); + } else { + writer.WriteLine("--{0} {1}", name, arg); + } + } + } +} diff --git a/nant/src/Tasks/MkDirTask.cs b/nant/src/Tasks/MkDirTask.cs new file mode 100755 index 00000000..fca374b3 --- /dev/null +++ b/nant/src/Tasks/MkDirTask.cs @@ -0,0 +1,49 @@ +// NAnt - A .NET build tool +// Copyright (C) 2001 Gerry Shaw +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Gerry Shaw (gerry_shaw@yahoo.com) +// Ian MacLean (ian_maclean@another.com) + +namespace SourceForge.NAnt { + + using System; + using System.IO; + + /// Creates a directory and any non-existent parent directories when necessary. + [TaskName("mkdir")] + public class MkDirTask : Task { + + [TaskAttribute("dir", Required=true)] + string _dir = null; // the directory to create + + protected override void ExecuteTask() { + try { + string directory = Project.GetFullPath(_dir); + if (!Directory.Exists(directory)) { + Log.WriteLine(LogPrefix + "Creating directory {0}", directory); + DirectoryInfo result = Directory.CreateDirectory(directory); + if (result == null) { + string msg = String.Format("Unknown error creating directory '{0}'", directory); + throw new BuildException(msg, Location); + } + } + } catch (Exception e) { + throw new BuildException(e.Message, Location, e); + } + } + } +} diff --git a/nant/src/Tasks/MoveTask.cs b/nant/src/Tasks/MoveTask.cs new file mode 100755 index 00000000..2b63014e --- /dev/null +++ b/nant/src/Tasks/MoveTask.cs @@ -0,0 +1,71 @@ +// NAnt - A .NET build tool +// Copyright (C) 2001 Gerry Shaw +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Gerry Shaw (gerry_shaw@yahoo.com) +// Ian MacLean (ian_maclean@another.com) + +namespace SourceForge.NAnt { + + using System; + using System.IO; + + [TaskName("move")] + public class MoveTask : CopyTask { + + /// + /// Actually does the file (and possibly empty directory) copies. + /// + protected override void DoFileOperations() { + if (FileCopyMap.Count > 0) { + + // loop thru our file list + foreach (string sourcePath in FileCopyMap.Keys) { + string destinationPath = (string)FileCopyMap[sourcePath]; + if (sourcePath == destinationPath) { + Log.WriteLine(LogPrefix + "Skipping self-move of {0}" + sourcePath); + continue; + } + + try { + // check if directory exists + if (Directory.Exists(sourcePath)) { + Log.WriteLine(LogPrefix + "moving directory {0} to {1}", sourcePath, destinationPath); + Directory.Move(sourcePath, destinationPath); + } + else { + + DirectoryInfo todir = new DirectoryInfo(destinationPath); + if ( !todir.Exists ) { + Directory.CreateDirectory( Path.GetDirectoryName(destinationPath) ); + } + + Log.WriteLine(LogPrefix + "Moving {0} to {1}", sourcePath, destinationPath); + // IM look into how Ant does this for directories + File.Move(sourcePath, destinationPath); + } + + } catch (IOException ioe) { + string msg = String.Format("Failed to move {0} to {1}\n{2}", sourcePath, destinationPath, ioe.Message); + throw new BuildException(msg, Location); + } + } + } + } + } +} + + diff --git a/nant/src/Tasks/NantTask.cs b/nant/src/Tasks/NantTask.cs new file mode 100755 index 00000000..1462ae97 --- /dev/null +++ b/nant/src/Tasks/NantTask.cs @@ -0,0 +1,65 @@ +// NAnt - A .NET build tool +// Copyright (C) 2001 Gerry Shaw +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Gerry Shaw (gerry_shaw@yahoo.com) + +namespace SourceForge.NAnt { + + using System; + using System.Collections.Specialized; + using System.Diagnostics; + using System.IO; + using System.Xml; + + [TaskName("nant")] + public class NantTask : Task { + + [TaskAttribute("buildfile")] + string _buildFileName = null; + + [TaskAttribute("basedir")] + string _baseDirectory = null; + + // TODO: add support for multiple targets + [TaskAttribute("target")] + string _target = null; + + protected override void ExecuteTask() { + string directory = Project.GetFullPath(_baseDirectory); + string buildFileName = _buildFileName; + if (buildFileName == null) { + buildFileName = Project.FindBuildFileName(directory); + } + + try { + Log.WriteLine(LogPrefix + "{0} {1}", buildFileName, _target); + Log.Indent(); + Project project = new Project(); + project.BaseDirectory = directory; + project.BuildFileName = buildFileName; + if (_target != null) { + project.BuildTargets.Add(_target); + } + if (!project.Run()) { + throw new BuildException("Nested build failed - refer to build log for exact reason."); + } + } finally { + Log.Unindent(); + } + } + } +} \ No newline at end of file diff --git a/nant/src/Tasks/PropertyTask.cs b/nant/src/Tasks/PropertyTask.cs new file mode 100755 index 00000000..90933ca7 --- /dev/null +++ b/nant/src/Tasks/PropertyTask.cs @@ -0,0 +1,37 @@ +// NAnt - A .NET build tool +// Copyright (C) 2001 Gerry Shaw +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Gerry Shaw (gerry_shaw@yahoo.com) + +namespace SourceForge.NAnt { + + using System; + + [TaskName("property")] + public class PropertyTask : Task { + + [TaskAttribute("name", Required=true)] + string _name = null; + + [TaskAttribute("value", Required=true)] + string _value = String.Empty; + + protected override void ExecuteTask() { + Project.Properties[_name] = _value; + } + } +} \ No newline at end of file diff --git a/nant/src/Tasks/SleepTask.cs b/nant/src/Tasks/SleepTask.cs new file mode 100755 index 00000000..d6c69cc9 --- /dev/null +++ b/nant/src/Tasks/SleepTask.cs @@ -0,0 +1,91 @@ +// NAnt - A .NET build tool +// Copyright (C) 2001 Gerry Shaw +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Ian MacLean (ian_maclean@another.com) + +namespace SourceForge.NAnt { + + using System; + using System.Xml; + using System.Threading; + + /// + /// A task for sleeping a short period of time, useful when a build or deployment process + /// requires an interval between tasks. + /// + + [TaskName("sleep")] + public class SleepTask : Task { + + /// hours to to add to the sleep time + [TaskAttribute("hours")] + string _hours = null; + + /// minutes to add to the sleep time + [TaskAttribute("minutes")] + string _minutes = 0.ToString(); + + /// seconds to add to the sleep time + [TaskAttribute("seconds")] + string _seconds = 0.ToString(); + + /// milliseconds to add to the sleep time + [TaskAttribute("milliseconds")] + string _milliseconds = 0.ToString(); + + /// flag controlling whether to break the build on an error + [TaskAttribute("failonerror")] + [BooleanValidator()] + string _failonerror = Boolean.FalseString; + + // Attribute properties + public int Hours { get { return Convert.ToInt32(_hours); } } + public int Minutes { get { return Convert.ToInt32(_minutes); } } + public int Seconds { get { return Convert.ToInt32(_seconds); } } + public int Milliseconds { get { return Convert.ToInt32(_milliseconds); } } + public bool FailOnError { get { return Convert.ToBoolean(_failonerror); } } + + ///return time to sleep + private int GetSleepTime() { + return ((((int) Hours * 60) + Minutes) * 60 + Seconds) * 1000 + Milliseconds; + } + + /// return time to sleep + /// + private void DoSleep(int millis ) { + Thread.Sleep(millis); + } + + /// + /// verify parameters + /// + /// taskNode used to define this task instance + protected override void InitializeTask(XmlNode taskNode) { + if (GetSleepTime() < 0) { + throw new BuildException("Negative sleep periods are not supported", Location); + } + } + + protected override void ExecuteTask() { + int sleepTime = GetSleepTime(); + Log.WriteLine(LogPrefix + "sleeping for {0} milliseconds", sleepTime); + DoSleep(sleepTime); + } + } +} + + diff --git a/nant/src/Tasks/StyleTask.cs b/nant/src/Tasks/StyleTask.cs new file mode 100755 index 00000000..05117217 --- /dev/null +++ b/nant/src/Tasks/StyleTask.cs @@ -0,0 +1,171 @@ +// NAnt - A .NET build tool +// Copyright (C) 2001 Gerry Shaw +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Serge (serge@wildwestsoftware.com) +// Gerry Shaw (gerry_shaw@yahoo.com) + +namespace SourceForge.NAnt { + + using System; + using System.IO; + using System.Xml; + using System.Xml.Xsl; + using System.Xml.XPath; + using System.Text.RegularExpressions; + + [TaskName("style")] + public class StyleTask : Task { + + // TODO: consider prefixing private fields with _ to stay consistent (gs) + + [TaskAttribute("basedir", Required=false)] + string baseDir = null; + + [TaskAttribute("destdir", Required=false)] + string destDir = null; + + [TaskAttribute("extension", Required=false)] + string extension = "html"; + + [TaskAttribute("style", Required=true)] + string xsltFile = null; + + [TaskAttribute("in", Required=true)] + string srcFile = null; + + [TaskAttribute("out", Required=false)] + string destFile = null; + + private static string GetPath(string dir, string file) { + // TODO: remove platform dependencies by using System.IO.Path (gs) + string d = (dir == null) + ? "" + : Regex.Replace(dir, "/", "\\"); + + return (d==null || d=="") + ? (file==null || file=="") ? "" : file + : d.EndsWith("\\") + ? d +file : d + "\\" + file; + } + + private XmlReader CreateXmlReader(string dir, string file) { + string xmlPath = GetPath(dir, file); + XmlTextReader xmlReader = null; + + try { + xmlReader = new XmlTextReader(new FileStream(xmlPath, FileMode.Open)); + } catch (Exception) { + xmlReader = null; + } + + return xmlReader; + } + + private XmlWriter CreateXmlWriter(string dir, string file) { + string xmlPath = GetPath(dir, file); + + XmlWriter xmlWriter = null; + + string targetDir = Path.GetDirectoryName(Path.GetFullPath(xmlPath)); + if (targetDir != null && targetDir != "" && !Directory.Exists(targetDir)) { + Directory.CreateDirectory(targetDir); + } + + try { + // UTF-8 encoding will be used + xmlWriter = new XmlTextWriter(xmlPath, null); + } catch (Exception) { + xmlWriter = null; + } + + return xmlWriter; + } + + protected override void ExecuteTask() { + string destFile = this.destFile; + + if (destFile == null || destFile == "") { + // TODO: use System.IO.Path (gs) + string ext = extension[0]=='.' + ? extension + : "." + extension; + + int extPos = srcFile.LastIndexOf('.'); + + if (extPos == -1) { + destFile = srcFile + ext; + } else { + destFile = srcFile.Substring(0, extPos) + ext; + } + } + + string srcPath = GetPath(baseDir, srcFile); + string destPath = GetPath(destDir, destFile); + string xsltPath = GetPath(baseDir, xsltFile); + + FileInfo srcInfo = new FileInfo(srcPath); + FileInfo destInfo = new FileInfo(destPath); + FileInfo xsltInfo = new FileInfo(xsltPath); + + if (!srcInfo.Exists) { + throw new BuildException("Unable to find source xml file."); + } + if (!xsltInfo.Exists) { + throw new BuildException("Unable to find stylesheet file."); + } + + bool destOutdated = !destInfo.Exists + || srcInfo.LastWriteTime > destInfo.LastWriteTime + || xsltInfo.LastWriteTime > destInfo.LastWriteTime; + + if (destOutdated) { + XmlReader xmlReader = CreateXmlReader(baseDir, srcFile); + XmlReader xslReader = CreateXmlReader(baseDir, xsltFile); + XmlWriter xmlWriter = CreateXmlWriter(destDir, destFile); + + Log.WriteLine(LogPrefix + "Transforming into " + Path.GetFullPath(destDir)); + + // TODO: remove assignments from conditional statement (gs) + if (xmlReader != null && xslReader != null && xmlWriter != null) { + XslTransform xslt = new XslTransform(); + XPathDocument xml = new XPathDocument(xmlReader); + + Log.WriteLine(LogPrefix + "Loading stylesheet " + Path.GetFullPath(xsltPath)); + try { + xslt.Load(xslReader); + } catch (XsltCompileException xce) { + throw new BuildException(xce.Message, xce); + } catch (Exception e) { + throw new BuildException(e.Message, e); + } + + Log.WriteLine(LogPrefix + "Processing " + Path.GetFullPath(srcPath) + " to " + Path.GetFullPath(destPath)); + try { + xslt.Transform(xml, null, xmlWriter); + } catch (Exception e) { + throw new BuildException(e.Message, e); + } + } else { + // not sure how to deal with this... + // TODO: remove this statement or do something useful (gs) + // Can this condition occur? I would have thought + // that an exception would be thrown. (gs) + } + } + } + } +} diff --git a/nant/src/Tasks/TStampTask.cs b/nant/src/Tasks/TStampTask.cs new file mode 100755 index 00000000..1806a304 --- /dev/null +++ b/nant/src/Tasks/TStampTask.cs @@ -0,0 +1,43 @@ +// NAnt - A .NET build tool +// Copyright (C) 2001 Gerry Shaw +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Gerry Shaw (gerry_shaw@yahoo.com) + +namespace SourceForge.NAnt { + + using System; + using System.IO; + + /// + /// Sets the following properties: + ///
    + ///
  • nant.dateStamp to yyyyMMdd
  • + ///
  • nant.timeStamp to HHmm
  • + ///
  • nant.today using default DataTime.ToString() method
  • + ///
+ ///
+ [TaskName("tstamp")] + public class TStampTask : Task { + protected override void ExecuteTask() { + DateTime now = DateTime.Now; + Log.WriteLine(LogPrefix + now.ToString()); + Project.Properties["nant.dstamp"] = now.ToString("yyyyMMdd"); + Project.Properties["nant.tstamp"] = now.ToString("HHmm"); + Project.Properties["nant.today"] = now.ToString(); + } + } +} diff --git a/nant/src/Tasks/TaskDefTask.cs b/nant/src/Tasks/TaskDefTask.cs new file mode 100755 index 00000000..4c7eca7b --- /dev/null +++ b/nant/src/Tasks/TaskDefTask.cs @@ -0,0 +1,42 @@ +// NAnt - A .NET build tool +// Copyright (C) 2001 Gerry Shaw +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Gerry Shaw (gerry_shaw@yahoo.com) + +namespace SourceForge.NAnt { + + using System; + using System.IO; + + [TaskName("taskdef")] + public class TaskDefTask : Task { + + [TaskAttribute("assembly", Required=true)] + string _assemblyFileName = null; + + protected override void ExecuteTask() { + string assemblyFileName = Project.GetFullPath(_assemblyFileName); + try { + int taskCount = Project.AddTasks(assemblyFileName); + Log.WriteLine(LogPrefix + "Added {0} tasks from {1}", taskCount, assemblyFileName); + } catch (Exception e) { + Log.WriteLine(LogPrefix + "Adding tasks from {0}", assemblyFileName); + throw new BuildException(e.Message, Location, e); + } + } + } +} diff --git a/nant/src/Tasks/VbcTask.cs b/nant/src/Tasks/VbcTask.cs new file mode 100755 index 00000000..4f93787e --- /dev/null +++ b/nant/src/Tasks/VbcTask.cs @@ -0,0 +1,40 @@ +// NAnt - A .NET build tool +// Copyright (C) 2001 Gerry Shaw +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Gerry Shaw (gerry_shaw@yahoo.com) +// Mike Krueger (mike@icsharpcode.net) + +namespace SourceForge.NAnt { + + using System; + using System.IO; + + [TaskName("vbc")] + public class VbcTask : CompilerBase { + + // TODO: add JScript.NET specific compiler options here (see CscTask) + + protected override void WriteOptions(TextWriter writer) { + // TODO: add support for compiler specific options + } + + protected override bool NeedsCompiling() { + // TODO: add checks for any referenced files OR return false to always compile + return base.NeedsCompiling(); + } + } +} diff --git a/nant/src/Util/Log.cs b/nant/src/Util/Log.cs new file mode 100755 index 00000000..b8756630 --- /dev/null +++ b/nant/src/Util/Log.cs @@ -0,0 +1,155 @@ +// NAnt - A .NET build tool +// Copyright (C) 2001 Gerry Shaw +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Gerry Shaw (gerry_shaw@yahoo.com) + +namespace SourceForge.NAnt { + + using System; + using System.Collections; + using System.IO; + using System.Text; + + public class TextWriterCollection : ArrayList { + } + + public class Log { + + static bool _autoFlush = false; + static int _indentLevel = 0; + static int _indentSize = 4; + + static TextWriterCollection _listeners; + + protected Log() { + } + + ~Log() { + // make sure we release any open file handles + Close(); + } + + public static bool AutoFlush { + get { return _autoFlush; } + set { _autoFlush = value; } + } + + public static int IndentLevel { + get { return _indentLevel; } + set { _indentLevel = value; } + } + + public static int IndentSize { + get { return _indentSize; } + set { _indentSize = value; } + } + + public static TextWriterCollection Listeners { + get { + if (_listeners == null) { + _listeners = new TextWriterCollection(); + _listeners.Add(Console.Out); + } + return _listeners; + } + } + + public static void Close() { + foreach (TextWriter writer in Listeners) { + // never close the Console.Out writer + if (writer != Console.Out) { + writer.Close(); + } + } + } + + public static void Flush() { + foreach (TextWriter writer in Listeners) { + writer.Flush(); + } + } + + public static void Indent() { + IndentLevel++; + } + + public static void Unindent() { + if (IndentLevel <= 0) { + throw new InvalidOperationException("IndentLevel must be greater than zero before calling Unindent()"); + } + IndentLevel--; + } + + /// + /// Flag to indicate next string will start on a new line so that it can be indented. + /// + private static bool _newline = true; + + private static void PreprocessValue(ref string value) { + // if we are starting a new line then first indent the string + if (_newline) { + if (IndentLevel > 0) { + StringBuilder sb = new StringBuilder(value); + sb.Insert(0, " ", IndentLevel * IndentSize); + value = sb.ToString(); + } + _newline = false; + } + } + + public static void Write(string value) { + PreprocessValue(ref value); + foreach (TextWriter writer in Listeners) { + writer.Write(value); + } + + if (AutoFlush) { + foreach (TextWriter writer in Listeners) { + writer.Flush(); + } + } + } + + public static void WriteLine() { + WriteLine(String.Empty); + } + + public static void WriteLine(string value) { + PreprocessValue(ref value); + foreach (TextWriter writer in Listeners) { + writer.WriteLine(value); + } + + if (AutoFlush) { + foreach (TextWriter writer in Listeners) { + writer.Flush(); + } + } + + // make sure we indent the next line + _newline = true; + } + + public static void Write(string format, params object[] arg) { + Write(String.Format(format, arg)); + } + + public static void WriteLine(string format, params object[] arg) { + WriteLine(String.Format(format, arg)); + } + } +} \ No newline at end of file diff --git a/nant/src/Util/XmlNodeTextPositionMap.cs b/nant/src/Util/XmlNodeTextPositionMap.cs new file mode 100755 index 00000000..fd10caaf --- /dev/null +++ b/nant/src/Util/XmlNodeTextPositionMap.cs @@ -0,0 +1,187 @@ +// NAnt - A .NET build tool +// Copyright (C) 2001 Gerry Shaw +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Gerry Shaw (gerry_shaw@yahoo.com) + +namespace SourceForge.NAnt { + + using System; + using System.IO; + using System.Text.RegularExpressions; + using System.Xml; + using System.Xml.XPath; + using System.Collections; + + public struct TextPosition { + public static readonly TextPosition InvalidPosition = new TextPosition(-1,-1); + + public TextPosition(int line, int column) { + Line = line; + Column = column; + } + + public int Line; + public int Column; + } + + /// + /// Maps XML nodes to the text positions from their original source. + /// + public class XPathTextPositionMap { + + Hashtable _map = new Hashtable(); + + public XPathTextPositionMap(string url) { + string parentXPath = "/"; // default to root + string previousXPath = ""; + int previousDepth = 0; + + // Load text reader + XmlTextReader reader = new XmlTextReader(url); + ArrayList indexAtDepth = new ArrayList(); + + // Explicitly load document XPath + _map.Add((object) "/", (object) new TextPosition(1, 1)); + + // loop thru all nodes in the document + while (reader.Read()) { + // reader to Node ... + if ( (reader.NodeType.ToString() != "Whitespace") // Ignore those we aren't interested in + && (reader.NodeType.ToString() != "EndElement") + && (reader.NodeType.ToString() != "ProcessingInstruction") + && (reader.NodeType.ToString() != "XmlDeclaration") + ) { + int level = reader.Depth; + string currentXPath = ""; + + // If we arr higher than before + if (reader.Depth < previousDepth) { + // Clear vars for new depth + string[] list = parentXPath.Split('/'); + string newXPath = ""; // once appended to / will be root node ... + + for (int j = 1; j < level+1; j++) { + newXPath += "/" + list[j]; + } + + // higher than before so trim xpath\ + parentXPath = newXPath; // one up from before + + // clear indexes for depth greater than ours + indexAtDepth.RemoveRange(level+1, indexAtDepth.Count - (level+1)); + + } else if (reader.Depth > previousDepth) { + // we are lower + parentXPath = previousXPath; + } + + // End depth setup + // Setup up index array + // add any needed extra items ( usually only 1 ) + // would have uses array but not sure what maximum depth will be beforehand + for (int index = indexAtDepth.Count; index < level+1; index++) { + indexAtDepth.Add(0); + } + // Set child index + if ((int) indexAtDepth[level] == 0) { + // first time thru + indexAtDepth[level] = 1; + } else { + indexAtDepth[level] = (int) indexAtDepth[level] + 1; // lower so append to xpath + } + + // Do actual XPath generation + if (parentXPath.EndsWith("/")) { + currentXPath = parentXPath; + } else { + currentXPath = parentXPath + "/"; // add seperator + } + + // Set the final XPath + currentXPath += "child::node()[" + indexAtDepth[level] + "]"; + + // Add to our hash structures + _map.Add((object) currentXPath, (object) new TextPosition(reader.LineNumber, reader.LinePosition)); + + // setup up loop vars for next iteration + previousXPath = currentXPath; + previousDepth = reader.Depth; + } + } + } + + public TextPosition GetTextPosition(XmlNode node) { + string xpath = GetXPathFromNode(node); + return GetTextPosition(xpath); + } + + public TextPosition GetTextPosition(string xpath) { + TextPosition pos; + if (_map.ContainsKey(xpath)) { + pos = (TextPosition) _map[xpath]; + } else { + pos = TextPosition.InvalidPosition; + } + return pos; + } + + private string GetXPathFromNode(XmlNode node) { + XPathNavigator nav = node.CreateNavigator(); + + string xpath = ""; + int index = 0; + + while (nav.NodeType.ToString() != "Root") { + // loop thru children until we find ourselves + XPathNavigator navParent = nav.Clone(); + navParent.MoveToParent(); + int parentIndex = 0; + navParent.MoveToFirstChild(); + if (navParent.IsSamePosition(nav)) { + index = parentIndex; + } + while (navParent.MoveToNext()) { + parentIndex++; + if (navParent.IsSamePosition(nav)) { + index = parentIndex; + } + } + + nav.MoveToParent(); // do loop condiditon here + + // if we are at doc and index = 0 then there is no xml proc instruction + if ((nav.NodeType.ToString()) != "Root" || (index == 0)) { + index = index + 1; // special case at root to avoid processing instruction .. + } + + string thisNode = "child::node()[" + index + "]"; + + if (xpath == "") { + xpath = thisNode; + } else { + // build xpath string + xpath = thisNode + "/" + xpath; + } + } + + // prepend slash to ... + xpath = "/" + xpath; + + return xpath; + } + } +}