Allow missing assembly dependencies for components. (dotnet/core-setup#4751)
authorVitek Karas <vitek.karas@microsoft.com>
Wed, 14 Nov 2018 11:15:30 +0000 (03:15 -0800)
committerGitHub <noreply@github.com>
Wed, 14 Nov 2018 11:15:30 +0000 (03:15 -0800)
When resolving assembly dependencies for components, don't fail if the assembly doesn't exist on the disk (but it's still present in the .deps.json as a runtime asset).
For dynamically loaded components this behavior makes sense as such components are typically distributed as just the necessary pieces, with everything else provided by the app.

This is a temporary change mainly as a workaround for dotnet/sdkdotnet/core-setup#2660. Issue dotnet/core-setupdotnet/core-setup#4752 is tracking future need for revisiting this change.

Commit migrated from https://github.com/dotnet/core-setup/commit/ca431d0cefee116b5c4ca292961ab60ddd81611f

src/installer/corehost/cli/deps_resolver.cpp
src/installer/corehost/cli/deps_resolver.h
src/installer/corehost/cli/hostpolicy.cpp
src/installer/test/HostActivationTests/GivenThatICareAboutComponentDependencyResolution.cs

index 1ed4a15..6aff6ff 100644 (file)
@@ -411,7 +411,8 @@ bool report_missing_assembly_in_manifest(const deps_entry_t& entry, bool continu
  */
 bool deps_resolver_t::resolve_tpa_list(
         pal::string_t* output,
-        std::unordered_set<pal::string_t>* breadcrumb)
+        std::unordered_set<pal::string_t>* breadcrumb,
+        bool ignore_missing_assemblies)
 {
     const std::vector<deps_entry_t> empty(0);
     name_to_resolved_asset_map_t items;
@@ -444,7 +445,7 @@ bool deps_resolver_t::resolve_tpa_list(
                 return true;
             }
 
-            return report_missing_assembly_in_manifest(entry);
+            return report_missing_assembly_in_manifest(entry, ignore_missing_assemblies);
         }
         else
         {
@@ -827,17 +828,16 @@ bool deps_resolver_t::resolve_probe_dirs(
 // Entrypoint to resolve TPA, native and resources path ordering to pass to CoreCLR.
 //
 //  Parameters:
-//     app_root          - The application local directory
-//     package_dir       - The directory path to where packages are restored
-//     package_cache_dir - The directory path to secondary cache for packages
-//     clr_dir           - The directory where the host loads the CLR
 //     probe_paths       - Pointer to struct containing fields that will contain
 //                         resolved path ordering.
+//     breadcrumb        - set of breadcrumb paths - or null if no breadcrumbs should be collected.
+//     ignore_missing_assemblies - if set to true, resolving TPA assemblies will not fail if an assembly can't be found on disk
+//                                 instead such entry will simply be ignored.
 //
 //
-bool deps_resolver_t::resolve_probe_paths(probe_paths_t* probe_paths, std::unordered_set<pal::string_t>* breadcrumb)
+bool deps_resolver_t::resolve_probe_paths(probe_paths_t* probe_paths, std::unordered_set<pal::string_t>* breadcrumb, bool ignore_missing_assemblies)
 {
-    if (!resolve_tpa_list(&probe_paths->tpa, breadcrumb))
+    if (!resolve_tpa_list(&probe_paths->tpa, breadcrumb, ignore_missing_assemblies))
     {
         return false;
     }
index 030287a..f5e5126 100644 (file)
@@ -138,7 +138,8 @@ public:
 
     bool resolve_probe_paths(
         probe_paths_t* probe_paths,
-        std::unordered_set<pal::string_t>* breadcrumb);
+        std::unordered_set<pal::string_t>* breadcrumb,
+        bool ignore_missing_assemblies = false);
 
     void init_known_entry_path(
         const deps_entry_t& entry,
@@ -186,7 +187,8 @@ private:
     // Resolve order for TPA lookup.
     bool resolve_tpa_list(
         pal::string_t* output,
-        std::unordered_set<pal::string_t>* breadcrumb);
+        std::unordered_set<pal::string_t>* breadcrumb,
+        bool ignore_missing_assemblies);
 
     // Resolve order for culture and native DLL lookup.
     bool resolve_probe_dirs(
index 7c576d0..51a9e28 100644 (file)
@@ -559,7 +559,7 @@ SHARED_API int corehost_resolve_component_dependencies(
     // doesn't guarantee that they will actually execute.
 
     probe_paths_t probe_paths;
-    if (!resolver.resolve_probe_paths(&probe_paths, nullptr))
+    if (!resolver.resolve_probe_paths(&probe_paths, nullptr, /* ignore_missing_assemblies */ true))
     {
         return StatusCode::ResolverResolveFailure;
     }
index 7d33133..67c9b9c 100644 (file)
@@ -178,8 +178,11 @@ namespace Microsoft.DotNet.CoreSetup.Test.HostActivation.NativeHostApis
                 .Execute()
                 .StdErrAfter("corehost_resolve_component_dependencies = {")
                 .Should().Pass()
-                .And.HaveStdOutContaining("corehost_resolve_component_dependencies:Fail[0x8000808C]")
-                .And.HaveStdErrContaining("An assembly specified in the application dependencies manifest (ComponentWithDependencies.deps.json) was not found:");
+                .And.HaveStdOutContaining("corehost_resolve_component_dependencies:Success")
+                .And.HaveStdOutContaining(
+                    $"corehost_resolve_component_dependencies assemblies:[" +
+                    $"{componentFixture.TestProject.AppDll}{Path.PathSeparator}" +
+                    $"{Path.Combine(componentFixture.TestProject.OutputDirectory, "Newtonsoft.Json.dll")}{Path.PathSeparator}]");
         }
 
         [Fact]