Hi, just joined this list because I'm planning on transitioning our current
build process (which is a big mess of shell scripts under cygwin) over to NAnt.
Thus far I like it a lot, however there was one critical thing which NAnt
didn't do, and which I couldn't find anything indicating how I might do it -
which is to continue the build upon project failure (after running failure
actions such as emailing), rather than just dying on the spot.

As such I fixed it myself (score +10 for Open Source)... If anyone else has
already done this or knows of a more 'normal' means, can you please let me
know, otherwise here's some patches for 0.85-rc2.

With these if you set the nant.resumeonfailure property to anything (true is
nice), then Nant will report a project fail, run the nant.onfailure action, but
then pick up where it left off. It will not rebuild projects which have
previously failed, and if any projects have a dependancy which has previously
failed then they'll be skipped too.

I'm kind of expecting someone to come back and say 'no we don't want that, go
away', but if by some small chance someone wants to include it, if I have to
jump through any hoops before submitting patches (signing agreements/etc) then
could you point me in the right direction? 

Thanks for the great product and for your time, Orion.
--- Project.cs  2005-01-24 03:42:28.000000000 +-1300
+++ Project.cs  2005-02-21 21:22:48.000000000 +-1300
@@ -105,12 +105,13 @@
         internal const string NAntPropertyProjectName = "nant.project.name";
         internal const string NAntPropertyProjectBuildFile = 
"nant.project.buildfile";
         internal const string NAntPropertyProjectBaseDir = 
"nant.project.basedir";
         internal const string NAntPropertyProjectDefault = 
"nant.project.default";
         internal const string NAntPropertyOnSuccess = "nant.onsuccess";
         internal const string NAntPropertyOnFailure = "nant.onfailure";
+               internal const string NAntPropertyResumeOnFailure = 
"nant.resumeonfailure";
 
         #endregion Internal Static Fields
 
         #region Public Instance Events
 
         public event BuildEventHandler BuildStarted;
@@ -875,20 +876,35 @@
             Target callingTarget = _currentTarget;
 
             do {
                 // determine target that should be executed
                 currentTarget = (Target) sortedTargets[currentIndex++];
 
+                               if(currentTarget.ExecuteFailed)
+                               {
+                                       Log(Level.Info,"Skipping Project {0} 
because Dependancy {1} failed",
+                                               targetName,currentTarget.Name);
+                                       break;
+                               }
+
                 // store target that will be executed
                 _currentTarget = currentTarget;
 
                 // only execute targets that have not been executed already, 
if 
                 // we are not forcing.
                 if (forceDependencies || !currentTarget.Executed) {
                     currentTarget.Execute();
                 }
+
+                               if(currentTarget.ExecuteFailed)
+                               {
+                                       Log(Level.Info,"Skipping Project {0} 
because Dependancy {1} failed",
+                                               targetName,currentTarget.Name);
+                                       break;
+                               }
+
             } while (!currentTarget.Name.Equals(targetName));
 
             // restore calling target, as a <call> task might have caused the 
             // current target to be executed and when finished executing this 
             // target, the target that contained the <call> task should be 
             // considered the current target again
--- Target.cs   2004-10-31 05:15:36.000000000 +-1300
+++ Target.cs   2005-02-23 09:43:13.000000000 +-1300
@@ -36,12 +36,13 @@
         private string _name = null;
         private string _description = null;
         private string _ifCondition = null;
         private string _unlessCondition = null;
         private StringCollection _dependencies = new StringCollection();
         private bool _executed = false;
+               private bool _executefailed = false;
 
         #endregion Private Instance Fields
 
         #region Public Instance Constructors
 
         /// <summary>
@@ -57,14 +58,22 @@
         /// <summary>
         /// This indicates whether the target has already executed.
         /// </summary>
         public bool Executed {
             get {
                 return _executed;
-            }
-        }
+            }
+        }
+
+               public bool ExecuteFailed
+               {
+                       get 
+                       {
+                               return _executefailed;
+                       }
+               }
 
         /// <summary>
         /// The name of the target.
         /// </summary>
         /// <remarks>
         ///   <para>
@@ -260,16 +269,29 @@
                         } else {
                             throw new 
BuildException(string.Format(CultureInfo.InvariantCulture, 
                                 "Invalid element <{0}>. Unknown task or 
datatype.", 
                                 childNode.Name), 
Project.LocationMap.GetLocation(childNode));
                         }
                     }
-                } finally {
+                } catch(BuildException ex) {
+                                       
if(Project.Properties[Project.NAntPropertyResumeOnFailure] == null)
+                                       {
+                                               this._executefailed = true;
+                                               throw ex;
+                                       }
+                                       else 
+                                       {
+                                               Log(Level.Warning,"TARGET 
FAILED: {0}\n{1}",_name,ex.RawMessage);
+                                               this._executefailed = true;
+                                               
Project.Execute(Project.Properties[Project.NAntPropertyOnFailure]);
+                                               //keep going
+                                       }
+                               } finally {
                     _executed = true;
                     Project.OnTargetFinished(this, new BuildEventArgs(this));
                 }
             }
         }
 
         #endregion Public Instance Methods
     }
 }

Reply via email to