Skip to content

Instantly share code, notes, and snippets.

@alexshikov
Last active April 11, 2016 11:51
Show Gist options
  • Save alexshikov/5e222ea9a251252a65aa58a14e57438c to your computer and use it in GitHub Desktop.
Save alexshikov/5e222ea9a251252a65aa58a14e57438c to your computer and use it in GitHub Desktop.
A script to exchange all MvvmCross or/and MvvmCross-Plugins NuGet dependencies on local binaries

How to use

Let's assume we want to test local changes of MvvmCross in one of MvvmCross-Samples projects.

Steps:

  1. Clone MvvmCross and MvvmCross-Samples into a folder
  2. Make changes to MvvmCross and rebuild all in Debug mode
  3. Assuming we want to test changes on ValueConvertion project, copy use_loca_mvx.fsx into MvvmCross-Samples/ValueConvertion folder
  4. Execute fsharpi use_local_mvx.fsx
  5. Clone MvvmCross-Plugins into the same folder to test plugin changes

How it works

The script is very dumb. You can either run it without parameters or provide -mvx:<path to /bin/Mvx folder> or/and -mvx-plugins:<path to /bin/Mvx>.

If no parameters specified, the script tries to look up for MvvmCross and MvvmCross-Plugins in parent folders.

Then script goes through each *.csproj file inside project folders and iterates string-lines looking up for MvvmCross library mentions. When library found and local MvvmCross folder specified, the script replaces folder reference.

ToDo

Test script on Windows

open System
open System.IO
open System.Linq
open System.Collections.Generic
let mutable mvxPath: string = ""
let mutable mvxPluginsPath: string = ""
// List of csproj files
let projectFiles =
Directory.GetFiles(".", "*.csproj", SearchOption.AllDirectories)
// return MvvmCross or MvvmCross-Plugins path depending on matching ".Plugin." in the path
let getReplacmentPath (path:string) =
let result =
match path with
| x when x.Contains(".Plugin.") -> mvxPluginsPath
| _ -> mvxPath
result
// Return updated path if Mvx or Plugin replacement provided
let pointTo (path: string, platform: string) =
let newPath = getReplacmentPath(path)
let result =
match newPath with
| "" -> path // Do nothing
| x -> Path.Combine(x, platform)
result
// Here is where magic goes
// Update single line from NuGet reference to local MvvmCross folder
let switchToLocal (line:string) =
// example of NuGet package path
// ..\packages\MvvmCross.Platform.4.0.0-beta8\lib\Xamarin.iOS10\MvvmCross.Platform.iOS.dll
// extract path from MSBuild line
let path = line.Replace("<HintPath>", "").Replace("</HintPath>", "").Replace("\\", "/").Trim()
let fileName = Path.GetFileNameWithoutExtension(path)
let dir = Path.GetDirectoryName(path)
let newDirPath =
match fileName with
| x when x.EndsWith("iOS") -> pointTo(dir, "iOS")
| x when x.EndsWith("Droid") -> pointTo(dir, "Droid")
| x when x.EndsWith("Mac") -> pointTo(dir, "Mac")
| x when x.EndsWith("Console") -> pointTo(dir, "Console")
| _ -> pointTo(dir, "Portable")
// rebuild line to match MSBuild pattern
let newPath = Path.Combine(newDirPath, Path.GetFileName (path)).Replace("/","\\")
"<HintPath>" + newPath + "</HintPath>"
// Process single line
let processLine (line:string) =
match line.Contains("MvvmCross") && line.Contains("<HintPath>") with
| true -> switchToLocal line
| false -> line
// store updated lines to file
let writeLinesToFile (outputFile:string, lines:IEnumerable<string>) =
File.WriteAllLines(outputFile, lines)
let store outputFile lines =
writeLinesToFile(outputFile,lines)
// Project file processor
let processProjectFile (file:string) =
let outputFile = file.Replace(".csproj", ".csproj")
let storeToFile = store outputFile
File.ReadAllLines(file)
|> Seq.map processLine
|> storeToFile
// entry processor
let startProcessing() =
projectFiles
|> Seq.iter processProjectFile
let rec lookupFolder root child =
let found =
Directory.GetDirectories(root)
|> Seq.filter (fun e -> Path.GetFileName(e) = child)
|> Seq.tryHead
let result =
match found with
| Some x -> Path.Combine(root, child)
| None ->
match root with
| x when Path.GetPathRoot(x) = x -> ""
| x ->
let parent = Directory.GetParent(root).FullName
lookupFolder parent child
result
// Auto-lookup for MvvmCross and MvvmCross-Plugins in root folders
let lookupFolderInParents dirName =
let current = Directory.GetCurrentDirectory()
let mutable result = lookupFolder current dirName
if result <> "" then
result <- Path.Combine(result, "bin", "Debug", "Mvx")
result
// parse single argument
let parseArgument(arg: string) =
if arg.StartsWith ("-mvx:") then
mvxPath <- arg.Substring ("-mvx:".Length)
if arg.StartsWith ("-mvx-plugins:") then
mvxPluginsPath <- arg.Substring ("-mvx-plugins:".Length)
// parse arguments
let parseArgs args =
for arg in args do
parseArgument arg
// Entry point
let run args =
parseArgs args
// auto-lookup for MvvmCross in parents
if mvxPath = "" then
printfn "-mvx parameter is not specified. Looking for MvvmCross path in parent folders"
mvxPath <- lookupFolderInParents "MvvmCross"
// auto-lookup for MvvmCross-Plugins in parents
if mvxPluginsPath = "" then
printfn "-mvx-plugins parameter is not specified. Looking for MvvmCross-Plugins path in parent folders"
mvxPluginsPath <- lookupFolderInParents "MvvmCross-Plugins"
printfn " MvvmCross path: %s" mvxPath
printfn " MvvmCross-Plugins path: %s" mvxPluginsPath
// start process
startProcessing()
// main
run fsi.CommandLineArgs
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment