From 1cbec5a49491f20f933785a5f368ecc57af59d4b Mon Sep 17 00:00:00 2001 From: Pavel Krymets Date: Wed, 16 Mar 2016 11:57:14 -0700 Subject: [PATCH 1/8] Generate embedded deps file that previos versions of DependencyModel can use --- src/dotnet/commands/dotnet-compile/ManagedCompiler.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dotnet/commands/dotnet-compile/ManagedCompiler.cs b/src/dotnet/commands/dotnet-compile/ManagedCompiler.cs index 2bff5ba89..46b7d7cb1 100644 --- a/src/dotnet/commands/dotnet-compile/ManagedCompiler.cs +++ b/src/dotnet/commands/dotnet-compile/ManagedCompiler.cs @@ -114,7 +114,7 @@ namespace Microsoft.DotNet.Tools.Compiler var dependencyContext = new DependencyContextBuilder().Build(compilationOptions, allExports, allExports, - true, // For now, just assume portable mode in the legacy deps file (this is going away soon anyway) + false, // For now, just assume non-portable mode in the legacy deps file (this is going away soon anyway) context.TargetFramework, context.RuntimeIdentifier ?? string.Empty); From 88fc96803ace3ebe583910522d35dc1a41154ea1 Mon Sep 17 00:00:00 2001 From: Andrew Stanton-Nurse Date: Wed, 16 Mar 2016 14:05:46 -0700 Subject: [PATCH 2/8] update README links --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b60817d4a..5f0ff2628 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ Installers |---------|:------:|:------:|:------:|:------:|:------:|:------:| |**Version**|![](https://dotnetcli.blob.core.windows.net/dotnet/beta/Binaries/Latest/Ubuntu_x64_Release_version_badge.svg)|![](https://dotnetcli.blob.core.windows.net/dotnet/beta/Binaries/Latest/Windows_x64_Release_version_badge.svg)|![](https://dotnetcli.blob.core.windows.net/dotnet/beta/Binaries/Latest/Windows_x86_Release_version_badge.svg)|![](https://dotnetcli.blob.core.windows.net/dotnet/beta/Binaries/Latest/OSX_x64_Release_version_badge.svg)|![](https://dotnetcli.blob.core.windows.net/dotnet/beta/Binaries/Latest/CentOS_x64_Release_version_badge.svg)|![](https://dotnetcli.blob.core.windows.net/dotnet/beta/Binaries/Latest/RHEL_x64_Release_version_badge.svg)| |**Installers**|[Download Debian Package](https://dotnetcli.blob.core.windows.net/dotnet/beta/Installers/Latest/dotnet-ubuntu-x64.latest.deb)|[Download Installer](https://dotnetcli.blob.core.windows.net/dotnet/beta/Installers/Latest/dotnet-win-x64.latest.exe)|[Download Installer](https://dotnetcli.blob.core.windows.net/dotnet/beta/Installers/Latest/dotnet-win-x86.latest.exe)|[Download Pkg](https://dotnetcli.blob.core.windows.net/dotnet/beta/Installers/Latest/dotnet-osx-x64.latest.pkg) |N/A |N/A | -|**Binaries**|[Download tar file](https://dotnetcli.blob.core.windows.net/dotnet/beta/Binaries/Latest/dotnet-ubuntu-x64.latest.tar.gz)|[Download zip file](https://dotnetcli.blob.core.windows.net/dotnet/beta/Binaries/Latest/dotnet-win-x64.latest.zip)|[Download zip file](https://dotnetcli.blob.core.windows.net/dotnet/beta/Binaries/Latest/dotnet-win-x86.latest.zip)|[Download tar file](https://dotnetcli.blob.core.windows.net/dotnet/beta/Binaries/Latest/dotnet-osx-x64.latest.tar.gz) |[Download tar file](https://dotnetcli.blob.core.windows.net/dotnet/beta/Binaries/Latest/dotnet-centos-x64.latest.tar.gz)|[Download tar file](https://dotnetcli.blob.core.windows.net/dotnet/beta/Binaries/Latest/dotnet-rhel-x64.latest.tar.gz) | +|**Binaries**|[Download tar file](https://dotnetcli.blob.core.windows.net/dotnet/beta/Binaries/Latest/dotnet-combined-framework-sdk-host-ubuntu-x64.latest.tar.gz)|[Download zip file](https://dotnetcli.blob.core.windows.net/dotnet/beta/Binaries/Latest/dotnet-combined-framework-sdk-host-win-x64.latest.zip)|[Download zip file](https://dotnetcli.blob.core.windows.net/dotnet/beta/Binaries/Latest/dotnet-combined-framework-sdk-host-win-x86.latest.zip)|[Download tar file](https://dotnetcli.blob.core.windows.net/dotnet/beta/Binaries/Latest/dotnet-combined-framework-sdk-host-osx-x64.latest.tar.gz) |[Download tar file](https://dotnetcli.blob.core.windows.net/dotnet/beta/Binaries/Latest/dotnet-combined-framework-sdk-host-centos-x64.latest.tar.gz)|[Download tar file](https://dotnetcli.blob.core.windows.net/dotnet/beta/Binaries/Latest/dotnet-combined-framework-sdk-host-rhel-x64.latest.tar.gz) | Interested in .NET Core + ASP.NET Core 1.0 RC1 bits? ---------------------------------------------------- From 0a5d95d2add2f9820db418e01ba32b8f8b5788ec Mon Sep 17 00:00:00 2001 From: Senthil Date: Wed, 16 Mar 2016 14:09:29 -0700 Subject: [PATCH 3/8] Fix casing of shared and add DT_DIR to readdir --- src/corehost/cli/fxr/fx_muxer.cpp | 2 +- src/corehost/common/pal.unix.cpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/corehost/cli/fxr/fx_muxer.cpp b/src/corehost/cli/fxr/fx_muxer.cpp index 8012d09c4..75a195982 100644 --- a/src/corehost/cli/fxr/fx_muxer.cpp +++ b/src/corehost/cli/fxr/fx_muxer.cpp @@ -29,7 +29,7 @@ pal::string_t fx_muxer_t::resolve_fx_dir(const pal::string_t& muxer_dir, runtime } auto fx_dir = muxer_dir; - append_path(&fx_dir, _X("Shared")); + append_path(&fx_dir, _X("shared")); append_path(&fx_dir, fx_name.c_str()); // If not roll forward or if pre-release, just return. diff --git a/src/corehost/common/pal.unix.cpp b/src/corehost/common/pal.unix.cpp index a58ad8761..117b07a89 100644 --- a/src/corehost/common/pal.unix.cpp +++ b/src/corehost/common/pal.unix.cpp @@ -202,6 +202,7 @@ void pal::readdir(const pal::string_t& path, std::vector* list) // We are interested in files only switch (entry->d_type) { + case DT_DIR: case DT_REG: break; From cd2b638b18b8db75b79d05d5e4acac4ce96b9a5f Mon Sep 17 00:00:00 2001 From: Nate Amundson Date: Wed, 16 Mar 2016 14:39:02 -0700 Subject: [PATCH 4/8] Trigger automated DockerHub builds This change triggers automated DockerHub builds for successful official Ubuntu builds of rel.1.0.0. The DockerHub repo for this is https://hub.docker.com/r/microsoft/dotnet-preview/. The variables DOCKER_HUB_REPO and DOCKER_HUB_TRIGGER_TOKEN are set in the "DotNet-CLI-CI (Ubuntu) [rel.1.0.0]" VSTS build definition. This change also allows the Environment TargetConditionAttribute to be used to require that an environment variable is set, in addition to the existing functionality of being able to be used to require that an environment variable is equal to one of a set of specified values. --- .../TargetConditions/EnvironmentAttribute.cs | 21 ++++--- scripts/dotnet-cli-build/PublishTargets.cs | 63 +++++++++++++++---- 2 files changed, 62 insertions(+), 22 deletions(-) diff --git a/scripts/Microsoft.DotNet.Cli.Build.Framework/TargetConditions/EnvironmentAttribute.cs b/scripts/Microsoft.DotNet.Cli.Build.Framework/TargetConditions/EnvironmentAttribute.cs index 2a9aea581..0a8455e5c 100644 --- a/scripts/Microsoft.DotNet.Cli.Build.Framework/TargetConditions/EnvironmentAttribute.cs +++ b/scripts/Microsoft.DotNet.Cli.Build.Framework/TargetConditions/EnvironmentAttribute.cs @@ -1,5 +1,5 @@ using System; -using System.Collections.Generic; +using System.Linq; namespace Microsoft.DotNet.Cli.Build.Framework { @@ -13,7 +13,11 @@ namespace Microsoft.DotNet.Cli.Build.Framework { if (string.IsNullOrEmpty(envVar)) { - throw new ArgumentNullException("envVar"); + throw new ArgumentNullException(nameof(envVar)); + } + if (expectedVals == null) + { + throw new ArgumentNullException(nameof(expectedVals)); } _envVar = envVar; @@ -24,15 +28,14 @@ namespace Microsoft.DotNet.Cli.Build.Framework { var actualVal = Environment.GetEnvironmentVariable(_envVar); - foreach (var expectedVal in _expectedVals) + if (_expectedVals.Any()) { - if (string.Equals(actualVal, expectedVal, StringComparison.Ordinal)) - { - return true; - } + return _expectedVals.Any(ev => string.Equals(actualVal, ev, StringComparison.Ordinal)); + } + else + { + return !string.IsNullOrEmpty(actualVal); } - - return false; } } } diff --git a/scripts/dotnet-cli-build/PublishTargets.cs b/scripts/dotnet-cli-build/PublishTargets.cs index 04af2b35c..71051aebf 100644 --- a/scripts/dotnet-cli-build/PublishTargets.cs +++ b/scripts/dotnet-cli-build/PublishTargets.cs @@ -1,12 +1,9 @@ using System; -using System.Collections.Generic; using System.IO; -using System.Runtime.InteropServices; +using System.Net.Http; +using System.Text; using Microsoft.DotNet.Cli.Build.Framework; -using Microsoft.Extensions.PlatformAbstractions; -using Microsoft.WindowsAzure; using Microsoft.WindowsAzure.Storage; -using Microsoft.WindowsAzure.Storage.Auth; using Microsoft.WindowsAzure.Storage.Blob; using static Microsoft.DotNet.Cli.Build.Framework.BuildHelpers; @@ -36,7 +33,8 @@ namespace Microsoft.DotNet.Cli.Build [Target(nameof(PrepareTargets.Init), nameof(PublishTargets.InitPublish), - nameof(PublishTargets.PublishArtifacts))] + nameof(PublishTargets.PublishArtifacts), + nameof(PublishTargets.TriggerDockerHubBuilds))] [Environment("PUBLISH_TO_AZURE_BLOB", "1", "true")] // This is set by CI systems public static BuildTargetResult Publish(BuildTargetContext c) { @@ -113,7 +111,7 @@ namespace Microsoft.DotNet.Cli.Build { var packageName = Monikers.GetDebianPackageName(c); var installerFile = c.BuildContext.Get("SdkInstallerFile"); - var uploadUrl = $"https://dotnetcli.blob.core.windows.net/dotnet/{Channel}/Installers/{Version}/{Path.GetFileName(installerFile)}"; + var uploadUrl = $"https://dotnetcli.blob.core.windows.net/dotnet/{Channel}/Installers/{Version}/{Path.GetFileName(installerFile)}"; var uploadJson = GenerateUploadJsonFile(packageName, Version, uploadUrl); Cmd(Path.Combine(Dirs.RepoRoot, "scripts", "publish", "repoapi_client.sh"), "-addpkg", uploadJson) @@ -123,6 +121,45 @@ namespace Microsoft.DotNet.Cli.Build return c.Success(); } + [Target] + [Environment("DOCKER_HUB_REPO")] + [Environment("DOCKER_HUB_TRIGGER_TOKEN")] + public static BuildTargetResult TriggerDockerHubBuilds(BuildTargetContext c) + { + string dockerHubRepo = Environment.GetEnvironmentVariable("DOCKER_HUB_REPO"); + string dockerHubTriggerToken = Environment.GetEnvironmentVariable("DOCKER_HUB_TRIGGER_TOKEN"); + + Uri baseDockerHubUri = new Uri("https://registry.hub.docker.com/u/"); + Uri dockerHubTriggerUri; + if (!Uri.TryCreate(baseDockerHubUri, $"{dockerHubRepo}/trigger/{dockerHubTriggerToken}/", out dockerHubTriggerUri)) + { + return c.Failed("Invalid DOCKER_HUB_REPO and/or DOCKER_HUB_TRIGGER_TOKEN"); + } + + c.Info($"Triggering automated DockerHub builds for {dockerHubRepo}"); + using (HttpClient client = new HttpClient()) + { + StringContent requestContent = new StringContent("{\"build\": true}", Encoding.UTF8, "application/json"); + try + { + HttpResponseMessage response = client.PostAsync(dockerHubTriggerUri, requestContent).Result; + if (!response.IsSuccessStatusCode) + { + StringBuilder sb = new StringBuilder(); + sb.AppendLine($"HTTP request to {dockerHubTriggerUri.ToString()} was unsuccessful."); + sb.AppendLine($"Response status code: {response.StatusCode}. Reason phrase: {response.ReasonPhrase}."); + sb.Append($"Respone content: {response.Content.ReadAsStringAsync().Result}"); + return c.Failed(sb.ToString()); + } + } + catch (AggregateException e) + { + return c.Failed($"HTTP request to {dockerHubTriggerUri.ToString()} failed. {e.ToString()}"); + } + } + return c.Success(); + } + private static string GenerateUploadJsonFile(string packageName, string version, string uploadUrl) { var repoID = Environment.GetEnvironmentVariable("REPO_ID"); @@ -133,12 +170,12 @@ namespace Microsoft.DotNet.Cli.Build { using (StreamWriter sw = new StreamWriter(fileStream)) { - sw.WriteLine("{"); - sw.WriteLine($" \"name\":\"{packageName}\","); - sw.WriteLine($" \"version\":\"{version}\","); - sw.WriteLine($" \"repositoryId\":\"{repoID}\","); - sw.WriteLine($" \"sourceUrl\":\"{uploadUrl}\""); - sw.WriteLine("}"); + sw.WriteLine("{"); + sw.WriteLine($" \"name\":\"{packageName}\","); + sw.WriteLine($" \"version\":\"{version}\","); + sw.WriteLine($" \"repositoryId\":\"{repoID}\","); + sw.WriteLine($" \"sourceUrl\":\"{uploadUrl}\""); + sw.WriteLine("}"); } } From 00905c3faf24880aa0873cd40a5c0b56606c7d19 Mon Sep 17 00:00:00 2001 From: Senthil Chellappan Date: Wed, 16 Mar 2016 15:13:22 -0700 Subject: [PATCH 5/8] Revert merging relpaths and relax erroring --- src/corehost/cli/deps_format.cpp | 48 ++++++++++++++++---------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/src/corehost/cli/deps_format.cpp b/src/corehost/cli/deps_format.cpp index e013ba89f..0dafed29c 100644 --- a/src/corehost/cli/deps_format.cpp +++ b/src/corehost/cli/deps_format.cpp @@ -129,23 +129,27 @@ bool deps_json_t::perform_rid_fallback(rid_specific_assets_t* portable_assets, c auto iter = std::find_if(fallback_rids.begin(), fallback_rids.end(), [&package](const pal::string_t& rid) { return package.second.count(rid); }); - if (iter == fallback_rids.end() || (*iter).empty()) + if (iter != fallback_rids.end()) { - trace::error(_X("Did not find a matching fallback rid for package %s for the host rid %s"), package.first.c_str(), host_rid.c_str()); - return false; + matched_rid = *iter; } - matched_rid = *iter; } - assert(!matched_rid.empty()); + + if (matched_rid.empty()) + { + package.second.clear(); + } + for (auto iter = package.second.begin(); iter != package.second.end(); /* */) { if (iter->first != matched_rid) { - iter = package.second.erase(iter); + trace::verbose(_X("Chose %s, so removing rid (%s) specific assets for package %s"), matched_rid.c_str(), iter->first.c_str(), package.first.c_str()); + iter = package.second.erase(iter); } else { - ++iter; + ++iter; } } } @@ -194,7 +198,6 @@ bool deps_json_t::process_targets(const json_value& json, const pal::string_t& t for (const auto& package : json.at(_X("targets")).at(target_name).as_object()) { // if (package.second.at(_X("type")).as_string() != _X("package")) continue; - const auto& asset_types = package.second.as_object(); for (int i = 0; i < s_known_asset_types.size(); ++i) { @@ -226,27 +229,24 @@ bool deps_json_t::load_portable(const json_value& json, const pal::string_t& tar return false; } - std::vector merged; auto package_exists = [&rid_assets, &non_rid_assets](const pal::string_t& package) -> bool { return rid_assets.count(package) || non_rid_assets.count(package); }; - auto get_relpaths = [&rid_assets, &non_rid_assets, &merged](const pal::string_t& package, int type_index) -> const std::vector& { - if (rid_assets.count(package) && non_rid_assets.count(package)) + auto get_relpaths = [&rid_assets, &non_rid_assets](const pal::string_t& package, int type_index) -> const std::vector& { + + // Is there any rid specific assets for this type ("native" or "runtime" or "resources") + if (rid_assets.count(package) && !rid_assets[package].empty()) { - const std::vector& rel1 = rid_assets[package].begin()->second[type_index]; - const std::vector& rel2 = non_rid_assets[package][type_index]; - merged.clear(); - merged.reserve(rel1.size() + rel2.size()); - merged.insert(merged.end(), rel1.begin(), rel1.end()); - merged.insert(merged.end(), rel2.begin(), rel2.end()); - return merged; - } - else - { - return rid_assets.count(package) - ? rid_assets[package].begin()->second[type_index] - : non_rid_assets[package][type_index]; + const auto& assets_by_type = rid_assets[package].begin()->second[type_index]; + if (!assets_by_type.empty()) + { + return assets_by_type; + } + + trace::verbose(_X("There were no rid specific %s asset for %s"), deps_json_t::s_known_asset_types[type_index], package.c_str()); } + + return non_rid_assets[package][type_index]; }; reconcile_libraries_with_targets(json, package_exists, get_relpaths); From 8ff5f9df6f87bf1d71f9696d3b905cfb57645840 Mon Sep 17 00:00:00 2001 From: Senthil Date: Wed, 16 Mar 2016 20:50:32 -0700 Subject: [PATCH 6/8] Return empty entries instead of creating empty ones --- src/corehost/cli/deps_format.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/corehost/cli/deps_format.cpp b/src/corehost/cli/deps_format.cpp index 0dafed29c..f9e02ffa4 100644 --- a/src/corehost/cli/deps_format.cpp +++ b/src/corehost/cli/deps_format.cpp @@ -232,7 +232,9 @@ bool deps_json_t::load_portable(const json_value& json, const pal::string_t& tar auto package_exists = [&rid_assets, &non_rid_assets](const pal::string_t& package) -> bool { return rid_assets.count(package) || non_rid_assets.count(package); }; - auto get_relpaths = [&rid_assets, &non_rid_assets](const pal::string_t& package, int type_index) -> const std::vector& { + + std::vector empty; + auto get_relpaths = [&rid_assets, &non_rid_assets, &empty](const pal::string_t& package, int type_index) -> const std::vector& { // Is there any rid specific assets for this type ("native" or "runtime" or "resources") if (rid_assets.count(package) && !rid_assets[package].empty()) @@ -246,7 +248,12 @@ bool deps_json_t::load_portable(const json_value& json, const pal::string_t& tar trace::verbose(_X("There were no rid specific %s asset for %s"), deps_json_t::s_known_asset_types[type_index], package.c_str()); } - return non_rid_assets[package][type_index]; + if (non_rid_assets.count(package)) + { + return non_rid_assets[package][type_index]; + } + + return empty; }; reconcile_libraries_with_targets(json, package_exists, get_relpaths); From ee27b1ff112ecbba96d6a74491103cdc1acff293 Mon Sep 17 00:00:00 2001 From: schellap Date: Thu, 17 Mar 2016 01:37:39 -0700 Subject: [PATCH 7/8] Enable logging and fix xunit runtimeconfig --- src/corehost/cli/fxr/fx_muxer.cpp | 98 ++++++++++++++++++++++++++----- src/corehost/cli/fxr/fx_muxer.h | 2 +- src/corehost/cli/hostpolicy.cpp | 3 +- src/corehost/cli/libhost.cpp | 7 ++- src/corehost/cli/libhost.h | 2 +- src/corehost/common/utils.cpp | 2 +- 6 files changed, 91 insertions(+), 23 deletions(-) diff --git a/src/corehost/cli/fxr/fx_muxer.cpp b/src/corehost/cli/fxr/fx_muxer.cpp index 75a195982..4cc2f60fe 100644 --- a/src/corehost/cli/fxr/fx_muxer.cpp +++ b/src/corehost/cli/fxr/fx_muxer.cpp @@ -16,8 +16,9 @@ typedef web::json::value json_value; -pal::string_t fx_muxer_t::resolve_fx_dir(const pal::string_t& muxer_dir, runtime_config_t* runtime, const pal::string_t& app_path) +pal::string_t fx_muxer_t::resolve_fx_dir(const pal::string_t& muxer_dir, runtime_config_t* runtime) { + trace::verbose(_X("--- Resolving FX directory from muxer dir [%s]"), muxer_dir.c_str()); const auto fx_name = runtime->get_fx_name(); const auto fx_ver = runtime->get_fx_version(); const auto roll_fwd = runtime->get_fx_roll_fwd(); @@ -25,6 +26,7 @@ pal::string_t fx_muxer_t::resolve_fx_dir(const pal::string_t& muxer_dir, runtime fx_ver_t specified(-1, -1, -1); if (!fx_ver_t::parse(fx_ver, &specified, false)) { + trace::error(_X("The specified runtimeconfig.json version [%s] could not be parsed"), fx_ver.c_str()); return pal::string_t(); } @@ -35,15 +37,20 @@ pal::string_t fx_muxer_t::resolve_fx_dir(const pal::string_t& muxer_dir, runtime // If not roll forward or if pre-release, just return. if (!roll_fwd || specified.is_prerelease()) { + trace::verbose(_X("Did not roll forward because rollfwd=%d and [%s] is prerelease=%d"), + roll_fwd, fx_ver.c_str(), specified.is_prerelease()); append_path(&fx_dir, fx_ver.c_str()); } else { + trace::verbose(_X("Attempting production FX roll forward starting from [%s]"), fx_ver.c_str()); + std::vector list; pal::readdir(fx_dir, &list); fx_ver_t max_specified = specified; for (const auto& version : list) { + trace::verbose(_X("Inspecting version... [%s]"), version.c_str()); fx_ver_t ver(-1, -1, -1); if (fx_ver_t::parse(version, &ver, true) && ver.get_major() == max_specified.get_major() && @@ -55,21 +62,26 @@ pal::string_t fx_muxer_t::resolve_fx_dir(const pal::string_t& muxer_dir, runtime pal::string_t max_specified_str = max_specified.as_str(); append_path(&fx_dir, max_specified_str.c_str()); } - trace::verbose(_X("Found fx in: %s"), fx_dir.c_str()); + + trace::verbose(_X("Chose FX version [%s]"), fx_dir.c_str()); return pal::directory_exists(fx_dir) ? fx_dir : pal::string_t(); } pal::string_t fx_muxer_t::resolve_cli_version(const pal::string_t& global_json) { + trace::verbose(_X("--- Resolving CLI version from global json [%s]"), global_json.c_str()); + pal::string_t retval; if (!pal::file_exists(global_json)) { + trace::verbose(_X("[%s] does not exist"), global_json.c_str()); return retval; } pal::ifstream_t file(global_json); if (!file.good()) { + trace::verbose(_X("[%s] could not be opened"), global_json.c_str()); return retval; } @@ -80,6 +92,7 @@ pal::string_t fx_muxer_t::resolve_cli_version(const pal::string_t& global_json) const auto sdk_iter = json.find(_X("sdk")); if (sdk_iter == json.end() || sdk_iter->second.is_null()) { + trace::verbose(_X("CLI '/sdk/version' field not present/null in [%s]"), global_json.c_str()); return retval; } @@ -87,19 +100,23 @@ pal::string_t fx_muxer_t::resolve_cli_version(const pal::string_t& global_json) const auto ver_iter = sdk_obj.find(_X("version")); if (ver_iter == sdk_obj.end() || ver_iter->second.is_null()) { + trace::verbose(_X("CLI 'sdk/version' field not present/null in [%s]"), global_json.c_str()); return retval; } retval = ver_iter->second.as_string(); } catch (...) { + trace::verbose(_X("A JSON parsing exception occurred")); } - trace::verbose(_X("Found cli in: %s"), retval.c_str()); + trace::verbose(_X("CLI version is [%s] in global json file [%s]"), retval.c_str(), global_json.c_str()); return retval; } pal::string_t resolve_sdk_version(pal::string_t sdk_path) { + trace::verbose(_X("--- Resolving SDK version from SDK dir [%s]"), sdk_path.c_str()); + pal::string_t retval; std::vector versions; @@ -108,6 +125,8 @@ pal::string_t resolve_sdk_version(pal::string_t sdk_path) fx_ver_t max_pre(-1, -1, -1); for (const auto& version : versions) { + trace::verbose(_X("Considering version... [%s]"), version.c_str()); + fx_ver_t ver(-1, -1, -1); if (fx_ver_t::parse(version, &ver, true)) { @@ -122,20 +141,26 @@ pal::string_t resolve_sdk_version(pal::string_t sdk_path) // No production, use the max pre-release. if (max_ver == fx_ver_t(-1, -1, -1)) { + trace::verbose(_X("No production version found, so using latest prerelease")); max_ver = max_pre; } pal::string_t max_ver_str = max_ver.as_str(); append_path(&sdk_path, max_ver_str.c_str()); + + trace::verbose(_X("Checking if resolved SDK dir [%s] exists"), sdk_path.c_str()); if (pal::directory_exists(sdk_path)) { retval = sdk_path; } + + trace::verbose(_X("Resolved SDK dir is [%s]"), retval.c_str()); return retval; } bool fx_muxer_t::resolve_sdk_dotnet_path(const pal::string_t& own_dir, pal::string_t* cli_sdk) { + trace::verbose(_X("--- Resolving dotnet from working dir")); pal::string_t cwd; pal::string_t global; if (pal::getcwd(&cwd)) @@ -144,18 +169,27 @@ bool fx_muxer_t::resolve_sdk_dotnet_path(const pal::string_t& own_dir, pal::stri { pal::string_t file = cur_dir; append_path(&file, _X("global.json")); + + trace::verbose(_X("Probing path [%s] for global.json"), file.c_str()); if (pal::file_exists(file)) { global = file; + trace::verbose(_X("Found global.json [%s]"), global.c_str()); break; } parent_dir = get_directory(cur_dir); if (parent_dir.empty() || parent_dir.size() == cur_dir.size()) { + trace::verbose(_X("Terminating global.json search at [%s]"), parent_dir.c_str()); break; } } } + else + { + trace::verbose(_X("Failed to obtain current working dir")); + } + pal::string_t retval; if (!global.empty()) { @@ -165,10 +199,16 @@ bool fx_muxer_t::resolve_sdk_dotnet_path(const pal::string_t& own_dir, pal::stri pal::string_t sdk_path = own_dir; append_path(&sdk_path, _X("sdk")); append_path(&sdk_path, cli_version.c_str()); + if (pal::directory_exists(sdk_path)) { + trace::verbose(_X("CLI directory [%s] from global.json exists"), sdk_path.c_str()); retval = sdk_path; } + else + { + trace::verbose(_X("CLI directory [%s] from global.json doesn't exist"), sdk_path.c_str()); + } } } if (retval.empty()) @@ -178,13 +218,15 @@ bool fx_muxer_t::resolve_sdk_dotnet_path(const pal::string_t& own_dir, pal::stri retval = resolve_sdk_version(sdk_path); } cli_sdk->assign(retval); - trace::verbose(_X("Found cli sdk in: %s"), cli_sdk->c_str()); + trace::verbose(_X("Found CLI SDK in: %s"), cli_sdk->c_str()); return !retval.empty(); } /* static */ int fx_muxer_t::execute(const int argc, const pal::char_t* argv[]) { + trace::error(_X("--- Executing in muxer mode...")); + pal::string_t own_path; // Get the full name of the application @@ -198,6 +240,7 @@ int fx_muxer_t::execute(const int argc, const pal::char_t* argv[]) if (argc <= 1) { + trace::error(_X("Usage: dotnet [--help | app.dll]")); return StatusCode::InvalidArgFailure; } if (ends_with(argv[1], _X(".dll"), false)) @@ -206,10 +249,12 @@ int fx_muxer_t::execute(const int argc, const pal::char_t* argv[]) if (!pal::realpath(&app_path)) { + trace::error(_X("Could not resolve app's full path [%s]"), app_path.c_str()); return StatusCode::LibHostExecModeFailure; } - runtime_config_t config(get_runtime_config_json(app_path)); + auto config_file = get_runtime_config_from_file(app_path); + runtime_config_t config(config_file); if (!config.is_valid()) { trace::error(_X("Invalid runtimeconfig.json [%s]"), config.get_path().c_str()); @@ -217,12 +262,14 @@ int fx_muxer_t::execute(const int argc, const pal::char_t* argv[]) } if (config.get_portable()) { - pal::string_t fx_dir = resolve_fx_dir(own_dir, &config, app_path); + trace::verbose(_X("Executing as a portable app as per config file [%s]"), config_file.c_str()); + pal::string_t fx_dir = resolve_fx_dir(own_dir, &config); corehost_init_t init(_X(""), _X(""), fx_dir, host_mode_t::muxer, &config); return policy_load_t::execute_app(fx_dir, &init, argc, argv); } else { + trace::verbose(_X("Executing as a standlone app as per config file [%s]"), config_file.c_str()); corehost_init_t init(_X(""), _X(""), _X(""), host_mode_t::muxer, &config); return policy_load_t::execute_app(get_directory(app_path), &init, argc, argv); } @@ -237,11 +284,13 @@ int fx_muxer_t::execute(const int argc, const pal::char_t* argv[]) std::unordered_map opts; if (!parse_known_args(argc - 2, &argv[2], known_opts, &opts, &num_args)) { + trace::error(_X("Failed to parse known arguments.")); return InvalidArgFailure; } int cur_i = 2 + num_args; if (cur_i >= argc) { + trace::error(_X("Parsed known args, but need more arguments.")); return InvalidArgFailure; } @@ -256,23 +305,31 @@ int fx_muxer_t::execute(const int argc, const pal::char_t* argv[]) pal::string_t deps_file = opts.count(opts_deps_file) ? opts[opts_deps_file] : _X(""); pal::string_t probe_path = opts.count(opts_probe_path) ? opts[opts_probe_path] : _X(""); - pal::string_t app_path = argv[cur_i]; - runtime_config_t config(get_runtime_config_json(app_path)); + pal::string_t app_or_deps = deps_file.empty() ? argv[cur_i] : deps_file; + auto config_file = get_runtime_config_from_file(app_or_deps); + runtime_config_t config(config_file); if (!config.is_valid()) { trace::error(_X("Invalid runtimeconfig.json [%s]"), config.get_path().c_str()); return StatusCode::InvalidConfigFile; } + if (!deps_file.empty() && !pal::file_exists(deps_file)) + { + trace::error(_X("Deps file [%s] specified but doesn't exist"), deps_file.c_str()); + return StatusCode::InvalidArgFailure; + } if (config.get_portable()) { - pal::string_t fx_dir = resolve_fx_dir(own_dir, &config, app_path); + trace::verbose(_X("Executing as a portable app as per config file [%s]"), config_file.c_str()); + pal::string_t fx_dir = resolve_fx_dir(own_dir, &config); corehost_init_t init(deps_file, probe_path, fx_dir, host_mode_t::muxer, &config); return policy_load_t::execute_app(fx_dir, &init, new_argv.size(), new_argv.data()); } else { + trace::verbose(_X("Executing as a standalone app as per config file [%s]"), config_file.c_str()); corehost_init_t init(deps_file, probe_path, _X(""), host_mode_t::muxer, &config); - pal::string_t impl_dir = get_directory(deps_file.empty() ? app_path : deps_file); + pal::string_t impl_dir = get_directory(app_or_deps); return policy_load_t::execute_app(impl_dir, &init, new_argv.size(), new_argv.data()); } } @@ -281,9 +338,17 @@ int fx_muxer_t::execute(const int argc, const pal::char_t* argv[]) pal::string_t sdk_dotnet; if (!resolve_sdk_dotnet_path(own_dir, &sdk_dotnet)) { + trace::error(_X("Could not resolve SDK directory from [%s]"), own_dir.c_str()); return StatusCode::LibHostSdkFindFailure; } append_path(&sdk_dotnet, _X("dotnet.dll")); + + if (!pal::file_exists(_X("dotnet.dll"))) + { + trace::error(_X("Could not find dotnet.dll at [%s]"), sdk_dotnet.c_str()); + return StatusCode::LibHostSdkFindFailure; + } + // Transform dotnet [command] [args] -> dotnet [dotnet.dll] [command] [args] std::vector new_argv(argc + 1); @@ -291,20 +356,21 @@ int fx_muxer_t::execute(const int argc, const pal::char_t* argv[]) new_argv[0] = argv[0]; new_argv[1] = sdk_dotnet.c_str(); - trace::verbose(_X("Using SDK dll=[%s]"), sdk_dotnet.c_str()); + trace::verbose(_X("Using dotnet SDK dll=[%s]"), sdk_dotnet.c_str()); - assert(ends_with(sdk_dotnet, _X(".dll"), false)); - - runtime_config_t config(get_runtime_config_json(sdk_dotnet)); + auto config_file = get_runtime_config_from_file(sdk_dotnet); + runtime_config_t config(config_file); if (config.get_portable()) { - pal::string_t fx_dir = resolve_fx_dir(own_dir, &config, sdk_dotnet); + trace::verbose(_X("Executing dotnet.dll as a portable app as per config file [%s]"), config_file.c_str()); + pal::string_t fx_dir = resolve_fx_dir(own_dir, &config); corehost_init_t init(_X(""), _X(""), fx_dir, host_mode_t::muxer, &config); return policy_load_t::execute_app(fx_dir, &init, new_argv.size(), new_argv.data()); } else { + trace::verbose(_X("Executing dotnet.dll as a standalone app as per config file [%s]"), config_file.c_str()); corehost_init_t init(_X(""), _X(""), _X(""), host_mode_t::muxer, &config); return policy_load_t::execute_app(get_directory(sdk_dotnet), &init, new_argv.size(), new_argv.data()); } @@ -316,4 +382,4 @@ SHARED_API int hostfxr_main(const int argc, const pal::char_t* argv[]) { trace::setup(); return fx_muxer_t().execute(argc, argv); -} \ No newline at end of file +} diff --git a/src/corehost/cli/fxr/fx_muxer.h b/src/corehost/cli/fxr/fx_muxer.h index de6518a4c..5ea4cea8b 100644 --- a/src/corehost/cli/fxr/fx_muxer.h +++ b/src/corehost/cli/fxr/fx_muxer.h @@ -9,7 +9,7 @@ class fx_muxer_t public: static int execute(const int argc, const pal::char_t* argv[]); private: - static pal::string_t resolve_fx_dir(const pal::string_t& muxer_path, runtime_config_t* runtime, const pal::string_t& app_path); + static pal::string_t resolve_fx_dir(const pal::string_t& muxer_path, runtime_config_t* runtime); static pal::string_t resolve_cli_version(const pal::string_t& global); static bool resolve_sdk_dotnet_path(const pal::string_t& own_dir, pal::string_t* cli_sdk); }; diff --git a/src/corehost/cli/hostpolicy.cpp b/src/corehost/cli/hostpolicy.cpp index 32bdb924d..7cf161fba 100644 --- a/src/corehost/cli/hostpolicy.cpp +++ b/src/corehost/cli/hostpolicy.cpp @@ -215,7 +215,8 @@ SHARED_API int corehost_main(const int argc, const pal::char_t* argv[]) } else { - runtime_config_t config(get_runtime_config_json(args.managed_application)); + auto config_path = get_runtime_config_from_file(args.managed_application); + runtime_config_t config(config_path); if (!config.is_valid()) { trace::error(_X("Invalid runtimeconfig.json [%s]"), config.get_path().c_str()); diff --git a/src/corehost/cli/libhost.cpp b/src/corehost/cli/libhost.cpp index 56d030505..4537554da 100644 --- a/src/corehost/cli/libhost.cpp +++ b/src/corehost/cli/libhost.cpp @@ -6,11 +6,12 @@ #include "trace.h" #include "libhost.h" -pal::string_t get_runtime_config_json(const pal::string_t& app_path) +pal::string_t get_runtime_config_from_file(const pal::string_t& file) { - auto name = get_filename_without_ext(app_path); + auto name = get_filename_without_ext(file); + name = name.substr(0, name.find(_X('.'))); auto json_name = name + _X(".runtimeconfig.json"); - auto json_path = get_directory(app_path); + auto json_path = get_directory(file); append_path(&json_path, json_name.c_str()); if (pal::file_exists(json_path)) diff --git a/src/corehost/cli/libhost.h b/src/corehost/cli/libhost.h index fa0d60e9c..d4e587e62 100644 --- a/src/corehost/cli/libhost.h +++ b/src/corehost/cli/libhost.h @@ -64,7 +64,7 @@ public: } }; -pal::string_t get_runtime_config_json(const pal::string_t& app_path); +pal::string_t get_runtime_config_from_file(const pal::string_t& file); host_mode_t detect_operating_mode(const int argc, const pal::char_t* argv[], pal::string_t* own_dir = nullptr); #endif // __LIBHOST_H__ diff --git a/src/corehost/common/utils.cpp b/src/corehost/common/utils.cpp index 65f1b8c42..1587e7df5 100644 --- a/src/corehost/common/utils.cpp +++ b/src/corehost/common/utils.cpp @@ -74,7 +74,7 @@ pal::string_t get_filename_without_ext(const pal::string_t& path) size_t name_pos = path.find_last_of(_X("/\\")); size_t dot_pos = path.rfind(_X('.')); size_t start_pos = (name_pos == pal::string_t::npos) ? 0 : (name_pos + 1); - size_t count = (dot_pos == pal::string_t::npos) ? pal::string_t::npos : (dot_pos - start_pos); + size_t count = (dot_pos == pal::string_t::npos || dot_pos < start_pos) ? pal::string_t::npos : (dot_pos - start_pos); return path.substr(start_pos, count); } From b93b915cc652e35bcf604fb9b4b244bc84e5527c Mon Sep 17 00:00:00 2001 From: Senthil Date: Thu, 17 Mar 2016 11:05:49 -0700 Subject: [PATCH 8/8] Fix error check and verbose --- src/corehost/cli/fxr/fx_muxer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/corehost/cli/fxr/fx_muxer.cpp b/src/corehost/cli/fxr/fx_muxer.cpp index 4cc2f60fe..b371832bc 100644 --- a/src/corehost/cli/fxr/fx_muxer.cpp +++ b/src/corehost/cli/fxr/fx_muxer.cpp @@ -225,7 +225,7 @@ bool fx_muxer_t::resolve_sdk_dotnet_path(const pal::string_t& own_dir, pal::stri /* static */ int fx_muxer_t::execute(const int argc, const pal::char_t* argv[]) { - trace::error(_X("--- Executing in muxer mode...")); + trace::verbose(_X("--- Executing in muxer mode...")); pal::string_t own_path; @@ -343,7 +343,7 @@ int fx_muxer_t::execute(const int argc, const pal::char_t* argv[]) } append_path(&sdk_dotnet, _X("dotnet.dll")); - if (!pal::file_exists(_X("dotnet.dll"))) + if (!pal::file_exists(sdk_dotnet)) { trace::error(_X("Could not find dotnet.dll at [%s]"), sdk_dotnet.c_str()); return StatusCode::LibHostSdkFindFailure;