/** * Probe helper for a deps entry. Lookup all probe configurations and then * lookup in the directory where the deps file is present. For app dirs, * 1. RID specific entries are present in the package relative structure. * 2. Non-RID entries are present in the directory path. */ bool deps_resolver_t::probe_deps_entry(const deps_entry_t& entry, const pal::string_t& deps_dir, pal::string_t* candidate) { if (probe_entry_in_configs(entry, candidate)) { return true; } if (entry.is_rid_specific && entry.to_rel_path(deps_dir, candidate)) { return true; } if (!entry.is_rid_specific && entry.to_dir_path(deps_dir, candidate)) { return true; } return false; }
bool deps_resolver_t::try_roll_forward(const deps_entry_t& entry, const pal::string_t& probe_dir, bool patch_roll_fwd, bool prerelease_roll_fwd, pal::string_t* candidate) { trace::verbose(_X("Attempting a roll forward for [%s/%s/%s] in [%s]"), entry.library_name.c_str(), entry.library_version.c_str(), entry.relative_path.c_str(), probe_dir.c_str()); const pal::string_t& lib_ver = entry.library_version; fx_ver_t cur_ver(-1, -1, -1); if (!fx_ver_t::parse(lib_ver, &cur_ver, false)) { trace::verbose(_X("No roll forward as specified version [%s] could not be parsed"), lib_ver.c_str()); return false; } pal::string_t path = probe_dir; append_path(&path, entry.library_name.c_str()); pal::string_t max_str = lib_ver; if (cur_ver.is_prerelease() && prerelease_roll_fwd) { pal::string_t maj_min_pat_star = cur_ver.prerelease_glob(); pal::string_t cache_key = path; append_path(&cache_key, maj_min_pat_star.c_str()); if (m_prerelease_roll_forward_cache.count(cache_key)) { max_str = m_prerelease_roll_forward_cache[cache_key]; trace::verbose(_X("Found cached roll forward version [%s] -> [%s]"), lib_ver.c_str(), max_str.c_str()); } else { try_prerelease_roll_forward_in_dir(path, cur_ver, &max_str); m_prerelease_roll_forward_cache[cache_key] = max_str; } } if (!cur_ver.is_prerelease() && patch_roll_fwd) { // Extract glob string of the form: 1.0.* from the version 1.0.0-prerelease-00001. pal::string_t maj_min_star = cur_ver.patch_glob(); pal::string_t cache_key = path; append_path(&cache_key, maj_min_star.c_str()); if (m_patch_roll_forward_cache.count(cache_key)) { max_str = m_patch_roll_forward_cache[cache_key]; trace::verbose(_X("Found cached roll forward version [%s] -> [%s]"), lib_ver.c_str(), max_str.c_str()); } else { try_patch_roll_forward_in_dir(path, cur_ver, &max_str); m_patch_roll_forward_cache[cache_key] = max_str; } } append_path(&path, max_str.c_str()); return entry.to_rel_path(path, candidate); }
bool deps_resolver_t::probe_entry_in_configs(const deps_entry_t& entry, pal::string_t* candidate) { candidate->clear(); for (const auto& config : m_probes) { trace::verbose(_X(" Considering entry [%s/%s/%s] and probe dir [%s]"), entry.library_name.c_str(), entry.library_version.c_str(), entry.relative_path.c_str(), config.probe_dir.c_str()); if (config.only_serviceable_assets && !entry.is_serviceable) { trace::verbose(_X(" Skipping... not serviceable asset")); continue; } if (config.only_runtime_assets && entry.asset_type != deps_entry_t::asset_types::runtime) { trace::verbose(_X(" Skipping... not runtime asset")); continue; } pal::string_t probe_dir = config.probe_dir; if (config.match_hash) { if (entry.to_hash_matched_path(probe_dir, candidate)) { assert(!config.is_roll_fwd_set()); trace::verbose(_X(" Matched hash for [%s]"), candidate->c_str()); return true; } trace::verbose(_X(" Skipping... match hash failed")); } else if (config.probe_deps_json) { // If the deps json has it then someone has already done rid selection and put the right stuff in the dir. // So checking just package name and version would suffice. No need to check further for the exact asset relative path. if (config.probe_deps_json->has_package(entry.library_name, entry.library_version) && entry.to_dir_path(probe_dir, candidate)) { trace::verbose(_X(" Probed deps json and matched [%s]"), candidate->c_str()); return true; } trace::verbose(_X(" Skipping... probe in deps json failed")); } else if (!config.is_roll_fwd_set()) { if (entry.to_full_path(probe_dir, candidate)) { trace::verbose(_X(" Specified no roll forward; matched [%s]"), candidate->c_str()); return true; } trace::verbose(_X(" Skipping... not found in probe dir")); } else if (config.is_roll_fwd_set()) { if (try_roll_forward(entry, probe_dir, config.patch_roll_fwd, config.prerelease_roll_fwd, candidate)) { trace::verbose(_X(" Specified roll forward; matched [%s]"), candidate->c_str()); return true; } trace::verbose(_X(" Skipping... could not roll forward and match in probe dir")); } // continue to try next probe config } return false; }
/** * Given a deps entry, do a probe (lookup) for the file, based on the probe config. * -- When crossgen-ed folders are looked up, look up only "runtime" (managed) assets. * -- When servicing directories are looked up, look up only if the deps file marks the entry as serviceable. * -- When a deps json based probe is performed, the deps entry's package name and version must match. * -- When looking into a published dir, for rid specific assets lookup rid split folders; for non-rid assets lookup the layout dir. */ bool deps_resolver_t::probe_deps_entry(const deps_entry_t& entry, const pal::string_t& deps_dir, int fx_level, pal::string_t* candidate) { candidate->clear(); for (const auto& config : m_probes) { trace::verbose(_X(" Considering entry [%s/%s/%s], probe dir [%s], probe fx level:%d, entry fx level:%d"), entry.library_name.c_str(), entry.library_version.c_str(), entry.asset.relative_path.c_str(), config.probe_dir.c_str(), config.fx_level, fx_level); if (config.only_serviceable_assets && !entry.is_serviceable) { trace::verbose(_X(" Skipping... not serviceable asset")); continue; } if (config.only_runtime_assets && entry.asset_type != deps_entry_t::asset_types::runtime) { trace::verbose(_X(" Skipping... not runtime asset")); continue; } pal::string_t probe_dir = config.probe_dir; if (config.is_fx()) { assert(config.fx_level > 0); // Only probe frameworks that are the same level or lower than the current entry because // a lower-level fx should not have a dependency on a higher-level fx and because starting // with fx_level allows it to override a higher-level fx location if the entry is newer. // Note that fx_level 0 is the highest level (the app) if (fx_level <= config.fx_level) { // If the deps json has the package name and version, then someone has already done rid selection and // put the right asset in the dir. So checking just package name and version would suffice. // No need to check further for the exact asset relative sub path. if (config.probe_deps_json->has_package(entry.library_name, entry.library_version) && entry.to_dir_path(probe_dir, candidate)) { trace::verbose(_X(" Probed deps json and matched '%s'"), candidate->c_str()); return true; } } trace::verbose(_X(" Skipping... not found in deps json.")); } else if (config.is_app()) { // This is a published dir probe, so look up rid specific assets in the rid folders. assert(config.fx_level == 0); if (fx_level <= config.fx_level) { if (entry.is_rid_specific) { if (entry.to_rel_path(deps_dir, candidate)) { trace::verbose(_X(" Probed deps dir and matched '%s'"), candidate->c_str()); return true; } } else { // Non-rid assets, lookup in the published dir. if (entry.to_dir_path(deps_dir, candidate)) { trace::verbose(_X(" Probed deps dir and matched '%s'"), candidate->c_str()); return true; } } } trace::verbose(_X(" Skipping... not found in deps dir '%s'"), deps_dir.c_str()); } else if (entry.to_full_path(probe_dir, candidate)) { trace::verbose(_X(" Probed package dir and matched '%s'"), candidate->c_str()); return true; } trace::verbose(_X(" Skipping... not found in probe dir '%s'"), probe_dir.c_str()); // continue to try next probe config } return false; }