Hi Ian,

I send you both files for the <record> task. Just tested them with latest version of NAnt and NAntContrib from cvs and they compile and works.

It should find them there. Are you running nant from \build\nant-0.8.3-debug\bin and does the nant.exe.config in that directory contain :
<nantsettings
defaultframework="net-1.0"
taskpath=".\optional">


taskpath allows you specify a ';' seperated list of directories that contain task assemblies. You may need to cvs update nant as well to get the taskpath related changes.

That was it... I was running with the latest nightly build, since i can get code from cvs at work, where i tested it.


Just a question, why if the task path a ';' separated list and not simply child nodes of nantsettings, with a node for each directory ?


Nick



From: Ian MacLean <[EMAIL PROTECTED]>
To: [EMAIL PROTECTED]
CC: "'N. V.'" <[EMAIL PROTECTED]>, [EMAIL PROTECTED], [EMAIL PROTECTED]
Subject: Re: [NAntC-Dev] NAnt.Optional.zip
Date: Thu, 03 Jul 2003 17:14:15 +0900
MIME-Version: 1.0


sorry for the confusion but :

we decided to keep the tasks in NAntcontrib for now and
move a bunch of them into nant - post 0.83 release - see the 'Namespaces and NAnt.Cnntrib tasks' post for details on what tasks will go where.


but don't worry the bullet remains bitten. I've rolled the changes that are in NAnt.optional.zip back into nantcontrib which is now building against current NAnt cvs. We will ship a nant contrib task assembly with nant for the upcoming release.

Nick:

But the record task doesn't work, it simply create an empty file and doesn't loag anything into it. Since I have an updated version, which works with the new logging system, i could sent it to you, after making some minors changes to reflect the namespace changes.

that would be awesome. All I did was comment stuff until it compiled. If you have a version that works with the new logging system just send it to me and I'll commit.

Another thing, I had to move the dll's from the bin\optional directly into bin to have NAnt recognize the tasks.

It should find them there. Are you running nant from \build\nant-0.8.3-debug\bin and does the nant.exe.config in that directory contain :
<nantsettings
defaultframework="net-1.0"
taskpath=".\optional">


taskpath allows you specify a ';' seperated list of directories that contain task assemblies. You may need to cvs update nant as well to get the taskpath related changes.

Ian

further 2 cents:

1) thanks for biting the bullet, very much!
2) does it make sense that nantcontrib ends up in a single dll as
opposed to several dlls, smaller, per task set?  seems to me it might
complicate the configuration a little bit more, but would yield easier
to handle subproject (eg: if one task is broken, the whole thing isn't
broken...)

/jean



