/// <summary>
        /// Determines equivalence with another object of the same type.
        /// </summary>
        /// <param name="other">The other object with which to compare this one.</param>
        /// <returns>True if the objects are equivalent, false otherwise.</returns>
        private bool InternalEquals(FullyQualifiedBuildRequest other)
        {
            if (Object.ReferenceEquals(this, other))
            {
                return(true);
            }

            if (_requestConfiguration != other._requestConfiguration)
            {
                return(false);
            }

            if (_resultsNeeded != other._resultsNeeded)
            {
                return(false);
            }

            if (_targets.Length != other._targets.Length)
            {
                return(false);
            }

            for (int i = 0; i < _targets.Length; ++i)
            {
                if (_targets[i] != other._targets[i])
                {
                    return(false);
                }
            }

            return(true);
        }
 public void TestConstructorBad1()
 {
     Assert.Throws<ArgumentNullException>(() =>
     {
         FullyQualifiedBuildRequest request = new FullyQualifiedBuildRequest(null, new string[1] { "foo" }, true);
     }
    );
 }
 public void TestConstructorBad2()
 {
     Assert.Throws<ArgumentNullException>(() =>
     {
         FullyQualifiedBuildRequest request = new FullyQualifiedBuildRequest(new BuildRequestConfiguration(new BuildRequestData("foo", new Dictionary<string, string>(), "tools", new string[0], null), "2.0"), null, true);
     }
    );
 }
        public void TestConstructorGood()
        {
            BuildRequestData data1 = new BuildRequestData("foo", new Dictionary<string, string>(), "tools", new string[0], null);
            FullyQualifiedBuildRequest request = new FullyQualifiedBuildRequest(new BuildRequestConfiguration(data1, "2.0"), new string[1] { "foo" }, true);

            request = new FullyQualifiedBuildRequest(new BuildRequestConfiguration(data1, "2.0"), new string[0] { }, true);

            BuildRequestData data3 = new BuildRequestData("foo", new Dictionary<string, string>(), "tools", new string[0], null);
            request = new FullyQualifiedBuildRequest(new BuildRequestConfiguration(data1, "2.0"), new string[0] { }, false);
        }
 public void TestProperties()
 {
     BuildRequestData data = new BuildRequestData("foo", new Dictionary<string, string>(), "tools", new string[0], null);
     BuildRequestConfiguration config = new BuildRequestConfiguration(data, "2.0");
     FullyQualifiedBuildRequest request = new FullyQualifiedBuildRequest(config, new string[1] { "foo" }, true);
     Assert.AreEqual(request.Config, config);
     Assert.AreEqual(request.Targets.Length, 1);
     Assert.AreEqual(request.Targets[0], "foo");
     Assert.AreEqual(request.ResultsNeeded, true);
 }
Esempio n. 6
0
        /// <summary>
        /// Determines equivalence with another object of the same type.
        /// </summary>
        /// <param name="other">The other object with which to compare this one.</param>
        /// <returns>True if the objects are equivalent, false otherwise.</returns>
        private bool InternalEquals(FullyQualifiedBuildRequest other)
        {
            if (ReferenceEquals(this, other))
            {
                return(true);
            }

            if (Config != other.Config)
            {
                return(false);
            }

            if (ResultsNeeded != other.ResultsNeeded)
            {
                return(false);
            }

            if (BuildRequestDataFlags != other.BuildRequestDataFlags)
            {
                return(false);
            }

            if (Targets.Length != other.Targets.Length)
            {
                return(false);
            }

            for (int i = 0; i < Targets.Length; ++i)
            {
                if (Targets[i] != other.Targets[i])
                {
                    return(false);
                }
            }

            return(true);
        }
 public void TestConstructorBad2()
 {
     FullyQualifiedBuildRequest request = new FullyQualifiedBuildRequest(new BuildRequestConfiguration(new BuildRequestData("foo", new Dictionary<string, string>(), "tools", new string[0], null), "2.0"), null, true);
 }
Esempio n. 8
0
 /// <summary>
 /// Create a new unsubmitted request entry
 /// </summary>
 /// <param name="sourceEntry">The build request originating these requests.</param>
 /// <param name="newRequests">The new requests to be issued.</param>
 public PendingUnsubmittedBuildRequests(BuildRequestEntry sourceEntry, FullyQualifiedBuildRequest[] newRequests)
 {
     this.SourceEntry = sourceEntry;
     this.NewRequests = newRequests;
     this.BlockingGlobalRequestId = BuildRequest.InvalidGlobalRequestId;
     this.BlockingTarget = null;
 }
