Created
October 25, 2016 15:26
-
-
Save chilversc/8aa317ca2f2754e64c5779be32a13ee0 to your computer and use it in GitHub Desktop.
Sort msbuild project items
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<Query Kind="Program" /> | |
static XNamespace ns = "http://schemas.microsoft.com/developer/msbuild/2003"; | |
static XName ItemGroup = ns + "ItemGroup"; | |
static XName Reference = ns + "Reference"; | |
static XName ProjectReference = ns + "ProjectReference"; | |
static XName Condition = "Condition"; | |
static XName Include = "Include"; | |
static XName OutputType = ns + "OutputType"; | |
static XName Folder = ns + "Folder"; | |
static XName RefactorLog = ns + "RefactorLog"; | |
static XName ArtifactReference = ns + "ArtifactReference"; | |
static XName PostDeploy = ns + "PostDeploy"; | |
static XName SqlCmdVariable = ns + "SqlCmdVariable"; | |
void Main(string[] args) | |
{ | |
if (args.Length == 0) { | |
Console.WriteLine ("Syntax: lprun SortProject.linq Core\\Core.csproj (...)"); | |
} else { | |
foreach (var file in args) { | |
if (File.Exists (file)) { | |
SortProject (file); | |
} else { | |
Console.Error.WriteLine ("File not found: {0}", file); | |
} | |
} | |
} | |
} | |
private void SortProject (string file) | |
{ | |
XDocument doc = XDocument.Load (file); | |
var root = doc.Root; | |
var groups = root | |
.Elements (ItemGroup) | |
.Where (group => !group.HasAttributes) | |
.ToList (); | |
foreach (var g in groups) { | |
g.Remove (); | |
} | |
var outputType = root.Descendants (OutputType).Select (x => x.Value).FirstOrDefault (); | |
var isDatabase = "Database".Equals(outputType, StringComparison.OrdinalIgnoreCase); | |
var items = GroupItems (groups.SelectMany (g => g.Elements ())); | |
if (isDatabase) { | |
root.Add (GroupItems (items.Elements (ArtifactReference))); | |
root.Add (GroupItems (items.Elements (SqlCmdVariable), ItemComparer.FullName)); | |
root.Add (GroupItems (items.Elements (Folder), ItemComparer.FullName)); | |
} else { | |
root.Add (GroupItems (items.Elements (Reference))); | |
root.Add (GroupItems (items.Elements (ProjectReference))); | |
} | |
root.Add (GroupItems (items.Elements ())); | |
doc.Save (file); | |
} | |
private IEnumerable<XElement> Find (XElement container, params XName[] names) | |
{ | |
return names.SelectMany (n => container.Elements (n)); | |
} | |
private XElement GroupItems (IEnumerable<XElement> elements) | |
{ | |
return GroupItems (elements, ItemComparer.Default); | |
} | |
private XElement GroupItems (IEnumerable<XElement> elements, IComparer<XElement> comparer) | |
{ | |
var container = new XElement (ItemGroup); | |
MoveElements (container, elements, comparer); | |
return container; | |
} | |
private void MoveElements (XElement container, IEnumerable<XElement> elements, IComparer<XElement> comparer) | |
{ | |
foreach (var element in elements.OrderBy (e => e, comparer).ToList ()) { | |
element.Remove (); | |
container.Add (element); | |
} | |
} | |
class ItemComparer : IComparer<XElement> | |
{ | |
private readonly Comparison<string> comparison; | |
private ItemComparer (Comparison<string> comparison) | |
{ | |
this.comparison = comparison; | |
} | |
public int Compare (XElement e1, XElement e2) | |
{ | |
var a1 = e1.Attribute (Include); | |
var a2 = e2.Attribute (Include); | |
if (a1 == null && a2 == null) return 0; | |
if (a1 == null) return 1; | |
if (a2 == null) return -1; | |
var v1 = a1.Value; | |
var v2 = a2.Value; | |
return comparison (v1, v2); | |
} | |
public static readonly ItemComparer Default = new ItemComparer ( | |
delegate (string v1, string v2) { | |
try { | |
var d1 = Path.GetDirectoryName (v1); | |
var d2 = Path.GetDirectoryName (v2); | |
var result = string.Compare (d1, d2, StringComparison.OrdinalIgnoreCase); | |
if (result != 0) return result; | |
var f1 = Path.GetFileName (v1); | |
var f2 = Path.GetFileName (v2); | |
result = string.Compare (f1, f2, StringComparison.OrdinalIgnoreCase); | |
return result; | |
} catch { | |
return string.Compare (v1, v2, StringComparison.OrdinalIgnoreCase); | |
} | |
}); | |
public static readonly ItemComparer FullName = new ItemComparer ( | |
delegate (string v1, string v2) { | |
return string.Compare (v1, v2, StringComparison.OrdinalIgnoreCase); | |
}); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment