Skip to content

Instantly share code, notes, and snippets.

@mavnn
Created July 12, 2013 10:20
Show Gist options
  • Select an option

  • Save mavnn/5983379 to your computer and use it in GitHub Desktop.

Select an option

Save mavnn/5983379 to your computer and use it in GitHub Desktop.
#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