Merge pull request #2720 from mono/fix-39325
[mono.git] / mcs / class / Microsoft.Build / Microsoft.Build.Execution / BuildManager.cs
index 3b4384b2f6be94c43f17d8d86dc91be4e277e9e4..c295d3ba67f30a6ead7b70938f594380a009c5f6 100644 (file)
@@ -2,8 +2,9 @@
 //
 // Author:
 //   Rolf Bjarne Kvinge (rolf@xamarin.com)
+//   Atsushi Enomoto (atsushi@xamarin.com)
 //
-// Copyright (C) 2011 Xamarin Inc.
+// Copyright (C) 2011,2013 Xamarin Inc.
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // a copy of this software and associated documentation files (the
 //
 
 using Microsoft.Build.Evaluation;
-
 using System;
+using System.Collections.Generic;
+using System.Threading;
+using Microsoft.Build.Internal;
+using System.Linq;
 
 namespace Microsoft.Build.Execution
 {
-        public class BuildManager
-        {
-                public BuildManager ()
-                {
-                        throw new NotImplementedException ();
-                }
+       public class BuildManager
+       {
+               static BuildManager default_manager = new BuildManager ();
 
-                public BuildManager (string hostName)
-                {
-                        throw new NotImplementedException ();
-                }
+               public static BuildManager DefaultBuildManager {
+                       get { return default_manager; }
+               }
+               
+               public BuildManager ()
+               {
+               }
 
-                public void BeginBuild (BuildParameters parameters)
-                {
-                        throw new NotImplementedException ();
-                }
+               public BuildManager (string hostName)
+               {
+                       throw new NotImplementedException ();
+               }
+               
+               public void Dispose ()
+               {
+                       if (submissions.Count > 0)
+                               WaitHandle.WaitAll (submissions.Select (s => s.WaitHandle).ToArray ());
+                       BuildNodeManager.Stop ();
+               }
 
-                public BuildResult Build (BuildParameters parameters, BuildRequestData requestData)
-                {
-                        throw new NotImplementedException ();
-                }
+               ~BuildManager ()
+               {
+                       // maybe processes created by out-of-process nodes should be signaled.
+               }
 
-                public BuildResult BuildRequest (BuildRequestData requestData)
-                {
-                        throw new NotImplementedException ();
-                }
+               readonly List<BuildSubmission> submissions = new List<BuildSubmission> ();
+               
+               BuildParameters ongoing_build_parameters;
+               
+               internal BuildParameters OngoingBuildParameters {
+                       get { return ongoing_build_parameters; }
+               }
 
-                public void CancelAllSubmissions ()
-                {
-                        throw new NotImplementedException ();
-                }
+               public void BeginBuild (BuildParameters parameters)
+               {
+                       if (ongoing_build_parameters != null)
+                               throw new InvalidOperationException ("There is already ongoing build");
+                       ongoing_build_parameters = parameters.Clone ();
+               }
 
-                public void EndBuild ()
-                {
-                        throw new NotImplementedException ();
-                }
+               public BuildResult Build (BuildParameters parameters, BuildRequestData requestData)
+               {
+                       BeginBuild (parameters);
+                       var ret = BuildRequest (requestData);
+                       EndBuild ();
+                       return ret;
+               }
 
-                public ProjectInstance GetProjectInstanceForBuild (Project project)
-                {
-                        throw new NotImplementedException ();
-                }
+               public BuildResult BuildRequest (BuildRequestData requestData)
+               {
+                       var sub = PendBuildRequest (requestData);
+                       sub.Execute ();
+                       return sub.BuildResult;
+               }
+               
+               public void CancelAllSubmissions ()
+               {
+                       foreach (var sub in submissions) {
+                               try {
+                                       if (!sub.IsCompleted)
+                                               sub.Cancel ();
+                               } catch (InvalidOperationException) {
+                                       // some submissions could be already done during this iteration. Ignore that.
+                               }
+                       }
+                       submissions.Clear ();
+               }
 
-                public BuildSubmission PendBuildRequest (BuildRequestData requestData)
-                {
-                        throw new NotImplementedException ();
-                }
+               public void EndBuild ()
+               {
+                       if (ongoing_build_parameters == null)
+                               throw new InvalidOperationException ("Build has not started");
+                       if (submissions.Count > 0)
+                               WaitHandle.WaitAll (submissions.Select (s => s.WaitHandle).ToArray ());
+                       ongoing_build_parameters = null;
+               }
+               
+               Dictionary<Project,ProjectInstance> instances = new Dictionary<Project, ProjectInstance> ();
 
-                public void ResetCaches ()
-                {
-                        throw new NotImplementedException ();
-                }
+               public ProjectInstance GetProjectInstanceForBuild (Project project)
+               {
+                       if (project == null)
+                               throw new ArgumentNullException ("project");
+                       if (project.FullPath == null)
+                               throw new ArgumentNullException ("project", "FullPath parameter in the project cannot be null.");
+                       if (project.FullPath == string.Empty)
+                               throw new ArgumentException ("FullPath parameter in the project cannot be empty.", "project");
+                       // other than that, any invalid path character is accepted...
+                       
+                       return GetProjectInstanceForBuildInternal (project);
+               }
+                       
+               internal ProjectInstance GetProjectInstanceForBuildInternal (Project project)
+               {
+                       if (!instances.ContainsKey (project))
+                               instances [project] = project.CreateProjectInstance ();
+                       return instances [project];
+               }
 
-                public static BuildManager DefaultBuildManager {
-                        get { throw new NotImplementedException (); }
-                }
-        }
-}
+               public BuildSubmission PendBuildRequest (BuildRequestData requestData)
+               {
+                       if (ongoing_build_parameters == null)
+                               throw new InvalidOperationException ("This method cannot be called before calling BeginBuild method.");
+                       var sub = new BuildSubmission (this, requestData);
+                       submissions.Add (sub);
+                       return sub;
+               }
 
+               public void ResetCaches ()
+               {
+                       if (OngoingBuildParameters != null)
+                               throw new InvalidOperationException ("Cannot reset caches while builds are in progress.");
+                       
+                       BuildNodeManager.ResetCaches ();
+               }
+               
+               BuildNodeManager build_node_manager;
+               
+               internal BuildNodeManager BuildNodeManager {
+                       get {
+                               if (build_node_manager == null)
+                                               build_node_manager = new BuildNodeManager (this);
+                               return build_node_manager;
+                       }
+               }
+       }
+}