Created
July 12, 2013 10:20
-
-
Save mavnn/5983379 to your computer and use it in GitHub Desktop.
Read the blog post at: http://blog.mavnn.co.uk/coding-hygiene-moving-from-project-references-to-nuget-dependencies/
This file contains hidden or 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
| #r "System.Xml.Linq" | |
| #r "tools\FAKE\FakeLib.dll" | |
| open System.IO | |
| open System.Xml | |
| open System.Xml.Linq | |
| open System.Xml.XPath | |
| open Fake | |
| // You'll want to replace these values... | |
| let nugetId = "my.package.id" | |
| let refName = "my.ref.name" | |
| let packageNode = XElement.Parse """<package id="my.package.id" version="1.0.0.6" targetFramework="net40" />""" | |
| let refXml = | |
| """ | |
| <Reference Include="my.ref.name"> | |
| <HintPath>..\..\packages\my.package.id.1.0.0.6\lib\net40\my.ref.name.dll</HintPath> | |
| <Private>True</Private> | |
| </Reference> | |
| """ | |
| let hintPathFromRoot = | |
| @"packages\my.package.id.1.0.0.6\lib\net40\my.ref.name.dll" | |
| let sourceRoot = "C:\WhereIKeepMyRepo" | |
| // You should be able to leave the rest alone | |
| let ns = "http://schemas.microsoft.com/developer/msbuild/2003" | |
| let nsm = new XmlNamespaceManager(new NameTable()) | |
| nsm.AddNamespace("ns", ns) | |
| let nugetPath = sourceRoot @@ "tools" @@ "NuGet" @@ "NuGet.exe" | |
| let HasProjectReference (projDoc : XDocument) refName = | |
| projDoc.Root.XPathSelectElements("//ns:ProjectReference[ns:Name='" + refName + "']", nsm) | |
| |> Seq.length | |
| |> (<) 0 | |
| let GetProjectReference (projDoc : XDocument) refName = | |
| projDoc.Root.XPathSelectElement("//ns:ProjectReference[ns:Name='" + refName + "']", nsm) | |
| let DeleteProjectReference refName (projFile : string) = | |
| let projDoc = XDocument.Load(projFile) | |
| if HasProjectReference projDoc refName then | |
| let ref = GetProjectReference projDoc refName | |
| ref.Remove() | |
| projDoc.Save(projFile) | |
| let HasReference (projDoc : XDocument) refName = | |
| projDoc.Root.XPathSelectElements("//ns:Reference[@Include='" + refName + "']", nsm) | |
| |> Seq.append <| projDoc.Root.XPathSelectElements("//ns:Reference[@Include[starts-with(., '" + refName + ",')]]", nsm) | |
| |> Seq.tryPick (fun e -> Some e) | |
| let FirstReference (projDoc : XDocument) = | |
| projDoc.Root.XPathSelectElements("//ns:Reference", nsm) | |
| |> Seq.head | |
| let GetHintPath hintPathFromRoot root projFile = | |
| let rootDir = DirectoryInfo(root) | |
| let projDir = DirectoryInfo(Path.GetDirectoryName(projFile)) | |
| let rec dirDiff (rootDir : DirectoryInfo) (currentDir : DirectoryInfo) levels = | |
| if rootDir.FullName = currentDir.FullName then | |
| levels | |
| else | |
| dirDiff rootDir (currentDir.Parent) (levels + 1) | |
| hintPathFromRoot::[for _ in 1..(dirDiff rootDir projDir 0) -> ".."] | |
| |> List.rev | |
| |> List.fold (@@) "." | |
| let UpdateHintPath projFile = | |
| let ref = XElement.Parse(refXml) | |
| let xs = XNamespace.Get(ns) | |
| let el = ref.XPathSelectElement("//HintPath") | |
| el.SetValue (GetHintPath hintPathFromRoot sourceRoot projFile) | |
| for node in ref.DescendantsAndSelf() do | |
| node.Name <- xs + node.Name.LocalName | |
| ref | |
| let EnsureReference refName (projFile : string) = | |
| let doc = XDocument.Load(projFile) | |
| match HasReference doc refName with | |
| | Some el -> el.Remove() | |
| | None -> () | |
| let el = FirstReference doc | |
| el.AddBeforeSelf(UpdateHintPath projFile) | |
| doc.Save(projFile) | |
| type PackageFile = | |
| | Exists of string | |
| | Missing of string | |
| let GetPackagesDotConfig projFile = | |
| let dir = Path.GetDirectoryName(projFile) | |
| let path = dir @@ "packages.config" | |
| if File.Exists(path) then | |
| Exists path | |
| else | |
| Missing path | |
| let HasPackageReference (doc : XDocument) nugetId = | |
| doc.XPathSelectElements("//package[@id = '" + nugetId + "']") | |
| |> Seq.length | |
| |> (<) 0 | |
| let EnsurePackagesDotConfigHasPackage nugetId projFile = | |
| let doc, path = | |
| match GetPackagesDotConfig projFile with | |
| | Missing path -> | |
| XDocument.Parse("<packages />"), path | |
| | Exists path -> | |
| XDocument.Load(path), path | |
| if not <| HasPackageReference doc nugetId then | |
| doc.Root.XPathSelectElement("/packages").Add(packageNode) | |
| doc.Save path | |
| let UpdateProj (projFile : string) = | |
| if HasProjectReference (XDocument.Load(projFile)) refName then | |
| DeleteProjectReference refName projFile | |
| EnsureReference refName projFile | |
| EnsurePackagesDotConfigHasPackage nugetId projFile | |
| !+ (@"**\*.csproj") | |
| ++ (@"**\*.fsproj") | |
| ++ (@"**\*.vbproj") | |
| |> Scan | |
| |> Seq.map (fun proj -> printfn "Updating %s" proj; proj) | |
| |> Seq.iter UpdateProj |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment