## Proposed changes
-Almost every file search is done in relation to the executable directory. It would be better to be able to search for some files in other directories as well. Suggested folders are the user location and the global .NET location. The user and global folders may vary depending on the running operational system. They are defined as follows:
-
-User location:
-
- Windows 32-bit: %SystemDrive%\Users\username\.dotnet\x86
- Windows 64-bit: %SystemDrive%\Users\username\.dotnet\x64
- Unix 32-bit: /home/username/.dotnet/x86
- Unix 64-bit: /home/username/.dotnet/x64
+Almost every file search is done in relation to the executable directory. It would be better to be able to search for some files in other directories as well, namely the global .NET location. The global folders may vary depending on the running operational system. They are defined as follows:
Global .NET location:
- For productions:
- 1. In relation to the user location: search for the most appropriate version by rolling forward. If it cannot be found, proceed to the next step.
- 2. In relation to the executable directory: search for the most appropriate version by rolling forward. If it cannot be found, proceed to the next step.
- 3. In relation to the global location: search for the most appropriate version by rolling forward. If it cannot be found, then we were not able to locate any compatible version.
+ 1. In relation to the executable directory: search for the most appropriate version by rolling forward. If it cannot be found, proceed to the next step.
+ 2. In relation to the global location: search for the most appropriate version by rolling forward. If it cannot be found, then we were not able to locate any compatible version.
- For pre-releases:
- 1. In relation to the user location: search for the specified version. If it cannot be found, search for the most appropriate version by rolling forward. If no compatible version can be found, proceed to the next step.
- 2. In relation to the executable directory: search for the specified version. If it cannot be found, search for the most appropriate version by rolling forward. If no compatible version can be found, proceed to the next step.
- 3. In relation to the global location: search for the specified version. If it cannot be found, search for the most appropriate version by rolling forward. If no compatible version can be found, then we were not able to locate any compatible version.
+ 1. In relation to the executable directory: search for the specified version. If it cannot be found, search for the most appropriate version by rolling forward. If no compatible version can be found, proceed to the next step.
+ 2. In relation to the global location: search for the specified version. If it cannot be found, search for the most appropriate version by rolling forward. If no compatible version can be found, then we were not able to locate any compatible version.
In the case that the desired version is defined through an argument, the multi-level lookup will happen as well but it will only consider the exact specified version (it will not roll forward).
The search would be conducted as follows:
-1. In relation to the user location: search for the specified version. If it cannot be found, choose the most appropriate available version. If there’s no available version, proceed to the next step.
-2. In relation to the executable directory: search for the specified version. If it cannot be found, choose the most appropriate available version. If there’s no available version, proceed to the next step.
-3. In relation to the global location: search for the specified version. If it cannot be found, choose the most appropriate available version. If there’s no available version, then we were not able to find any version folder and an error message must be returned.
+1. In relation to the executable directory: search for the specified version. If it cannot be found, choose the most appropriate available version. If there’s no available version, proceed to the next step.
+2. In relation to the global location: search for the specified version. If it cannot be found, choose the most appropriate available version. If there’s no available version, then we were not able to find any version folder and an error message must be returned.
return false;
}
-void fx_muxer_t::resolve_roll_forward(pal::string_t& fx_dir,
+fx_ver_t fx_muxer_t::resolve_framework_version(const std::vector<fx_ver_t>& version_list,
const pal::string_t& fx_ver,
const fx_ver_t& specified,
const bool& patch_roll_fwd,
{
trace::verbose(_X("Attempting FX roll forward starting from [%s]"), fx_ver.c_str());
- std::vector<pal::string_t> list;
- pal::readdir(fx_dir, &list);
+
fx_ver_t most_compatible = specified;
if (!specified.is_prerelease())
{
{
trace::verbose(_X("'Roll forward on no candidate fx' enabled. Looking for the least production greater than or equal to [%s]"), fx_ver.c_str());
fx_ver_t next_lowest(-1, -1, -1);
- for (const auto& version : list)
+ for (const auto& ver : version_list)
{
- fx_ver_t ver(-1, -1, -1);
- if (fx_ver_t::parse(version, &ver, true) && (ver >= specified))
+
+ if (!ver.is_prerelease() && ver >= specified)
{
next_lowest = (next_lowest == fx_ver_t(-1, -1, -1)) ? ver : std::min(next_lowest, ver);
}
if (patch_roll_fwd)
{
trace::verbose(_X("Applying patch roll forward from [%s]"), most_compatible.as_str().c_str());
- for (const auto& version : list)
+ for (const auto& ver : version_list)
{
- trace::verbose(_X("Inspecting version... [%s]"), version.c_str());
- fx_ver_t ver(-1, -1, -1);
+ trace::verbose(_X("Inspecting version... [%s]"), ver.as_str().c_str());
- if (fx_ver_t::parse(version, &ver, true) && // true -- only prod. prevents roll forward to prerelease.
+ if (!ver.is_prerelease() && // only prod. prevents roll forward to prerelease.
ver.get_major() == most_compatible.get_major() &&
ver.get_minor() == most_compatible.get_minor())
{
}
else
{
- for (const auto& version : list)
+ for (const auto& ver : version_list)
{
- trace::verbose(_X("Inspecting version... [%s]"), version.c_str());
- fx_ver_t ver(-1, -1, -1);
+ trace::verbose(_X("Inspecting version... [%s]"), ver.as_str().c_str());
- if (fx_ver_t::parse(version, &ver, false) && // false -- implies both production and prerelease.
- ver.is_prerelease() && // prevent roll forward to production.
+ //both production and prerelease.
+ if (ver.is_prerelease() && // prevent roll forward to production.
ver.get_major() == specified.get_major() &&
ver.get_minor() == specified.get_minor() &&
ver.get_patch() == specified.get_patch() &&
}
}
}
- pal::string_t most_compatible_str = most_compatible.as_str();
- append_path(&fx_dir, most_compatible_str.c_str());
+
+ return most_compatible;
}
pal::string_t fx_muxer_t::resolve_fx_dir(host_mode_t mode,
// Multi-level SharedFX lookup will look for the most appropriate version in several locations
// by following the priority rank below:
- // User directory
// .exe directory
// Global .NET directory
// If it is not activated, then only .exe directory will be considered
std::vector<pal::string_t> hive_dir;
pal::string_t local_dir;
- pal::string_t global_dir;
+ std::vector<pal::string_t> global_dirs;
bool multilevel_lookup = multilevel_lookup_enabled();
- if (multilevel_lookup)
+ hive_dir.push_back(own_dir);
+ if (multilevel_lookup && pal::get_global_dotnet_dirs(&global_dirs))
{
- if (pal::get_local_dotnet_dir(&local_dir))
+ for (pal::string_t dir : global_dirs)
{
- hive_dir.push_back(local_dir);
+ hive_dir.push_back(dir);
}
}
- hive_dir.push_back(own_dir);
- if (multilevel_lookup && pal::get_global_dotnet_dir(&global_dir))
- {
- hive_dir.push_back(global_dir);
- }
bool patch_roll_fwd_enabled = config.get_patch_roll_fwd();
+ pal::string_t selected_fx_dir;
+ fx_ver_t selected_ver(-1, -1, -1);
for (pal::string_t dir : hive_dir)
{
{
trace::verbose(_X("Did not roll forward because specified version='%s', patch_roll_fwd=%d, roll_fwd_on_no_candidate_fx=%d, chose [%s]"),
specified_fx_version.c_str(), patch_roll_fwd_enabled, roll_fwd_on_no_candidate_fx_val, fx_ver.c_str());
+
append_path(&fx_dir, fx_ver.c_str());
+ if (pal::directory_exists(fx_dir))
+ {
+ trace::verbose(_X("Chose FX version [%s]"), fx_dir.c_str());
+ return fx_dir;
+ }
}
else
{
- resolve_roll_forward(fx_dir, fx_ver, specified, patch_roll_fwd_enabled, roll_fwd_on_no_candidate_fx_val);
- }
+ std::vector<pal::string_t> list;
+ std::vector<fx_ver_t> version_list;
+ pal::readdir(fx_dir, &list);
- if (pal::directory_exists(fx_dir))
- {
- trace::verbose(_X("Chose FX version [%s]"), fx_dir.c_str());
- return fx_dir;
+ for (const auto& version : list)
+ {
+ fx_ver_t ver(-1, -1, -1);
+ if (fx_ver_t::parse(version, &ver, false))
+ {
+ version_list.push_back(ver);
+ }
+ }
+
+ fx_ver_t resolved_ver = resolve_framework_version(version_list, fx_ver, specified, patch_roll_fwd_enabled, roll_fwd_on_no_candidate_fx_val);
+
+ pal::string_t resolved_ver_str = resolved_ver.as_str();
+ append_path(&fx_dir, resolved_ver_str.c_str());
+
+ if (pal::directory_exists(fx_dir))
+ {
+ //Continue to search for a better match if available
+ std::vector<fx_ver_t> version_list;
+ version_list.push_back(resolved_ver);
+ version_list.push_back(selected_ver);
+ resolved_ver = resolve_framework_version(version_list, fx_ver, specified, patch_roll_fwd_enabled, roll_fwd_on_no_candidate_fx_val);
+
+ if (resolved_ver != selected_ver)
+ {
+ trace::verbose(_X("Changing Selected FX version from [%s] to [%s]"), selected_fx_dir.c_str(), fx_dir.c_str());
+ selected_ver = resolved_ver;
+ selected_fx_dir = fx_dir;
+ }
+ }
}
}
- trace::error(_X("It was not possible to find any compatible framework version"));
- return pal::string_t();
+ if (selected_fx_dir.empty())
+ {
+ trace::error(_X("It was not possible to find any compatible framework version"));
+ return pal::string_t();
+ }
+
+ trace::verbose(_X("Chose FX version [%s]"), selected_fx_dir.c_str());
+ return selected_fx_dir;
}
pal::string_t fx_muxer_t::resolve_cli_version(const pal::string_t& global_json)
std::vector<pal::string_t> hive_dir;
pal::string_t local_dir;
- pal::string_t global_dir;
+ std::vector<pal::string_t> global_dirs;
bool multilevel_lookup = multilevel_lookup_enabled();
if (multilevel_lookup)
hive_dir.push_back(own_dir);
}
- if (multilevel_lookup && pal::get_global_dotnet_dir(&global_dir))
+ if (multilevel_lookup && pal::get_global_dotnet_dirs(&global_dirs))
{
- hive_dir.push_back(global_dir);
+ for (pal::string_t dir : global_dirs)
+ {
+ hive_dir.push_back(dir);
+ }
}
pal::string_t cli_version;