Skip to content

Commit

Permalink
DllPackageFragmentInstaller - fixing an issue when it installs an inc…
Browse files Browse the repository at this point in the history
…orrect assembly binding that breaks the site
  • Loading branch information
napernik committed Feb 19, 2016
1 parent d216b6d commit 3b110f2
Showing 1 changed file with 30 additions and 56 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@
using System.Linq;
using System.Reflection;
using System.Xml.Linq;
using Composite.Core.Extensions;
using Composite.Core.IO;
using Composite.Core.Types;
using Composite.Core.Xml;

using Texts = Composite.Core.ResourceSystem.LocalizationFiles.Composite_Core_PackageSystem_PackageFragmentInstallers;
Expand Down Expand Up @@ -185,8 +183,8 @@ public override IEnumerable<XElement> Install()
{
Verify.IsNotNull(_filesToCopy, "{0} has not been validated", this.GetType().Name);

var dependencies = new List<Pair<string, Version>>();
var asmBindingsToAdd = new List<AssemblyBindingInfo>();
var asmBindingsToAdd = new List<AssemblyName>();


var fileElements = new List<XElement>();
foreach (FileToCopy fileToCopy in _filesToCopy)
Expand All @@ -199,11 +197,10 @@ public override IEnumerable<XElement> Install()
this.InstallerContext.ZipFileSystem.WriteFileToDisk(fileToCopy.SourceFilename, tempFileName);

// Checking for dll version here:
var sourceFileVersionInfo = FileVersionInfo.GetVersionInfo(tempFileName);
var sourceFileVersion = GetDllProductVersion(tempFileName);

dependencies.Add(new Pair<string, Version>(fileToCopy.TargetRelativeFilePath, sourceFileVersion));

var sourceAssemblyName = AssemblyName.GetAssemblyName(tempFileName);
var sourceAssemblyVersion = sourceAssemblyName.Version;
var sourceFileVersion = GetDllFileVersion(tempFileName);

string targetDirectory = Path.GetDirectoryName(fileToCopy.TargetFilePath);
if (!Directory.Exists(targetDirectory))
{
Expand All @@ -216,25 +213,28 @@ public override IEnumerable<XElement> Install()

if (C1File.Exists(fileToCopy.TargetFilePath) && fileToCopy.Overwrite)
{
var existingFileVersion = GetDllProductVersion(fileToCopy.TargetFilePath);
var existingAssemblyVersion = AssemblyName.GetAssemblyName(fileToCopy.TargetFilePath).Version;
var existingFileVersion = GetDllFileVersion(fileToCopy.TargetFilePath);

if (existingFileVersion == sourceFileVersion)
if (existingAssemblyVersion == sourceAssemblyVersion
&& existingFileVersion >= sourceFileVersion)
{
Log.LogInformation(LogTitle,
"Skipping installation for file '{0}' version '{1}'. A file with the same version already exists.",
fileToCopy.TargetRelativeFilePath, sourceFileVersion);
"Skipping installation for file '{0}' version '{1}'. An assembly with the same version already exists.",
fileToCopy.TargetRelativeFilePath, sourceAssemblyVersion);
continue;
}

if (existingFileVersion > sourceFileVersion)
if (existingAssemblyVersion > sourceAssemblyVersion)
{
Log.LogInformation(LogTitle,
"Skipping installation for file '{0}' version '{1}', as a file with a newer version '{2}' already exists.",
fileToCopy.TargetRelativeFilePath, sourceFileVersion, existingFileVersion);
fileToCopy.TargetRelativeFilePath, sourceAssemblyVersion, existingAssemblyVersion);
continue;
}

addAssemblyBinding = true;
addAssemblyBinding = existingAssemblyVersion < sourceAssemblyVersion;

if ((C1File.GetAttributes(fileToCopy.TargetFilePath) & FileAttributes.ReadOnly) > 0)
{
FileUtils.RemoveReadOnly(fileToCopy.TargetFilePath);
Expand All @@ -257,12 +257,7 @@ public override IEnumerable<XElement> Install()

if (addAssemblyBinding)
{
asmBindingsToAdd.Add(new AssemblyBindingInfo
{
FilePath = fileToCopy.TargetFilePath,
FileVersionInfo = sourceFileVersionInfo,
VersionInfo = sourceFileVersion
});
asmBindingsToAdd.Add(sourceAssemblyName);
}


Expand All @@ -286,26 +281,27 @@ public override IEnumerable<XElement> Install()
yield return new XElement("Files", fileElements);
}

private Version GetDllProductVersion(string dllFilePath)
private Version GetDllFileVersion(string dllFilePath)
{
var fileVersionInfo = FileVersionInfo.GetVersionInfo(dllFilePath);
return new Version(
fileVersionInfo.ProductMajorPart,
fileVersionInfo.ProductMinorPart,
fileVersionInfo.ProductBuildPart);
fileVersionInfo.FileMajorPart,
fileVersionInfo.FileMinorPart,
fileVersionInfo.FileBuildPart,
fileVersionInfo.FilePrivatePart);
}