Esempio n. 9
0
        /// <summary>
        /// Gets the results uses to continue the current build request.
        /// </summary>
        private BuildResult[] GetResultsForContinuation(FullyQualifiedBuildRequest[] requests, bool isContinue)
        {
            IDictionary<int, BuildResult> results;
            results = _continueResults;
            _continueResults = null;
            if (results == null)
            {
                // This catches the case where an MSBuild call is making a series of non-parallel build requests after Cancel has been
                // invoked.  In this case, the wait above will immediately fall through and there will be no results.  We just need to be
                // sure that we return a complete set of results which indicate we are aborting.
                ErrorUtilities.VerifyThrow(!isContinue, "Unexpected null results during continue");
                results = new Dictionary<int, BuildResult>();
                for (int i = 0; i < requests.Length; i++)
                {
                    results[i] = new BuildResult(new BuildRequest(), new BuildAbortedException());
                }
            }

            // See if we got any exceptions we should throw.
            foreach (BuildResult result in results.Values)
            {
                if (result.CircularDependency)
                {
                    throw new CircularDependencyException();
                }
            }

            // The build results will have node request IDs in the same order as the requests were issued,
            // which is in the array order above.
            List<BuildResult> resultsList = new List<BuildResult>(results.Values);
            resultsList.Sort(delegate (BuildResult left, BuildResult right)
            {
                if (left.NodeRequestId < right.NodeRequestId)
                {
                    return -1;
                }
                else if (left.NodeRequestId == right.NodeRequestId)
                {
                    return 0;
                }

                return 1;
            });

            return resultsList.ToArray();
        }
 public void TestConstructorBad1()
 {
     FullyQualifiedBuildRequest request = new FullyQualifiedBuildRequest(null, new string[1] { "foo" }, true);
 }
Esempio n. 11
0
        private void NewBuildRequestsCallback(BuildRequestEntry entry, FullyQualifiedBuildRequest[] requests)
        {
            _newBuildRequests_FQRequests = requests;
            _newBuildRequests_BuildRequests = new BuildRequest[requests.Length];
            _newBuildRequests_Entry = entry;

            int index = 0;
            foreach (FullyQualifiedBuildRequest request in requests)
            {
                IConfigCache configCache = (IConfigCache)_host.GetComponent(BuildComponentType.ConfigCache);
                BuildRequestConfiguration matchingConfig = configCache.GetMatchingConfiguration(request.Config);
                BuildRequest newRequest = CreateNewBuildRequest(matchingConfig.ConfigurationId, request.Targets);

                entry.WaitForResult(newRequest);
                _newBuildRequests_BuildRequests[index++] = newRequest;
            }
            _newBuildRequestsEvent.Set();
        }
Esempio n. 12
0
 internal void SetNewBuildRequests(FullyQualifiedBuildRequest[] requests)
 {
     _newRequests = requests;
 }
