Skip to content

Commit 2f67373

Browse files
committed
Fix resolve_sdk
See also dotnet/runtime#118418
1 parent 09de658 commit 2f67373

File tree

3 files changed

+96
-37
lines changed

3 files changed

+96
-37
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ keywords = ["nethost", "hostfxr", "dotnet", "bindings", "coreclr"]
1515
num_enum = { version = "0.7", default-features = false }
1616
thiserror = { version = "2.0", default-features = false }
1717
derive_more = { version = "2.0", features = ["deref", "from", "display"], default-features = false }
18-
hostfxr-sys = { version = "0.12", features = ["enum-map", "undocumented", "wrapper", "optional-apis"], default-features = false }
18+
hostfxr-sys = { version = "0.13", features = ["enum-map", "undocumented", "wrapper", "optional-apis"], default-features = false }
1919
coreclr-hosting-shared = { version = "0.1", default-features = false }
2020
destruct-drop = { version = "0.2", default-features = false }
2121
enum-map = { version = "2.7", default-features = false }

src/hostfxr/library2_1.rs

Lines changed: 93 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,7 @@ use crate::{
99

1010
use coreclr_hosting_shared::char_t;
1111

12-
use std::{
13-
cell::RefCell,
14-
io,
15-
mem::MaybeUninit,
16-
path::{Path, PathBuf},
17-
ptr, slice,
18-
};
12+
use std::{cell::RefCell, io, mem::MaybeUninit, path::PathBuf, ptr, slice};
1913

2014
use super::UNSUPPORTED_HOST_VERSION_ERROR_CODE;
2115

@@ -87,6 +81,11 @@ impl Hostfxr {
8781
} else {
8882
hostfxr_resolve_sdk2_flags_t::disallow_prerelease
8983
};
84+
85+
// Reset the output
86+
let raw_result = RawResolveSdkResult::default();
87+
RESOLVE_SDK2_DATA.with(|sdk| *sdk.borrow_mut() = Some(raw_result));
88+
9089
let result = unsafe {
9190
self.lib.hostfxr_resolve_sdk2(
9291
sdk_dir.as_ptr(),
@@ -98,10 +97,10 @@ impl Hostfxr {
9897
.unwrap_or(UNSUPPORTED_HOST_VERSION_ERROR_CODE);
9998
HostingResult::from(result).into_result()?;
10099

101-
let sdk_path = RESOLVE_SDK2_DATA
100+
let raw_result = RESOLVE_SDK2_DATA
102101
.with(|sdk| sdk.borrow_mut().take())
103102
.unwrap();
104-
Ok(sdk_path)
103+
Ok(ResolveSdkResult::new(raw_result))
105104
}
106105

107106
/// Get the list of all available SDKs ordered by ascending version.
@@ -185,7 +184,7 @@ impl Hostfxr {
185184

186185
thread_local! {
187186
static GET_AVAILABLE_SDKS_DATA: RefCell<Option<Vec<PathBuf>>> = const { RefCell::new(None) };
188-
static RESOLVE_SDK2_DATA: RefCell<Option<ResolveSdkResult>> = const { RefCell::new(None) };
187+
static RESOLVE_SDK2_DATA: RefCell<Option<RawResolveSdkResult>> = const { RefCell::new(None) };
189188
}
190189

191190
extern "C" fn get_available_sdks_callback(sdk_count: i32, sdks_ptr: *const *const char_t) {
@@ -204,45 +203,105 @@ extern "C" fn get_available_sdks_callback(sdk_count: i32, sdks_ptr: *const *cons
204203

205204
extern "C" fn resolve_sdk2_callback(key: hostfxr_resolve_sdk2_result_key_t, value: *const char_t) {
206205
RESOLVE_SDK2_DATA.with(|sdks| {
207-
let path = unsafe { PdCStr::from_str_ptr(value) }.to_os_string().into();
208-
*sdks.borrow_mut() = Some(match key {
206+
let path: PathBuf = unsafe { PdCStr::from_str_ptr(value) }.to_os_string().into();
207+
let mut guard = sdks.borrow_mut();
208+
let raw_result = guard.as_mut().unwrap();
209+
match key {
209210
hostfxr_resolve_sdk2_result_key_t::resolved_sdk_dir => {
210-
ResolveSdkResult::ResolvedSdkDirectory(path)
211+
assert_eq!(raw_result.resolved_sdk_dir, None);
212+
raw_result.resolved_sdk_dir = Some(path);
211213
}
212214
hostfxr_resolve_sdk2_result_key_t::global_json_path => {
213-
ResolveSdkResult::GlobalJsonPath(path)
215+
assert_eq!(raw_result.global_json_path, None);
216+
raw_result.global_json_path = Some(path);
217+
}
218+
hostfxr_resolve_sdk2_result_key_t::requested_version => {
219+
assert_eq!(raw_result.requested_version, None);
220+
raw_result.requested_version = Some(path);
221+
}
222+
hostfxr_resolve_sdk2_result_key_t::global_json_state => {
223+
assert_eq!(raw_result.global_json_state, None);
224+
raw_result.global_json_state = Some(path);
214225
}
215-
});
226+
_ => {
227+
// new key encountered
228+
}
229+
}
216230
});
217231
}
218232

233+
#[derive(Debug, Default)]
234+
struct RawResolveSdkResult {
235+
pub resolved_sdk_dir: Option<PathBuf>,
236+
pub global_json_path: Option<PathBuf>,
237+
pub requested_version: Option<PathBuf>,
238+
pub global_json_state: Option<PathBuf>,
239+
}
240+
219241
/// Result of [`Hostfxr::resolve_sdk`].
220242
#[derive(Debug, Clone, PartialEq, Eq)]
221243
#[cfg_attr(feature = "doc-cfg", doc(cfg(feature = "netcore2_1")))]
222244
#[must_use]
223-
pub enum ResolveSdkResult {
224-
/// `global.json` was not present or did not impact the resolved SDK location.
225-
ResolvedSdkDirectory(PathBuf),
226-
/// `global.json` was used during resolution.
227-
GlobalJsonPath(PathBuf),
245+
pub struct ResolveSdkResult {
246+
/// Path to the directory of the resolved sdk.
247+
pub sdk_dir: PathBuf,
248+
/// State of the global.json encountered during sdk resolution.
249+
pub global_json: GlobalJsonState,
250+
}
251+
252+
/// State of global.json during sdk resolution with [`Hostfxr::resolve_sdk`].
253+
#[derive(Debug, Clone, PartialEq, Eq)]
254+
pub enum GlobalJsonState {
255+
/// The global.json contained invalid data, such as a malformed version number.
256+
InvalidData,
257+
/// The global.json does not contain valid json.
258+
InvalidJson,
259+
/// No global.json was found.
260+
NotFound,
261+
/// A global.json was found and was valid.
262+
Found(GlobalJsonInfo),
228263
}
229264

230265
impl ResolveSdkResult {
231-
/// Returns the path to the resolved SDK directory.
232-
#[must_use]
233-
pub fn into_path(self) -> PathBuf {
234-
match self {
235-
ResolveSdkResult::GlobalJsonPath(path)
236-
| ResolveSdkResult::ResolvedSdkDirectory(path) => path,
266+
fn new(raw: RawResolveSdkResult) -> Self {
267+
use hostfxr_sys::hostfxr_resolve_sdk2_global_json_state;
268+
let global_json = match raw.global_json_state {
269+
None => GlobalJsonState::NotFound, // assume not found, but could also be invalid
270+
Some(s) => match s.to_string_lossy().as_ref() {
271+
hostfxr_resolve_sdk2_global_json_state::INVALID_DATA => {
272+
GlobalJsonState::InvalidData
273+
}
274+
hostfxr_resolve_sdk2_global_json_state::INVALID_JSON => {
275+
GlobalJsonState::InvalidJson
276+
}
277+
hostfxr_resolve_sdk2_global_json_state::VALID => {
278+
GlobalJsonState::Found(GlobalJsonInfo {
279+
path: raw
280+
.global_json_path
281+
.expect("global.json found but no path provided"),
282+
requested_version: raw
283+
.requested_version
284+
.expect("global.json found but requested version not provided")
285+
.to_string_lossy()
286+
.to_string(),
287+
})
288+
}
289+
_ => GlobalJsonState::NotFound,
290+
},
291+
};
292+
let sdk_dir = raw
293+
.resolved_sdk_dir
294+
.expect("resolve_sdk2 succeeded but no sdk_dir provided.");
295+
Self {
296+
sdk_dir,
297+
global_json,
237298
}
238299
}
300+
}
239301

240-
/// Returns the path to the resolved SDK directory.
241-
#[must_use]
242-
pub fn path(&self) -> &Path {
243-
match self {
244-
ResolveSdkResult::GlobalJsonPath(path)
245-
| ResolveSdkResult::ResolvedSdkDirectory(path) => path,
246-
}
247-
}
302+
/// Info about global.json if valid with [`Hostfxr::resolve_sdk`].
303+
#[derive(Debug, Clone, PartialEq, Eq)]
304+
pub struct GlobalJsonInfo {
305+
path: PathBuf,
306+
requested_version: String,
248307
}

tests/sdk_resolve.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ fn resolve_sdk() {
2828
true,
2929
)
3030
.unwrap();
31-
32-
assert!(actual_sdks.contains(&sdk.into_path()));
31+
32+
assert!(actual_sdks.contains(&sdk.sdk_dir));
3333
}
3434

3535
#[test]

0 commit comments

Comments
 (0)