Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion build.fsx
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ Target "QuickIntegrationTests" (fun _ ->
// --------------------------------------------------------------------------------------
// Build a NuGet package

let mergeLibs = ["paket.exe"; "Paket.Core.dll"; "FSharp.Core.dll"; "Newtonsoft.Json.dll"; "Argu.dll"; "Chessie.dll"; "Mono.Cecil.dll"]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to ILMerge this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not for current platforms as it's part of netstandard, but might be needed to support older platforms and/or resolve discussed version conflict/s

let mergeLibs = ["paket.exe"; "Paket.Core.dll"; "FSharp.Core.dll"; "Newtonsoft.Json.dll"; "Argu.dll"; "Chessie.dll"]

Target "MergePaketTool" (fun _ ->
CreateDir buildMergedDir
Expand Down
2 changes: 1 addition & 1 deletion paket.dependencies
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ nuget Newtonsoft.Json redirects: force
nuget Argu >= 5.1.0
nuget FSharp.Core redirects: force
nuget Chessie >= 0.6
nuget Mono.Cecil prerelease
nuget System.Reflection.Metadata ~> 1.6.0 prerelease

nuget System.Security.Cryptography.ProtectedData

Expand Down
21 changes: 6 additions & 15 deletions paket.lock
Original file line number Diff line number Diff line change
Expand Up @@ -226,15 +226,6 @@ NUGET
NETStandard.Library (>= 1.6.1) - restriction: && (< monoandroid) (< monotouch) (< net46) (>= netstandard1.3) (< netstandard2.0) (< xamarinios) (< xamarinmac) (< xamarintvos) (< xamarinwatchos)
System.Security.AccessControl (>= 4.4) - restriction: || (>= monoandroid) (>= monotouch) (&& (< net46) (>= netstandard2.0)) (>= net461) (>= netcoreapp2.0) (>= xamarinios) (>= xamarinmac) (>= xamarintvos) (>= xamarinwatchos)
System.Security.Principal.Windows (>= 4.4) - restriction: || (>= monoandroid) (>= monotouch) (&& (< net46) (>= netstandard2.0)) (>= net461) (>= netcoreapp2.0) (>= xamarinios) (>= xamarinmac) (>= xamarintvos) (>= xamarinwatchos)
Mono.Cecil (0.10.0-beta6)
System.Collections (>= 4.0.11) - restriction: && (< net35) (>= netstandard1.3)
System.IO.FileSystem (>= 4.0.1) - restriction: && (< net35) (>= netstandard1.3)
System.IO.FileSystem.Primitives (>= 4.0.1) - restriction: && (< net35) (>= netstandard1.3)
System.Reflection (>= 4.1) - restriction: && (< net35) (>= netstandard1.3)
System.Runtime.Extensions (>= 4.1) - restriction: && (< net35) (>= netstandard1.3)
System.Security.Cryptography.Algorithms (>= 4.2) - restriction: && (< net35) (>= netstandard1.3)
System.Security.Cryptography.Csp (>= 4.0) - restriction: && (< net35) (>= netstandard1.3)
System.Threading (>= 4.0.11) - restriction: && (< net35) (>= netstandard1.3)
Moq (4.7.99)
Castle.Core (>= 4.1.1) - restriction: || (>= net45) (>= netstandard1.3)
NETStandard.Library (>= 1.6.1) - restriction: && (< net45) (>= netstandard1.3)
Expand Down Expand Up @@ -398,8 +389,8 @@ NUGET
System.Runtime.Extensions (>= 4.3) - restriction: || (&& (< monoandroid) (< monotouch) (< net45) (>= netstandard1.3) (< win8) (< wpa81) (< xamarinios) (< xamarinmac) (< xamarintvos) (< xamarinwatchos)) (< portable-net45+win8+wpa81)
System.Threading (>= 4.3) - restriction: || (&& (< monoandroid) (< monotouch) (< net45) (>= netstandard1.3) (< win8) (< wpa81) (< xamarinios) (< xamarinmac) (< xamarintvos) (< xamarinwatchos)) (< portable-net45+win8+wpa81)
System.Threading.Tasks (>= 4.3) - restriction: || (&& (< monoandroid) (< monotouch) (< net45) (>= netstandard1.3) (< win8) (< wpa81) (< xamarinios) (< xamarinmac) (< xamarintvos) (< xamarinwatchos)) (&& (< monoandroid) (< net45) (>= netstandard1.1) (< netstandard1.3) (< win8) (< wpa81)) (< portable-net45+win8+wpa81)
System.Collections.Immutable (1.4) - restriction: || (&& (>= monoandroid) (>= netcoreapp1.0)) (&& (>= monoandroid) (>= netcoreapp1.1)) (&& (>= monotouch) (>= netcoreapp1.0)) (&& (>= monotouch) (>= netcoreapp1.1)) (&& (>= netcoreapp1.0) (< netcoreapp1.1) (>= netstandard2.0)) (&& (>= netcoreapp1.0) (< netcoreapp1.1) (< netstandard2.0)) (&& (>= netcoreapp1.0) (< netstandard1.1)) (&& (>= netcoreapp1.0) (< portable-net45+win8)) (&& (>= netcoreapp1.0) (>= xamarinios)) (&& (>= netcoreapp1.0) (>= xamarinmac)) (&& (>= netcoreapp1.0) (>= xamarintvos)) (&& (>= netcoreapp1.0) (>= xamarinwatchos)) (&& (>= netcoreapp1.1) (< netcoreapp2.0) (>= netstandard2.0)) (&& (>= netcoreapp1.1) (< netstandard1.1)) (&& (>= netcoreapp1.1) (< netstandard2.0)) (&& (>= netcoreapp1.1) (< portable-net45+win8)) (&& (>= netcoreapp1.1) (>= xamarinios)) (&& (>= netcoreapp1.1) (>= xamarinmac)) (&& (>= netcoreapp1.1) (>= xamarintvos)) (&& (>= netcoreapp1.1) (>= xamarinwatchos))
NETStandard.Library (>= 1.6.1) - restriction: && (>= netstandard1.0) (< netstandard2.0) (< xamarinmac)
System.Collections.Immutable (1.5.0-rc1) - restriction: || (>= net45) (&& (< netcoreapp2.1) (>= netstandard2.0)) (&& (>= netstandard1.1) (< netstandard2.0) (< win8) (< wpa81)) (&& (< netstandard1.1) (>= portable-net45+win8+wpa81) (< win8)) (&& (< netstandard1.1) (>= win8)) (&& (< netstandard2.0) (>= wpa81))
NETStandard.Library (>= 1.6.1) - restriction: || (&& (< net45) (>= netstandard1.0) (< netstandard1.3) (< win8) (< wp8) (< wpa81)) (&& (< net45) (>= netstandard1.3) (< netstandard2.0) (< win8) (< wpa81))
System.Collections.NonGeneric (4.3) - redirects: force, restriction: || (&& (< monoandroid) (< monotouch) (< net20) (>= netstandard1.5) (< win8) (< wpa81) (< xamarinios) (< xamarinmac) (< xamarintvos) (< xamarinwatchos)) (&& (< monoandroid) (< net20) (< netstandard1.3) (>= netstandard1.5) (< win8) (< wpa81)) (&& (< net20) (>= net462))
System.Diagnostics.Debug (>= 4.3) - restriction: && (< monoandroid) (< monotouch) (< net46) (>= netstandard1.3) (< xamarinios) (< xamarinmac) (< xamarintvos) (< xamarinwatchos)
System.Globalization (>= 4.3) - restriction: && (< monoandroid) (< monotouch) (< net46) (>= netstandard1.3) (< xamarinios) (< xamarinmac) (< xamarintvos) (< xamarinwatchos)
Expand Down Expand Up @@ -819,9 +810,9 @@ NUGET
Microsoft.NETCore.Targets (>= 1.1) - restriction: || (&& (< monoandroid) (< monotouch) (< net45) (>= netstandard1.0) (< win8) (< wp8) (< wpa81) (< xamarinios) (< xamarinmac) (< xamarintvos) (< xamarinwatchos)) (< portable-net45+win8+wp8+wpa81)
System.Reflection (>= 4.3) - restriction: || (&& (< monoandroid) (< monotouch) (< net45) (>= netstandard1.0) (< win8) (< wp8) (< wpa81) (< xamarinios) (< xamarinmac) (< xamarintvos) (< xamarinwatchos)) (< portable-net45+win8+wp8+wpa81)
System.Runtime (>= 4.3) - restriction: || (&& (< monoandroid) (< monotouch) (< net45) (>= netstandard1.0) (< win8) (< wp8) (< wpa81) (< xamarinios) (< xamarinmac) (< xamarintvos) (< xamarinwatchos)) (< portable-net45+win8+wp8+wpa81)
System.Reflection.Metadata (1.5) - restriction: || (&& (>= netcoreapp1.0) (< netcoreapp1.1)) (&& (>= netcoreapp1.1) (< netcoreapp2.0))
NETStandard.Library (>= 1.6.1) - restriction: && (< monoandroid) (< monotouch) (>= netstandard1.1) (< netstandard2.0) (< xamarinios) (< xamarinmac) (< xamarintvos) (< xamarinwatchos)
System.Collections.Immutable (>= 1.4) - restriction: || (>= monoandroid) (>= monotouch) (&& (< netcoreapp2.0) (>= netstandard2.0)) (&& (>= netstandard1.1) (< netstandard2.0)) (&& (< netstandard1.1) (>= portable-net45+win8)) (&& (< portable-net45+win8) (>= portable-net45+win8+wpa81)) (>= xamarinios) (>= xamarinmac) (>= xamarintvos) (>= xamarinwatchos)
System.Reflection.Metadata (1.6.0-rc1)
NETStandard.Library (>= 1.6.1) - restriction: && (< net45) (>= netstandard1.1) (< netstandard2.0) (< win8) (< wpa81)
System.Collections.Immutable (>= 1.5.0-rc1) - restriction: || (>= net45) (&& (< netcoreapp2.1) (>= netstandard2.0)) (&& (>= netstandard1.1) (< netstandard2.0) (< win8) (< wpa81)) (&& (< netstandard1.1) (>= portable-net45+win8+wpa81) (< win8)) (&& (< netstandard1.1) (>= win8)) (&& (< netstandard2.0) (>= wpa81))
System.Reflection.Primitives (4.3) - restriction: || (&& (< monoandroid) (< monotouch) (< net45) (>= netstandard1.6) (< netstandard2.0) (< wpa81) (< xamarinios) (< xamarinmac) (< xamarintvos) (< xamarinwatchos)) (&& (< monoandroid) (< net45) (>= netstandard1.2) (< netstandard1.3) (< wpa81)) (&& (< monoandroid) (< net45) (>= netstandard1.3) (< netstandard1.4) (< wpa81)) (&& (< monoandroid) (< net45) (>= netstandard1.4) (< netstandard1.5) (< wpa81)) (&& (< monoandroid) (< net45) (>= netstandard1.5) (< netstandard1.6) (< wpa81)) (&& (< net45) (>= netstandard1.1) (< portable-net451+win81+wpa81)) (&& (>= netstandard1.0) (< portable-net45+win8+wpa81)) (&& (< netstandard1.5) (>= uap10.0) (< uap10.1))
Microsoft.NETCore.Platforms (>= 1.1) - restriction: || (&& (< monoandroid) (< monotouch) (< net45) (>= netstandard1.0) (< win8) (< wp8) (< wpa81) (< xamarinios) (< xamarinmac) (< xamarintvos) (< xamarinwatchos)) (< portable-net45+win8+wp8+wpa81)
Microsoft.NETCore.Targets (>= 1.1) - restriction: || (&& (< monoandroid) (< monotouch) (< net45) (>= netstandard1.0) (< win8) (< wp8) (< wpa81) (< xamarinios) (< xamarinmac) (< xamarintvos) (< xamarinwatchos)) (< portable-net45+win8+wp8+wpa81)
Expand Down Expand Up @@ -923,7 +914,7 @@ NUGET
System.Security.Cryptography.Encoding (>= 4.3) - restriction: || (&& (< monoandroid) (< monotouch) (< net46) (>= netstandard1.6) (< netstandard2.0) (< xamarinios) (< xamarinmac) (< xamarintvos) (< xamarinwatchos)) (&& (< monoandroid) (< net46) (>= netstandard1.4) (< netstandard1.6))
System.Security.Cryptography.Primitives (>= 4.3) - restriction: || (&& (< monoandroid) (< monotouch) (< net46) (>= netstandard1.6) (< netstandard2.0) (< xamarinios) (< xamarinmac) (< xamarintvos) (< xamarinwatchos)) (&& (< monoandroid) (< net46) (>= netstandard1.3) (< netstandard1.4)) (&& (< monoandroid) (< net46) (>= netstandard1.4) (< netstandard1.6)) (&& (>= net46) (< netstandard1.4))
System.Text.Encoding (>= 4.3) - restriction: || (&& (< monoandroid) (< monotouch) (< net46) (>= netstandard1.6) (< netstandard2.0) (< xamarinios) (< xamarinmac) (< xamarintvos) (< xamarinwatchos)) (&& (< monoandroid) (< net46) (>= netstandard1.4) (< netstandard1.6))
System.Security.Cryptography.Csp (4.3) - restriction: && (< net35) (>= netstandard1.3)
System.Security.Cryptography.Csp (4.3) - restriction: || (&& (>= netcoreapp1.0) (< netcoreapp1.1)) (&& (>= netcoreapp1.1) (< netcoreapp2.0))
Microsoft.NETCore.Platforms (>= 1.1) - restriction: && (< monoandroid) (< monotouch) (< net46) (>= netstandard1.3) (< xamarinios) (< xamarinmac) (< xamarintvos) (< xamarinwatchos)
System.IO (>= 4.3) - restriction: && (< monoandroid) (< monotouch) (< net46) (>= netstandard1.3) (< xamarinios) (< xamarinmac) (< xamarintvos) (< xamarinwatchos)
System.Reflection (>= 4.3) - restriction: && (< monoandroid) (< monotouch) (< net46) (>= netstandard1.3) (< xamarinios) (< xamarinmac) (< xamarintvos) (< xamarinwatchos)
Expand Down
1 change: 1 addition & 0 deletions src/Paket.Core.preview3/Paket.Core.fsproj
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
<Paket>True</Paket>
<Link>Globbing.fs</Link>
</Compile>
<Compile Include="$(PaketCoreSourcesDir)\Common\AssemblyMetadata.fs" />
<Compile Include="$(PaketCoreSourcesDir)\Common\Async.fs" />
<Compile Include="$(PaketCoreSourcesDir)\Common\Domain.fs" />
<Compile Include="$(PaketCoreSourcesDir)\Common\Logging.fsi" />
Expand Down
2 changes: 1 addition & 1 deletion src/Paket.Core.preview3/paket.references
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
Newtonsoft.Json
Mono.Cecil
System.Reflection.Metadata
Chessie
System.Security.Cryptography.ProtectedData

Expand Down
74 changes: 74 additions & 0 deletions src/Paket.Core/Common/AssemblyMetadata.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
module Paket.AssemblyMetadata

open Chessie.ErrorHandling
open System
open System.IO
open System.Globalization
open System.Reflection
open System.Reflection
open System.Reflection.Metadata
open System.Reflection.PortableExecutable

/// Calculates the short form of the public key token for use with binding redirects, if it exists.
let getPublicKeyToken (assembly:AssemblyName) =
("", assembly.GetPublicKeyToken())
||> Array.fold(fun state b -> state + b.ToString("X2"))
|> function
| "" -> None
| token -> Some (token.ToLower())

/// Creates AssemblyName of AssemblyReference opened on the MetadataReader;
/// expected to be part of next release of the Metadata support, so we can remove this.
/// Can throw AccessViolation if used incorrectly, with unrelated or disposed reader.
let private getAssemblyName (reader:MetadataReader) (reference:AssemblyReference) =
let assemblyName = reader.GetString(reference.Name)
let cultureInfo =
if reference.Culture.IsNil then null
else CultureInfo(reader.GetString(reference.Culture))
let hasPublicKey = reference.Flags.HasFlag(AssemblyFlags.PublicKey)
let assemblyFlag =
if hasPublicKey then AssemblyNameFlags.PublicKey else AssemblyNameFlags.None
let assemblyName =
new AssemblyName(
Name = assemblyName,
Flags = assemblyFlag,
Version = reference.Version,
CultureInfo = cultureInfo)
let keyOrToken =
let keyOrTokenHandle = reference.PublicKeyOrToken
if keyOrTokenHandle.IsNil then null else reader.GetBlobBytes(keyOrTokenHandle)
if hasPublicKey then
assemblyName.SetPublicKey(keyOrToken)
else
assemblyName.SetPublicKeyToken(keyOrToken)
assemblyName;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

semicolon?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

still new to F# :) is this incorrect? I prefer using semicolon when using a variable like this, just to make it the return value

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

usually we leave out semicolons ;)


type AssemblyDefinition =
| AssemblyFile of String
| AssemblyInfo of FileInfo
| AssemblyName of AssemblyName

/// Uses the assembly file metadata from the provided source,
/// to return AssemblyName list of its referenced assemblies.
let getAssemblyReferences (assembly:AssemblyDefinition) =
try
let assemblyFilePath =
match assembly with
| AssemblyFile file -> file
| AssemblyInfo info -> info.FullName
| AssemblyName name -> Uri(name.CodeBase).LocalPath
use file = File.OpenRead(assemblyFilePath)
use reader = new PEReader(file, PEStreamOptions.PrefetchMetadata)
let metadataReader = reader.GetMetadataReader()
metadataReader.AssemblyReferences
|> Seq.map (fun aref ->
try
let reference = metadataReader.GetAssemblyReference(aref)
pass(getAssemblyName metadataReader reference)
with
| ex -> fail ex)
|> collect
with
| ex -> fail ex


8 changes: 0 additions & 8 deletions src/Paket.Core/Installation/BindingRedirects.fs
Original file line number Diff line number Diff line change
Expand Up @@ -194,11 +194,3 @@ let applyBindingRedirectsToFolder isFirstGroup createNewBindingFiles cleanBindin

for p in projects do
applyBindingRedirects p

/// Calculates the short form of the public key token for use with binding redirects, if it exists.
let getPublicKeyToken (assembly:Mono.Cecil.AssemblyDefinition) =
("", assembly.Name.PublicKeyToken)
||> Array.fold(fun state b -> state + b.ToString("X2"))
|> function
| "" -> None
| token -> Some (token.ToLower())
32 changes: 23 additions & 9 deletions src/Paket.Core/Installation/InstallProcess.fs
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,18 @@
module Paket.InstallProcess

open Paket
open System
open Chessie.ErrorHandling
open Paket
open Paket.Domain
open Paket.Logging
open Paket.BindingRedirects
open System.IO
open Paket.PackageSources
open Paket.Requirements
open ProviderImplementation.AssemblyReader
open System.Collections.Generic
open System
open System.Reflection

let updatePackagesConfigFile (model: Map<GroupName*PackageName,SemVerInfo*InstallSettings>) packagesConfigFileName =
let packagesInConfigFile = PackagesConfigFile.Read packagesConfigFileName
Expand Down Expand Up @@ -293,20 +296,31 @@ let private applyBindingRedirects isFirstGroup createNewBindingFiles cleanBindin
librariesForPackage
|> Seq.choose(fun (library,redirects,profile) ->
try
let assembly = Mono.Cecil.AssemblyDefinition.ReadAssembly(library.Path)
Some (assembly, BindingRedirects.getPublicKeyToken assembly, assembly.MainModule.AssemblyReferences, redirects, profile)
let assemblyName = AssemblyName.GetAssemblyName(library.Path)
let publicKeyToken = AssemblyMetadata.getPublicKeyToken assemblyName
let metadataName = AssemblyMetadata.AssemblyName assemblyName
let references =
match AssemblyMetadata.getAssemblyReferences metadataName with
| Trial.Pass list -> list
| Trial.Warn(list, warn) ->
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where does Trial.Warn come from?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Chessie – it seemed convenient to use here

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But I don't see it emitted, so this case can never happen, correct?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AFAIK it can be produced in getAssemblyReferences by the pass|fail –> collect pipeline

warn |> List.iter (fun ex -> ex |> string |> traceWarn)
list
| Trial.Fail exns ->
exns |> List.iter (fun ex -> ex |> string |> traceError)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Depending on the scenarios where this happens (traceError and traceWarn) we might need to restrict this to verbose mode later.
Any idea when this happens?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it should only happen on metadata errors, not really expected – it might be safely restricted to one-time warning or error though

List.empty
Copy link
Member

@matthid matthid May 29, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is List.empty the correct thing to do here?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

probably not – should I just re-throw here?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably yes, it will be caught with an evil with _ -> None below. We probably should add some logging there (at the very least in verbose mode)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it would get double-logged then -- but I think we can do a throw with inner exception here to keep the original info/stack and get it logged in the caller only

Some (assemblyName, publicKeyToken, references, redirects, profile)
with _ -> None)
|> Seq.sortBy(fun (assembly,_,_,_,_) -> assembly.Name.Version)
|> Seq.sortBy(fun (assembly,_,_,_,_) -> assembly.Version)
|> Seq.toList
|> List.rev
|> function | head :: _ -> Some head | _ -> None)
|> Seq.cache

