@@ -9,13 +9,7 @@ use crate::{
99
1010use 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
2014use 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
186185thread_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
191190extern "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
205204extern "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
230265impl 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}
0 commit comments