Merge pull request #600 from tr8dr/master
[mono.git] / mcs / class / Microsoft.Build.Engine / Microsoft.Build.BuildEngine / TaskBatchingImpl.cs
1 //
2 // TaskBatchingImpl.cs: Class that implements Task Batching Algorithm from the wiki.
3 //
4 // Author:
5 //   Marek Sieradzki (marek.sieradzki@gmail.com)
6 //   Ankit Jain (jankit@novell.com)
7 //
8 // (C) 2005 Marek Sieradzki
9 // Copyright 2008 Novell, Inc (http://www.novell.com)
10 // Copyright 2009 Novell, Inc (http://www.novell.com)
11 //
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
19 //
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
22 //
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30
31 using System;
32 using System.Collections.Generic;
33 using System.Xml;
34
35 namespace Microsoft.Build.BuildEngine {
36         internal class TaskBatchingImpl : BatchingImplBase
37         {
38                 public TaskBatchingImpl (Project project)
39                         : base (project)
40                 {
41                 }
42
43                 public bool Build (IBuildTask buildTask, out bool executeOnErrors)
44                 {
45                         executeOnErrors = false;
46                         try {
47                                 Init ();
48
49                                 // populate list of referenced items and metadata
50                                 ParseTaskAttributes (buildTask);
51                                 if (consumedMetadataReferences.Count == 0) {
52                                         // No batching required
53                                         if (ConditionParser.ParseAndEvaluate (buildTask.Condition, project))
54                                                 return buildTask.Execute ();
55                                         else // skipped, it should be logged
56                                                 return true;
57                                 }
58
59                                 BatchAndPrepareBuckets ();
60                                 return Run (buildTask, out executeOnErrors);
61                         } finally {
62                                 consumedItemsByName = null;
63                                 consumedMetadataReferences = null;
64                                 consumedQMetadataReferences = null;
65                                 consumedUQMetadataReferences = null;
66                                 batchedItemsByName = null;
67                                 commonItemsByName = null;
68                         }
69                 }
70
71                 bool Run (IBuildTask buildTask, out bool executeOnErrors)
72                 {
73                         executeOnErrors = false;
74
75                         // Run the task in batches
76                         bool retval = true;
77                         if (buckets.Count == 0) {
78                                 // batched mode, but no values in the corresponding items!
79                                 if (ConditionParser.ParseAndEvaluate (buildTask.Condition, project)) {
80                                         retval = buildTask.Execute ();
81                                         if (!retval && !buildTask.ContinueOnError)
82                                                 executeOnErrors = true;
83                                 }
84
85                                 return retval;
86                         }
87
88                         // batched
89                         foreach (Dictionary<string, BuildItemGroup> bucket in buckets) {
90                                 project.PushBatch (bucket, commonItemsByName);
91                                 try {
92                                         if (ConditionParser.ParseAndEvaluate (buildTask.Condition, project)) {
93                                                  retval = buildTask.Execute ();
94                                                  if (!retval && !buildTask.ContinueOnError) {
95                                                         executeOnErrors = true;
96                                                         break;
97                                                  }
98                                         }
99                                 } finally {
100                                         project.PopBatch ();
101                                 }
102                         }
103
104                         return retval;
105                 }
106
107
108                 // Parse task attributes to get list of referenced metadata and items
109                 // to determine batching
110                 //
111                 void ParseTaskAttributes (IBuildTask buildTask)
112                 {
113                         foreach (var attr in buildTask.GetAttributes ()) {
114                                 ParseAttribute (attr);
115                         }
116                 }
117         }
118
119 }