Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add requested version to hostfxr_resolve_sdk2 #68355

Merged
merged 2 commits into from
Apr 25, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
elinor-fung marked this conversation as resolved.
Show resolved Hide resolved
// 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;
};