Esempio n. 13
0
        /// <summary>
        /// Thread to process the build request
        /// </summary>
        private void BuilderThreadProc()
        {
            bool completeSuccess = true;
            WaitHandle[] handles = new WaitHandle[2] { _cancelEvent, _continueEvent };

            _threadStarted.Set();

            // Add a request for each of the referenced projects. All we need to do is to make sure that the new project definition for the referenced
            // project has been added to the host collection

            FullyQualifiedBuildRequest[] fq = new FullyQualifiedBuildRequest[_currentProjectDefinition.ChildDefinitions.Count];
            int fqCount = 0;
            foreach (RequestDefinition childDefinition in _currentProjectDefinition.ChildDefinitions)
            {
                BuildRequestConfiguration unresolvedConfig = childDefinition.UnresolvedConfiguration;
                fq[fqCount++] = new FullyQualifiedBuildRequest(unresolvedConfig, childDefinition.TargetsToBuild, true);
            }

            try
            {
                // Check to see if there was a cancel before we do anything
                if (_cancelEvent.WaitOne(1, false))
                {
                    HandleCancel();
                    return;
                }

                // Submit the build request for the references if we have any
                if (fqCount > 0)
                {
                    OnNewBuildRequests(_requestedEntry, fq);

                    // Wait for all of them to complete till our entry is marked ready
                    int evt = WaitHandle.WaitAny(handles);

                    // If a cancel occurs then we are done. Set the result to an exception
                    if (evt == 0)
                    {
                        HandleCancel();
                        return;
                    }

                    // If we get a continue then one of the reference has complete. Set the result in the cache only in case of success.
                    // Even though there may have been error - we cannot abandone the loop as there are already 
                    // requests in progress which may call back to this thread
                    else if (evt == 1)
                    {
                        IDictionary<int, BuildResult> results = _requestedEntry.Continue();
                        foreach (BuildResult configResult in results.Values)
                        {
                            if (configResult.OverallResult == BuildResultCode.Failure)
                            {
                                completeSuccess = false;
                            }
                            else
                            {
                                _resultsCache.AddResult(configResult);
                            }
                        }
                    }
                }

                // Check to see if there was a cancel we process the final result
                if (_cancelEvent.WaitOne(1, false))
                {
                    HandleCancel();
                    return;
                }

                // Simulate execution time for the actual entry if one was specified and if the entry built successfully
                if (_currentProjectDefinition.ExecutionTime > 0 && completeSuccess == true)
                {
                    Thread.Sleep(_currentProjectDefinition.ExecutionTime);
                }

                // Create and send the result
                BuildResult result = new BuildResult(_requestedEntry.Request);

                // No specific target was asked to build. Return the default result
                if (_requestedEntry.Request.Targets.Count == 0)
                {
                    result.AddResultsForTarget(RequestDefinition.defaultTargetName, new TargetResult(new TaskItem[1], completeSuccess ? TestUtilities.GetSuccessResult() : TestUtilities.GetStopWithErrorResult()));
                }
                else
                {
                    foreach (string target in _requestedEntry.Request.Targets)
                    {
                        result.AddResultsForTarget(target, new TargetResult(new TaskItem[1], completeSuccess ? TestUtilities.GetSuccessResult() : TestUtilities.GetStopWithErrorResult()));
                    }
                }

                _resultsCache.AddResult(result);
                _requestedEntry.Complete(result);
                RaiseRequestComplete(_requestedEntry);
                return;
            }

            catch (Exception e)
            {
                if (_requestedEntry != null)
                {
                    string message = String.Format("Test: Unhandeled exception occured: \nMessage: {0} \nStack:\n{1}", e.Message, e.StackTrace);
                    BuildResult errorResult = new BuildResult(_requestedEntry.Request, new InvalidOperationException(message));
                    _requestedEntry.Complete(errorResult);
                    RaiseRequestComplete(_requestedEntry);
                }
            }
        }
Esempio n. 14
0
        public void TestRequestWithReferenceCancelled()
        {
            BuildRequestConfiguration configuration = CreateTestProject(1);
            try
            {
                TestTargetBuilder targetBuilder = (TestTargetBuilder)_host.GetComponent(BuildComponentType.TargetBuilder);
                IConfigCache configCache = (IConfigCache)_host.GetComponent(BuildComponentType.ConfigCache);
                FullyQualifiedBuildRequest[] newRequest = new FullyQualifiedBuildRequest[1] { new FullyQualifiedBuildRequest(configuration, new string[1] { "testTarget2" }, true) };
                targetBuilder.SetNewBuildRequests(newRequest);
                configCache.AddConfiguration(configuration);

                BuildRequest request = CreateNewBuildRequest(1, new string[1] { "target1" });
                BuildRequestEntry entry = new BuildRequestEntry(request, configuration);
                BuildResult result = new BuildResult(request);
                result.AddResultsForTarget("target1", GetEmptySuccessfulTargetResult());
                targetBuilder.SetResultsToReturn(result);

                _requestBuilder.BuildRequest(GetNodeLoggingContext(), entry);
                WaitForEvent(_newBuildRequestsEvent, "New Build Requests");
                Assert.Equal(_newBuildRequests_Entry, entry);
                ObjectModelHelpers.AssertArrayContentsMatch(_newBuildRequests_FQRequests, newRequest);

                BuildResult newResult = new BuildResult(_newBuildRequests_BuildRequests[0]);
                newResult.AddResultsForTarget("testTarget2", GetEmptySuccessfulTargetResult());
                entry.ReportResult(newResult);

                _requestBuilder.ContinueRequest();
                Thread.Sleep(500);
                _requestBuilder.CancelRequest();

                WaitForEvent(_buildRequestCompletedEvent, "Build Request Completed");
                Assert.Equal(BuildRequestEntryState.Complete, entry.State);
                Assert.Equal(entry, _buildRequestCompleted_Entry);
                Assert.Equal(BuildResultCode.Failure, _buildRequestCompleted_Entry.Result.OverallResult);
            }
            finally
            {
                DeleteTestProject(configuration);
            }
        }
