Skip to content

Instantly share code, notes, and snippets.

@johannesegger
Created August 31, 2017 07:13
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save johannesegger/1c845a89aa59db89560633c2bc83ec83 to your computer and use it in GitHub Desktop.
Save johannesegger/1c845a89aa59db89560633c2bc83ec83 to your computer and use it in GitHub Desktop.
Nuke .sln parser
using System.Xml;
using System.Xml.Linq;
using System.Xml.XPath;
namespace Nuke.Common.Tools.VisualStudio
{
public class VSProject
{
public VSProject(string outputType, string assemblyName)
{
OutputType = outputType;
AssemblyName = assemblyName;
}
public string OutputType { get; }
public string AssemblyName { get; }
public static VSProject Parse(string path)
{
// TODO support new csproj format
var doc = XDocument.Load(path);
var nsMgr = new XmlNamespaceManager(new NameTable());
nsMgr.AddNamespace("x", "http://schemas.microsoft.com/developer/msbuild/2003");
var outputType = doc.XPathSelectElement("/x:Project/x:PropertyGroup/x:OutputType", nsMgr).Value;
var assemblyName = doc.XPathSelectElement("/x:Project/x:PropertyGroup/x:AssemblyName", nsMgr).Value;
return new VSProject(outputType, assemblyName);
}
}
}
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using Nuke.Core.Utilities;
namespace Nuke.Common.Tools.VisualStudio
{
public class VSSolution
{
public IReadOnlyCollection<Project> Projects { get; }
public VSSolution(IEnumerable<Project> projects)
{
Projects = projects.ToList();
}
public static VSSolution Parse(string path)
{
string guidExpr(string name) =>
$@"\{{(?<{Regex.Escape(name)}>[0-9a-fA-F]{{8}}-[0-9a-fA-F]{{4}}-[0-9a-fA-F]{{4}}-[0-9a-fA-F]{{4}}-[0-9a-fA-F]{{12}})\}}";
string quotedGuidExpr(string name) =>
$@"""{guidExpr(name)}""";
string quotedTextExpr(string name) =>
$@"""(?<{Regex.Escape(name)}>[^""]*)""";
var lines = File.ReadAllLines(path);
var childToParentMap = lines
.SkipWhile(line => !Regex.IsMatch(line, @"^\s*GlobalSection\(NestedProjects\) = preSolution$"))
.Skip(1)
.TakeWhile(line => !Regex.IsMatch(line, @"^\s*EndGlobalSection$"))
.Select(line => Regex.Match(line, $@"^\s*{guidExpr("child")}\s*=\s*{guidExpr("parent")}$"))
.ToDictionary(m => Guid.Parse(m.Groups["child"].Value), m => Guid.Parse(m.Groups["parent"].Value));
var projects = lines
.Select(line => Regex.Match(line, $@"^Project\({quotedGuidExpr("typeId")}\)\s*=\s*{quotedTextExpr("name")},\s*{quotedTextExpr("path")},\s*{quotedGuidExpr("id")}$"))
.Where(m => m.Success)
.Select(m =>
{
var id = Guid.Parse(m.Groups["id"].Value);
return new Project(
id,
m.Groups["name"].Value,
Path.GetFullPath(Path.Combine(Path.GetDirectoryName(path), m.Groups["path"].Value)),
Guid.Parse(m.Groups["typeId"].Value),
childToParentMap.TryGetValue(id, out var parentId) ? (Guid?)parentId : null);
})
.Where(p => p.Name != ".build");
return new VSSolution(projects);
}
public class Project
{
public Project(
Guid id,
string name,
string path,
Guid typeId,
Guid? parentId)
{
Id = id;
Name = name;
Path = path;
Directory = System.IO.Path.GetDirectoryName(Path);
TypeId = typeId;
ParentId = parentId;
}
public Guid Id { get; }
public string Name { get; }
public string Path { get; }
public string Directory { get; }
public Guid TypeId { get; }
public Guid? ParentId { get; }
public IEnumerable<Project> GetParents(IEnumerable<Project> projects)
{
var idToProjectMap = projects
.ToDictionary(p => p.Id, p => p);
var parentId = ParentId;
while (parentId != null)
{
var parent = idToProjectMap[parentId.Value];
yield return parent;
parentId = parent.ParentId;
}
}
public IEnumerable<Project> GetParentsAndSelf(IEnumerable<Project> projects)
{
yield return this;
foreach (var parent in GetParents(projects))
{
yield return parent;
}
}
public string GetFullProjectName(IEnumerable<Project> projects)
{
return GetParentsAndSelf(projects)
.Select(p => p.Name.Replace(".", "_"))
.Reverse()
.Join("\\");
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment