Rewrite the document to describe only existing behavior
authorVitek Karas <vitek.karas@microsoft.com>
Thu, 13 Feb 2020 12:00:26 +0000 (04:00 -0800)
committerVitek Karas <vitek.karas@microsoft.com>
Thu, 13 Feb 2020 12:00:26 +0000 (04:00 -0800)
The doc was originally written as a proposal for a behavior change. So it's hard to read and determine the current behavior. Since the new behavior has been in place since 2.1, it's more valuable to have only the current version described.

docs/design/features/assembly-conflict-resolution.md

index 472043a..f0c752d 100644 (file)
@@ -2,9 +2,7 @@
 # Assembly Conflict Resolution
 
 ## Summary
-This document describes current and proposed behavior for dealing with references to assemblies that exist physically in more than one location including the "app" location and "framework" location(s). It proposes moving from "app wins" to "framework wins" during a [minor] or [major] roll-forward when the framework has a newer version of the given assembly.
-
-The corresponding issue is https://github.com/dotnet/core-setup/issues/3546.
+This document describes current behavior for dealing with references to assemblies that exist physically in more than one location including the "app" location and "framework" location(s).
 
 ## Current behavior
 
@@ -34,25 +32,18 @@ The order in which each layer's deps.json is processed is:
 
 #### Algorithm
 1. Determine the probing paths
-1. For each entry in the app's deps.json
-1. ->For each probing path
-1. -->If the probing path is a framework, then check its deps.json to see if it contains the exact package (by name and version). If so, then use the framework's location and end probing for this entry
-1. -->If the probing path is not a framework, then use that location and end probing for this entry
-1. Read the additional deps from `--additional-deps` and repeat steps 3-5
-1. Read each framework's deps.json (higher to lower) and repeat steps 3-5
+1. For each entry in the app's `.deps.json`
+1. ->If there's already a resolved entry with the same asset name, then check the assembly and file version of the new entry against the already resolved one. If the new entry is equal or lower, skip it. Otherwise remove the existing one and go to the "else" branch below
+1. ->Else (new asset, or replaced with higher version) probe for the actual asset file
+1. -->For each probing path except frameworks that are higher-level
+1. --->If the probing path is a framework, then check its `.deps.json` to see if it contains the exact package (by name and version). If it is, then use that location and end probing for this entry.
+1. --->If the probing path is not a framework, then use that location and end probing for this entry
+1. Read the additional deps from `--additional-deps` and repeat steps 3-7
+1. Read each framework's deps.json (higher to lower) and repeat steps 3-7
 1. Pass the set of assemblies and their paths to the CLR
 
-Note that for an app, its probing path comes *after* the framework's, so intuitively it would appear that "framework wins" in collisions. However, because the app's deps.json is parsed *before* the framework's deps.json and because the app will likely reference an OOB package that the framework doesn't (because a framework, at least Microsoft.NETCore.App, has its own metapackage and does not reference OOB packages), the framework probing path never matches up in step 4 for the app's deps.json package\assembly entry, so it goes to the next probing path which is the app's and because the package matches the "app wins".
-
-## Changes for 2.1+
-Probe the app location before the framework's. This means flip (3) and (4) under **Probe Ordering** above and treat the app as the highest-level framework. The reason is that there may be frameworks that use OOB packages like apps, and we want to have "app wins" in non roll-forward cases.
-
-Replace step 3 under **Algorithm** above with:
-* For each probing path except frameworks that are higher-level
-
-The reason for this change is that a given framework should never have a dependency on a higher-level framework, and is expected to find deps assets in its layer or lower. This is also required so that the given framework can find its asset, and replace the higher-level asset (see next paragraph).
+Note that for an app both it's `.deps.json` as well as probing path comes before the framework's so mostly it will win. Also because the app will likely reference an OOB package that the framework doesn't (because a framework, at least Microsoft.NETCore.App, has its own metapackage and does not reference OOB packages), the framework probing path never matches up in step 4 for the app's `.deps.json` package\assembly entry, so the "app wins".
 
-Replace step 4 under **Algorithm** above with:
-* If the probing path is a framework, then check its deps.json to see if it contains the exact package (by name and version). If so check if a [minor] or [major] roll-forward occurred for this framework. If true (roll-forward), then check its deps.json to see if it contains a newer version of the assembly (by Assembly Version and then File Version if necessary) compared to a previously found deps entry and use that and end probing for this entry. If false (no roll-forward), then use that location and end probing for this entry.
+The reason for only probing paths from equal or lower level framework in step 3 is that a given framework should never have a dependency on a higher-level framework, and is expected to find deps assets in its layer or lower. This is also required so that the given framework can find its asset, and replace the higher-level asset (see next paragraph).
 
 In order to compare Assembly Version and File Version, additional metadata will need to be written to each deps.json file. If this metadata is not present (as in the case of applications published prior to 2.1) then the assembly will be considered older and will not replace any locations that the assembly was previously found at.