Esempio n. 15
0
        /// <summary>
        /// This is called back when this request needs to issue new requests and possible wait on them.  This method will
        /// block the builder's thread if any of the requests require us to wait for their results.
        /// </summary>
        /// <param name="requests">The list of build requests to be built.</param>
        /// <returns>The results, or null if the build should terminate.</returns>
        private async Task<BuildResult[]> StartNewBuildRequests(FullyQualifiedBuildRequest[] requests)
        {
            // Determine if we need to wait for results from any of these requests.
            // UNDONE: Currently we never set ResultsNeeded to anything but true.  The purpose of this flag would be
            // to issue another top-level build request which no other request depends on, but which must finish in order for
            // the build to be considered complete.  This would be brand new semantics.
            bool waitForResults = false;
            foreach (FullyQualifiedBuildRequest request in requests)
            {
                if (request.ResultsNeeded)
                {
                    waitForResults = true;
                    break;
                }
            }

            _blockType = BlockType.BlockedOnChildRequests;

            // Save the current operating environment, if necessary
            if (waitForResults)
            {
                SaveOperatingEnvironment();
            }

            // Issue the requests to the engine            
            RaiseOnNewBuildRequests(requests);

            // TODO: OPTIMIZATION: By returning null here, we commit to having to unwind the stack all the
            // way back to RequestThreadProc and then shutting down the thread before we can receive the
            // results and continue with them.  It is not always the case that this will be desirable, however,
            // particularly if the results we need are immediately available.  In those cases, it would be 
            // useful to wait here for a short period in case those results become available - one second
            // might be enough.  This means we may occasionally get more than one builder thread lying around
            // waiting for something to happen, but that would be short lived.  At the same time it would
            // allow these already-available results to be utilized immediately without the unwind
            // semantics.

            // Now wait for results if we are supposed to.
            BuildResult[] results;
            if (waitForResults)
            {
                WaitHandle[] handles = new WaitHandle[] { _terminateEvent, _continueEvent };

                int handle;
                if (IsBuilderUsingLegacyThreadingSemantics(_componentHost, _requestEntry))
                {
                    handle = RequestBuilder.WaitWithBuilderThreadStart(handles, true, _componentHost.LegacyThreadingData, _requestEntry.Request.SubmissionId);
                }
                else if (_inMSBuildCallback)
                {
                    CultureInfo savedCulture = CultureInfo.CurrentCulture;
                    CultureInfo savedUICulture = CultureInfo.CurrentUICulture;

                    handle = await handles.ToTask();

                    Thread.CurrentThread.CurrentCulture = savedCulture;
                    Thread.CurrentThread.CurrentUICulture = savedUICulture;
                }
                else
                {
                    handle = WaitHandle.WaitAny(handles);
                }

                // If this is not a shutdown case, then the entry should be in the active state.
                if (handle == 1)
                {
                    // Restore the operating environment.
                    RestoreOperatingEnvironment();
                    VerifyEntryInActiveState();
                }

                results = GetResultsForContinuation(requests, handle == 1);
            }
            else
            {
                results = new BuildResult[] { };
            }

            ErrorUtilities.VerifyThrow(requests.Length == results.Length, "# results != # requests");

            _blockType = BlockType.Unblocked;
            return results;
        }
Esempio n. 16
0
 /// <summary>
 /// Not Implemented
 /// </summary>
 private void MockIRequestBuilderCallback_OnNewBuildRequests(BuildRequestEntry sourceEntry, FullyQualifiedBuildRequest[] requests)
 {
     throw new NotImplementedException();
 }
