Created
October 17, 2014 09:02
-
-
Save a-h/e49022a04050be0c6f69 to your computer and use it in GitHub Desktop.
Handle merge conflicts in NuGet packages.config files
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
using System.Xml.Serialization; | |
using System.IO; | |
public static class Program | |
{ | |
void Main() | |
{ | |
AcceptLatestPackages(@"C:\projects\MergeMigrations_AddTableB\"); | |
} | |
private void AcceptLatestPackages(string directory) | |
{ | |
foreach(var subdirectory in Directory.GetDirectories(directory)) | |
{ | |
AcceptLatestPackages(subdirectory); | |
} | |
foreach(var file in Directory.GetFiles(directory, "packages.config", SearchOption.AllDirectories)) | |
{ | |
string workingPackagesConfig = file + ".working"; | |
bool workingPackagesConfigExists = File.Exists(workingPackagesConfig); | |
string incomingPackagesConfig = Directory.GetFiles(directory, "packages.config.merge-right.*").FirstOrDefault(); | |
bool incomingPackagesConfigExists = string.IsNullOrEmpty(incomingPackagesConfig) ? false : File.Exists(incomingPackagesConfig); | |
if(workingPackagesConfigExists && incomingPackagesConfigExists) | |
{ | |
var updatedPackagesConfig = ResolveConflict(workingPackagesConfig, incomingPackagesConfig); | |
// Overwrite the packages.config file which has merge markers in it. | |
// e.g. | |
// <<<<<<< .working | |
// <package id="Newtonsoft.Json" version="6.0.4" targetFramework="net45" /> | |
// ======= | |
// <package id="Newtonsoft.Json" version="6.0.5" targetFramework="net45" /> | |
// >>>>>>> .merge-right.r44653 | |
Packages.Save(updatedPackagesConfig, file); | |
} | |
} | |
} | |
public Packages ResolveConflict(string workingPackagesConfig, string incomingPackagesConfig) | |
{ | |
var working = Packages.Load(workingPackagesConfig).ToDictionary(p => p.Id); | |
var incoming = Packages.Load(incomingPackagesConfig).ToDictionary(p => p.Id); | |
var toAddFromIncoming = new List<Package>(); | |
var toReplaceWithIncoming = new List<Package>(); | |
foreach(var incomingKey in incoming.Keys) | |
{ | |
if(working.ContainsKey(incomingKey)) | |
{ | |
// Check versions. | |
var workingPackage = working[incomingKey]; | |
var incomingPackage = incoming[incomingKey]; | |
// If the incoming version is higher, use it. | |
if(incomingPackage.Version.CompareTo(workingPackage.Version) > 0) | |
{ | |
toReplaceWithIncoming.Add(incomingPackage); | |
} | |
} | |
else | |
{ | |
// If there's a new package to merge, add it in. | |
toAddFromIncoming.Add(incoming[incomingKey]); | |
} | |
} | |
foreach(var itemToAdd in toAddFromIncoming) | |
{ | |
working.Add(itemToAdd.Id, itemToAdd); | |
} | |
foreach(var itemToReplace in toReplaceWithIncoming) | |
{ | |
working.Remove(itemToReplace.Id); | |
working.Add(itemToReplace.Id, itemToReplace); | |
} | |
var rv = new Packages(); | |
rv.AddRange(working.Select(g => g.Value).OrderBy(p => p.Id)); | |
return rv; | |
} | |
} | |
[XmlRoot("packages")] | |
public class Packages : List<Package> | |
{ | |
public static Packages Load(string fileName) | |
{ | |
using(var fs = new FileStream(fileName, FileMode.Open, FileAccess.Read)) | |
{ | |
var serializer = new XmlSerializer(typeof(Packages)); | |
return (Packages)serializer.Deserialize(fs); | |
} | |
} | |
public static void Save(Packages packages, string fileName) | |
{ | |
using(var fs = new FileStream(fileName, FileMode.Create, FileAccess.Write)) | |
{ | |
Save(packages, fs); | |
} | |
} | |
public static void Save(Packages packages, Stream fs) | |
{ | |
var serializer = new XmlSerializer(typeof(Packages)); | |
// Remove namespace attributes. | |
var ns = new XmlSerializerNamespaces(); | |
ns.Add("",""); | |
serializer.Serialize(fs, packages, ns); | |
} | |
public override string ToString() | |
{ | |
var ms = new MemoryStream(); | |
Packages.Save(this, ms); | |
return Encoding.UTF8.GetString(ms.ToArray()); | |
} | |
} | |
[XmlType("package")] | |
public class Package | |
{ | |
[XmlAttribute("id")] | |
public string Id { get; set; } | |
[XmlAttribute("version")] | |
public string Version { get; set; } | |
[XmlAttribute("targetFramework")] | |
public string TargetFramework { get; set; } | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment