Example #1
0
        /// <summary>
        /// Creates and caches a built result.
        /// </summary>
        private BuildResult CacheBuildResult(BuildRequest request, string target, WorkUnitResult workUnitResult)
        {
            BuildResult   result       = CreateBuildResult(request, target, workUnitResult);
            IResultsCache resultsCache = _host.GetComponent(BuildComponentType.ResultsCache) as IResultsCache;

            resultsCache.AddResult(result);
            return(result);
        }
Example #2
0
 internal void SetResultsToReturn(BuildResult result)
 {
     _cache.AddResult(result);
 }
Example #3
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);
                }
            }
        }
Example #4
0
        /// <summary>
        /// Builds the specified targets.
        /// </summary>
        /// <param name="loggingContext">The logging context for the project.</param>
        /// <param name="entry">The BuildRequestEntry for which we are building targets.</param>
        /// <param name="callback">The callback to be used to handle new project build requests.</param>
        /// <param name="targetNames">The names of the targets to build.</param>
        /// <param name="baseLookup">The Lookup containing all current items and properties for this target.</param>
        /// <param name="cancellationToken">The <see cref="CancellationToken"/> to use when building the targets.</param>
        /// <returns>The target's outputs and result codes</returns>
        public async Task <BuildResult> BuildTargets(ProjectLoggingContext loggingContext, BuildRequestEntry entry, IRequestBuilderCallback callback, string[] targetNames, Lookup baseLookup, CancellationToken cancellationToken)
        {
            ErrorUtilities.VerifyThrowArgumentNull(loggingContext, "projectLoggingContext");
            ErrorUtilities.VerifyThrowArgumentNull(entry, nameof(entry));
            ErrorUtilities.VerifyThrowArgumentNull(callback, "requestBuilderCallback");
            ErrorUtilities.VerifyThrowArgumentNull(targetNames, nameof(targetNames));
            ErrorUtilities.VerifyThrowArgumentNull(baseLookup, nameof(baseLookup));
            ErrorUtilities.VerifyThrow(targetNames.Length > 0, "List of targets must be non-empty");
            ErrorUtilities.VerifyThrow(_componentHost != null, "InitializeComponent must be called before building targets.");

            _requestEntry           = entry;
            _requestBuilderCallback = callback;
            _projectLoggingContext  = loggingContext;
            _cancellationToken      = cancellationToken;

            // Clone the base lookup so that if we are re-entered by another request while this one in blocked, we don't have visibility to
            // their state, and they have no visibility into ours.
            _baseLookup = baseLookup.Clone();

            _targetsToBuild = new ConcurrentStack <TargetEntry>();

            // Get the actual target objects from the names
            BuildRequestConfiguration configuration = _requestEntry.RequestConfiguration;

            bool previousCacheableStatus = configuration.IsCacheable;

            configuration.IsCacheable = false;
            configuration.RetrieveFromCache();
            _projectInstance = configuration.Project;

            // Now get the current results cache entry.
            IResultsCache resultsCache        = (IResultsCache)_componentHost.GetComponent(BuildComponentType.ResultsCache);
            BuildResult   existingBuildResult = resultsCache.GetResultsForConfiguration(_requestEntry.Request.ConfigurationId);

            _buildResult = new BuildResult(entry.Request, existingBuildResult, null);

            if (existingBuildResult == null)
            {
                // Add this result so that if our project gets re-entered we won't rebuild any targets we have already built.
                resultsCache.AddResult(_buildResult);
            }

            List <TargetSpecification> targets = new List <TargetSpecification>(targetNames.Length);

            foreach (string targetName in targetNames)
            {
                var targetExists = _projectInstance.Targets.ContainsKey(targetName);
                if (!targetExists && entry.Request.BuildRequestDataFlags.HasFlag(BuildRequestDataFlags.SkipNonexistentTargets))
                {
                    _projectLoggingContext.LogComment(Framework.MessageImportance.Low,
                                                      "TargetSkippedWhenSkipNonexistentTargets", targetName);

                    continue;
                }

                targets.Add(new TargetSpecification(targetName, targetExists ? _projectInstance.Targets[targetName].Location : _projectInstance.ProjectFileLocation));
            }

            // Push targets onto the stack.  This method will reverse their push order so that they
            // get built in the same order specified in the array.
            await PushTargets(targets, null, baseLookup, false, false, TargetBuiltReason.None);

            // Now process the targets
            ITaskBuilder taskBuilder = _componentHost.GetComponent(BuildComponentType.TaskBuilder) as ITaskBuilder;

            try
            {
                await ProcessTargetStack(taskBuilder);
            }
            finally
            {
                // If there are still targets left on the stack, they need to be removed from the 'active targets' list
                foreach (TargetEntry target in _targetsToBuild)
                {
                    configuration.ActivelyBuildingTargets.Remove(target.Name);
                }

                ((IBuildComponent)taskBuilder).ShutdownComponent();
            }

            if (_cancellationToken.IsCancellationRequested)
            {
                throw new BuildAbortedException();
            }

            // Gather up outputs for the requested targets and return those.  All of our information should be in the base lookup now.
            ComputeAfterTargetFailures(targetNames);
            BuildResult resultsToReport = new BuildResult(_buildResult, targetNames);

            // Return after-build project state if requested.
            if (_requestEntry.Request.BuildRequestDataFlags.HasFlag(BuildRequestDataFlags.ProvideProjectStateAfterBuild))
            {
                resultsToReport.ProjectStateAfterBuild = _projectInstance;
            }

            if (_requestEntry.Request.RequestedProjectState != null)
            {
                resultsToReport.ProjectStateAfterBuild =
                    _projectInstance.FilteredCopy(_requestEntry.Request.RequestedProjectState);
            }

            configuration.IsCacheable = previousCacheableStatus;

            return(resultsToReport);
        }
Example #5
0
 /// <summary>
 /// Call the actual implementation
 /// </summary>
 /// <param name="result">The result to add.</param>
 public void AddResult(BuildResult result)
 {
     _addCount++;
     _resultCache.AddResult(result);
 }