Esempio n. 17
0
        /// <summary>
        /// This method is responsible for evaluating whether we have enough information to make the request of the Build Manager,
        /// or if we need to obtain additional configuration information.  It then issues either configuration
        /// requests or build requests, or both as needed.
        /// </summary>
        /// <param name="issuingEntry">The BuildRequestEntry which is making the request</param>
        /// <param name="newRequests">The array of "child" build requests to be issued.</param>
        /// <remarks>
        /// When we receive a build request, we first have to determine if we already have a configuration which matches the
        /// one used by the request.  We do this because everywhere we deal with requests and results beyond this function, we
        /// use configuration ids, which are assigned once by the Build Manager and are global to the system.  If we do
        /// not have a global configuration id, we can't check to see if we already have build results for the request, so we 
        /// cannot send the request out.  Thus, first we determine the configuration id.
        /// 
        /// Assuming we don't have the global configuration id locally, we will send the configuration to the Build Manager.
        /// It will look up or assign the global configuration id and send it back to us.
        /// 
        /// Once we have the global configuration id, we can then look up results locally.  If we have enough results to fulfill
        /// the request, we give them back to the request, otherwise we have to forward the request to the Build Mangager
        /// for scheduling.
        /// </remarks>
        private void IssueBuildRequests(BuildRequestEntry issuingEntry, FullyQualifiedBuildRequest[] newRequests)
        {
            ErrorUtilities.VerifyThrow(_componentHost != null, "No host object set");

            // For each request, we need to determine if we have a local configuration in the
            // configuration cache.  If we do, we can issue the build request immediately.
            // Otherwise, we need to ask the Build Manager for configuration IDs and issue those requests
            // later.
            IConfigCache globalConfigCache = (IConfigCache)_componentHost.GetComponent(BuildComponentType.ConfigCache);

            // We are going to potentially issue several requests.  We don't want the state of the request being modified by
            // other threads while this occurs, so we lock the request for the duration.  This lock is the same lock
            // used by the BuildRequestEntry itself to lock each of its data-modifying methods, effectively preventing
            // any other thread from modifying the BuildRequestEntry while we hold it.  This mechanism also means that it
            // is not necessary for other threads to take the global lock explicitly if they are just doing single operations
            // to the entry rather than a series of them.
            lock (issuingEntry.GlobalLock)
            {
                List<BuildResult> existingResultsToReport = new List<BuildResult>();
                HashSet<NGen<int>> unresolvedConfigurationsAdded = new HashSet<NGen<int>>();

                foreach (FullyQualifiedBuildRequest request in newRequests)
                {
                    // Do we have a matching configuration?
                    BuildRequestConfiguration matchingConfig = globalConfigCache.GetMatchingConfiguration(request.Config);
                    BuildRequest newRequest = null;
                    if (matchingConfig == null)
                    {
                        // No configuration locally, are we already waiting for it?
                        matchingConfig = _unresolvedConfigurations.GetMatchingConfiguration(request.Config);
                        if (matchingConfig == null)
                        {
                            // Not waiting for it
                            request.Config.ConfigurationId = GetNextUnresolvedConfigurationId();
                            _unresolvedConfigurations.AddConfiguration(request.Config);
                            unresolvedConfigurationsAdded.Add(request.Config.ConfigurationId);
                        }
                        else
                        {
                            request.Config.ConfigurationId = matchingConfig.ConfigurationId;
                        }

                        // Whether we are already waiting for a configuration or we need to wait for another one
                        // we will add this request as waiting for a configuration.  As new configuration resolutions
                        // come in, we will check our requests which are waiting for configurations move them to
                        // waiting for results.  It is important that we tell the issuing request to wait for a result
                        // prior to issuing any necessary configuration request so that we don't get into a state where
                        // we receive the configuration response before we enter the wait state.
                        newRequest = new BuildRequest(issuingEntry.Request.SubmissionId, GetNextBuildRequestId(), request.Config.ConfigurationId, request.Targets, issuingEntry.Request.HostServices, issuingEntry.Request.BuildEventContext, issuingEntry.Request);

                        issuingEntry.WaitForResult(newRequest);

                        if (matchingConfig == null)
                        {
                            // Issue the config resolution request
                            TraceEngine("Request {0}({1}) (nr {2}) is waiting on configuration {3} (IBR)", issuingEntry.Request.GlobalRequestId, issuingEntry.Request.ConfigurationId, issuingEntry.Request.NodeRequestId, request.Config.ConfigurationId);
                            issuingEntry.WaitForConfiguration(request.Config);
                        }
                    }
                    else
                    {
                        // We have a configuration, see if we already have results locally.
                        newRequest = new BuildRequest(issuingEntry.Request.SubmissionId, GetNextBuildRequestId(), matchingConfig.ConfigurationId, request.Targets, issuingEntry.Request.HostServices, issuingEntry.Request.BuildEventContext, issuingEntry.Request);

                        IResultsCache resultsCache = (IResultsCache)_componentHost.GetComponent(BuildComponentType.ResultsCache);
                        ResultsCacheResponse response = resultsCache.SatisfyRequest(newRequest, matchingConfig.ProjectInitialTargets, matchingConfig.ProjectDefaultTargets, matchingConfig.GetAfterTargetsForDefaultTargets(newRequest), skippedResultsAreOK: false);
                        if (response.Type == ResultsCacheResponseType.Satisfied)
                        {
                            // We have a result, give it back to this request.
                            issuingEntry.WaitForResult(newRequest);

                            // Log the fact that we handled this from the cache.
                            _nodeLoggingContext.LogRequestHandledFromCache(newRequest, _configCache[newRequest.ConfigurationId], response.Results);

                            // Can't report the result directly here, because that could cause the request to go from
                            // Waiting to Ready.
                            existingResultsToReport.Add(response.Results);
                        }
                        else
                        {
                            // No result, to wait for it.
                            issuingEntry.WaitForResult(newRequest);
                        }
                    }
                }

                // If we have any results we had to report, do so now.
                foreach (BuildResult existingResult in existingResultsToReport)
                {
                    issuingEntry.ReportResult(existingResult);
                }

                // Issue any configuration requests we may still need.
                List<BuildRequestConfiguration> unresolvedConfigurationsToIssue = issuingEntry.GetUnresolvedConfigurationsToIssue();
                if (unresolvedConfigurationsToIssue != null)
                {
                    foreach (BuildRequestConfiguration unresolvedConfigurationToIssue in unresolvedConfigurationsToIssue)
                    {
                        unresolvedConfigurationsAdded.Remove(unresolvedConfigurationToIssue.ConfigurationId);
                        IssueConfigurationRequest(unresolvedConfigurationToIssue);
                    }
                }

                // Remove any configurations we ended up not waiting for, otherwise future requests will think we are still waiting for them
                // and will never get submitted.
                foreach (int unresolvedConfigurationId in unresolvedConfigurationsAdded)
                {
                    _unresolvedConfigurations.RemoveConfiguration(unresolvedConfigurationId);
                }

                // Finally, if we can issue build requests, do so.
                List<BuildRequest> requestsToIssue = issuingEntry.GetRequestsToIssueIfReady();
                if (requestsToIssue != null)
                {
                    BuildRequestBlocker blocker = new BuildRequestBlocker(issuingEntry.Request.GlobalRequestId, issuingEntry.GetActiveTargets(), requestsToIssue.ToArray());
                    IssueBuildRequest(blocker);
                }

                if (issuingEntry.State == BuildRequestEntryState.Ready)
                {
                    ErrorUtilities.VerifyThrow((requestsToIssue == null) || (requestsToIssue.Count == 0), "Entry shouldn't be ready if we also issued requests.");
                    ActivateBuildRequest(issuingEntry);
                }
            }
        }
