Skip to content

Commit

Permalink
Add requested version to hostfxr_resolve_sdk2 (#68355)
Browse files Browse the repository at this point in the history
  • Loading branch information
elinor-fung committed Apr 25, 2022
1 parent 3af0cf4 commit 3f4ac7f
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ internal enum hostfxr_resolve_sdk2_result_key_t : int
{
resolved_sdk_dir = 0,
global_json_path = 1,
requested_version = 2,
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
Expand Down
10 changes: 6 additions & 4 deletions src/installer/tests/HostActivation.Tests/NativeHostApis.cs
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ public SdkResolutionFixture(SharedTestState state)

Directory.CreateDirectory(WorkingDir);

// start with an empty global.json, it will be ignored, but prevent one lying on disk
// start with an empty global.json, it will be ignored, but prevent one lying on disk
// on a given machine from impacting the test.
File.WriteAllText(GlobalJson, "{}");

Expand Down Expand Up @@ -224,17 +224,19 @@ public void Hostfxr_resolve_sdk2_without_global_json_and_disallowing_previews()
[Fact]
public void Hostfxr_resolve_sdk2_with_global_json_and_disallowing_previews()
{
// With global.json specifying a preview, roll forward to preview
// With global.json specifying a preview, roll forward to preview
// since flag has no impact if global.json specifies a preview.
// Also check that global.json that impacted resolution is reported.

var f = new SdkResolutionFixture(sharedTestState);

File.WriteAllText(f.GlobalJson, "{ \"sdk\": { \"version\": \"5.6.6-preview\" } }");
string requestedVersion = "5.6.6-preview";
File.WriteAllText(f.GlobalJson, "{ \"sdk\": { \"version\": \"" + requestedVersion + "\" } }");
string expectedData = string.Join(';', new[]
{
("resolved_sdk_dir", Path.Combine(f.LocalSdkDir, "5.6.7-preview")),
("global_json_path", f.GlobalJson),
("requested_version", requestedVersion),
});

f.Dotnet.Exec(f.AppDll, new[] { "hostfxr_resolve_sdk2", f.ExeDir, f.WorkingDir, "disallow_prerelease" })
Expand Down Expand Up @@ -425,7 +427,7 @@ public void Hostfxr_get_dotnet_environment_info_with_multilevel_lookup_only_self
public void Hostfxr_get_dotnet_environment_info_global_install_path()
{
var f = new SdkResolutionFixture(sharedTestState);

f.Dotnet.Exec(f.AppDll, new[] { "hostfxr_get_dotnet_environment_info" })
.CaptureStdOut()
.CaptureStdErr()
Expand Down
27 changes: 20 additions & 7 deletions src/native/corehost/fxr/hostfxr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ enum class hostfxr_resolve_sdk2_result_key_t : int32_t
{
resolved_sdk_dir = 0,
global_json_path = 1,
requested_version = 2,
};

typedef void (HOSTFXR_CALLTYPE *hostfxr_resolve_sdk2_result_fn)(
Expand Down Expand Up @@ -208,17 +209,22 @@ typedef void (HOSTFXR_CALLTYPE *hostfxr_resolve_sdk2_result_fn)(
// than once. String values passed are valid only for the
// duration of a call.
//
// If resolution succeeds, result will be invoked with
// resolved_sdk_dir key and the value will hold the
// path to the resolved SDK director, otherwise it will
// be null.
// If resolution succeeds, then result will be invoked with
// resolved_sdk_dir key and the value will hold the path to
// the resolved SDK directory.
//
// If global.json is used then result will be invoked with
// global_json_path key and the value will hold the path
// If global.json is used, then result will be invoked with
// global_json_path key and the value will hold the path
// to global.json. If there was no global.json found,
// or the contents of global.json did not impact resolution
// (e.g. no version specified), then result will not be
// invoked with global_json_path key.
// invoked with global_json_path key. This will occur for
// both resolution success and failure.
//
// If a specific version is requested (via global.json), then
// result will be invoked with requested_version key and the
// value will hold the requested version. This will occur for
// both resolution success and failure.
//
// Return value:
// 0 on success, otherwise failure
Expand Down Expand Up @@ -265,6 +271,13 @@ SHARED_API int32_t HOSTFXR_CALLTYPE hostfxr_resolve_sdk2(
resolver.global_file_path().c_str());
}

if (!resolver.get_requested_version().is_empty())
{
result(
hostfxr_resolve_sdk2_result_key_t::requested_version,
resolver.get_requested_version().as_str().c_str());
}

return !resolved_sdk_dir.empty()
? StatusCode::Success
: StatusCode::SdkResolverResolveFailure;
Expand Down
41 changes: 23 additions & 18 deletions src/native/corehost/fxr/sdk_resolver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,22 +34,27 @@ sdk_resolver::sdk_resolver(bool allow_prerelease) :
}

sdk_resolver::sdk_resolver(fx_ver_t version, sdk_roll_forward_policy roll_forward, bool allow_prerelease) :
version(move(version)),
requested_version(move(version)),
roll_forward(roll_forward),
allow_prerelease(allow_prerelease)
{
}

pal::string_t const& sdk_resolver::global_file_path() const
const pal::string_t& sdk_resolver::global_file_path() const
{
return global_file;
}

const fx_ver_t& sdk_resolver::get_requested_version() const
{
return requested_version;
}

pal::string_t sdk_resolver::resolve(const pal::string_t& dotnet_root, bool print_errors) const
{
if (trace::is_enabled())
{
auto requested = version.is_empty() ? pal::string_t{} : version.as_str();
auto requested = requested_version.is_empty() ? pal::string_t{} : requested_version.as_str();
trace::verbose(
_X("Resolving SDKs with version = '%s', rollForward = '%s', allowPrerelease = %s"),
requested.empty() ? _X("latest") : requested.c_str(),
Expand Down Expand Up @@ -98,9 +103,9 @@ void sdk_resolver::print_resolution_error(const pal::string_t& dotnet_root, cons
{
bool sdk_exists = false;
const pal::char_t *no_sdk_message = _X("No .NET SDKs were found.");
if (!version.is_empty())
if (!requested_version.is_empty())
{
pal::string_t requested = version.as_str();
pal::string_t requested = requested_version.as_str();
trace::error(
_X("%sA compatible .NET SDK was not found.\n")
_X("\n")
Expand Down Expand Up @@ -176,7 +181,7 @@ sdk_resolver sdk_resolver::from_nearest_global_file(const pal::string_t& cwd, bo
}

// If the requested version is a prerelease, always allow prerelease versions
if (resolver.version.is_prerelease())
if (resolver.requested_version.is_prerelease())
{
resolver.allow_prerelease = true;
}
Expand Down Expand Up @@ -285,7 +290,7 @@ bool sdk_resolver::parse_global_file(pal::string_t global_file_path)
return false;
}

if (!fx_ver_t::parse(version_value->value.GetString(), &version, false))
if (!fx_ver_t::parse(version_value->value.GetString(), &requested_version, false))
{
trace::warning(
_X("Version '%s' is not valid for the 'sdk/version' value in [%s]"),
Expand Down Expand Up @@ -324,7 +329,7 @@ bool sdk_resolver::parse_global_file(pal::string_t global_file_path)
}

// All policies other than 'latestMajor' require a version to operate
if (roll_forward != sdk_roll_forward_policy::latest_major && version.is_empty())
if (roll_forward != sdk_roll_forward_policy::latest_major && requested_version.is_empty())
{
trace::warning(
_X("The roll-forward policy '%s' requires a 'sdk/version' value in [%s]"),
Expand All @@ -350,7 +355,7 @@ bool sdk_resolver::parse_global_file(pal::string_t global_file_path)

allow_prerelease = allow_prerelease_value->value.GetBool();

if (!allow_prerelease && version.is_prerelease())
if (!allow_prerelease && requested_version.is_prerelease())
{
trace::warning(_X("Ignoring the 'sdk/allowPrerelease' value in [%s] because a prerelease version was specified"), global_file_path.c_str());
allow_prerelease = true;
Expand All @@ -373,18 +378,18 @@ bool sdk_resolver::matches_policy(const fx_ver_t& current) const
}

// If no version was requested, then all versions match
if (version.is_empty())
if (requested_version.is_empty())
{
return true;
}

int requested_feature = version.get_patch() / 100;
int requested_feature = requested_version.get_patch() / 100;
int current_feature = current.get_patch() / 100;

int requested_minor = version.get_minor();
int requested_minor = requested_version.get_minor();
int current_minor = current.get_minor();

int requested_major = version.get_major();
int requested_major = requested_version.get_major();
int current_major = current.get_major();

// Rolling forward on patch requires the same major/minor/feature
Expand Down Expand Up @@ -415,7 +420,7 @@ bool sdk_resolver::matches_policy(const fx_ver_t& current) const
}

// The version must be at least what was requested
return current >= version;
return current >= requested_version;
}

bool sdk_resolver::is_better_match(const fx_ver_t& current, const fx_ver_t& previous) const
Expand All @@ -430,7 +435,7 @@ bool sdk_resolver::is_better_match(const fx_ver_t& current, const fx_ver_t& prev

// Use the later of the two if there is no requested version, the policy requires it,
// or if everything is equal up to the feature level (latest patch always wins)
if (version.is_empty() ||
if (requested_version.is_empty() ||
is_policy_use_latest() ||
(current.get_major() == previous.get_major() &&
current.get_minor() == previous.get_minor() &&
Expand Down Expand Up @@ -463,16 +468,16 @@ bool sdk_resolver::resolve_sdk_path_and_version(const pal::string_t& dir, pal::s
trace::verbose(_X("Searching for SDK versions in [%s]"), dir.c_str());

// If an exact match is preferred, check for the existence of the version
if (exact_match_preferred() && !version.is_empty())
if (exact_match_preferred() && !requested_version.is_empty())
{
auto probe_path = dir;
append_path(&probe_path, version.as_str().c_str());
append_path(&probe_path, requested_version.as_str().c_str());

if (pal::directory_exists(probe_path))
{
trace::verbose(_X("Found requested SDK directory [%s]"), probe_path.c_str());
sdk_path = move(probe_path);
resolved_version = version;
resolved_version = requested_version;

// The SDK path has been resolved
return true;
Expand Down
6 changes: 4 additions & 2 deletions src/native/corehost/fxr/sdk_resolver.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@ class sdk_resolver
explicit sdk_resolver(bool allow_prerelease = true);
sdk_resolver(fx_ver_t version, sdk_roll_forward_policy roll_forward, bool allow_prerelease);

pal::string_t const& global_file_path() const;
const pal::string_t& global_file_path() const;

const fx_ver_t& get_requested_version() const;

pal::string_t resolve(const pal::string_t& dotnet_root, bool print_errors = true) const;

Expand All @@ -62,7 +64,7 @@ class sdk_resolver
bool resolve_sdk_path_and_version(const pal::string_t& dir, pal::string_t& sdk_path, fx_ver_t& resolved_version) const;

pal::string_t global_file;
fx_ver_t version;
fx_ver_t requested_version;
sdk_roll_forward_policy roll_forward;
bool allow_prerelease;
};

0 comments on commit 3f4ac7f

Please sign in to comment.