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)); }
/// <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); }
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); }