Esempio n. 18
0
        /// <summary>
        /// Invokes the OnNewBuildRequests event
        /// </summary>
        /// <param name="requests">The requests to be fulfilled.</param>
        private void RaiseOnNewBuildRequests(FullyQualifiedBuildRequest[] requests)
        {
            NewBuildRequestsDelegate newRequestDelegate = OnNewBuildRequests;

            if (null != newRequestDelegate)
            {
                newRequestDelegate(_requestEntry, requests);
            }
        }
        /// <summary>
        /// Determines equivalence with another object of the same type.
        /// </summary>
        /// <param name="other">The other object with which to compare this one.</param>
        /// <returns>True if the objects are equivalent, false otherwise.</returns>
        private bool InternalEquals(FullyQualifiedBuildRequest other)
        {
            if (Object.ReferenceEquals(this, other))
            {
                return true;
            }

            if (_requestConfiguration != other._requestConfiguration)
            {
                return false;
            }

            if (_resultsNeeded != other._resultsNeeded)
            {
                return false;
            }

            if (_targets.Length != other._targets.Length)
            {
                return false;
            }

            for (int i = 0; i < _targets.Length; ++i)
            {
                if (_targets[i] != other._targets[i])
                {
                    return false;
                }
            }

            return true;
        }
Esempio n. 20
0
 /// <summary>
 /// Raised when the active request needs to build new requests.
 /// </summary>
 /// <param name="sourceEntry">The request issuing the requests.</param>
 /// <param name="newRequests">The requests being issued.</param>
 /// <remarks>Called by the RequestBuilder (implicitly through an event).  Non-overlapping with other RequestBuilders.</remarks>
 private void Builder_OnNewBuildRequests(BuildRequestEntry sourceEntry, FullyQualifiedBuildRequest[] newRequests)
 {
     QueueAction(
         () =>
         {
             _unsubmittedRequests.Enqueue(new PendingUnsubmittedBuildRequests(sourceEntry, newRequests));
             IssueUnsubmittedRequests();
             EvaluateRequestStates();
         },
         isLastTask: false);
 }
