public static IEnumerable <InstallItemDiff> GetDiffs(IEnumerable <InstallItem> left, IEnumerable <InstallItem> right) { var leftList = left.Where(i => i.Type != InstallType.Warning).ToArray(); var rightList = right.Where(i => i.Type != InstallType.Warning).ToArray(); var compares = ListCompare.Create(leftList, rightList, i => i.Reference); var results = new List <InstallItemDiff>(); foreach (var compare in compares) { if (compare.Base < 0) { results.Add(new InstallItemDiff() { _itemRef = rightList[compare.Compare].Reference, _type = rightList[compare.Compare].Type, DiffType = DiffType.RightOnly, RightScript = rightList[compare.Compare].Script }); } else if (compare.Compare < 0) { results.Add(new InstallItemDiff() { _itemRef = leftList[compare.Base].Reference, _type = leftList[compare.Base].Type, DiffType = DiffType.LeftOnly, LeftScript = leftList[compare.Base].Script }); } else { results.Add(new InstallItemDiff() { _itemRef = leftList[compare.Base].Reference, _type = leftList[compare.Base].Type, DiffType = (AmlDiff.IsDifferent(new XmlNodeReader(leftList[compare.Base].Script), new XmlNodeReader(rightList[compare.Compare].Script)) ? DiffType.Different : DiffType.Identical), LeftScript = leftList[compare.Base].Script, RightScript = rightList[compare.Compare].Script }); } } return(results); }
public static PackageMetadataProvider WriteAmlMergeScripts(this IDiffDirectory baseDir, IDiffDirectory compareDir , Func <string, int, XmlWriter> callback = null) { Func <IDiffFile, IComparable> keyGetter = i => i.Path.Replace('\\', '/').TrimStart('/'); var basePaths = baseDir.GetFiles().OrderBy(keyGetter).ToArray(); var comparePaths = compareDir.GetFiles().OrderBy(keyGetter).ToArray(); var completed = 0; var total = basePaths.Length + comparePaths.Length; var result = new List <FileDiff>(); var metadata = new PackageMetadataProvider(); basePaths.MergeSorted(comparePaths, keyGetter, (i, b, c) => { try { var path = (c ?? b).Path; if (path.EndsWith(".xslt.xml") || path.EndsWith(".innpkg")) { return; } completed++; switch (i) { case -1: // Delete using (var baseStream = ReadFile(b, p => Array.Find(basePaths, f => f.Path == p))) using (var writer = callback(path, completed * 100 / total)) { var elem = AmlDiff.GetMergeScript(baseStream, null); if (elem.Elements().Any()) { elem.WriteTo(writer); } } break; case 1: // Add using (var baseStream = ReadFile(c, p => Array.Find(comparePaths, f => f.Path == p))) { var elem = XElement.Load(baseStream); IdentityMergeToAdd(elem); if (ItemAddToIgnore(elem)) { return; } using (var writer = callback(path, completed * 100 / total)) { elem.WriteTo(writer); metadata.Add(elem); } } break; default: // Edit total--; using (var baseStream = ReadFile(b, p => Array.Find(basePaths, f => f.Path == p))) using (var compareStream = ReadFile(c, p => Array.Find(comparePaths, f => f.Path == p))) using (var writer = callback(path, completed * 100 / total)) { var baseElem = Utils.LoadXml(baseStream); var compareElem = Utils.LoadXml(compareStream); metadata.Add(compareElem); var elem = AmlDiff.GetMergeScript(baseElem, compareElem); if (elem.Elements().Any()) { elem.WriteTo(writer); } } break; } } catch (XmlException ex) { ex.Data["Index"] = i; if (b != null) { ex.Data["BasePath"] = b.Path; } if (c != null) { ex.Data["ComparePath"] = c.Path; } throw; } }); return(metadata); }
public static PackageMetadataProvider WriteAmlMergeScripts(this IDiffDirectory baseDir, IDiffDirectory compareDir , Func <string, int, XmlWriter> callback = null) { Func <IDiffFile, IComparable> keyGetter = i => i.Path; var basePaths = baseDir.GetFiles().OrderBy(keyGetter).ToArray(); var comparePaths = compareDir.GetFiles().OrderBy(keyGetter).ToArray(); var completed = 0; var total = basePaths.Length + comparePaths.Length; var result = new List <FileDiff>(); var metadata = new PackageMetadataProvider(); basePaths.MergeSorted(comparePaths, keyGetter, (i, b, c) => { try { var path = (c ?? b).Path; if (path.EndsWith(".xslt.xml") || path.EndsWith(".innpkg")) { return; } completed++; switch (i) { case -1: // Delete using (var baseStream = ReadFile(b, p => Array.Find(basePaths, f => f.Path == p))) using (var writer = callback(path, completed * 100 / total)) { var elem = AmlDiff.GetMergeScript(baseStream, null); if (elem.Elements().Any()) { elem.WriteTo(writer); } } break; case 1: // Add using (var baseStream = c.OpenRead()) using (var writer = callback(path, completed * 100 / total)) { var elem = XElement.Load(baseStream); elem.WriteTo(writer); metadata.Add(elem); } break; default: // Edit total--; using (var baseStream = ReadFile(b, p => Array.Find(basePaths, f => f.Path == p))) using (var compareStream = ReadFile(c, p => Array.Find(comparePaths, f => f.Path == p))) using (var writer = callback(path, completed * 100 / total)) { var baseElem = Utils.LoadXml(baseStream); var compareElem = Utils.LoadXml(compareStream); metadata.Add(compareElem); var elem = AmlDiff.GetMergeScript(baseElem, compareElem); if (elem.Elements().Any()) { elem.WriteTo(writer); } } break; } } catch (XmlException ex) { throw new XmlException(string.Format("{0} ({1}, {2}, {3})", ex.Message, i, b.Path, c.Path), ex); } }); return(metadata); }
/// <summary> /// Writes the difference between two directories /// </summary> /// <param name="baseDir">The base directory which needs to be transformed</param> /// <param name="compareDir">The comparison directory which is what the base directoy should look like after transformation</param> /// <param name="callback">Gets an XML writer to write the merge script given the path and current progress (integer between 0 and 100)</param> /// <returns>Metadata regarding the target state</returns> public static PackageMetadataProvider WriteAmlMergeScripts(this IPackage baseDir, IPackage compareDir , Func <string, int, XmlWriter> callback) { Func <IPackageFile, IComparable> keyGetter = i => i.Path.ToUpperInvariant().Replace('\\', '/').TrimStart('/'); var basePaths = baseDir.Files().OrderBy(keyGetter).ToList(); var comparePaths = compareDir.Files().OrderBy(keyGetter).ToList(); var completed = 0; var total = basePaths.Count + comparePaths.Count; var metadata = new PackageMetadataProvider(); var baseScripts = new List <AmlScript>(); var compareScripts = new List <AmlScript>(); Action <MergeType, AmlScript, AmlScript> mergeScripts = (type, baseScript, compareScript) => { switch (type) { case MergeType.StartOnly: // Delete completed++; using (var writer = callback(baseScript.Path, completed * 100 / total)) { var elem = AmlDiff.GetMergeScript(baseScript.Script, null); if (elem.Elements().Any()) { elem.WriteTo(writer); } } break; case MergeType.DestinationOnly: // Add completed++; using (var writer = callback(compareScript.Path, completed * 100 / total)) { compareScript.Script.WriteTo(writer); metadata.Add(compareScript.Script); } break; default: total--; completed++; var path = compareScript.Path; if (!string.Equals(baseScript.Path, compareScript.Path, StringComparison.OrdinalIgnoreCase) && !string.IsNullOrEmpty(compareScript.Id) && baseScript.Path.IndexOf(compareScript.Id) >= 0) { path = baseScript.Path; } using (var writer = callback(path, completed * 100 / total)) { metadata.Add(compareScript.Script); var elem = AmlDiff.GetMergeScript(baseScript.Script, compareScript.Script); if (elem.Elements().Any()) { elem.WriteTo(writer); } } break; } }; basePaths.MergeSorted(comparePaths, keyGetter, (type, baseFile, compareFile) => { try { var path = (compareFile ?? baseFile).Path; if (path.EndsWith(".xslt.xml", StringComparison.OrdinalIgnoreCase) || path.EndsWith(".innpkg", StringComparison.OrdinalIgnoreCase)) { return; } switch (type) { case MergeType.StartOnly: // Delete var baseScript = new AmlScript(baseFile, baseDir); if (baseScript.Key == null) { mergeScripts(type, baseScript, null); } else { baseScripts.Add(baseScript); } break; case MergeType.DestinationOnly: // Add var compareScript = new AmlScript(compareFile, compareDir); IdentityMergeToAdd(compareScript.Script); if (ItemAddToIgnore(compareScript.Script)) { return; } if (compareScript.Key == null) { mergeScripts(type, null, compareScript); } else { compareScripts.Add(compareScript); } break; default: // Edit baseScript = new AmlScript(baseFile, baseDir); compareScript = new AmlScript(compareFile, compareDir); if (baseScript.Key == compareScript.Key) { mergeScripts(type, baseScript, compareScript); } else { baseScripts.Add(baseScript); compareScripts.Add(compareScript); } break; } } catch (XmlException ex) { ex.Data["MergeType"] = type.ToString(); if (baseFile != null) { ex.Data["BasePath"] = baseFile.Path; } if (compareFile != null) { ex.Data["ComparePath"] = compareFile.Path; } throw; } }); baseScripts = baseScripts.OrderBy(s => s.Key).ToList(); compareScripts = compareScripts.OrderBy(s => s.Key).ToList(); baseScripts.MergeSorted(compareScripts, s => s.Key, mergeScripts); return(metadata); }