Skip to content

Commit

Permalink
Merge pull request #188 from ikvm-revived/hotfix/8.2.2
Browse files Browse the repository at this point in the history
Use SHA1, MD5 and MVID to speed up IkvmIdentity calculation
  • Loading branch information
wasabii authored Oct 25, 2022
2 parents fa66d3e + 9cd821a commit 79755a9
Showing 1 changed file with 46 additions and 5 deletions.
51 changes: 46 additions & 5 deletions src/IKVM.MSBuild.Tasks/IkvmReferenceItemPrepare.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@
using System.IO;
using System.Linq;
using System.Reflection;
using System.Reflection.Metadata;
using System.Reflection.PortableExecutable;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;

using IKVM.Util.Jar;
using IKVM.Util.Modules;
Expand Down Expand Up @@ -336,13 +339,13 @@ internal string CalculateIkvmIdentity(IkvmReferenceItem item)
var manifest = new StringWriter();
manifest.WriteLine("ToolVersion={0}", ToolVersion);
manifest.WriteLine("TargetFramework={0}", TargetFramework);
manifest.WriteLine("RuntimeAssembly={0}", GetHashForFile(RuntimeAssembly));
manifest.WriteLine("RuntimeAssembly={0}", GetIdentityForFile(RuntimeAssembly));
manifest.WriteLine("AssemblyName={0}", item.AssemblyName);
manifest.WriteLine("AssemblyVersion={0}", item.AssemblyVersion);
manifest.WriteLine("AssemblyFileVersion={0}", item.AssemblyFileVersion);
manifest.WriteLine("ClassLoader={0}", item.ClassLoader);
manifest.WriteLine("Debug={0}", item.Debug ? "true" : "false");
manifest.WriteLine("KeyFile={0}", string.IsNullOrWhiteSpace(item.KeyFile) == false ? GetHashForFile(item.KeyFile) : "");
manifest.WriteLine("KeyFile={0}", string.IsNullOrWhiteSpace(item.KeyFile) == false ? GetIdentityForFile(item.KeyFile) : "");
manifest.WriteLine("DelaySign={0}", item.DelaySign ? "true" : "false");

// each Compile item should be a jar or class file
Expand Down Expand Up @@ -396,13 +399,30 @@ string GetHashForString(string value)
/// </summary>
/// <param name="file"></param>
/// <returns></returns>
string GetHashForFile(string file)
string GetIdentityForFile(string file)
{
if (string.IsNullOrWhiteSpace(file))
throw new ArgumentException($"'{nameof(file)}' cannot be null or whitespace.", nameof(file));
if (File.Exists(file) == false)
throw new FileNotFoundException($"Could not find file '{file}'.");

// file might have a companion SHA1 hash, let's use it, no calculation required
var sha1File = file + ".sha1";
if (File.Exists(sha1File))
if (File.ReadAllText(sha1File) is string h)
return $"SHA1:{Regex.Match(h.Trim(), @"^([\w\-]+)").Value}";

// file might have a companion MD5 hash, let's use it, no calculation required
var md5File = file + ".md5";
if (File.Exists(md5File))
if (File.ReadAllText(md5File) is string h)
return $"MD5:{Regex.Match(h.Trim(), @"^([\w\-]+)").Value}";

// if the file is potentially a .NET assembly
if (Path.GetExtension(file) == ".dll" || Path.GetExtension(file) == ".exe")
if (TryGetIdentityForAssembly(file) is string h)
return h;

using var stm = File.OpenRead(file);
var hsh = md5.ComputeHash(stm);
var bld = new StringBuilder(hsh.Length * 2);
Expand All @@ -412,6 +432,27 @@ string GetHashForFile(string file)
return bld.ToString();
}

/// <summary>
/// Attempts to get an identity value for a file that might be an assembly.
/// </summary>
/// <param name="file"></param>
/// <returns></returns>
string TryGetIdentityForAssembly(string file)
{
try
{
using var fsstm = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.Read);
using var perdr = new PEReader(fsstm);
var mrdr = perdr.GetMetadataReader();
var mvid = mrdr.GetGuid(mrdr.GetModuleDefinition().Mvid);
return $"MVID:{mvid}";
}
catch
{
return null;
}
}

/// <summary>
/// Writes a File entry for the given path.
/// </summary>
Expand All @@ -425,7 +466,7 @@ string GetCompileLine(IkvmReferenceItem item, string path)
if (File.Exists(path) == false)
throw new FileNotFoundException($"Cannot generate hash for missing file '{path}' on '{item.ItemSpec}'.");

return $"Compile={GetHashForFile(path)}";
return $"Compile={GetIdentityForFile(path)}";
}

/// <summary>
Expand All @@ -448,7 +489,7 @@ string GetReferenceLine(IkvmReferenceItem item, ITaskItem reference)
if (File.Exists(reference.ItemSpec) == false)
throw new FileNotFoundException($"Could not find reference file '{reference.ItemSpec}'.");

return $"Reference={GetHashForFile(reference.ItemSpec)}";
return $"Reference={GetIdentityForFile(reference.ItemSpec)}";
}

/// <summary>
Expand Down

0 comments on commit 79755a9

Please sign in to comment.