private void UpdateBindingRedirects(IEnumerable<AssemblyBindingInfo> changedFiles)
private void UpdateBindingRedirects(IEnumerable<AssemblyName> assemblyNames)
{
string webConfigPath = PathUtil.Resolve("~/web.config");

var webConfig = XDocument.Load(webConfigPath);

var assemblyBindingConfig = new AssemblyBindingConfiguration(webConfig);

foreach (var file in changedFiles)
foreach (var assemblyName in assemblyNames)
{
assemblyBindingConfig.AddRedirectsForAssembly(file.FilePath, file.FileVersionInfo, file.VersionInfo);
assemblyBindingConfig.AddRedirectsForAssembly(assemblyName);
}

assemblyBindingConfig.SaveIfChanged(webConfigPath);
Expand All @@ -320,13 +316,6 @@ private string GetBackupFileName(string targetFilePath)
return directory.GetHashCode() + "_" + fileName;
}

private class AssemblyBindingInfo
{
public FileVersionInfo FileVersionInfo;
public Version VersionInfo;
public string FilePath;
}


private sealed class FileToCopy
{
Expand Down Expand Up @@ -378,22 +367,10 @@ private DependantAssembly[] GetDependantAssemblies()
.ToArray();
}

public void AddRedirectsForAssembly(string filePath, FileVersionInfo fileVersionInfo, Version version)
public void AddRedirectsForAssembly(AssemblyName assemblyName)
{
string newTargetVersionStr = "{0}.{1}.{2}.0".FormatWith(version.Major, version.Minor, version.Build);

AssemblyName assemblyName;

try
{
assemblyName = AssemblyName.GetAssemblyName(filePath);
}
catch (Exception ex)
{
Log.LogWarning(LogTitle, "Failed to get assembly name for dll '{0}'", fileVersionInfo.InternalName ?? fileVersionInfo.FileName);
Log.LogWarning(LogTitle, ex);
return;
}
var version = assemblyName.Version;
string newTargetVersionStr = assemblyName.Version.ToString();

var existingBinding = GetDependantAssemblies().FirstOrDefault(a => a.Name == assemblyName.Name);

Expand All @@ -406,14 +383,11 @@ public void AddRedirectsForAssembly(string filePath, FileVersionInfo fileVersion
}

var oldRedirectToVersion = new Version(existingBinding.NewVersion);
if (oldRedirectToVersion.Major == version.Major
&& oldRedirectToVersion.Minor == version.Minor
&& oldRedirectToVersion.Build == version.Build)
if (oldRedirectToVersion == version)
{
return;
}


existingBinding.OldVersion = "0.0.0.0-" + newTargetVersionStr;
existingBinding.NewVersion = newTargetVersionStr;

Expand Down Expand Up @@ -444,7 +418,7 @@ private string GetPublicKeyToken(AssemblyName assemblyName)

return publicKeyTokenBytes == null || publicKeyTokenBytes.Length == 0
? "null"
: string.Join("", publicKeyTokenBytes.Select(b => string.Format("{0:x2}", b)));
: string.Join("", publicKeyTokenBytes.Select(b => $"{b:x2}"));
}

public void SaveIfChanged(string fileName)
Expand Down

0 comments on commit 3b110f2

Please sign in to comment.