Read original app.config and add to it

This commit is contained in:
Pavel Krymets 2015-12-10 08:58:18 -08:00
parent 1115fc22fa
commit 91acc03a13
2 changed files with 81 additions and 35 deletions

View file

@ -34,43 +34,77 @@ namespace Microsoft.DotNet.Tools.Compiler
private readonly SHA1 _sha1 = SHA1.Create(); private readonly SHA1 _sha1 = SHA1.Create();
public XDocument Generate(IEnumerable<LibraryExport> dependencies) public XDocument Generate(IEnumerable<LibraryExport> dependencies, XDocument document)
{ {
var redirects = CollectRedirects(dependencies); var redirects = CollectRedirects(dependencies);
if (!redirects.Any()) if (!redirects.Any())
{ {
// No redirects required // No redirects required
return null; return document;
}
document = document ?? new XDocument();
var configuration = GetOrAddElement(document, ConfigurationElementName);
var runtime = GetOrAddElement(configuration, RuntimeElementName);
var assemblyBindings = GetOrAddElement(runtime, AssemblyBindingElementName);
foreach (var redirect in redirects)
{
AddDependentAssembly(redirect, assemblyBindings);
} }
var document = new XDocument(
new XElement(ConfigurationElementName,
new XElement(RuntimeElementName,
new XElement(AssemblyBindingElementName,
redirects.Select(GetDependentAssembly)
)
)
)
);
return document; return document;
} }
private XElement GetDependentAssembly(AssemblyRedirect redirect) private void AddDependentAssembly(AssemblyRedirect redirect, XElement assemblyBindings)
{ {
var culture = string.IsNullOrEmpty(redirect.From.Culture) ? "neutral" : redirect.From.Culture; var dependencyElement = assemblyBindings.Elements(DependentAssemblyElementName)
.FirstOrDefault(element => IsSameAssembly(redirect, element));
return new XElement(DependentAssemblyElementName, if (dependencyElement == null)
{
dependencyElement = new XElement(DependentAssemblyElementName,
new XElement(AssemblyIdentityElementName, new XElement(AssemblyIdentityElementName,
new XAttribute(NameAttributeName, redirect.From.Name), new XAttribute(NameAttributeName, redirect.From.Name),
new XAttribute(PublicKeyTokenAttributeName, redirect.From.PublicKeyToken), new XAttribute(PublicKeyTokenAttributeName, redirect.From.PublicKeyToken),
new XAttribute(CultureAttributeName, culture) new XAttribute(CultureAttributeName, redirect.From.Culture)
),
new XElement(BindingRedirectElementName,
new XAttribute(OldVersionAttributeName, redirect.From.Version),
new XAttribute(NewVersionAttributeName, redirect.To.Version)
) )
); );
assemblyBindings.Add(dependencyElement);
}
dependencyElement.Add(new XElement(BindingRedirectElementName,
new XAttribute(OldVersionAttributeName, redirect.From.Version),
new XAttribute(NewVersionAttributeName, redirect.To.Version)
));
}
private bool IsSameAssembly(AssemblyRedirect redirect, XElement dependentAssemblyElement)
{
var identity = dependentAssemblyElement.Element(AssemblyIdentityElementName);
if (identity == null)
{
return false;
}
return (string) identity.Attribute(NameAttributeName) == redirect.From.Name &&
(string) identity.Attribute(PublicKeyTokenAttributeName) == redirect.From.PublicKeyToken &&
(string) identity.Attribute(CultureAttributeName) == redirect.From.Culture;
}
public static XElement GetOrAddElement(XContainer parent, XName elementName)
{
XElement element;
if (parent.Element(elementName) != null)
{
element = parent.Element(elementName);
}
else
{
element = new XElement(elementName);
parent.Add(element);
}
return element;
} }
private AssemblyRedirect[] CollectRedirects(IEnumerable<LibraryExport> dependencies) private AssemblyRedirect[] CollectRedirects(IEnumerable<LibraryExport> dependencies)
@ -110,14 +144,11 @@ namespace Microsoft.DotNet.Tools.Compiler
var definition = metadataReader.GetAssemblyDefinition(); var definition = metadataReader.GetAssemblyDefinition();
var publicKey = metadataReader.GetBlobBytes(definition.PublicKey);
var publicKeyToken = GetPublicKeyToken(publicKey);
var identity = new AssemblyIdentity( var identity = new AssemblyIdentity(
metadataReader.GetString(definition.Name), metadataReader.GetString(definition.Name),
definition.Version, definition.Version,
metadataReader.GetString(definition.Culture), metadataReader.GetString(definition.Culture),
publicKeyToken GetPublicKeyToken(metadataReader.GetBlobBytes(definition.PublicKey))
); );
var references = new List<AssemblyIdentity>(metadataReader.AssemblyReferences.Count); var references = new List<AssemblyIdentity>(metadataReader.AssemblyReferences.Count);
@ -184,7 +215,7 @@ namespace Microsoft.DotNet.Tools.Compiler
{ {
Name = name; Name = name;
Version = version; Version = version;
Culture = culture; Culture = string.IsNullOrEmpty(culture)? "neutral" : culture;
PublicKeyToken = publicKeyToken; PublicKeyToken = publicKeyToken;
} }

View file

@ -6,7 +6,7 @@ using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Xml.Linq;
using Microsoft.Dnx.Runtime.Common.CommandLine; using Microsoft.Dnx.Runtime.Common.CommandLine;
using Microsoft.DotNet.Cli.Utils; using Microsoft.DotNet.Cli.Utils;
using Microsoft.DotNet.Cli.Compiler.Common; using Microsoft.DotNet.Cli.Compiler.Common;
@ -507,17 +507,32 @@ namespace Microsoft.DotNet.Tools.Compiler
private static void GenerateBindingRedirects(ProjectContext runtimeContext, string outputPath, LibraryExporter exporter) private static void GenerateBindingRedirects(ProjectContext runtimeContext, string outputPath, LibraryExporter exporter)
{ {
var generator = new BindingRedirectGenerator(); var appConfigNames = new[] { "app.config", "App.config" };
var config = generator.Generate(exporter.GetAllExports()); XDocument baseAppConfig = null;
if (config != null) foreach (var appConfigName in appConfigNames)
{
var baseAppConfigPath = Path.Combine(runtimeContext.ProjectDirectory, appConfigName);
if (File.Exists(baseAppConfigPath))
{
using (var fileStream = File.OpenRead(baseAppConfigPath))
{
baseAppConfig = XDocument.Load(fileStream);
break;
}
}
}
var generator = new BindingRedirectGenerator();
var appConfig = generator.Generate(exporter.GetAllExports(), baseAppConfig);
if (appConfig != null)
{ {
// TODO: Handle existing App.config file transformation
// We have something to generate
var path = Path.Combine(outputPath, runtimeContext.ProjectFile.Name + ".exe.config"); var path = Path.Combine(outputPath, runtimeContext.ProjectFile.Name + ".exe.config");
using (var stream = File.Create(path)) using (var stream = File.Create(path))
{ {
config.Save(stream); appConfig.Save(stream);
} }
} }
} }