let referencesDifferentProfiles (assemblyName : Mono.Cecil.AssemblyNameDefinition) profile =
let referencesDifferentProfiles (assemblyName : AssemblyName) profile =
(targetProfiles |> Seq.exists ((=) profile))
&& assemblies
|> Seq.filter (fun (_,_,_,_,p) -> p <> profile)
|> Seq.map (fun (a,_,_,_,_) -> a.Name)
|> Seq.map (fun (a,_,_,_,_) -> a)
|> Seq.filter (fun a -> a.Name = assemblyName.Name)
|> Seq.exists (fun a -> a.Version <> assemblyName.Version)

Expand All @@ -320,16 +334,16 @@ let private applyBindingRedirects isFirstGroup createNewBindingFiles cleanBindin
| Some BindingRedirectsSettings.Off -> false
| _ -> false)
|> Seq.filter (fun (assembly,_,_,redirects,profile) ->
let assemblyName = assembly.Name
let assemblyName = assembly
redirects = Some BindingRedirectsSettings.Force
|| referencesDifferentProfiles assemblyName profile
|| assemblies
|> Seq.collect (fun (_,_,refs,_,_) -> refs)
|> Seq.filter (fun a -> assemblyName.Name = a.Name)
|> Seq.exists (fun a -> assemblyName.Version > a.Version))
|> Seq.map(fun (assembly, token,_,_,_) ->
{ BindingRedirect.AssemblyName = assembly.Name.Name
Version = assembly.Name.Version.ToString()
{ BindingRedirect.AssemblyName = assembly.Name
Version = assembly.Version.ToString()
PublicKeyToken = token
Culture = None })
|> Seq.sort
Expand Down
Loading