예제 #1
0
        /// <summary>
        /// Helper method so we can keep the real Expander.ExpandMetadataAndProperties private.
        /// </summary>
        /// <param name="bucket"></param>
        /// <param name="expression"></param>
        /// <returns></returns>
        /// <owner>RGoel</owner>
        private static string ExpandMetadataAndProperties
        (
            ItemBucket bucket,
            string expression
        )
        {
            Expander itemExpander = new Expander(bucket.Expander, ExpanderOptions.ExpandPropertiesAndMetadata);

            return(itemExpander.ExpandAllIntoString(expression, (new XmlDocument()).CreateAttribute("foo")));
        }
예제 #2
0
        /// <summary>
        /// Helper method so we can keep the real Expander.ExpandItemsIntoString private.
        /// </summary>
        /// <param name="bucket"></param>
        /// <param name="expression"></param>
        /// <returns></returns>
        /// <owner>RGoel</owner>
        private static string ExpandItemsIntoString
        (
            ItemBucket bucket,
            string expression
        )
        {
            Expander itemExpander = new Expander(new ReadOnlyLookup(bucket.Lookup), null, ExpanderOptions.ExpandItems);

            return(itemExpander.ExpandAllIntoString(expression, (new XmlDocument()).CreateAttribute("foo")));
        }
예제 #3
0
        public UsingTaskInfo CopyAndExpand(Expander expander)
        {
            string newTaskName     = expander.ExpandAllIntoString(UsingTask.TaskName, UsingTask.TaskNameAttribute);
            string newCondition    = null;
            string newAssemblyName = null;
            string newAssemblyFile = null;

            if (UsingTask.Condition != null)
            {
                newCondition = expander.ExpandAllIntoString(UsingTask.Condition, UsingTask.ConditionAttribute);
            }
            if (UsingTask.AssemblyName != null)
            {
                newAssemblyName = expander.ExpandAllIntoString(UsingTask.AssemblyName, UsingTask.AssemblyNameAttribute);
            }
            if (UsingTask.AssemblyFile != null)
            {
                newAssemblyFile = expander.ExpandAllIntoString(UsingTask.AssemblyFile, UsingTask.AssemblyFileAttribute);
            }

            return(new UsingTaskInfo(newTaskName, newAssemblyName, newAssemblyFile, newCondition));
        }
