use codex to make the codebase MUCH more maintainable
This commit is contained in:
@@ -0,0 +1,764 @@
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn build_env_rootfs_uses_selected_non_live_rootfs() {
|
||||
let tmp = tempfile::tempdir().unwrap();
|
||||
let expected = tmp.path().canonicalize().unwrap();
|
||||
|
||||
assert_eq!(
|
||||
build_cmd::build_env_rootfs(tmp.path()),
|
||||
expected.to_string_lossy()
|
||||
);
|
||||
assert_eq!(build_cmd::build_env_rootfs(Path::new("/")), "/");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn clean_build_workspace_removes_build_and_source_cache_dirs() -> Result<()> {
|
||||
let rootfs = tempfile::tempdir().context("Failed to create temp rootfs")?;
|
||||
let mut cfg = config::Config::for_rootfs(rootfs.path());
|
||||
cfg.build_dir = rootfs.path().join("tmp/build");
|
||||
cfg.cache_dir = rootfs.path().join("tmp/sources");
|
||||
|
||||
fs::create_dir_all(&cfg.build_dir)
|
||||
.with_context(|| format!("Failed to create {}", cfg.build_dir.display()))?;
|
||||
fs::create_dir_all(&cfg.cache_dir)
|
||||
.with_context(|| format!("Failed to create {}", cfg.cache_dir.display()))?;
|
||||
|
||||
let mut build_file = fs::File::create(cfg.build_dir.join("artifact.txt"))?;
|
||||
build_file.write_all(b"build data")?;
|
||||
build_file.flush()?;
|
||||
|
||||
let mut source_file = fs::File::create(cfg.cache_dir.join("source.tar.zst"))?;
|
||||
source_file.write_all(b"source data")?;
|
||||
source_file.flush()?;
|
||||
|
||||
clean_build_workspace(&cfg)?;
|
||||
|
||||
assert!(!cfg.build_dir.exists());
|
||||
assert!(!cfg.cache_dir.exists());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn clean_build_workspace_noops_when_dirs_are_missing() -> Result<()> {
|
||||
let rootfs = tempfile::tempdir().context("Failed to create temp rootfs")?;
|
||||
let mut cfg = config::Config::for_rootfs(rootfs.path());
|
||||
cfg.build_dir = rootfs.path().join("tmp/build");
|
||||
cfg.cache_dir = rootfs.path().join("tmp/sources");
|
||||
|
||||
clean_build_workspace(&cfg)?;
|
||||
|
||||
assert!(!cfg.build_dir.exists());
|
||||
assert!(!cfg.cache_dir.exists());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn clean_build_source_dirs_removes_build_dir_only() -> Result<()> {
|
||||
let rootfs = tempfile::tempdir().context("Failed to create temp rootfs")?;
|
||||
let mut cfg = config::Config::for_rootfs(rootfs.path());
|
||||
cfg.build_dir = rootfs.path().join("tmp/build");
|
||||
cfg.cache_dir = rootfs.path().join("tmp/sources");
|
||||
|
||||
fs::create_dir_all(&cfg.build_dir)
|
||||
.with_context(|| format!("Failed to create {}", cfg.build_dir.display()))?;
|
||||
fs::create_dir_all(&cfg.cache_dir)
|
||||
.with_context(|| format!("Failed to create {}", cfg.cache_dir.display()))?;
|
||||
|
||||
clean_build_source_dirs(&cfg)?;
|
||||
|
||||
assert!(!cfg.build_dir.exists());
|
||||
assert!(cfg.cache_dir.exists());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn clean_build_source_dirs_noops_when_build_dir_missing() -> Result<()> {
|
||||
let rootfs = tempfile::tempdir().context("Failed to create temp rootfs")?;
|
||||
let mut cfg = config::Config::for_rootfs(rootfs.path());
|
||||
cfg.build_dir = rootfs.path().join("tmp/build");
|
||||
cfg.cache_dir = rootfs.path().join("tmp/sources");
|
||||
|
||||
fs::create_dir_all(&cfg.cache_dir)
|
||||
.with_context(|| format!("Failed to create {}", cfg.cache_dir.display()))?;
|
||||
|
||||
clean_build_source_dirs(&cfg)?;
|
||||
|
||||
assert!(!cfg.build_dir.exists());
|
||||
assert!(cfg.cache_dir.exists());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn binary_archive_staging_uses_config_build_dir_instead_of_process_tmpdir() -> Result<()> {
|
||||
let rootfs = tempfile::tempdir().context("Failed to create temp rootfs")?;
|
||||
let pkg_dir = tempfile::tempdir().context("Failed to create temp package dir")?;
|
||||
let archive_path = pkg_dir.path().join("pkg-1.0-1-x86_64.depot.pkg.tar.zst");
|
||||
|
||||
let file = fs::File::create(&archive_path)
|
||||
.with_context(|| format!("Failed to create {}", archive_path.display()))?;
|
||||
let encoder =
|
||||
zstd::stream::write::Encoder::new(file, 3).context("Failed to create zstd encoder")?;
|
||||
let mut tar = tar::Builder::new(encoder);
|
||||
let payload = b"hello";
|
||||
let mut header = tar::Header::new_gnu();
|
||||
header.set_path("usr/bin/hello").unwrap();
|
||||
header.set_size(payload.len() as u64);
|
||||
header.set_mode(0o755);
|
||||
header.set_cksum();
|
||||
tar.append(&header, &payload[..]).unwrap();
|
||||
let encoder = tar.into_inner().unwrap();
|
||||
encoder.finish().unwrap();
|
||||
|
||||
let mut cfg = config::Config::for_rootfs(rootfs.path());
|
||||
cfg.build_dir = rootfs.path().join("var/cache/depot/build");
|
||||
|
||||
let staged = extract_package_archive_to_staging(&cfg, &archive_path)?;
|
||||
|
||||
assert!(staged.path().starts_with(staging_temp_root(&cfg)));
|
||||
assert!(staged.path().join("usr/bin/hello").exists());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(unix)]
|
||||
fn child_install_command_includes_lib32_only_flag_when_requested() -> Result<()> {
|
||||
use std::os::unix::fs::PermissionsExt;
|
||||
|
||||
let temp = tempfile::tempdir().context("Failed to create temp dir")?;
|
||||
let script_path = temp.path().join("capture-lib32-child-install.sh");
|
||||
let args_path = temp.path().join("args.txt");
|
||||
let script = format!(
|
||||
"#!/bin/sh\nprintf '%s\\n' \"$@\" > \"{}\"\n",
|
||||
args_path.display()
|
||||
);
|
||||
fs::write(&script_path, script)
|
||||
.with_context(|| format!("Failed to write {}", script_path.display()))?;
|
||||
fs::set_permissions(&script_path, fs::Permissions::from_mode(0o755))
|
||||
.with_context(|| format!("Failed to chmod {}", script_path.display()))?;
|
||||
|
||||
run_install_command_with_program(
|
||||
&script_path,
|
||||
&[PathBuf::from("/tmp/pkg.toml")],
|
||||
Path::new("/"),
|
||||
ChildInstallCommandOptions {
|
||||
no_deps: true,
|
||||
assume_yes: true,
|
||||
no_flags: false,
|
||||
cross_prefix: None,
|
||||
clean: false,
|
||||
lib32_only: true,
|
||||
install_test_deps: false,
|
||||
install_context: None,
|
||||
dep_chain: None,
|
||||
},
|
||||
)?;
|
||||
|
||||
let captured_args = fs::read_to_string(&args_path)
|
||||
.with_context(|| format!("Failed to read {}", args_path.display()))?;
|
||||
assert!(captured_args.lines().any(|line| line == "--lib32-only"));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn direct_install_checks_manual_sources_before_dependency_resolution() -> Result<()> {
|
||||
let rootfs = tempfile::tempdir().context("Failed to create temp rootfs")?;
|
||||
let spec_dir = tempfile::tempdir().context("Failed to create temp spec dir")?;
|
||||
let spec_path = spec_dir.path().join("demo.toml");
|
||||
fs::write(
|
||||
&spec_path,
|
||||
r#"[package]
|
||||
name = "demo"
|
||||
version = "1.0.0"
|
||||
revision = 1
|
||||
description = "demo"
|
||||
homepage = "https://example.test/demo"
|
||||
license = "MIT"
|
||||
|
||||
[build]
|
||||
type = "custom"
|
||||
|
||||
[dependencies]
|
||||
runtime = ["definitely-missing-dep"]
|
||||
optional = []
|
||||
|
||||
[[manual_sources]]
|
||||
file = "missing.patch"
|
||||
"#,
|
||||
)?;
|
||||
|
||||
let mut config = config::Config::for_rootfs(rootfs.path());
|
||||
config.build_dir = rootfs.path().join("var/cache/depot/build");
|
||||
config.cache_dir = rootfs.path().join("var/cache/depot/sources");
|
||||
config.db_dir = rootfs.path().join("var/lib/depot");
|
||||
|
||||
ui::set_assume_yes(true);
|
||||
let result = run_direct_install_request(
|
||||
DirectInstallOptions {
|
||||
rootfs: rootfs.path(),
|
||||
no_deps: false,
|
||||
no_flags: false,
|
||||
cross_prefix: None,
|
||||
clean: false,
|
||||
dry_run: false,
|
||||
lib32_only: false,
|
||||
install_test_deps: false,
|
||||
},
|
||||
&config,
|
||||
spec_path,
|
||||
);
|
||||
ui::set_assume_yes(false);
|
||||
|
||||
let err = result.expect_err("missing manual source should fail before dependency install");
|
||||
assert!(
|
||||
err.to_string()
|
||||
.contains("Manual source not found: missing.patch")
|
||||
);
|
||||
assert!(
|
||||
!err.to_string()
|
||||
.contains("Could not find package spec for dependency")
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn build_command_checks_manual_sources_before_dependency_resolution() -> Result<()> {
|
||||
let _guard = assume_yes_test_lock();
|
||||
let temp = tempfile::tempdir().context("Failed to create temp dir")?;
|
||||
let rootfs = temp.path().join("rootfs");
|
||||
let spec_dir = temp.path().join("packages").join("demo");
|
||||
fs::create_dir_all(&rootfs)?;
|
||||
fs::create_dir_all(&spec_dir)?;
|
||||
|
||||
let spec_path = spec_dir.join("demo.toml");
|
||||
fs::write(
|
||||
&spec_path,
|
||||
r#"[package]
|
||||
name = "demo"
|
||||
version = "1.0.0"
|
||||
revision = 1
|
||||
description = "demo"
|
||||
homepage = "https://example.test/demo"
|
||||
license = "MIT"
|
||||
|
||||
[[source]]
|
||||
url = "https://example.test/demo-1.0.0.tar.gz"
|
||||
sha256 = "skip"
|
||||
extract_dir = "demo-1.0.0"
|
||||
|
||||
[build]
|
||||
type = "custom"
|
||||
|
||||
[dependencies]
|
||||
build = ["definitely-missing-dep"]
|
||||
runtime = []
|
||||
optional = []
|
||||
|
||||
[[manual_sources]]
|
||||
file = "missing.patch"
|
||||
"#,
|
||||
)?;
|
||||
|
||||
let result = run(Cli {
|
||||
command: Commands::Build(BuildArgs {
|
||||
rootfs_args: rootfs_args(rootfs),
|
||||
prompt_args: prompt_args(true),
|
||||
build_exec_args: build_exec_args(),
|
||||
lib32_args: lib32_args(),
|
||||
spec_pos: Some(spec_path),
|
||||
spec: None,
|
||||
install: false,
|
||||
install_deps: true,
|
||||
cleanup_deps: false,
|
||||
}),
|
||||
});
|
||||
|
||||
let err = result.expect_err("missing manual source should fail before dependency install");
|
||||
assert!(
|
||||
err.to_string()
|
||||
.contains("Manual source not found: missing.patch")
|
||||
);
|
||||
assert!(
|
||||
!err.to_string()
|
||||
.contains("Failed to resolve required build tool package")
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn source_build_warning_messages_include_dependency_context() {
|
||||
let plan = planner::ExecutionPlan {
|
||||
steps: vec![
|
||||
planner::PlannedStep {
|
||||
package: "dep-src".into(),
|
||||
action: planner::PlanAction::BuildAndInstall,
|
||||
origin: planner::PlanOrigin::Source {
|
||||
path: PathBuf::from("/tmp/dep-src.toml"),
|
||||
local_sibling: false,
|
||||
},
|
||||
requested_by: vec!["dependency dep-src".into(), "app needs dep-src".into()],
|
||||
},
|
||||
planner::PlannedStep {
|
||||
package: "dep-bin".into(),
|
||||
action: planner::PlanAction::InstallBinary,
|
||||
origin: planner::PlanOrigin::Binary {
|
||||
repo_name: "core".into(),
|
||||
record: Box::new(test_binary_repo_record(
|
||||
"dep-bin",
|
||||
"dep-bin-1.0-1-x86_64.tar.zst",
|
||||
)),
|
||||
},
|
||||
requested_by: vec!["app needs dep-bin".into()],
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
assert_eq!(
|
||||
source_build_warning_messages(&plan),
|
||||
vec!["dep-src (requested dependency 'dep-src', needed by 'app')".to_string()]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn planned_source_build_prereqs_check_manual_sources_before_confirmation() -> Result<()> {
|
||||
let rootfs = tempfile::tempdir().context("Failed to create temp rootfs")?;
|
||||
let spec_dir = tempfile::tempdir().context("Failed to create temp spec dir")?;
|
||||
let spec_path = spec_dir.path().join("demo.toml");
|
||||
fs::write(
|
||||
&spec_path,
|
||||
r#"[package]
|
||||
name = "demo"
|
||||
version = "1.0.0"
|
||||
revision = 1
|
||||
description = "demo"
|
||||
homepage = "https://example.test/demo"
|
||||
license = "MIT"
|
||||
|
||||
[[source]]
|
||||
url = "https://example.test/demo-1.0.0.tar.gz"
|
||||
sha256 = "skip"
|
||||
extract_dir = "demo-1.0.0"
|
||||
|
||||
[build]
|
||||
type = "custom"
|
||||
|
||||
[dependencies]
|
||||
build = []
|
||||
runtime = []
|
||||
optional = []
|
||||
|
||||
[[manual_sources]]
|
||||
file = "missing.patch"
|
||||
"#,
|
||||
)?;
|
||||
|
||||
let config = config::Config::for_rootfs(rootfs.path());
|
||||
let plan = planner::ExecutionPlan {
|
||||
steps: vec![planner::PlannedStep {
|
||||
package: "demo".into(),
|
||||
action: planner::PlanAction::BuildAndInstall,
|
||||
origin: planner::PlanOrigin::Source {
|
||||
path: spec_path,
|
||||
local_sibling: true,
|
||||
},
|
||||
requested_by: vec!["requested spec".into()],
|
||||
}],
|
||||
};
|
||||
|
||||
let err = validate_source_build_prereqs_for_plan(&plan, rootfs.path(), &config)
|
||||
.expect_err("missing local manual source should fail before confirmation");
|
||||
assert!(
|
||||
err.to_string()
|
||||
.contains("Manual source not found: missing.patch")
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cleanup_targets_keep_runtime_dependencies_for_build_install() {
|
||||
let plan = planner::ExecutionPlan {
|
||||
steps: vec![
|
||||
planner::PlannedStep {
|
||||
package: "zlib".into(),
|
||||
action: planner::PlanAction::InstallBinary,
|
||||
origin: planner::PlanOrigin::Source {
|
||||
path: PathBuf::from("packages/core/zlib/zlib.toml"),
|
||||
local_sibling: false,
|
||||
},
|
||||
requested_by: vec!["cmake needs zlib".into(), "llvm-runtime needs zlib".into()],
|
||||
},
|
||||
planner::PlannedStep {
|
||||
package: "cmake".into(),
|
||||
action: planner::PlanAction::InstallBinary,
|
||||
origin: planner::PlanOrigin::Source {
|
||||
path: PathBuf::from("packages/core/cmake/cmake.toml"),
|
||||
local_sibling: false,
|
||||
},
|
||||
requested_by: vec!["dependency cmake".into()],
|
||||
},
|
||||
planner::PlannedStep {
|
||||
package: "llvm-runtime".into(),
|
||||
action: planner::PlanAction::InstallBinary,
|
||||
origin: planner::PlanOrigin::Source {
|
||||
path: PathBuf::from("packages/core/llvm-runtime/llvm-runtime.toml"),
|
||||
local_sibling: false,
|
||||
},
|
||||
requested_by: vec!["dependency llvm-runtime".into()],
|
||||
},
|
||||
],
|
||||
};
|
||||
let mut tracker = AutoInstalledDependencyTracker::default();
|
||||
tracker.record_plan(&plan, &["cmake".into()], AutoInstalledDependencyKind::Build);
|
||||
tracker.record_plan(
|
||||
&plan,
|
||||
&["llvm-runtime".into()],
|
||||
AutoInstalledDependencyKind::Runtime,
|
||||
);
|
||||
|
||||
assert_eq!(tracker.cleanup_targets(false), vec!["cmake".to_string()]);
|
||||
assert_eq!(
|
||||
tracker.cleanup_targets(true),
|
||||
vec![
|
||||
"llvm-runtime".to_string(),
|
||||
"cmake".to_string(),
|
||||
"zlib".to_string()
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn build_type_runs_automatic_tests_matches_builder_behavior() {
|
||||
assert!(build_type_runs_automatic_tests(&test_package_spec(
|
||||
package::BuildType::Autotools,
|
||||
None,
|
||||
&[]
|
||||
)));
|
||||
assert!(build_type_runs_automatic_tests(&test_package_spec(
|
||||
package::BuildType::Perl,
|
||||
None,
|
||||
&[]
|
||||
)));
|
||||
assert!(build_type_runs_automatic_tests(&test_package_spec(
|
||||
package::BuildType::Meson,
|
||||
None,
|
||||
&[]
|
||||
)));
|
||||
assert!(build_type_runs_automatic_tests(&test_package_spec(
|
||||
package::BuildType::CMake,
|
||||
None,
|
||||
&[]
|
||||
)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn requested_test_deps_prompt_can_disable_tests() -> Result<()> {
|
||||
let _guard = assume_yes_test_lock();
|
||||
let mut spec = test_package_spec(package::BuildType::Meson, None, &[]);
|
||||
spec.dependencies.test = vec!["pytest".into()];
|
||||
|
||||
ui::set_assume_yes(true);
|
||||
let prompted = maybe_prompt_to_skip_tests_for_missing_requested_deps(
|
||||
&mut spec,
|
||||
&["pytest".into()],
|
||||
"Requested test dependencies are missing",
|
||||
)?;
|
||||
ui::set_assume_yes(false);
|
||||
|
||||
assert!(prompted);
|
||||
assert!(spec.build.flags.skip_tests);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn requested_test_deps_prompt_is_ignored_for_non_automatic_test_builders() -> Result<()> {
|
||||
let _guard = assume_yes_test_lock();
|
||||
let mut spec = test_package_spec(package::BuildType::Custom, None, &[]);
|
||||
spec.dependencies.test = vec!["pytest".into()];
|
||||
|
||||
ui::set_assume_yes(true);
|
||||
let prompted = maybe_prompt_to_skip_tests_for_missing_requested_deps(
|
||||
&mut spec,
|
||||
&["pytest".into()],
|
||||
"Requested test dependencies are missing",
|
||||
)?;
|
||||
ui::set_assume_yes(false);
|
||||
|
||||
assert!(!prompted);
|
||||
assert!(!spec.build.flags.skip_tests);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn requested_test_deps_prompt_is_ignored_for_multilib_builds() -> Result<()> {
|
||||
let _guard = assume_yes_test_lock();
|
||||
let mut spec = test_package_spec(package::BuildType::Meson, None, &[]);
|
||||
spec.build.flags.build_32 = true;
|
||||
spec.dependencies.test = vec!["pytest".into()];
|
||||
|
||||
ui::set_assume_yes(true);
|
||||
let prompted = maybe_prompt_to_skip_tests_for_missing_requested_deps(
|
||||
&mut spec,
|
||||
&["pytest".into()],
|
||||
"Requested test dependencies are missing",
|
||||
)?;
|
||||
ui::set_assume_yes(false);
|
||||
|
||||
assert!(!prompted);
|
||||
assert!(!spec.build.flags.skip_tests);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn should_not_install_test_deps_for_cli_lib32_only_builds() {
|
||||
let mut spec = test_package_spec(package::BuildType::Meson, None, &[]);
|
||||
spec.dependencies.lib32 = Some(package::DependencyGroup {
|
||||
build: Vec::new(),
|
||||
runtime: Vec::new(),
|
||||
test: vec!["lib32-pytest".into()],
|
||||
optional: Vec::new(),
|
||||
groups: Vec::new(),
|
||||
});
|
||||
|
||||
assert!(!should_install_test_deps(
|
||||
&spec,
|
||||
true,
|
||||
deps::RequestedOutputs::Lib32Only
|
||||
));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn build_command_requires_install_deps_flag_for_missing_dependencies() -> Result<()> {
|
||||
let _guard = 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 config = config::Config::for_rootfs(&rootfs);
|
||||
register_required_development_package_if_configured(&config, &rootfs)?;
|
||||
|
||||
let result = run(Cli {
|
||||
command: Commands::Build(BuildArgs {
|
||||
rootfs_args: rootfs_args(rootfs.clone()),
|
||||
prompt_args: prompt_args(true),
|
||||
build_exec_args: build_exec_args(),
|
||||
lib32_args: lib32_args(),
|
||||
spec_pos: Some(app_spec),
|
||||
spec: None,
|
||||
install: false,
|
||||
install_deps: false,
|
||||
cleanup_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_uses_only_lib32_flag_rules() {
|
||||
let mut base = test_package_spec(package::BuildType::Custom, None, &[]);
|
||||
base.build.flags.cflags = vec!["-O2".into()];
|
||||
base.build.flags.replace_cflags = vec!["-O2=>-O3".into()];
|
||||
base.build.flags.cflags_lib32 = vec!["-m32".into()];
|
||||
base.build.flags.replace_cflags_lib32 = vec!["-m32=>-mstackrealign".into()];
|
||||
base.build.flags.cxxflags = vec!["-O2".into()];
|
||||
base.build.flags.replace_cxxflags = vec!["-O2=>-O3".into()];
|
||||
base.build.flags.cxxflags_lib32 = vec!["-fno-rtti".into()];
|
||||
base.build.flags.replace_cxxflags_lib32 = vec!["-fno-rtti=>-fno-exceptions".into()];
|
||||
|
||||
let lib32 = make_lib32_build_spec(&base);
|
||||
|
||||
assert!(lib32.build.flags.lib32_variant);
|
||||
assert_eq!(lib32.build.flags.cflags, vec!["-m32"]);
|
||||
assert_eq!(
|
||||
lib32.build.flags.replace_cflags,
|
||||
vec!["-m32=>-mstackrealign"]
|
||||
);
|
||||
assert_eq!(lib32.build.flags.cxxflags, vec!["-fno-rtti"]);
|
||||
assert_eq!(
|
||||
lib32.build.flags.replace_cxxflags,
|
||||
vec!["-fno-rtti=>-fno-exceptions"]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn make_lib32_package_spec_uses_lib32_dependency_override() {
|
||||
let mut base = test_package_spec(package::BuildType::Custom, None, &[]);
|
||||
base.dependencies.runtime = vec!["zlib".into()];
|
||||
base.dependencies.lib32 = Some(package::DependencyGroup {
|
||||
build: vec!["gcc-multilib".into()],
|
||||
runtime: vec!["lib32-zlib".into()],
|
||||
test: Vec::new(),
|
||||
optional: vec!["lib32-gtk-doc".into()],
|
||||
groups: Vec::new(),
|
||||
});
|
||||
|
||||
let lib32 = make_lib32_package_spec(&base);
|
||||
|
||||
assert_eq!(lib32.package.name, "lib32-pkg");
|
||||
assert_eq!(lib32.dependencies.build, vec!["gcc-multilib"]);
|
||||
assert_eq!(lib32.dependencies.runtime, vec!["lib32-zlib", "pkg"]);
|
||||
assert_eq!(lib32.dependencies.optional, vec!["lib32-gtk-doc"]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn make_lib32_package_spec_does_not_inherit_primary_alternatives() {
|
||||
let mut base = test_package_spec(package::BuildType::Custom, None, &[]);
|
||||
base.alternatives.provides = vec!["editor".into()];
|
||||
base.alternatives.conflicts = vec!["nano".into()];
|
||||
base.alternatives.replaces = vec!["vi".into()];
|
||||
|
||||
let lib32 = make_lib32_package_spec(&base);
|
||||
|
||||
assert_eq!(lib32.package.name, "lib32-pkg");
|
||||
assert!(lib32.alternatives.provides.is_empty());
|
||||
assert!(lib32.alternatives.conflicts.is_empty());
|
||||
assert!(lib32.alternatives.replaces.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn requested_outputs_prefers_lib32_only_spec_flag() {
|
||||
let mut spec = test_package_spec(package::BuildType::Custom, None, &[]);
|
||||
spec.build.flags.lib32_only = true;
|
||||
|
||||
assert_eq!(
|
||||
requested_outputs(&spec, false),
|
||||
deps::RequestedOutputs::Lib32Only
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn expand_install_requests_for_groups_uses_source_specs() -> Result<()> {
|
||||
let temp = tempfile::tempdir()?;
|
||||
let rootfs = temp.path().join("rootfs");
|
||||
let repo_root = temp.path().join("repos");
|
||||
let core = repo_root.join("core").join("foo");
|
||||
let desktop = repo_root.join("desktop").join("bar");
|
||||
fs::create_dir_all(&rootfs)?;
|
||||
fs::create_dir_all(&core)?;
|
||||
fs::create_dir_all(&desktop)?;
|
||||
|
||||
let foo_spec = core.join("foo.toml");
|
||||
fs::write(
|
||||
&foo_spec,
|
||||
r#"[package]
|
||||
name = "foo"
|
||||
version = "1.0.0"
|
||||
revision = 1
|
||||
description = "foo"
|
||||
homepage = "https://example.test/foo"
|
||||
license = "MIT"
|
||||
|
||||
[[source]]
|
||||
url = "https://example.test/foo-1.0.0.tar.gz"
|
||||
sha256 = "skip"
|
||||
extract_dir = "foo-1.0.0"
|
||||
|
||||
[build]
|
||||
type = "custom"
|
||||
|
||||
[dependencies]
|
||||
groups = ["base"]
|
||||
runtime = []
|
||||
optional = []
|
||||
"#,
|
||||
)?;
|
||||
|
||||
let bar_spec = desktop.join("bar.toml");
|
||||
fs::write(
|
||||
&bar_spec,
|
||||
r#"[package]
|
||||
name = "bar"
|
||||
version = "1.0.0"
|
||||
revision = 1
|
||||
description = "bar"
|
||||
homepage = "https://example.test/bar"
|
||||
license = "MIT"
|
||||
|
||||
[[source]]
|
||||
url = "https://example.test/bar-1.0.0.tar.gz"
|
||||
sha256 = "skip"
|
||||
extract_dir = "bar-1.0.0"
|
||||
|
||||
[build]
|
||||
type = "custom"
|
||||
|
||||
[dependencies]
|
||||
groups = ["base", "desktop"]
|
||||
runtime = []
|
||||
optional = []
|
||||
"#,
|
||||
)?;
|
||||
|
||||
let mut config = config::Config::for_rootfs(&rootfs);
|
||||
config.repo_clone_dir = repo_root;
|
||||
config.binary_repos.clear();
|
||||
|
||||
let (expanded, groups) =
|
||||
expand_install_requests_for_groups(&config, &rootfs, &[PathBuf::from("base")])?;
|
||||
|
||||
assert_eq!(groups, vec!["base".to_string()]);
|
||||
assert_eq!(expanded, vec![PathBuf::from("bar"), PathBuf::from("foo")]);
|
||||
Ok(())
|
||||
}
|
||||
Reference in New Issue
Block a user