-----Original Message-----
From: [EMAIL PROTECTED] [mailto:[EMAIL PROTECTED] On Behalf Of N. V.
Sent: Wednesday, July 02, 2003 17:37
To: [EMAIL PROTECTED]; [EMAIL PROTECTED]; [EMAIL PROTECTED]
Subject: Re: [NAntC-Dev] NAnt.Optional.zip



Hi Ian,


I just tested this, with my build files which uses vssget, sql and record task and the vssget and sql task works fines (i prefered when the sql task wasn't writting every params to the the Console, but that's not really a problem).



Another thing, I had to move the dll's from the bin\optional directly into bin to have NAnt recognize the tasks.



Nick




From: Ian MacLean <[EMAIL PROTECTED]>
To: [EMAIL PROTECTED], [EMAIL PROTECTED]
Subject: [NAntC-Dev] NAnt.Optional.zip
Date: Sun, 29 Jun 2003 20:08:22 +0900


grab it from http://www26.brinkster.com/ianm74/NAnt.Optional.zip

unzip it under nant\src and add the following line to TaskAssemblies.txt : NAnt.Optional

then just run the main nant build.
this creates a new folder optional under build\nant-0.8.3-debug\bin with
the optional tasks dll and its dependencies. If you run the

newly built

NAnt it will load the optional tasks as well as the core

ones. I just got

it compiling and tested a few of the tasks. Please try it

out and let me

know if anything is broken.


Ian



_________________________________________________________________
MSN Messenger : discutez en direct avec vos amis ! http://messenger.fr.msn.ca/
//
// NAntContrib
// Copyright (C) 2002 Tomas Restrepo ([EMAIL PROTECTED])
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library 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
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
//

using System;
using System.Collections;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Text;
using NAnt.Core.Attributes;
using NAnt.Core;

namespace NAnt.Contrib.Util
{

        #region IRecorder interface
  /// <summary>
  /// Recorder interface user with the Record task
  /// </summary>
  public interface IRecorder
  {
     /// <summary>
     /// Name of this recorder (possibly a file name)
     /// </summary>
     string Name {
        get;
     }

     /// <summary>
     /// Underlying LogListener instance
     /// </summary>
     IBuildLogger Logger {
        get;
     }

     /// <summary>
     /// Define whether the underlying writer is AutoFlushed or not
     /// </summary>
     bool AutoFlush {
         get;
         set;
     }

     /// <summary>Start Recording</summary>
     void Start();
     /// <summary>Stop Recording</summary>
     void Stop();
     /// <summary>Close the recorder</summary>
     void Close();
     /// <summary>Flush the recorder</summary>
     void Flush();

  } // interface IRecorder
        #endregion IRecorder interface

        #region class RecorderCollection
  /// <summary>
  /// Keeps track of used recorders
  /// </summary>
  internal class RecorderCollection
  {
     private Hashtable _list;

     public RecorderCollection()
     {
        _list = new Hashtable();
     }

     public void AddRecorder(IRecorder recorder)
     {
        _list.Add(recorder.Name, recorder);
     }
     public IRecorder GetRecorder(string name)
     {
        if ( _list.ContainsKey(name) )
           return (IRecorder)_list[name];
        else
           return null;
     }
     public void RemoveRecorder(string name)
     {
        if ( _list.ContainsKey(name) )
           _list.Remove(name);
     }

  } // class RecorderCollection
        #endregion class RecorderCollection


internal class FileLogListener : IBuildLogger, IRecorder { #region Public Instance Constructors

                         /// <summary>
                         /// Initializes a new instance of the <see cref="DefaultLogger" 
/>
                         /// class.
                         /// </summary>
                         public FileLogListener(string name)
                         {
                                 _name = name;
                                 _stopped = true;
                                 _threshold = Level.Info;
                                 _outputWriter = null;
                                 _autoFlush = false;
                         }

#endregion Public Instance Constructors

#region Implementation of IBuildLogger

/// <summary>
/// Gets or sets the highest level of message this logger should respond
/// to.
/// </summary>
/// <value>The highest level of message this logger should respond to.</value>
/// <remarks>
/// Only messages with a message level higher than or equal to the given
/// level should be written to the log.
/// </remarks>
public virtual Level Threshold
{
get { return _threshold; }
set { _threshold = value; }
}


                         /// <summary>
                         /// Gets or sets the <see cref="TextWriter" /> to which the 
logger is
                         /// to send its output.
                         /// </summary>
                         public virtual TextWriter OutputWriter
                         {
                                 get { return _outputWriter; }
                                 set { _outputWriter = value; }
                         }

                         /// <summary>
                         /// Flushes buffered build events or messages to the 
underlying storage.
                         /// </summary>
                         public virtual void Flush()
                         {
                                 if(OutputWriter == null)
                                         return;
                                 OutputWriter.Flush();
                         }

#endregion Implementation of IBuildLogger

#region Implementation of IBuildListener

/// <summary>
/// Signals that a build has started.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">A <see cref="BuildEventArgs" /> object that contains the event data.</param>
/// <remarks>
/// This event is fired before any targets have started.
/// </remarks>
public virtual void BuildStarted(object sender, BuildEventArgs e)
{
}


/// <summary>
/// Signals that the last target has finished.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">A <see cref="BuildEventArgs" /> object that contains the event data.</param>
/// <remarks>
/// This event will still be fired if an error occurred during the build.
/// </remarks>
public virtual void BuildFinished(object sender, BuildEventArgs e)
{
Exception error = e.Exception;
int indentationLevel = 0;


if (e.Project != null)
{
indentationLevel = e.Project.IndentationLevel * e.Project.IndentationSize;
}


                                 if (error == null)
                                 {
                                         OutputMessage(Level.Info, "", 
indentationLevel);
                                         OutputMessage(Level.Info, "BUILD SUCCEEDED", 
indentationLevel);
                                         OutputMessage(Level.Info, "", 
indentationLevel);
                                 }
                                 else
                                 {
                                         OutputMessage(Level.Error, "", 
indentationLevel);
                                         OutputMessage(Level.Error, "BUILD FAILED", 
indentationLevel);
                                         OutputMessage(Level.Error, "", 
indentationLevel);

if (error is BuildException)
{
if (Threshold <= Level.Verbose)
{
OutputMessage(Level.Error, error.ToString(), indentationLevel);
}
else
{
if (error.Message != null)
{
OutputMessage(Level.Error, error.Message, indentationLevel);
}
if (error.InnerException != null && error.InnerException.Message != null)
{
OutputMessage(Level.Error, error.InnerException.Message, indentationLevel);
}
}
}
else
{
OutputMessage(Level.Error, "INTERNAL ERROR", indentationLevel);
OutputMessage(Level.Error, "", indentationLevel);
OutputMessage(Level.Error, error.ToString(), indentationLevel);
OutputMessage(Level.Error, "", indentationLevel);
OutputMessage(Level.Error, "Please send bug report to [EMAIL PROTECTED]", indentationLevel);
}


                                         OutputMessage(Level.Info, "", 
indentationLevel);
                                 }

                                 // make sure all messages are written to the 
underlying storage
                                 Flush();
                         }

/// <summary>
/// Signals that a target has started.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">A <see cref="BuildEventArgs" /> object that contains the event data.</param>
public virtual void TargetStarted(object sender, BuildEventArgs e)
{
int indentationLevel = 0;


if (e.Project != null)
{
indentationLevel = e.Project.IndentationLevel * e.Project.IndentationSize;
}


                                 if (e.Target != null)
                                 {
                                         OutputMessage(Level.Info, string.Empty, 
indentationLevel);
                                         OutputMessage(
                                                 Level.Info,
                                                 string.Format(CultureInfo.InvariantCulture, 
"{0}:", e.Target.Name),
                                                 indentationLevel);
                                         OutputMessage(Level.Info, string.Empty, 
indentationLevel);
                                 }
                         }

/// <summary>
/// Signals that a task has finished.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">A <see cref="BuildEventArgs" /> object that contains the event data.</param>
/// <remarks>
/// This event will still be fired if an error occurred during the build.
/// </remarks>
public virtual void TargetFinished(object sender, BuildEventArgs e)
{
}


/// <summary>
/// Signals that a task has started.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">A <see cref="BuildEventArgs" /> object that contains the event data.</param>
public virtual void TaskStarted(object sender, BuildEventArgs e)
{
}


/// <summary>
/// Signals that a task has finished.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">A <see cref="BuildEventArgs" /> object that contains the event data.</param>
/// <remarks>
/// This event will still be fired if an error occurred during the build.
/// </remarks>
public virtual void TaskFinished(object sender, BuildEventArgs e)
{
}


/// <summary>
/// Signals that a message has been logged.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">A <see cref="BuildEventArgs" /> object that contains the event data.</param>
/// <remarks>
/// Only messages with a priority higher or equal to the threshold of
/// the logger will actually be output in the build log.
/// </remarks>
public virtual void MessageLogged(object sender, BuildEventArgs e)
{
int indentationLength = 0;


// calculate indentation length from Project
if (e.Project != null)
{
indentationLength = e.Project.IndentationLevel * e.Project.IndentationSize;
}


                                 // output the message
                                 OutputMessage(e.MessageLevel, e.Message, 
indentationLength);
                         }

#endregion Implementation of IBuildListener

#region Implementation of IRecorder

                         public string Name
                         {
                                 get { return _name; }
                         }
                         public IBuildLogger Logger
                         {
                                 get { return this; }
                         }
                         public bool AutoFlush
                         {
                                 get { return _autoFlush; }
                                 set
                                 {
                                         _autoFlush = value;
                                         if(_outputWriter == null)
                                                 return;
                                         ((StreamWriter)_outputWriter).AutoFlush = 
value;
                                 }
                         }
                         public void Start()
                         {
                                 _stopped = false;
                                 if(_outputWriter == null)
                                         _outputWriter = new 
StreamWriter(File.OpenWrite(_name));
                                 ((StreamWriter)_outputWriter).AutoFlush = _autoFlush;
                         }
                         public void Stop()
                         {
                                 _stopped = true;
                         }
                         public void Close()
                         {
                                 Stop();
                                 _outputWriter.Close();
                                 _outputWriter = null;
                         }
     #endregion Implementation of IRecorder

#region Protected Instance Methods

                         /// <summary>
                         /// Empty implementation which allows derived classes to 
receive the
                         /// output that is generated in this logger.
                         /// </summary>
                         /// <param name="message">The message being logged.</param>
                         protected virtual void Log(string message)
                         {
                         }

#endregion Protected Instance Methods

#region Private Instance Methods

/// <summary>
/// Outputs an indented message to the build log if its priority is
/// greather than or equal to the <see cref="Threshold" /> of the
/// logger.
/// </summary>
/// <param name="mesageLevel">The priority of the message to output.</param>
/// <param name="message">The message to output.</param>
/// <param name="indentationLength">The number of characters that the message should be indented.</param>
private void OutputMessage(Level mesageLevel, string message, int indentationLength)
{
string indentedMessage = null;


if(!_stopped && (mesageLevel >= Threshold))
{
if ( OutputWriter == null )
throw new BuildException("Tried to write to an invalid FileLogListener instance!");


                                         if (indentationLength > 0)
                                         {
                                                 StringBuilder sb = new 
StringBuilder(message);
                                                 sb.Insert(0, " ", indentationLength);
                                                 indentedMessage = sb.ToString();
                                         }
                                         else
                                         {
                                                 indentedMessage = message;
                                         }

                                         // output the message to the console
//                                       Console.Out.WriteLine(indentedMessage);

//                                       // if an OutputWriter was set, write the 
message to it
//                                       if (OutputWriter != null)
//                                       {
                                                 
OutputWriter.WriteLine(indentedMessage);
//                                       }

                                         Log(indentedMessage);
                                 }
                         }

#endregion Private Instance Methods

#region Private Instance Fields

                         private Level _threshold = Level.Info;
                         private TextWriter _outputWriter = null;
                         private string _name = string.Empty;
                         private bool _stopped = true;
                         private bool _autoFlush = false;

       #endregion Private Instance Fields
                 }
} // namespace NAnt.Contrib.Util
//
// NAntContrib
// Copyright (C) 2002 Tomas Restrepo ([EMAIL PROTECTED])
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
//
// This library 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
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
//

using System;
using System.Collections;
using System.IO;
using System.Reflection;
using System.Text;
using NAnt.Core.Attributes;
using NAnt.Core;

using NAnt.Contrib.Util;

namespace NAnt.Contrib.Tasks
{

/// <summary>
/// A task that records the build's output
/// to a file. Loosely based on Ant's Record task.
/// </summary>
/// <remarks>
/// This task allows you to record the build's output,
/// or parts of it to a file. You can start and stop
/// recording at any place in the build process.
/// </remarks>
/// <example>
/// <code><![CDATA[
/// <record name="${outputdir}\Buildlog.txt" level="info" action="Start"/>
/// <record name="${outputdir}\Buildlog.txt" action="Close"/>
/// ]]></code>
/// </example>
[TaskName("record")]
public class RecordTask : Task
{
//
// valid actions
//
enum Actions
{
Start = 0,
Stop = 1,
Close = 2,
Flush = 3
}


                private string _logname;
                private Actions _action;
                static RecorderCollection _recorders = new RecorderCollection();
                private bool _autoFlush = false;
                private Level _thresholdLevel = Level.Info;
                private bool _autoFlushSet = false;
                private bool _thresholdLevelSet = false;

                /// <summary>
                /// Name of Destination file.
                /// </summary>
                [TaskAttribute("name", Required=true)]
                public string LogName
                {
                        get { return _logname; }
                        set { _logname = value; }
                }

                /*      /// <summary>
                                        /// Whether to append to the destination file 
(true),
                                        /// or replace it (false). Default is false.
                                        /// </summary>
                                        [TaskAttribute("append")]
                                        public string Append {
                                                        get { return 
_append.ToString(); }
                                                        set { _append = 
bool.Parse(value); }
                                        }
                                        */

/// <summary>
/// Action to apply to this log instance
/// </summary>
/// <remarks>It can take on of the following values: start, stop, close, flush</remarks>
[TaskAttribute("action", Required=true)]
public string Action
{
get { return _action.ToString(); }
set { _action = (Actions)Enum.Parse(typeof(Actions), value); }
}


                /// <summary>
                /// Determines whether the recorder will flush it's buffer
                /// after every write to it.
                /// Default value is false
                /// </summary>
                /// <remarks>Effective only with the start action</remarks>
                [TaskAttribute("autoflush", Required=false)]
                [BooleanValidator()]
                public bool AutoFlush
                {
                        get { return _autoFlush; }
                        set { _autoFlush = value; }
                }

/// <summary>
/// Determine the level of logging. default value is <b>info</b>
/// </summary>
/// <remarks>It can takes the following values: error, warning, info, verbose, debug</remarks>
/// <remarks>Effective only with the start action</remarks>
[TaskAttribute("level", Required=false)]
public string ThresholdLevel
{
get{ return this._thresholdLevel.ToString(); }
set{ this._thresholdLevel = (Level)Enum.Parse(typeof(Level), value); }
}



///<summary>
///Initializes task and ensures the supplied attributes are valid.
///</summary>
///<param name="taskNode">Xml node used to define this task instance.</param>
protected override void InitializeTask(System.Xml.XmlNode taskNode)
{
if (LogName == null) {
throw new BuildException("Record attribute \"name\" is required.", Location);
}
if (Action == null) {
throw new BuildException("Record attribute \"action\" is required.", Location);
}


                                _autoFlushSet = (taskNode.Attributes["autoflush"] != 
null);
                                _thresholdLevelSet = (taskNode.Attributes["level"] != 
null);
     }

     /// <summary>
     /// This is where the work is done
     /// </summary>
     protected override void ExecuteTask()
     {
        IRecorder recorder = _recorders.GetRecorder(LogName);

switch ( _action )
{
case Actions.Start:
if ( recorder == null ) {
recorder = new FileLogListener(LogName);
_recorders.AddRecorder(recorder);
}
if(_autoFlushSet)
recorder.AutoFlush = _autoFlush;
if(_thresholdLevelSet)
recorder.Logger.Threshold = _thresholdLevel;
recorder.Start();
AttachRecorder(recorder);
break;
case Actions.Stop:
if ( recorder == null )
throw new BuildException("Tried to stop non-existent recorder");
DetachRecorder(recorder);
recorder.Stop();
break;
case Actions.Close:
if ( recorder == null )
throw new BuildException("Tried to close non-existent recorder");
DetachRecorder(recorder);
recorder.Close();
_recorders.RemoveRecorder(recorder.Name);
break;
case Actions.Flush:
if ( recorder == null )
throw new BuildException("Tried to flush non-existent recorder");
recorder.Flush();
break;
}


}

                private void DetachRecorder(IRecorder recorder)
                {
                        IBuildLogger logger = recorder.Logger;

                        // unhook up to build events
                        Project.BuildStarted -= new 
BuildEventHandler(logger.BuildStarted);
                        Project.BuildFinished -= new 
BuildEventHandler(logger.BuildFinished);
                        Project.TargetStarted -= new 
BuildEventHandler(logger.TargetStarted);
                        Project.TargetFinished -= new 
BuildEventHandler(logger.TargetFinished);
                        Project.TaskStarted -= new 
BuildEventHandler(logger.TaskStarted);
                        Project.TaskFinished -= new 
BuildEventHandler(logger.TaskFinished);
                        Project.MessageLogged -= new 
BuildEventHandler(logger.MessageLogged);

                        if(Project.BuildListeners.Contains(logger))
                                Project.BuildListeners.Remove(logger);
                }

                private void AttachRecorder(IRecorder recorder)
                {
                        DetachRecorder(recorder);

IBuildLogger logger = recorder.Logger;

                        // hook up to build events
                        Project.BuildStarted += new 
BuildEventHandler(logger.BuildStarted);
                        Project.BuildFinished += new 
BuildEventHandler(logger.BuildFinished);
                        Project.TargetStarted += new 
BuildEventHandler(logger.TargetStarted);
                        Project.TargetFinished += new 
BuildEventHandler(logger.TargetFinished);
                        Project.TaskStarted += new 
BuildEventHandler(logger.TaskStarted);
                        Project.TaskFinished += new 
BuildEventHandler(logger.TaskFinished);
                        Project.MessageLogged += new 
BuildEventHandler(logger.MessageLogged);

                        Project.BuildListeners.Add(logger);
                }


} // class RecordTask


} // namespace NAnt.Contrib.Tasks



Reply via email to