/// <summary> /// Write the latest version of the XML definition file. /// Always refer to the schema location as a relative path to the bam executable. /// Always reference the default namespace in the first element. /// Don't use a namespace prefix on child elements, as the default namespace covers them. /// </summary> public void Write() { if (System.IO.File.Exists(this.XMLFilename)) { var attributes = System.IO.File.GetAttributes(this.XMLFilename); if (0 != (attributes & System.IO.FileAttributes.ReadOnly)) { throw new Exception("File '{0}' cannot be written to as it is read only", this.XMLFilename); } } this.Dependents.Sort(); var document = new System.Xml.XmlDocument(); var namespaceURI = "http://www.buildamation.com"; var packageDefinition = document.CreateElement("PackageDefinition", namespaceURI); { var xmlns = "http://www.w3.org/2001/XMLSchema-instance"; var schemaAttribute = document.CreateAttribute("xsi", "schemaLocation", xmlns); var mostRecentSchemaRelativePath = "./Schema/BamPackageDefinitionV1.xsd"; schemaAttribute.Value = System.String.Format("{0} {1}", namespaceURI, mostRecentSchemaRelativePath); packageDefinition.Attributes.Append(schemaAttribute); packageDefinition.SetAttribute("name", this.Name); if (null != this.Version) { packageDefinition.SetAttribute("version", this.Version); } } document.AppendChild(packageDefinition); // package description if (!string.IsNullOrEmpty(this.Description)) { var descriptionElement = document.CreateElement("Description", namespaceURI); descriptionElement.InnerText = this.Description; packageDefinition.AppendChild(descriptionElement); } // package repositories var packageRepos = new StringArray(this.PackageRepositories); // TODO: could these be marked as transient? // don't write out the repo that this package resides in packageRepos.Remove(this.GetPackageRepository()); // nor an associated repo for tests var associatedRepo = this.GetAssociatedPackageDirectoryForTests(); if (null != associatedRepo) { packageRepos.Remove(associatedRepo); } if (packageRepos.Count > 0) { var packageRootsElement = document.CreateElement("PackageRepositories", namespaceURI); var bamDir = this.GetBamDirectory() + System.IO.Path.DirectorySeparatorChar; // slash added to make it look like a directory foreach (string repo in packageRepos) { var relativePackageRepo = RelativePathUtilities.GetPath(repo, bamDir); if (OSUtilities.IsWindowsHosting) { // standardize on non-Windows directory separators relativePackageRepo = relativePackageRepo.Replace(System.IO.Path.DirectorySeparatorChar, System.IO.Path.AltDirectorySeparatorChar); } var rootElement = document.CreateElement("Repo", namespaceURI); rootElement.SetAttribute("dir", relativePackageRepo); packageRootsElement.AppendChild(rootElement); } packageDefinition.AppendChild(packageRootsElement); } if (this.Dependents.Count > 0) { var dependentsEl = document.CreateElement("Dependents", namespaceURI); foreach (var package in this.Dependents) { var packageName = package.Item1; var packageVersion = package.Item2; var packageIsDefault = package.Item3; System.Xml.XmlElement packageElement = null; { var node = dependentsEl.FirstChild; while (node != null) { var attributes = node.Attributes; var nameAttribute = attributes["Name"]; if ((null != nameAttribute) && (nameAttribute.Value == packageName)) { packageElement = node as System.Xml.XmlElement; break; } node = node.NextSibling; } } if (null == packageElement) { packageElement = document.CreateElement("Package", namespaceURI); packageElement.SetAttribute("name", packageName); if (null != packageVersion) { packageElement.SetAttribute("version", packageVersion); } if (packageIsDefault.HasValue) { packageElement.SetAttribute("default", packageIsDefault.Value.ToString().ToLower()); } dependentsEl.AppendChild(packageElement); } } packageDefinition.AppendChild(dependentsEl); } if (this.BamAssemblies.Count > 0) { var requiredAssemblies = document.CreateElement("BamAssemblies", namespaceURI); foreach (var assembly in this.BamAssemblies) { var assemblyElement = document.CreateElement("BamAssembly", namespaceURI); assemblyElement.SetAttribute("name", assembly.Name); if (assembly.MajorVersion.HasValue) { assemblyElement.SetAttribute("major", assembly.MajorVersion.ToString()); if (assembly.MinorVersion.HasValue) { assemblyElement.SetAttribute("minor", assembly.MinorVersion.ToString()); if (assembly.PatchVersion.HasValue) { // honour any existing BamAssembly with a specific patch version assemblyElement.SetAttribute("patch", assembly.PatchVersion.ToString()); } } } requiredAssemblies.AppendChild(assemblyElement); } packageDefinition.AppendChild(requiredAssemblies); } if (this.DotNetAssemblies.Count > 0) { var requiredDotNetAssemblies = document.CreateElement("DotNetAssemblies", namespaceURI); foreach (var desc in this.DotNetAssemblies) { var assemblyElement = document.CreateElement("DotNetAssembly", namespaceURI); assemblyElement.SetAttribute("name", desc.Name); if (null != desc.RequiredTargetFramework) { assemblyElement.SetAttribute("requiredTargetFramework", desc.RequiredTargetFramework); } requiredDotNetAssemblies.AppendChild(assemblyElement); } packageDefinition.AppendChild(requiredDotNetAssemblies); } // supported platforms { var supportedPlatformsElement = document.CreateElement("SupportedPlatforms", namespaceURI); if (EPlatform.Windows == (this.SupportedPlatforms & EPlatform.Windows)) { var platformElement = document.CreateElement("Platform", namespaceURI); platformElement.SetAttribute("name", "Windows"); supportedPlatformsElement.AppendChild(platformElement); } if (EPlatform.Linux == (this.SupportedPlatforms & EPlatform.Linux)) { var platformElement = document.CreateElement("Platform", namespaceURI); platformElement.SetAttribute("name", "Linux"); supportedPlatformsElement.AppendChild(platformElement); } if (EPlatform.OSX == (this.SupportedPlatforms & EPlatform.OSX)) { var platformElement = document.CreateElement("Platform", namespaceURI); platformElement.SetAttribute("name", "OSX"); supportedPlatformsElement.AppendChild(platformElement); } packageDefinition.AppendChild(supportedPlatformsElement); } // definitions this.Definitions.Remove(this.GetPackageDefinitionName()); if (this.Definitions.Count > 0) { var definitionsElement = document.CreateElement("Definitions", namespaceURI); foreach (string define in this.Definitions) { var defineElement = document.CreateElement("Definition", namespaceURI); defineElement.SetAttribute("name", define); definitionsElement.AppendChild(defineElement); } packageDefinition.AppendChild(definitionsElement); } var xmlWriterSettings = new System.Xml.XmlWriterSettings(); xmlWriterSettings.Indent = true; xmlWriterSettings.CloseOutput = true; xmlWriterSettings.OmitXmlDeclaration = false; xmlWriterSettings.NewLineOnAttributes = false; xmlWriterSettings.NewLineChars = "\n"; xmlWriterSettings.ConformanceLevel = System.Xml.ConformanceLevel.Document; xmlWriterSettings.Encoding = new System.Text.UTF8Encoding(false); using (var xmlWriter = System.Xml.XmlWriter.Create(this.XMLFilename, xmlWriterSettings)) { document.WriteTo(xmlWriter); xmlWriter.WriteWhitespace(xmlWriterSettings.NewLineChars); } if (this.validate) { this.Validate(); } }