예제 #1
0
        private static bool TryReadLegacyManifest(IPackageFile manifestFile, IPackage package, ILogger logger, out InstallScript installScript)
        {
            installScript = new InstallScript();
            var scripts  = new List <InstallItem>();
            var manifest = new XmlDocument();

            using (var manifestStream = manifestFile.Open())
                manifest.Load(manifestStream);

            foreach (var pkg in manifest.DocumentElement.Elements("package"))
            {
                if (string.IsNullOrEmpty(installScript.Title))
                {
                    installScript.Title = pkg.Attribute("name", "");
                }
                var folderPath = pkg.Attribute("path");
                if (folderPath == ".\\")
                {
                    folderPath = Utils.CleanFileName(pkg.Attribute("name", "")).Replace('.', '\\');
                }
                foreach (var file in package.Files()
                         .Where(f => f.Path.StartsWith(folderPath + "/", StringComparison.OrdinalIgnoreCase) &&
                                f.Path.EndsWith(".xml", StringComparison.OrdinalIgnoreCase)))
                {
                    try
                    {
                        var doc = new XmlDocument(manifest.NameTable);
                        using (var stream = file.Open())
                            doc.Load(stream);

                        var items = doc.DocumentElement.LocalName == "Item"
              ? new[] { doc.DocumentElement }
              : doc.DocumentElement.Elements("Item");
                        foreach (var item in items)
                        {
                            scripts.Add(InstallItem.FromScript(item, file.Path));
                        }
                    }
                    catch (Exception ex)
                    {
                        ex.Data["path"] = file.Path;
                        throw;
                    }
                }
            }

            installScript.Lines = scripts;
            return(CleanKeyedNames(installScript.Lines, logger));
        }
예제 #2
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);
        }
예제 #3
0
        private static bool TryReadPackage(IPackageFile manifestFile, IPackage package, ILogger logger, out InstallScript installScript)
        {
            installScript = new InstallScript();
            var result   = true;
            var scripts  = new List <InstallItem>();
            var manifest = new XmlDocument();

            using (var manifestStream = manifestFile.Open())
                manifest.Load(manifestStream);

            if (manifest.DocumentElement.HasAttribute("created"))
            {
                installScript.Created = DateTime.Parse(manifest.DocumentElement.GetAttribute("created"));
            }
            installScript.Creator     = manifest.DocumentElement.GetAttribute("creator");
            installScript.Description = manifest.DocumentElement.GetAttribute("description");
            if (manifest.DocumentElement.HasAttribute("modified"))
            {
                installScript.Modified = DateTime.Parse(manifest.DocumentElement.GetAttribute("modified"));
            }
            installScript.Version = manifest.DocumentElement.GetAttribute("revision");
            installScript.Title   = manifest.DocumentElement.GetAttribute("title");
            if (manifest.DocumentElement.HasAttribute("website"))
            {
                installScript.Website = new Uri(manifest.DocumentElement.GetAttribute("website"));
            }

            foreach (var child in manifest.DocumentElement.ChildNodes.OfType <XmlElement>())
            {
                if (child.LocalName == "Item")
                {
                    scripts.Add(InstallItem.FromScript(child));
                }
                else
                {
                    var currPath = child.GetAttribute("path");
                    var files    = Enumerable.Empty <IPackageFile>();
                    if (currPath == "*")
                    {
                        files = package.Files();
                        installScript.DependencySorted = false;
                    }
                    else if (!string.IsNullOrEmpty(currPath))
                    {
                        if (package.TryAccessFile(currPath, false, out var file))
                        {
                            files = new[] { file };
                        }
                        else
                        {
                            result = false;
                            logger.LogError("The file {Path} is referenced in the manifest, but not found in the package.", currPath);
                            continue;
                        }
                    }

                    var reportXmlPaths = new HashSet <string>(files
                                                              .Where(f => f.Path.EndsWith(".xslt", StringComparison.OrdinalIgnoreCase))
                                                              .Select(f => f.Path + ".xml"), StringComparer.OrdinalIgnoreCase);

                    foreach (var file in files
                             .Where(f => !reportXmlPaths.Contains(f.Path)))
                    {
                        try
                        {
                            var doc = new XmlDocument(manifest.NameTable);
                            using (var writer = doc.CreateNavigator().AppendChild())
                                file.WriteAml(package, writer);
                            var items = doc.DocumentElement.LocalName == "Item"
                ? new[] { doc.DocumentElement }
                : doc.DocumentElement.Elements("Item");
                            foreach (var item in items)
                            {
                                scripts.Add(InstallItem.FromScript(item, file.Path));
                            }
                        }
                        catch (XmlException ex)
                        {
                            result = false;
                            logger.LogError(ex, "The AML script at {Path} is malformed", file.Path);
                        }
                        catch (Exception ex)
                        {
                            ex.Data["path"] = file.Path;
                            throw;
                        }
                    }
                }
            }

            installScript.Lines = scripts;
            result = CleanKeyedNames(installScript.Lines, logger) || result;
            return(result);
        }