mirror of
https://github.com/asterinas/asterinas.git
synced 2025-06-09 13:26:48 +00:00
Delay the canonicalization until after processing the CLI arguments
This commit is contained in:
parent
539984bbed
commit
b3b5e136bd
2
osdk/Cargo.lock
generated
2
osdk/Cargo.lock
generated
@ -146,7 +146,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cargo-osdk"
|
name = "cargo-osdk"
|
||||||
version = "0.8.0"
|
version = "0.8.1"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"assert_cmd",
|
"assert_cmd",
|
||||||
"clap",
|
"clap",
|
||||||
|
@ -1,24 +0,0 @@
|
|||||||
// SPDX-License-Identifier: MPL-2.0
|
|
||||||
|
|
||||||
//! The module implementing the evaluation feature.
|
|
||||||
|
|
||||||
use std::{io, path::Path, process};
|
|
||||||
|
|
||||||
/// This function is used to evaluate the string using the host's shell recursively
|
|
||||||
/// in order.
|
|
||||||
pub fn eval(cwd: impl AsRef<Path>, s: &String) -> io::Result<String> {
|
|
||||||
let mut eval = process::Command::new("bash");
|
|
||||||
eval.arg("-c");
|
|
||||||
eval.arg(format!("echo \"{}\"", s));
|
|
||||||
eval.current_dir(cwd.as_ref());
|
|
||||||
let output = eval.output()?;
|
|
||||||
if !output.stderr.is_empty() {
|
|
||||||
println!(
|
|
||||||
"[Info] {}",
|
|
||||||
String::from_utf8_lossy(&output.stderr).trim_end_matches('\n')
|
|
||||||
);
|
|
||||||
}
|
|
||||||
Ok(String::from_utf8_lossy(&output.stdout)
|
|
||||||
.trim_end_matches('\n')
|
|
||||||
.to_string())
|
|
||||||
}
|
|
@ -12,7 +12,7 @@ use serde::{de, Deserialize, Deserializer, Serialize};
|
|||||||
|
|
||||||
use super::scheme::Scheme;
|
use super::scheme::Scheme;
|
||||||
|
|
||||||
use crate::{config::scheme::QemuScheme, error::Errno, error_msg, util::get_cargo_metadata};
|
use crate::{error::Errno, error_msg, util::get_cargo_metadata};
|
||||||
|
|
||||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
pub struct OsdkMeta {
|
pub struct OsdkMeta {
|
||||||
@ -128,82 +128,7 @@ fn deserialize_toml_manifest(path: impl AsRef<Path>) -> Option<TomlManifest> {
|
|||||||
for scheme in manifest.map.values_mut() {
|
for scheme in manifest.map.values_mut() {
|
||||||
scheme.work_dir = Some(cwd.to_path_buf());
|
scheme.work_dir = Some(cwd.to_path_buf());
|
||||||
}
|
}
|
||||||
// Canonicalize all the path fields
|
|
||||||
let canonicalize = |target: &mut PathBuf| {
|
|
||||||
let last_cwd = std::env::current_dir().unwrap();
|
|
||||||
std::env::set_current_dir(cwd).unwrap();
|
|
||||||
*target = target.canonicalize().unwrap_or_else(|err| {
|
|
||||||
error_msg!(
|
|
||||||
"Cannot canonicalize path `{}`: {}",
|
|
||||||
target.to_string_lossy(),
|
|
||||||
err,
|
|
||||||
);
|
|
||||||
std::env::set_current_dir(&last_cwd).unwrap();
|
|
||||||
process::exit(Errno::GetMetadata as _);
|
|
||||||
});
|
|
||||||
std::env::set_current_dir(last_cwd).unwrap();
|
|
||||||
};
|
|
||||||
let canonicalize_scheme = |scheme: &mut Scheme| {
|
|
||||||
macro_rules! canonicalize_paths_in_scheme {
|
|
||||||
($scheme:expr) => {
|
|
||||||
if let Some(ref mut boot) = $scheme.boot {
|
|
||||||
if let Some(ref mut initramfs) = boot.initramfs {
|
|
||||||
canonicalize(initramfs);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if let Some(ref mut qemu) = $scheme.qemu {
|
|
||||||
if let Some(ref mut qemu_path) = qemu.path {
|
|
||||||
canonicalize(qemu_path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if let Some(ref mut grub) = $scheme.grub {
|
|
||||||
if let Some(ref mut grub_mkrescue_path) = grub.grub_mkrescue {
|
|
||||||
canonicalize(grub_mkrescue_path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
canonicalize_paths_in_scheme!(scheme);
|
|
||||||
if let Some(ref mut run) = scheme.run {
|
|
||||||
canonicalize_paths_in_scheme!(run);
|
|
||||||
}
|
|
||||||
if let Some(ref mut test) = scheme.test {
|
|
||||||
canonicalize_paths_in_scheme!(test);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
canonicalize_scheme(&mut manifest.default_scheme);
|
|
||||||
for scheme in manifest.map.values_mut() {
|
|
||||||
canonicalize_scheme(scheme);
|
|
||||||
}
|
|
||||||
// Do evaluations on the need to be evaluated string field, namely,
|
|
||||||
// QEMU arguments.
|
|
||||||
use super::eval::eval;
|
|
||||||
let eval_scheme = |scheme: &mut Scheme| {
|
|
||||||
let eval_qemu = |qemu: &mut Option<QemuScheme>| {
|
|
||||||
if let Some(ref mut qemu) = qemu {
|
|
||||||
if let Some(ref mut args) = qemu.args {
|
|
||||||
*args = match eval(cwd, args) {
|
|
||||||
Ok(v) => v,
|
|
||||||
Err(e) => {
|
|
||||||
error_msg!("Failed to evaluate qemu args: {:#?}", e);
|
|
||||||
process::exit(Errno::ParseMetadata as _);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
eval_qemu(&mut scheme.qemu);
|
|
||||||
if let Some(ref mut run) = scheme.run {
|
|
||||||
eval_qemu(&mut run.qemu);
|
|
||||||
}
|
|
||||||
if let Some(ref mut test) = scheme.test {
|
|
||||||
eval_qemu(&mut test.qemu);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
eval_scheme(&mut manifest.default_scheme);
|
|
||||||
for scheme in manifest.map.values_mut() {
|
|
||||||
eval_scheme(scheme);
|
|
||||||
}
|
|
||||||
Some(manifest)
|
Some(manifest)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,8 +5,6 @@
|
|||||||
//! arguments if the arguments is missing, e.g., the path of QEMU. The final configuration is stored in `BuildConfig`,
|
//! arguments if the arguments is missing, e.g., the path of QEMU. The final configuration is stored in `BuildConfig`,
|
||||||
//! `RunConfig` and `TestConfig`. These `*Config` are used for `build`, `run` and `test` subcommand.
|
//! `RunConfig` and `TestConfig`. These `*Config` are used for `build`, `run` and `test` subcommand.
|
||||||
|
|
||||||
mod eval;
|
|
||||||
|
|
||||||
pub mod manifest;
|
pub mod manifest;
|
||||||
pub mod scheme;
|
pub mod scheme;
|
||||||
pub mod unix_args;
|
pub mod unix_args;
|
||||||
@ -14,7 +12,11 @@ pub mod unix_args;
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test;
|
mod test;
|
||||||
|
|
||||||
use std::{env, path::PathBuf};
|
use std::{
|
||||||
|
env, io,
|
||||||
|
path::{Path, PathBuf},
|
||||||
|
process,
|
||||||
|
};
|
||||||
|
|
||||||
use linux_bzimage_builder::PayloadEncoding;
|
use linux_bzimage_builder::PayloadEncoding;
|
||||||
use scheme::{
|
use scheme::{
|
||||||
@ -25,6 +27,8 @@ use crate::{
|
|||||||
arch::{get_default_arch, Arch},
|
arch::{get_default_arch, Arch},
|
||||||
cli::CommonArgs,
|
cli::CommonArgs,
|
||||||
config::unix_args::apply_kv_array,
|
config::unix_args::apply_kv_array,
|
||||||
|
error::Errno,
|
||||||
|
error_msg,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// The global configuration for the OSDK actions.
|
/// The global configuration for the OSDK actions.
|
||||||
@ -37,7 +41,11 @@ pub struct Config {
|
|||||||
pub test: Action,
|
pub test: Action,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn apply_args_before_finalize(action_scheme: &mut ActionScheme, args: &CommonArgs) {
|
fn apply_args_before_finalize(
|
||||||
|
action_scheme: &mut ActionScheme,
|
||||||
|
args: &CommonArgs,
|
||||||
|
workdir: &PathBuf,
|
||||||
|
) {
|
||||||
if action_scheme.grub.is_none() {
|
if action_scheme.grub.is_none() {
|
||||||
action_scheme.grub = Some(GrubScheme::default());
|
action_scheme.grub = Some(GrubScheme::default());
|
||||||
}
|
}
|
||||||
@ -61,7 +69,11 @@ fn apply_args_before_finalize(action_scheme: &mut ActionScheme, args: &CommonArg
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if let Some(initramfs) = &args.initramfs {
|
if let Some(initramfs) = &args.initramfs {
|
||||||
boot.initramfs = Some(initramfs.clone());
|
let Ok(initramfs) = initramfs.canonicalize() else {
|
||||||
|
error_msg!("The initramfs path provided with argument `--initramfs` does not match any files.");
|
||||||
|
process::exit(Errno::GetMetadata as _);
|
||||||
|
};
|
||||||
|
boot.initramfs = Some(initramfs);
|
||||||
}
|
}
|
||||||
if let Some(boot_method) = args.boot_method {
|
if let Some(boot_method) = args.boot_method {
|
||||||
boot.method = Some(boot_method);
|
boot.method = Some(boot_method);
|
||||||
@ -73,12 +85,90 @@ fn apply_args_before_finalize(action_scheme: &mut ActionScheme, args: &CommonArg
|
|||||||
}
|
}
|
||||||
if let Some(ref mut qemu) = action_scheme.qemu {
|
if let Some(ref mut qemu) = action_scheme.qemu {
|
||||||
if let Some(path) = &args.qemu_exe {
|
if let Some(path) = &args.qemu_exe {
|
||||||
qemu.path = Some(path.clone());
|
let Ok(qemu_path) = path.canonicalize() else {
|
||||||
|
error_msg!(
|
||||||
|
"The QEMU path provided with argument `--qemu-exe` does not match any files."
|
||||||
|
);
|
||||||
|
process::exit(Errno::GetMetadata as _);
|
||||||
|
};
|
||||||
|
qemu.path = Some(qemu_path);
|
||||||
}
|
}
|
||||||
if let Some(bootdev_options) = &args.bootdev_append_options {
|
if let Some(bootdev_options) = &args.bootdev_append_options {
|
||||||
qemu.bootdev_append_options = Some(bootdev_options.clone());
|
qemu.bootdev_append_options = Some(bootdev_options.clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
canonicalize_and_eval(action_scheme, workdir);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn canonicalize_and_eval(action_scheme: &mut ActionScheme, workdir: &PathBuf) {
|
||||||
|
let canonicalize = |target: &mut PathBuf| {
|
||||||
|
let last_cwd = std::env::current_dir().unwrap();
|
||||||
|
std::env::set_current_dir(workdir).unwrap();
|
||||||
|
|
||||||
|
*target = target.canonicalize().unwrap_or_else(|err| {
|
||||||
|
error_msg!(
|
||||||
|
"Cannot canonicalize path `{}`: {}",
|
||||||
|
target.to_string_lossy(),
|
||||||
|
err,
|
||||||
|
);
|
||||||
|
std::env::set_current_dir(&last_cwd).unwrap();
|
||||||
|
process::exit(Errno::GetMetadata as _);
|
||||||
|
});
|
||||||
|
std::env::set_current_dir(last_cwd).unwrap();
|
||||||
|
};
|
||||||
|
|
||||||
|
if let Some(ref mut boot) = action_scheme.boot {
|
||||||
|
if let Some(ref mut initramfs) = boot.initramfs {
|
||||||
|
canonicalize(initramfs);
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(ref mut qemu) = action_scheme.qemu {
|
||||||
|
if let Some(ref mut qemu_path) = qemu.path {
|
||||||
|
canonicalize(qemu_path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(ref mut grub) = action_scheme.grub {
|
||||||
|
if let Some(ref mut grub_mkrescue_path) = grub.grub_mkrescue {
|
||||||
|
canonicalize(grub_mkrescue_path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do evaluations on the need to be evaluated string field, namely,
|
||||||
|
// QEMU arguments.
|
||||||
|
|
||||||
|
if let Some(ref mut qemu) = action_scheme.qemu {
|
||||||
|
if let Some(ref mut args) = qemu.args {
|
||||||
|
*args = match eval(workdir, args) {
|
||||||
|
Ok(v) => v,
|
||||||
|
Err(e) => {
|
||||||
|
error_msg!("Failed to evaluate qemu args: {:#?}", e);
|
||||||
|
process::exit(Errno::ParseMetadata as _);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This function is used to evaluate the string using the host's shell recursively
|
||||||
|
/// in order.
|
||||||
|
pub fn eval(cwd: impl AsRef<Path>, s: &String) -> io::Result<String> {
|
||||||
|
let mut eval = process::Command::new("bash");
|
||||||
|
eval.arg("-c");
|
||||||
|
eval.arg(format!("echo \"{}\"", s));
|
||||||
|
eval.current_dir(cwd.as_ref());
|
||||||
|
let output = eval.output()?;
|
||||||
|
if !output.stderr.is_empty() {
|
||||||
|
println!(
|
||||||
|
"[Info] {}",
|
||||||
|
String::from_utf8_lossy(&output.stderr).trim_end_matches('\n')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
Ok(String::from_utf8_lossy(&output.stdout)
|
||||||
|
.trim_end_matches('\n')
|
||||||
|
.to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn apply_args_after_finalize(action: &mut Action, args: &CommonArgs) {
|
fn apply_args_after_finalize(action: &mut Action, args: &CommonArgs) {
|
||||||
@ -111,7 +201,7 @@ impl Config {
|
|||||||
let run = {
|
let run = {
|
||||||
let mut run = scheme.run.clone().unwrap_or_default();
|
let mut run = scheme.run.clone().unwrap_or_default();
|
||||||
run.inherit(&default_scheme);
|
run.inherit(&default_scheme);
|
||||||
apply_args_before_finalize(&mut run, common_args);
|
apply_args_before_finalize(&mut run, common_args, scheme.work_dir.as_ref().unwrap());
|
||||||
let mut run = run.finalize(target_arch);
|
let mut run = run.finalize(target_arch);
|
||||||
apply_args_after_finalize(&mut run, common_args);
|
apply_args_after_finalize(&mut run, common_args);
|
||||||
check_compatibility(run.grub.boot_protocol, run.build.encoding.clone());
|
check_compatibility(run.grub.boot_protocol, run.build.encoding.clone());
|
||||||
@ -120,7 +210,7 @@ impl Config {
|
|||||||
let test = {
|
let test = {
|
||||||
let mut test = scheme.test.clone().unwrap_or_default();
|
let mut test = scheme.test.clone().unwrap_or_default();
|
||||||
test.inherit(&default_scheme);
|
test.inherit(&default_scheme);
|
||||||
apply_args_before_finalize(&mut test, common_args);
|
apply_args_before_finalize(&mut test, common_args, scheme.work_dir.as_ref().unwrap());
|
||||||
let mut test = test.finalize(target_arch);
|
let mut test = test.finalize(target_arch);
|
||||||
apply_args_after_finalize(&mut test, common_args);
|
apply_args_after_finalize(&mut test, common_args);
|
||||||
check_compatibility(test.grub.boot_protocol, test.build.encoding.clone());
|
check_compatibility(test.grub.boot_protocol, test.build.encoding.clone());
|
||||||
|
Loading…
x
Reference in New Issue
Block a user