예제 #4
0
        /// <summary>
        /// Reads the given &lt;UsingTask&gt; tag and saves the task information specified in it.
        /// </summary>
        /// <param name="usingTask"></param>
        /// <param name="expander"></param>
        /// <param name="loggingServices"></param>
        /// <param name="buildEventContext"></param>
        public void RegisterTask(UsingTask usingTask, Expander expander, EngineLoggingServices loggingServices, BuildEventContext buildEventContext)
        {
            if (
                // if the <UsingTask> tag doesn't have a condition on it
                (usingTask.Condition == null)
                ||
                // or if the condition holds
                Utilities.EvaluateCondition(usingTask.Condition, usingTask.ConditionAttribute, expander,
                                            null, ParserOptions.AllowProperties | ParserOptions.AllowItemLists, loggingServices, buildEventContext)
                )
            {
                // Lazily allocate the hashtables if they are needed
                if (registeredTasks == null)
                {
                    cachedTaskClassesWithExactMatch = new Hashtable(StringComparer.OrdinalIgnoreCase);
                    cachedTaskClassesWithFuzzyMatch = new Hashtable(StringComparer.OrdinalIgnoreCase);
                    registeredTasks = new Hashtable(StringComparer.OrdinalIgnoreCase);
                }

                string assemblyName = null;
                string assemblyFile = null;

                if (usingTask.AssemblyName != null)
                {
                    // expand out all embedded properties and items in the assembly name
                    assemblyName = expander.ExpandAllIntoString(usingTask.AssemblyName, usingTask.AssemblyNameAttribute);

                    ProjectErrorUtilities.VerifyThrowInvalidProject(assemblyName.Length > 0,
                                                                    usingTask.AssemblyNameAttribute, "InvalidEvaluatedAttributeValue", assemblyName, usingTask.AssemblyName, XMakeAttributes.assemblyName, XMakeElements.usingTask);
                }
                else
                {
                    // expand out all embedded properties and items in the assembly file/path
                    assemblyFile = expander.ExpandAllIntoString(usingTask.AssemblyFile, usingTask.AssemblyFileAttribute);

                    ProjectErrorUtilities.VerifyThrowInvalidProject(assemblyFile.Length > 0,
                                                                    usingTask.AssemblyFileAttribute, "InvalidEvaluatedAttributeValue", assemblyFile, usingTask.AssemblyFile, XMakeAttributes.assemblyFile, XMakeElements.usingTask);

                    // figure out the directory of the project in which this <UsingTask> node was defined
                    string projectFile = XmlUtilities.GetXmlNodeFile(usingTask.TaskNameAttribute.OwnerElement, String.Empty);
                    string projectDir  = (projectFile.Length > 0)
                        ? Path.GetDirectoryName(projectFile)
                        : String.Empty;

                    // ensure the assembly file/path is relative to the project in which this <UsingTask> node was defined -- we
                    // don't want paths from imported projects being interpreted relative to the main project file
                    try
                    {
                        assemblyFile = Path.Combine(projectDir, assemblyFile);
                    }
                    catch (ArgumentException ex)
                    {
                        // Invalid chars in AssemblyFile path
                        ProjectErrorUtilities.VerifyThrowInvalidProject(false, usingTask.AssemblyFileAttribute,
                                                                        "InvalidAttributeValueWithException", assemblyFile,
                                                                        XMakeAttributes.assemblyFile, XMakeElements.usingTask, ex.Message);
                    }
                }

                AssemblyLoadInfo taskAssembly = new AssemblyLoadInfo(assemblyName, assemblyFile);

                // expand out all embedded properties and items
                string taskName = expander.ExpandAllIntoString(usingTask.TaskName, usingTask.TaskNameAttribute);

                ProjectErrorUtilities.VerifyThrowInvalidProject(taskName.Length > 0,
                                                                usingTask.TaskNameAttribute, "InvalidEvaluatedAttributeValue", taskName, usingTask.TaskName, XMakeAttributes.taskName, XMakeElements.usingTask);

                // since more than one task can have the same name, we want to keep track of all assemblies that are declared to
                // contain tasks with a given name...
                ArrayList taskAssemblies = (ArrayList)registeredTasks[taskName];

                if (taskAssemblies == null)
                {
                    taskAssemblies            = new ArrayList();
                    registeredTasks[taskName] = taskAssemblies;
                }

                taskAssemblies.Add(taskAssembly);
            }
        }
