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)
new XElement(AssemblyIdentityElementName, {
new XAttribute(NameAttributeName, redirect.From.Name), dependencyElement = new XElement(DependentAssemblyElementName,
new XAttribute(PublicKeyTokenAttributeName, redirect.From.PublicKeyToken), new XElement(AssemblyIdentityElementName,
new XAttribute(CultureAttributeName, culture) new XAttribute(NameAttributeName, redirect.From.Name),
), new XAttribute(PublicKeyTokenAttributeName, redirect.From.PublicKeyToken),
new XElement(BindingRedirectElementName, new XAttribute(CultureAttributeName, redirect.From.Culture)
)
);
assemblyBindings.Add(dependencyElement);
}
dependencyElement.Add(new XElement(BindingRedirectElementName,
new XAttribute(OldVersionAttributeName, redirect.From.Version), new XAttribute(OldVersionAttributeName, redirect.From.Version),
new XAttribute(NewVersionAttributeName, redirect.To.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)
@ -109,15 +143,12 @@ namespace Microsoft.DotNet.Tools.Compiler
var metadataReader = peReader.GetMetadataReader(); var metadataReader = peReader.GetMetadataReader();
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);
} }
} }
} }