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);
        }
Exemple #3
0
        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);
        }
Exemple #4
0
        /// <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);
        }