implemented well-known item metadata.
authorAtsushi Eno <atsushieno@veritas-vos-liberabit.com>
Thu, 24 Oct 2013 12:36:18 +0000 (21:36 +0900)
committerAtsushi Eno <atsushieno@veritas-vos-liberabit.com>
Fri, 29 Nov 2013 09:21:09 +0000 (18:21 +0900)
mcs/class/Microsoft.Build/Microsoft.Build.Evaluation/Project.cs
mcs/class/Microsoft.Build/Microsoft.Build.Evaluation/ProjectItem.cs
mcs/class/Microsoft.Build/Test/Microsoft.Build.Evaluation/ProjectItemTest.cs

index 77b642873e0f0424f302a0797b37a0646edc5615..9beceedafb71a3b6c86de4430c1323c71e1365e6 100644 (file)
@@ -243,7 +243,8 @@ namespace Microsoft.Build.Evaluation
                                        foreach (var p in ige.Items) {
                                                var inc = ExpandString (p.Include);
                                                foreach (var each in inc.Split (item_sep, StringSplitOptions.RemoveEmptyEntries)) {
-                                                       var item = new ProjectItem (this, p, each);
+                                                       // FIXME: this "each" path could still be wildcard that needs to be expanded.
+                                                       var item = new ProjectItem (this, p, each, each);
                                                        this.raw_items.Add (item);
                                                        if (ShouldInclude (ige.Condition) && ShouldInclude (p.Condition))
                                                                all_evaluated_items.Add (item);
@@ -653,5 +654,12 @@ namespace Microsoft.Build.Evaluation
                {
                        return ProjectCollection.OngoingImports.Count > 0 ? ProjectCollection.OngoingImports.Peek () : FullPath ?? string.Empty;
                }
+               
+               internal string GetFullPath (string pathRelativeToProject)
+               {
+                       if (Path.IsPathRooted (pathRelativeToProject))
+                               return pathRelativeToProject;
+                       return Path.GetFullPath (Path.Combine (DirectoryPath, pathRelativeToProject));
+               }
        }
 }
index c94cb5b038943d1b2c689b68249a98eda27991b2..1c88e430bd242cbb931faa16e8c40c9bde9a60f0 100644 (file)
@@ -34,13 +34,15 @@ using System.Collections.Generic;
 using System.Diagnostics;
 using System.Linq;
 using Microsoft.Build.Construction;
+using System.IO;
+using Microsoft.Build.Framework;
 
 namespace Microsoft.Build.Evaluation
 {
        [DebuggerDisplay ("{ItemType}={EvaluatedInclude} [{UnevaluatedInclude}] #DirectMetadata={DirectMetadataCount}")]
        public class ProjectItem
        {
-               internal ProjectItem (Project project, ProjectItemElement xml, string evaluatedInclude)
+               internal ProjectItem (Project project, ProjectItemElement xml, string evaluatedInclude, string filename)
                {
                        this.project = project;
                        this.xml = xml;
@@ -50,20 +52,49 @@ namespace Microsoft.Build.Evaluation
                        foreach (var item in xml.Metadata)
                                metadata.Add (new ProjectMetadata (project, ItemType, metadata, m => metadata.Remove (m), item));
                        evaluated_include = evaluatedInclude;
+                       this.filename = filename;
+                       is_imported = project.ProjectCollection.OngoingImports.Any ();                  
                }
                
-               Project project;
-               ProjectItemElement xml;
-               List<ProjectMetadata> metadata = new List<ProjectMetadata> ();
-               string evaluated_include;
+               readonly Project project;
+               readonly ProjectItemElement xml;
+               readonly List<ProjectMetadata> metadata = new List<ProjectMetadata> ();
+               readonly string evaluated_include;
+               readonly bool is_imported;
+               readonly string filename;
 
                public ProjectMetadata GetMetadata (string name)
                {
                        return metadata.FirstOrDefault (m => m.Name == name);
                }
+               
+               static readonly char [] path_sep = {Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar};
+               
+               static readonly Dictionary<string,Func<ProjectItem,string>> well_known_metadata = new Dictionary<string, Func<ProjectItem,string>> {
+                               {"FullPath", p => Path.Combine (p.Project.GetFullPath (p.filename)) },
+                               {"RootDir", p => Path.GetPathRoot (p.Project.GetFullPath (p.filename)) },
+                               {"Filename", p => Path.GetFileName (p.filename) },
+                               {"Extension", p => Path.GetExtension (p.filename) },
+                               {"RelativeDir", p => {
+                                       var idx = p.filename.LastIndexOfAny (path_sep);
+                                       return idx < 0 ? string.Empty : p.filename.Substring (0, idx + 1); }
+                                       },
+                               {"Directory", p => {
+                                       var fp = p.Project.GetFullPath (p.filename);
+                                       return Path.GetDirectoryName (fp).Substring (Path.GetPathRoot (fp).Length); }
+                                       },
+                               // FIXME: implement RecursiveDir: Microsoft.Build.BuildEngine.DirectoryScanner would be reusable with some changes.
+                               {"Identity", p => p.EvaluatedInclude },
+                               {"ModifiedTime", p => new FileInfo (p.Project.GetFullPath (p.filename)).LastWriteTime.ToString ("yyyy-MM-dd HH:mm:ss.fffffff") },
+                               {"CreatedTime", p => new FileInfo (p.Project.GetFullPath (p.filename)).CreationTime.ToString ("yyyy-MM-dd HH:mm:ss.fffffff") },
+                               {"AccessedTime", p => new FileInfo (p.Project.GetFullPath (p.filename)).LastAccessTime.ToString ("yyyy-MM-dd HH:mm:ss.fffffff") },
+                               };
 
                public string GetMetadataValue (string name)
                {
+                       var wellKnown = well_known_metadata.FirstOrDefault (p => p.Key.Equals (name, StringComparison.OrdinalIgnoreCase));
+                       if (wellKnown.Value != null)
+                               return wellKnown.Value (this);
                        var m = GetMetadata (name);
                        return m != null ? m.EvaluatedValue : string.Empty;
                }
@@ -108,7 +139,7 @@ namespace Microsoft.Build.Evaluation
                }
 
                public bool IsImported {
-                       get { throw new NotImplementedException (); }
+                       get { return is_imported; }
                }
 
                public string ItemType {
@@ -135,6 +166,6 @@ namespace Microsoft.Build.Evaluation
 
                public ProjectItemElement Xml {
                        get { return xml; }
-               }
+               }               
        }
 }
index e72627c93e7c0bdeab0da6e9c9cf95c92077600e..8044f8811e5fbe11485a40e860c25eeb09b1b7fd 100644 (file)
@@ -65,6 +65,10 @@ namespace MonoTests.Microsoft.Build.Evaluation
                        Assert.AreEqual ("valueX1", meta.UnevaluatedValue, "#4");
                        Assert.IsNotNull (meta.Predecessor, "#5");
                        Assert.AreEqual ("value1", meta.Predecessor.UnevaluatedValue, "#6");
+                       
+                       // Well-known metadata don't show up via GetMetadata(), but does show up via GetMetadataValue().
+                       Assert.AreEqual (null, item.GetMetadata ("Filename"), "#7");
+                       Assert.AreEqual ("bar.txt", item.GetMetadataValue ("Filename"), "#8");
                }
        }
 }