예제 #5
0
        /// <summary>
        /// Builds this target if it has not already been built as part of its parent project. Before we actually execute the
        /// tasks for this target, though, we first call on all the dependent targets to build themselves.
        /// This function may throw InvalidProjectFileException
        /// </summary>
        internal void Build
        (
            ProjectBuildState buildContext
        )
        {
            // Depending on the build state, we may do different things.
            switch (buildState)
            {
            case BuildState.InProgress:
                // In single proc mode if the build state was already "in progress"
                // and somebody just told us to build ourselves, it means that there is
                // a loop (circular dependency) in the target dependency graph. In multi
                // proc mode we need to analyze the dependency graph before we can
                // tell if there a circular dependency or if two independent chains
                // of targets happen to need the result of this target.
                if (parentEngine.Router.SingleThreadedMode || buildContext.ContainsCycle(this.Name))
                {
                    ProjectErrorUtilities.VerifyThrowInvalidProject(false, TargetElement, "CircularDependency", targetName);
                }
                else
                {
                    buildContext.CurrentBuildContextState = ProjectBuildState.BuildContextState.WaitingForTarget;
                    this.executionState.AddWaitingBuildContext(buildContext);
                }
                break;

            case BuildState.CompletedSuccessfully:
            case BuildState.CompletedUnsuccessfully:
                // If this target has already been built as part of this project,
                // we're not going to build it again.  Just return the result
                // from when it was built previously.  Note:  This condition
                // could really only ever hold true if the user specifically
                // requested us to build multiple targets and there existed
                // a direct or indirect dependency relationship between two or
                // more of those top-level targets.
                // Note: we aren't really entering the target in question here, so don't use the target
                // event context. Using the target ID for skipped messages would force us to
                // cache the individual target IDs for unloaded projects and it's not really worth the trouble.
                // Just use the parent event context.
                parentEngine.LoggingServices.LogComment(buildContext.ProjectBuildEventContext,
                                                        ((buildState == BuildState.CompletedSuccessfully) ? "TargetAlreadyCompleteSuccess" : "TargetAlreadyCompleteFailure"),
                                                        this.targetName);

                // Only contexts which are generated from an MSBuild task could need
                // the outputs of this target, such contexts have a non-null evaluation
                // request
                if ((buildState == BuildState.CompletedSuccessfully) &&
                    (buildContext.BuildRequest.OutputsByTarget != null &&
                     buildContext.NameOfBlockingTarget == null))
                {
                    error.VerifyThrow(
                        String.Compare(EscapingUtilities.UnescapeAll(buildContext.NameOfTargetInProgress), this.Name, StringComparison.OrdinalIgnoreCase) == 0,
                        "The name of the target in progress is inconsistent with the target being built");

                    error.VerifyThrow(targetOutputItems != null,
                                      "If the target built successfully, we must have its outputs.");

                    buildContext.BuildRequest.OutputsByTarget[Name] = targetOutputItems.ToArray();
                }

                if (buildContext.NameOfBlockingTarget == null)
                {
                    buildContext.BuildRequest.ResultByTarget[Name] = buildState;
                }
                break;

            case BuildState.NotStarted:
            case BuildState.Skipped:
            {
                // Always have to create a new context in build as other projects or targets may try and build this target
                BuildEventContext targetBuildEventContext = new BuildEventContext
                                                            (
                    buildContext.ProjectBuildEventContext.NodeId,
                    this.id,
                    buildContext.ProjectBuildEventContext.ProjectContextId,
                    buildContext.ProjectBuildEventContext.TaskId
                                                            );

                Expander expander = new Expander(this.parentProject.evaluatedProperties, this.parentProject.evaluatedItemsByName);

                // We first make sure no batching was attempted with the target's condition.
                if (!conditionCheckedForInvalidMetadataReferences)
                {
                    if (ExpressionShredder.ContainsMetadataExpressionOutsideTransform(this.Condition))
                    {
                        ProjectErrorUtilities.ThrowInvalidProject(this.conditionAttribute, "TargetConditionHasInvalidMetadataReference", targetName, this.Condition);
                    }
                    conditionCheckedForInvalidMetadataReferences = true;
                }

                // If condition is false (based on propertyBag), set this target's state to
                // "Skipped" since we won't actually build it.
                if (!Utilities.EvaluateCondition(this.Condition, this.conditionAttribute,
                                                 expander, null, ParserOptions.AllowProperties | ParserOptions.AllowItemLists,
                                                 parentEngine.LoggingServices, targetBuildEventContext))
                {
                    buildState = BuildState.Skipped;

                    if (buildContext.NameOfBlockingTarget == null)
                    {
                        buildContext.BuildRequest.ResultByTarget[Name] = buildState;
                    }

                    if (!parentEngine.LoggingServices.OnlyLogCriticalEvents)
                    {
                        // Expand the expression for the Log.
                        string expanded = expander.ExpandAllIntoString(this.Condition, this.conditionAttribute);
                        // By design: Not building dependencies. This is what NAnt does too.
                        parentEngine.LoggingServices.LogComment(targetBuildEventContext, "TargetSkippedFalseCondition",
                                                                this.targetName, this.Condition, expanded);
                    }
                }
                else
                {
                    // This target has not been built yet.  So build it!
                    // Change our state to "in progress". TargetParameters will need to be re-calculated if Inputs and Outputs attribute has changed.
                    buildState = BuildState.InProgress;
                    List <string> batchableTargetParameters = GetBatchableTargetParameters();
                    executionState = new TargetExecutionWrapper(this, taskElementList, batchableTargetParameters, targetElement, expander, targetBuildEventContext);
                    ContinueBuild(buildContext, null);
                }
            }
            break;

            default:
                error.VerifyThrow(false, "Build state {0} not handled in Target.Build method", buildState);
                break;
            }
        }