Example #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"));
 }
Example #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"));
 }
Example #3
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;
            }
        }
Example #4
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);
        }
Example #5
0
        public void ExpandAllIntoStringExpanderOptions()
        {
            ReadOnlyLookup lookup;
            Dictionary<string, string> itemMetadata;
            CreateComplexPropertiesItemsMetadata(out lookup, out itemMetadata);

            string value = @"@(Resource->'%(Filename)') ; @(Content) ; @(NonExistent) ; $(NonExistent) ; %(NonExistent) ; $(OutputPath) ; $(TargetPath) ; %(Language)_%(Culture)";

            Expander expander = new Expander(lookup, itemMetadata, ExpanderOptions.ExpandProperties);

            Assertion.AssertEquals(@"@(Resource->'%(Filename)') ; @(Content) ; @(NonExistent) ;  ; %(NonExistent) ; \jk ; l\mno%3bpqr\stu ; @(IntermediateAssembly->'%(RelativeDir)') ; %(Language)_%(Culture)", expander.ExpandAllIntoString(value, null));

            expander = new Expander(expander, ExpanderOptions.ExpandPropertiesAndMetadata);

            Assertion.AssertEquals(@"@(Resource->'%(Filename)') ; @(Content) ; @(NonExistent) ;  ;  ; \jk ; l\mno%3bpqr\stu ; @(IntermediateAssembly->'%(RelativeDir)') ; english_abc%3bdef;ghi", expander.ExpandAllIntoString(value, null));

            expander = new Expander(expander, ExpanderOptions.ExpandAll);

            Assertion.AssertEquals(@"string$(p);dialogs%3b ; splash.bmp ;  ;  ;  ; \jk ; l\mno%3bpqr\stu ; subdir1\;subdir2\ ; english_abc%3bdef;ghi", expander.ExpandAllIntoString(value, null));

            expander = new Expander(expander, ExpanderOptions.ExpandItems);

            Assertion.AssertEquals(@"string$(p);dialogs%3b ; splash.bmp ;  ; $(NonExistent) ; %(NonExistent) ; $(OutputPath) ; $(TargetPath) ; %(Language)_%(Culture)", expander.ExpandAllIntoString(value, null));
        }
Example #6
0
        public void ExpandAllIntoStringComplex()
        {
            ReadOnlyLookup lookup;
            Dictionary<string, string> itemMetadata;
            CreateComplexPropertiesItemsMetadata(out lookup, out itemMetadata);

            Expander expander = new Expander(lookup, itemMetadata);

            XmlAttribute xmlattribute = (new XmlDocument()).CreateAttribute("dummy");
            xmlattribute.Value = "@(Resource->'%(Filename)') ; @(Content) ; @(NonExistent) ; $(NonExistent) ; %(NonExistent) ; " +
                "$(OutputPath) ; $(TargetPath) ; %(Language)_%(Culture)";

            Assertion.AssertEquals(
                @"string$(p);dialogs%3b ; splash.bmp ;  ;  ;  ; \jk ; l\mno%3bpqr\stu ; subdir1\;subdir2\ ; english_abc%3bdef;ghi",
                expander.ExpandAllIntoString(xmlattribute.Value, xmlattribute));

            Assertion.AssertEquals(
                @"string$(p);dialogs%3b ; splash.bmp ;  ;  ;  ; \jk ; l\mno%3bpqr\stu ; subdir1\;subdir2\ ; english_abc%3bdef;ghi",
                expander.ExpandAllIntoString(xmlattribute));
        }
Example #7
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);
            }
        }