Esempio n. 21
0
        /// <summary>
        /// This method instructs the request builder to build the specified projects using the specified parameters.  This is
        /// what is ultimately used by something like an MSBuild task which needs to invoke a project-to-project reference.  IBuildEngine
        /// and IBuildEngine2 have BuildProjectFile methods which boil down to an invocation of this method as well.
        /// </summary>
        /// <param name="projectFiles">An array of projects to be built.</param>
        /// <param name="properties">The property groups to use for each project.  Must be the same number as there are project files.</param>
        /// <param name="toolsVersions">The tools version to use for each project.  Must be the same number as there are project files.</param>
        /// <param name="targets">The targets to be built.  Each project will be built with the same targets.</param>
        /// <param name="waitForResults">True to wait for the results </param>
        /// <returns>True if the requests were satisfied, false if they were aborted.</returns>
        public async Task<BuildResult[]> BuildProjects(string[] projectFiles, PropertyDictionary<ProjectPropertyInstance>[] properties, string[] toolsVersions, string[] targets, bool waitForResults)
        {
            VerifyIsNotZombie();
            ErrorUtilities.VerifyThrowArgumentNull(projectFiles, "projectFiles");
            ErrorUtilities.VerifyThrowArgumentNull(properties, "properties");
            ErrorUtilities.VerifyThrowArgumentNull(targets, "targets");
            ErrorUtilities.VerifyThrowArgumentNull(toolsVersions, "toolsVersions");
            ErrorUtilities.VerifyThrow(_componentHost != null, "No host object set");
            ErrorUtilities.VerifyThrow(projectFiles.Length == properties.Length, "Properties and project counts not the same");
            ErrorUtilities.VerifyThrow(projectFiles.Length == toolsVersions.Length, "Tools versions and project counts not the same");

            FullyQualifiedBuildRequest[] requests = new FullyQualifiedBuildRequest[projectFiles.Length];

            for (int i = 0; i < projectFiles.Length; ++i)
            {
                if (!Path.IsPathRooted(projectFiles[i]))
                {
                    projectFiles[i] = Path.Combine(_requestEntry.ProjectRootDirectory, projectFiles[i]);
                }

                // Canonicalize
                projectFiles[i] = FileUtilities.NormalizePath(projectFiles[i]);

                // A tools version specified by an MSBuild task or similar has priority
                string explicitToolsVersion = toolsVersions[i];

                // Otherwise go to any explicit tools version on the project who made this callback
                if (explicitToolsVersion == null && _requestEntry.RequestConfiguration.ExplicitToolsVersionSpecified)
                {
                    explicitToolsVersion = _requestEntry.RequestConfiguration.ToolsVersion;
                }

                // Otherwise let the BuildRequestConfiguration figure out what tools version will be used
                BuildRequestData data = new BuildRequestData(projectFiles[i], properties[i].ToDictionary(), explicitToolsVersion, targets, null);

                BuildRequestConfiguration config = new BuildRequestConfiguration(data, _componentHost.BuildParameters.DefaultToolsVersion, _componentHost.BuildParameters.GetToolset);

                requests[i] = new FullyQualifiedBuildRequest(config, targets, waitForResults);
            }

            // Send the requests off
            BuildResult[] results = await StartNewBuildRequests(requests);

            ErrorUtilities.VerifyThrow(requests.Length == results.Length, "# results != # requests");

            return results;
        }