feat: update depot version to 0.20.0 and add --install-deps flag for automatic dependency installation
This commit is contained in:
Generated
+1
-1
@@ -418,7 +418,7 @@ checksum = "807800ff3288b621186fe0a8f3392c4652068257302709c24efd918c3dffcdc2"
|
||||
|
||||
[[package]]
|
||||
name = "depot"
|
||||
version = "0.19.1"
|
||||
version = "0.20.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"ar",
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
[package]
|
||||
name = "depot"
|
||||
version = "0.19.1"
|
||||
version = "0.20.0"
|
||||
edition = "2024"
|
||||
|
||||
[lints.rust]
|
||||
|
||||
@@ -47,7 +47,7 @@ depot install zlib-1.2.11-1-x86_64.depot.pkg.tar.zst
|
||||
- Binary package installs verify both checksums and detached minisign signatures (`.sig`).
|
||||
- `remove <PACKAGE>`: Remove an installed package.
|
||||
- `build <SPEC>`: Build a package and create an archive without installing.
|
||||
- Resolves and offers to install missing build dependencies before fetching/building.
|
||||
- Use `--install-deps` to automatically install missing build/runtime/test dependencies before fetching/building.
|
||||
- Missing test dependencies automatically disable test execution unless `--test-deps` or `[install].test_deps = true` is set.
|
||||
- `update [PACKAGE ...]`: Update installed packages from configured repositories.
|
||||
- With no package names, updates every installed package that has a newer repo version available.
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
project(
|
||||
'depot',
|
||||
version: '0.19.1',
|
||||
version: '0.20.0',
|
||||
meson_version: '>=0.60.0',
|
||||
default_options: ['buildtype=release'],
|
||||
)
|
||||
|
||||
+13
@@ -93,6 +93,10 @@ pub enum Commands {
|
||||
/// Install package to rootfs after creating package archive(s)
|
||||
#[arg(long)]
|
||||
install: bool,
|
||||
|
||||
/// Automatically install missing dependencies before building
|
||||
#[arg(long)]
|
||||
install_deps: bool,
|
||||
},
|
||||
/// Update installed packages from configured repositories
|
||||
Update {
|
||||
@@ -347,4 +351,13 @@ mod tests {
|
||||
let cli = Cli::try_parse_from(["depot", "--test-deps", "install", "foo"]).unwrap();
|
||||
assert!(cli.test_deps);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn build_install_deps_flag_is_parsed() {
|
||||
let cli = Cli::try_parse_from(["depot", "build", "--install-deps", "pkg.toml"]).unwrap();
|
||||
match cli.command {
|
||||
Commands::Build { install_deps, .. } => assert!(install_deps),
|
||||
_ => panic!("expected build command"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+381
-65
@@ -2867,6 +2867,12 @@ struct InstallPlanExecutionOptions<'a> {
|
||||
install_test_deps: bool,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
struct ChildInstallBatch {
|
||||
requests: Vec<PathBuf>,
|
||||
lib32_only: bool,
|
||||
}
|
||||
|
||||
fn step_requests_only_lib32(
|
||||
step: &planner::PlannedStep,
|
||||
options: &InstallPlanExecutionOptions<'_>,
|
||||
@@ -2878,6 +2884,71 @@ fn step_requests_only_lib32(
|
||||
.any(|reason| reason.starts_with("requested "))
|
||||
}
|
||||
|
||||
fn build_live_rootfs_child_install_batches(
|
||||
steps: &[&planner::PlannedStep],
|
||||
options: &InstallPlanExecutionOptions<'_>,
|
||||
binary_archives: &HashMap<(String, String), db::repo::BinaryRepoCachedArchive>,
|
||||
) -> Result<Vec<ChildInstallBatch>> {
|
||||
let mut batches = Vec::new();
|
||||
let mut pending_binary_requests = Vec::new();
|
||||
|
||||
for step in steps {
|
||||
match &step.origin {
|
||||
planner::PlanOrigin::Source { path, .. } => {
|
||||
if !pending_binary_requests.is_empty() {
|
||||
batches.push(ChildInstallBatch {
|
||||
requests: std::mem::take(&mut pending_binary_requests),
|
||||
lib32_only: false,
|
||||
});
|
||||
}
|
||||
batches.push(ChildInstallBatch {
|
||||
requests: vec![path.clone()],
|
||||
lib32_only: step_requests_only_lib32(step, options),
|
||||
});
|
||||
}
|
||||
planner::PlanOrigin::Binary { repo_name, record } => {
|
||||
let cached = binary_archives
|
||||
.get(&(repo_name.clone(), record.filename.clone()))
|
||||
.with_context(|| {
|
||||
format!(
|
||||
"Cached archive missing for planned binary step '{}' from repo '{}'",
|
||||
record.filename, repo_name
|
||||
)
|
||||
})?;
|
||||
pending_binary_requests.push(cached.package_path.clone());
|
||||
}
|
||||
planner::PlanOrigin::Installed => {}
|
||||
}
|
||||
}
|
||||
|
||||
if !pending_binary_requests.is_empty() {
|
||||
batches.push(ChildInstallBatch {
|
||||
requests: pending_binary_requests,
|
||||
lib32_only: false,
|
||||
});
|
||||
}
|
||||
|
||||
Ok(batches)
|
||||
}
|
||||
|
||||
fn flush_binary_install_batch(
|
||||
pending_plans: &mut Vec<PlannedPackageInstall>,
|
||||
pending_staging_dirs: &mut Vec<tempfile::TempDir>,
|
||||
installed_outcomes: &mut Vec<InstalledPackageOutcome>,
|
||||
rootfs: &Path,
|
||||
config: &config::Config,
|
||||
) -> Result<()> {
|
||||
if pending_plans.is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let installed = install_planned_packages_to_rootfs(pending_plans, rootfs, config)?;
|
||||
installed_outcomes.extend(installed);
|
||||
pending_plans.clear();
|
||||
pending_staging_dirs.clear();
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn execute_install_plan_with_child_commands(
|
||||
plan: &planner::ExecutionPlan,
|
||||
rootfs: &Path,
|
||||
@@ -2940,44 +3011,8 @@ fn execute_install_plan_with_child_commands(
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if should_delegate_live_rootfs_installs(rootfs) {
|
||||
for step in actionable_steps {
|
||||
let install_request = match &step.origin {
|
||||
planner::PlanOrigin::Source { path, .. } => path.clone(),
|
||||
planner::PlanOrigin::Binary { repo_name, record } => {
|
||||
let repo_cfg = config.binary_repos.get(repo_name).with_context(|| {
|
||||
format!("Binary repo '{}' not found in config", repo_name)
|
||||
})?;
|
||||
db::repo::fetch_binary_package_archive(
|
||||
repo_name,
|
||||
repo_cfg,
|
||||
rootfs,
|
||||
record,
|
||||
&config.package_cache_dir,
|
||||
)?
|
||||
}
|
||||
planner::PlanOrigin::Installed => continue,
|
||||
};
|
||||
run_install_command_with_program(
|
||||
&std::env::current_exe().context("Failed to locate depot executable")?,
|
||||
&[install_request],
|
||||
rootfs,
|
||||
ChildInstallCommandOptions {
|
||||
no_deps: true,
|
||||
assume_yes: true,
|
||||
no_flags: options.no_flags,
|
||||
cross_prefix: options.cross_prefix,
|
||||
clean: options.clean,
|
||||
lib32_only: step_requests_only_lib32(step, &options),
|
||||
install_test_deps: options.install_test_deps,
|
||||
install_context: None,
|
||||
dep_chain: None,
|
||||
},
|
||||
)?;
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let mut binary_archives: HashMap<(String, String), db::repo::BinaryRepoCachedArchive> =
|
||||
HashMap::new();
|
||||
let mut binary_phase_items = Vec::new();
|
||||
for step in &actionable_steps {
|
||||
if let planner::PlanOrigin::Binary { repo_name, record } = &step.origin {
|
||||
@@ -2988,8 +3023,6 @@ fn execute_install_plan_with_child_commands(
|
||||
}
|
||||
}
|
||||
|
||||
let mut binary_archives: HashMap<(String, String), db::repo::BinaryRepoCachedArchive> =
|
||||
HashMap::new();
|
||||
if !binary_phase_items.is_empty() {
|
||||
ui::info(format!(
|
||||
"Downloading {} binary package(s) and detached signatures...",
|
||||
@@ -3134,6 +3167,31 @@ fn execute_install_plan_with_child_commands(
|
||||
signature_pb.finish_and_clear();
|
||||
}
|
||||
|
||||
if should_delegate_live_rootfs_installs(rootfs) {
|
||||
let exe = std::env::current_exe().context("Failed to locate depot executable")?;
|
||||
let batches =
|
||||
build_live_rootfs_child_install_batches(&actionable_steps, &options, &binary_archives)?;
|
||||
for batch in batches {
|
||||
run_install_command_with_program(
|
||||
&exe,
|
||||
&batch.requests,
|
||||
rootfs,
|
||||
ChildInstallCommandOptions {
|
||||
no_deps: true,
|
||||
assume_yes: true,
|
||||
no_flags: options.no_flags,
|
||||
cross_prefix: options.cross_prefix,
|
||||
clean: options.clean,
|
||||
lib32_only: batch.lib32_only,
|
||||
install_test_deps: options.install_test_deps,
|
||||
install_context: None,
|
||||
dep_chain: None,
|
||||
},
|
||||
)?;
|
||||
}
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let mut binary_pre_hook_plans = Vec::new();
|
||||
for step in &actionable_steps {
|
||||
if let planner::PlanOrigin::Binary { repo_name, record } = &step.origin {
|
||||
@@ -3160,9 +3218,19 @@ fn execute_install_plan_with_child_commands(
|
||||
let exe = std::env::current_exe().context("Failed to locate depot executable")?;
|
||||
let total_steps = actionable_steps.len();
|
||||
let mut binary_post_hook_plans = Vec::new();
|
||||
let mut pending_binary_install_plans = Vec::new();
|
||||
let mut pending_binary_install_staging_dirs = Vec::new();
|
||||
let mut installed_binary_outcomes = Vec::new();
|
||||
for (idx, step) in actionable_steps.into_iter().enumerate() {
|
||||
match &step.origin {
|
||||
planner::PlanOrigin::Source { path, .. } => {
|
||||
flush_binary_install_batch(
|
||||
&mut pending_binary_install_plans,
|
||||
&mut pending_binary_install_staging_dirs,
|
||||
&mut installed_binary_outcomes,
|
||||
rootfs,
|
||||
config,
|
||||
)?;
|
||||
ui::info(format!(
|
||||
"[{}/{}] building+installing {} from source",
|
||||
idx + 1,
|
||||
@@ -3207,16 +3275,25 @@ fn execute_install_plan_with_child_commands(
|
||||
let staged = extract_package_archive_to_staging(config, &cached.package_path)?;
|
||||
let spec = load_package_spec_from_staging_or_repo_record(staged.path(), record)?;
|
||||
let plans = plan_package_outputs_for_install(&spec, staged.path(), rootfs, config)?;
|
||||
let installed = install_planned_packages_to_rootfs(&plans, rootfs, config)?;
|
||||
binary_post_hook_plans.extend(plans);
|
||||
for pkg in installed {
|
||||
log_install_success(&pkg);
|
||||
}
|
||||
binary_post_hook_plans.extend(plans.iter().cloned());
|
||||
pending_binary_install_plans.extend(plans);
|
||||
pending_binary_install_staging_dirs.push(staged);
|
||||
}
|
||||
planner::PlanOrigin::Installed => {}
|
||||
}
|
||||
}
|
||||
|
||||
flush_binary_install_batch(
|
||||
&mut pending_binary_install_plans,
|
||||
&mut pending_binary_install_staging_dirs,
|
||||
&mut installed_binary_outcomes,
|
||||
rootfs,
|
||||
config,
|
||||
)?;
|
||||
for pkg in installed_binary_outcomes {
|
||||
log_install_success(&pkg);
|
||||
}
|
||||
|
||||
run_transaction_hooks_for_plans(
|
||||
rootfs,
|
||||
install::hooks::HookPhase::Post,
|
||||
@@ -3903,6 +3980,7 @@ pub fn run(cli: Cli) -> Result<()> {
|
||||
spec_pos,
|
||||
spec,
|
||||
install,
|
||||
install_deps,
|
||||
} => {
|
||||
warn_if_running_as_root_for_build("build", &cli.rootfs);
|
||||
let spec_path = spec.or(spec_pos).context("No spec file provided")?;
|
||||
@@ -3916,6 +3994,14 @@ pub fn run(cli: Cli) -> Result<()> {
|
||||
pkg_spec.apply_config(&config);
|
||||
let requested_outputs = requested_outputs(&pkg_spec, cli.lib32_only);
|
||||
|
||||
let build_targets = vec![format!(
|
||||
"{} v{}-{}",
|
||||
pkg_spec.package.name, pkg_spec.package.version, pkg_spec.package.revision
|
||||
)];
|
||||
if !ui::prompt_package_action("build", &build_targets, true)? {
|
||||
anyhow::bail!("Aborted");
|
||||
}
|
||||
|
||||
// Ensure database directory exists
|
||||
std::fs::create_dir_all(&config.db_dir).with_context(|| {
|
||||
format!(
|
||||
@@ -3974,12 +4060,17 @@ pub fn run(cli: Cli) -> Result<()> {
|
||||
},
|
||||
)?;
|
||||
print_plan_summary(&dep_plan);
|
||||
if !ui::prompt_package_action(
|
||||
"dependency installation",
|
||||
&missing_required,
|
||||
true,
|
||||
)? {
|
||||
anyhow::bail!("Aborted");
|
||||
if !install_deps {
|
||||
if cli.dry_run {
|
||||
ui::info(
|
||||
"Dry run enabled, stopping before dependency installation/build.",
|
||||
);
|
||||
return Ok(());
|
||||
}
|
||||
anyhow::bail!(
|
||||
"Missing dependencies: {}. Re-run with --install-deps to install them automatically, or install them manually.",
|
||||
missing_required.join(", ")
|
||||
);
|
||||
}
|
||||
if cli.dry_run {
|
||||
ui::info("Dry run enabled, stopping before dependency installation/build.");
|
||||
@@ -4041,17 +4132,22 @@ pub fn run(cli: Cli) -> Result<()> {
|
||||
missing_test.join(", ")
|
||||
));
|
||||
print_plan_summary(&dep_plan);
|
||||
if !ui::prompt_package_action(
|
||||
"dependency installation",
|
||||
&missing_test,
|
||||
true,
|
||||
)? {
|
||||
if !install_deps {
|
||||
if cli.dry_run {
|
||||
ui::info(
|
||||
"Dry run enabled, stopping before dependency installation/build.",
|
||||
);
|
||||
return Ok(());
|
||||
}
|
||||
if !maybe_prompt_to_skip_tests_for_missing_requested_deps(
|
||||
&mut pkg_spec,
|
||||
&missing_test,
|
||||
"Requested test dependencies were not installed",
|
||||
)? {
|
||||
anyhow::bail!("Aborted");
|
||||
anyhow::bail!(
|
||||
"Missing test dependencies: {}. Re-run with --install-deps to install them automatically, or install them manually.",
|
||||
missing_test.join(", ")
|
||||
);
|
||||
}
|
||||
} else if !cli.dry_run {
|
||||
execute_install_plan_with_child_commands(
|
||||
@@ -4103,14 +4199,6 @@ pub fn run(cli: Cli) -> Result<()> {
|
||||
let build_lock_path = locking::lock_path(&config);
|
||||
let _build_lock_guard = locking::try_write(&mut build_lock, &build_lock_path, "build")?;
|
||||
|
||||
let build_targets = vec![format!(
|
||||
"{} v{}-{}",
|
||||
pkg_spec.package.name, pkg_spec.package.version, pkg_spec.package.revision
|
||||
)];
|
||||
if !ui::prompt_package_action("build", &build_targets, true)? {
|
||||
anyhow::bail!("Aborted");
|
||||
}
|
||||
|
||||
if cli.dry_run {
|
||||
ui::info("Dry run enabled, stopping before fetch/build.");
|
||||
return Ok(());
|
||||
@@ -4834,6 +4922,30 @@ pub fn run(cli: Cli) -> Result<()> {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use std::sync::Mutex;
|
||||
|
||||
static ASSUME_YES_TEST_LOCK: Mutex<()> = Mutex::new(());
|
||||
|
||||
fn test_binary_repo_record(name: &str, filename: &str) -> db::repo::BinaryRepoPackageRecord {
|
||||
db::repo::BinaryRepoPackageRecord {
|
||||
repo_name: "core".into(),
|
||||
name: name.into(),
|
||||
version: "1.0".into(),
|
||||
revision: 1,
|
||||
completed_at: None,
|
||||
filename: filename.into(),
|
||||
size: 1,
|
||||
sha256: "sha256".into(),
|
||||
sha512: "sha512".into(),
|
||||
description: None,
|
||||
homepage: None,
|
||||
license: None,
|
||||
provides: Vec::new(),
|
||||
conflicts: Vec::new(),
|
||||
runtime_dependencies: Vec::new(),
|
||||
optional_dependencies: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
fn test_package_spec(
|
||||
build_type: package::BuildType,
|
||||
@@ -5959,6 +6071,7 @@ optional = []
|
||||
|
||||
#[test]
|
||||
fn requested_test_deps_prompt_can_disable_tests() -> Result<()> {
|
||||
let _guard = ASSUME_YES_TEST_LOCK.lock().expect("assume-yes test lock");
|
||||
let mut spec = test_package_spec(package::BuildType::Meson, None, &[]);
|
||||
spec.dependencies.test = vec!["pytest".into()];
|
||||
|
||||
@@ -5977,6 +6090,7 @@ optional = []
|
||||
|
||||
#[test]
|
||||
fn requested_test_deps_prompt_is_ignored_for_non_automatic_test_builders() -> Result<()> {
|
||||
let _guard = ASSUME_YES_TEST_LOCK.lock().expect("assume-yes test lock");
|
||||
let mut spec = test_package_spec(package::BuildType::Custom, None, &[]);
|
||||
spec.dependencies.test = vec!["pytest".into()];
|
||||
|
||||
@@ -6015,6 +6129,7 @@ optional = []
|
||||
spec_pos: Some(PathBuf::from("foo.toml")),
|
||||
spec: None,
|
||||
install: false,
|
||||
install_deps: false,
|
||||
}));
|
||||
assert!(!command_requires_live_root(&Commands::Search {
|
||||
query: "foo".to_string(),
|
||||
@@ -6033,6 +6148,207 @@ optional = []
|
||||
)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn live_rootfs_child_install_batches_group_consecutive_binary_steps() -> Result<()> {
|
||||
let source_path = PathBuf::from("/tmp/requested.toml");
|
||||
let expat_archive = PathBuf::from("/tmp/expat.pkg.tar.zst");
|
||||
let python_archive = PathBuf::from("/tmp/python.pkg.tar.zst");
|
||||
let compiler_rt_archive = PathBuf::from("/tmp/lib32-compiler-rt.pkg.tar.zst");
|
||||
|
||||
let expat_record = test_binary_repo_record("expat", "expat-1.0-1-x86_64.depot.pkg.tar.zst");
|
||||
let python_record =
|
||||
test_binary_repo_record("python", "python-1.0-1-x86_64.depot.pkg.tar.zst");
|
||||
let compiler_rt_record = test_binary_repo_record(
|
||||
"lib32-compiler-rt",
|
||||
"lib32-compiler-rt-1.0-1-x86_64.depot.pkg.tar.zst",
|
||||
);
|
||||
|
||||
let steps = vec![
|
||||
planner::PlannedStep {
|
||||
package: "expat".into(),
|
||||
action: planner::PlanAction::InstallBinary,
|
||||
origin: planner::PlanOrigin::Binary {
|
||||
repo_name: "core".into(),
|
||||
record: Box::new(expat_record.clone()),
|
||||
},
|
||||
requested_by: vec!["pkg needs expat".into()],
|
||||
},
|
||||
planner::PlannedStep {
|
||||
package: "python".into(),
|
||||
action: planner::PlanAction::InstallBinary,
|
||||
origin: planner::PlanOrigin::Binary {
|
||||
repo_name: "core".into(),
|
||||
record: Box::new(python_record.clone()),
|
||||
},
|
||||
requested_by: vec!["pkg needs python".into()],
|
||||
},
|
||||
planner::PlannedStep {
|
||||
package: "pkg".into(),
|
||||
action: planner::PlanAction::BuildAndInstall,
|
||||
origin: planner::PlanOrigin::Source {
|
||||
path: source_path.clone(),
|
||||
local_sibling: false,
|
||||
},
|
||||
requested_by: vec!["requested spec".into()],
|
||||
},
|
||||
planner::PlannedStep {
|
||||
package: "lib32-compiler-rt".into(),
|
||||
action: planner::PlanAction::InstallBinary,
|
||||
origin: planner::PlanOrigin::Binary {
|
||||
repo_name: "core".into(),
|
||||
record: Box::new(compiler_rt_record.clone()),
|
||||
},
|
||||
requested_by: vec!["pkg needs lib32-compiler-rt".into()],
|
||||
},
|
||||
];
|
||||
let step_refs = steps.iter().collect::<Vec<_>>();
|
||||
|
||||
let mut binary_archives = HashMap::new();
|
||||
binary_archives.insert(
|
||||
("core".to_string(), expat_record.filename.clone()),
|
||||
db::repo::BinaryRepoCachedArchive {
|
||||
package_path: expat_archive.clone(),
|
||||
signature_path: PathBuf::from("/tmp/expat.sig"),
|
||||
},
|
||||
);
|
||||
binary_archives.insert(
|
||||
("core".to_string(), python_record.filename.clone()),
|
||||
db::repo::BinaryRepoCachedArchive {
|
||||
package_path: python_archive.clone(),
|
||||
signature_path: PathBuf::from("/tmp/python.sig"),
|
||||
},
|
||||
);
|
||||
binary_archives.insert(
|
||||
("core".to_string(), compiler_rt_record.filename.clone()),
|
||||
db::repo::BinaryRepoCachedArchive {
|
||||
package_path: compiler_rt_archive.clone(),
|
||||
signature_path: PathBuf::from("/tmp/lib32-compiler-rt.sig"),
|
||||
},
|
||||
);
|
||||
|
||||
let options = InstallPlanExecutionOptions {
|
||||
no_flags: false,
|
||||
cross_prefix: None,
|
||||
clean: false,
|
||||
dry_run: false,
|
||||
confirm_installation: false,
|
||||
lib32_only_requested_specs: true,
|
||||
install_test_deps: false,
|
||||
};
|
||||
|
||||
let batches =
|
||||
build_live_rootfs_child_install_batches(&step_refs, &options, &binary_archives)?;
|
||||
|
||||
assert_eq!(
|
||||
batches,
|
||||
vec![
|
||||
ChildInstallBatch {
|
||||
requests: vec![expat_archive, python_archive],
|
||||
lib32_only: false,
|
||||
},
|
||||
ChildInstallBatch {
|
||||
requests: vec![source_path],
|
||||
lib32_only: true,
|
||||
},
|
||||
ChildInstallBatch {
|
||||
requests: vec![compiler_rt_archive],
|
||||
lib32_only: false,
|
||||
},
|
||||
]
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn build_command_requires_install_deps_flag_for_missing_dependencies() -> Result<()> {
|
||||
let _guard = ASSUME_YES_TEST_LOCK.lock().expect("assume-yes test lock");
|
||||
let temp = tempfile::tempdir().context("Failed to create temp dir")?;
|
||||
let rootfs = temp.path().join("rootfs");
|
||||
let repo_root = temp.path().join("packages");
|
||||
let app_dir = repo_root.join("app");
|
||||
let dep_dir = repo_root.join("dep");
|
||||
fs::create_dir_all(&rootfs)?;
|
||||
fs::create_dir_all(&app_dir)?;
|
||||
fs::create_dir_all(&dep_dir)?;
|
||||
|
||||
let app_spec = app_dir.join("app.toml");
|
||||
fs::write(
|
||||
&app_spec,
|
||||
r#"[package]
|
||||
name = "app"
|
||||
version = "1.0.0"
|
||||
revision = 1
|
||||
description = "app"
|
||||
homepage = "https://example.test/app"
|
||||
license = "MIT"
|
||||
|
||||
[[source]]
|
||||
url = "https://example.test/app-1.0.0.tar.gz"
|
||||
sha256 = "skip"
|
||||
extract_dir = "app-1.0.0"
|
||||
|
||||
[build]
|
||||
type = "custom"
|
||||
|
||||
[dependencies]
|
||||
build = ["dep"]
|
||||
runtime = []
|
||||
optional = []
|
||||
"#,
|
||||
)
|
||||
.with_context(|| format!("Failed to write {}", app_spec.display()))?;
|
||||
|
||||
let dep_spec = dep_dir.join("dep.toml");
|
||||
fs::write(
|
||||
&dep_spec,
|
||||
r#"[package]
|
||||
name = "dep"
|
||||
version = "1.0.0"
|
||||
revision = 1
|
||||
description = "dep"
|
||||
homepage = "https://example.test/dep"
|
||||
license = "MIT"
|
||||
|
||||
[[source]]
|
||||
url = "https://example.test/dep-1.0.0.tar.gz"
|
||||
sha256 = "skip"
|
||||
extract_dir = "dep-1.0.0"
|
||||
|
||||
[build]
|
||||
type = "custom"
|
||||
|
||||
[dependencies]
|
||||
build = []
|
||||
runtime = []
|
||||
optional = []
|
||||
"#,
|
||||
)
|
||||
.with_context(|| format!("Failed to write {}", dep_spec.display()))?;
|
||||
|
||||
let result = run(Cli {
|
||||
rootfs: rootfs.clone(),
|
||||
no_deps: false,
|
||||
no_flags: false,
|
||||
cross_prefix: None,
|
||||
clean: false,
|
||||
yes: true,
|
||||
dry_run: false,
|
||||
test_deps: false,
|
||||
lib32_only: false,
|
||||
command: Commands::Build {
|
||||
spec_pos: Some(app_spec),
|
||||
spec: None,
|
||||
install: false,
|
||||
install_deps: false,
|
||||
},
|
||||
});
|
||||
ui::set_assume_yes(false);
|
||||
|
||||
let err = result.expect_err("build should require --install-deps when deps are missing");
|
||||
assert!(err.to_string().contains("Re-run with --install-deps"));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn make_lib32_build_spec_merges_replace_flag_rules() {
|
||||
let mut base = test_package_spec(package::BuildType::Custom, None, &[]);
|
||||
|
||||
Reference in New Issue
Block a user