aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore6
-rw-r--r--Cargo.lock308
-rw-r--r--Cargo.toml2
-rw-r--r--apps/fparkan-game/src/main.rs1
-rw-r--r--crates/fparkan-assets/src/lib.rs2
-rw-r--r--crates/fparkan-corpus/src/lib.rs7
-rw-r--r--crates/fparkan-fx/src/lib.rs2
-rw-r--r--crates/fparkan-material/src/lib.rs1
-rw-r--r--crates/fparkan-mission-format/src/lib.rs1
-rw-r--r--crates/fparkan-msh/src/lib.rs2
-rw-r--r--crates/fparkan-nres/src/lib.rs1
-rw-r--r--crates/fparkan-prototype/src/lib.rs2
-rw-r--r--crates/fparkan-resource/src/lib.rs1
-rw-r--r--crates/fparkan-rsli/src/lib.rs4
-rw-r--r--crates/fparkan-runtime/src/lib.rs5
-rw-r--r--crates/fparkan-terrain-format/src/lib.rs3
-rw-r--r--crates/fparkan-terrain/src/lib.rs2
-rw-r--r--crates/fparkan-texm/src/lib.rs1
-rw-r--r--xtask/src/main.rs103
19 files changed, 440 insertions, 14 deletions
diff --git a/.gitignore b/.gitignore
index 2c15862..3391914 100644
--- a/.gitignore
+++ b/.gitignore
@@ -69,10 +69,6 @@ $RECYCLE.BIN/
debug/
target/
-# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
-# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
-Cargo.lock
-
# These are backup files generated by rustfmt
**/*.rs.bk
@@ -215,4 +211,4 @@ poetry.toml
.ruff_cache/
# LSP config files
-pyrightconfig.json \ No newline at end of file
+pyrightconfig.json
diff --git a/Cargo.lock b/Cargo.lock
new file mode 100644
index 0000000..edce011
--- /dev/null
+++ b/Cargo.lock
@@ -0,0 +1,308 @@
+# This file is automatically @generated by Cargo.
+# It is not intended for manual editing.
+version = 4
+
+[[package]]
+name = "adler2"
+version = "2.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa"
+
+[[package]]
+name = "cfg-if"
+version = "1.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801"
+
+[[package]]
+name = "crc32fast"
+version = "1.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9481c1c90cbf2ac953f07c8d4a58aa3945c425b7185c9154d67a65e4230da511"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "encoding_rs"
+version = "0.8.35"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "75030f3c4f45dafd7586dd6780965a8c7e8e285a5ecb86713e63a79c5b2766f3"
+dependencies = [
+ "cfg-if",
+]
+
+[[package]]
+name = "flate2"
+version = "1.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "843fba2746e448b37e26a819579957415c8cef339bf08564fe8b7ddbd959573c"
+dependencies = [
+ "crc32fast",
+ "miniz_oxide",
+]
+
+[[package]]
+name = "fparkan-animation"
+version = "0.1.0"
+
+[[package]]
+name = "fparkan-assets"
+version = "0.1.0"
+dependencies = [
+ "fparkan-material",
+ "fparkan-msh",
+ "fparkan-nres",
+ "fparkan-path",
+ "fparkan-prototype",
+ "fparkan-resource",
+ "fparkan-texm",
+ "fparkan-vfs",
+]
+
+[[package]]
+name = "fparkan-binary"
+version = "0.1.0"
+
+[[package]]
+name = "fparkan-cli"
+version = "0.1.0"
+dependencies = [
+ "fparkan-corpus",
+ "fparkan-nres",
+ "fparkan-prototype",
+ "fparkan-resource",
+ "fparkan-rsli",
+ "fparkan-runtime",
+ "fparkan-vfs",
+]
+
+[[package]]
+name = "fparkan-corpus"
+version = "0.1.0"
+dependencies = [
+ "fparkan-path",
+]
+
+[[package]]
+name = "fparkan-diagnostics"
+version = "0.1.0"
+
+[[package]]
+name = "fparkan-fx"
+version = "0.1.0"
+dependencies = [
+ "fparkan-binary",
+ "fparkan-nres",
+]
+
+[[package]]
+name = "fparkan-game"
+version = "0.1.0"
+dependencies = [
+ "fparkan-render",
+ "fparkan-runtime",
+ "fparkan-vfs",
+ "fparkan-world",
+]
+
+[[package]]
+name = "fparkan-headless"
+version = "0.1.0"
+dependencies = [
+ "fparkan-runtime",
+ "fparkan-vfs",
+ "fparkan-world",
+]
+
+[[package]]
+name = "fparkan-material"
+version = "0.1.0"
+dependencies = [
+ "encoding_rs",
+ "fparkan-nres",
+ "fparkan-path",
+ "fparkan-resource",
+ "fparkan-vfs",
+]
+
+[[package]]
+name = "fparkan-mission-format"
+version = "0.1.0"
+dependencies = [
+ "encoding_rs",
+ "fparkan-binary",
+]
+
+[[package]]
+name = "fparkan-msh"
+version = "0.1.0"
+dependencies = [
+ "encoding_rs",
+ "fparkan-animation",
+ "fparkan-nres",
+]
+
+[[package]]
+name = "fparkan-nres"
+version = "0.1.0"
+dependencies = [
+ "fparkan-binary",
+ "fparkan-path",
+]
+
+[[package]]
+name = "fparkan-path"
+version = "0.1.0"
+
+[[package]]
+name = "fparkan-platform"
+version = "0.1.0"
+
+[[package]]
+name = "fparkan-platform-sdl"
+version = "0.1.0"
+dependencies = [
+ "fparkan-platform",
+]
+
+[[package]]
+name = "fparkan-prototype"
+version = "0.1.0"
+dependencies = [
+ "encoding_rs",
+ "fparkan-binary",
+ "fparkan-material",
+ "fparkan-msh",
+ "fparkan-nres",
+ "fparkan-path",
+ "fparkan-resource",
+ "fparkan-texm",
+ "fparkan-vfs",
+]
+
+[[package]]
+name = "fparkan-render"
+version = "0.1.0"
+dependencies = [
+ "fparkan-world",
+]
+
+[[package]]
+name = "fparkan-render-gl"
+version = "0.1.0"
+dependencies = [
+ "fparkan-render",
+]
+
+[[package]]
+name = "fparkan-resource"
+version = "0.1.0"
+dependencies = [
+ "fparkan-nres",
+ "fparkan-path",
+ "fparkan-rsli",
+ "fparkan-vfs",
+]
+
+[[package]]
+name = "fparkan-rsli"
+version = "0.1.0"
+dependencies = [
+ "flate2",
+]
+
+[[package]]
+name = "fparkan-runtime"
+version = "0.1.0"
+dependencies = [
+ "fparkan-mission-format",
+ "fparkan-nres",
+ "fparkan-path",
+ "fparkan-platform",
+ "fparkan-prototype",
+ "fparkan-render",
+ "fparkan-resource",
+ "fparkan-terrain",
+ "fparkan-terrain-format",
+ "fparkan-vfs",
+ "fparkan-world",
+]
+
+[[package]]
+name = "fparkan-terrain"
+version = "0.1.0"
+dependencies = [
+ "fparkan-nres",
+ "fparkan-terrain-format",
+]
+
+[[package]]
+name = "fparkan-terrain-format"
+version = "0.1.0"
+dependencies = [
+ "fparkan-binary",
+ "fparkan-nres",
+]
+
+[[package]]
+name = "fparkan-test-support"
+version = "0.1.0"
+dependencies = [
+ "fparkan-render",
+]
+
+[[package]]
+name = "fparkan-texm"
+version = "0.1.0"
+dependencies = [
+ "fparkan-nres",
+]
+
+[[package]]
+name = "fparkan-vfs"
+version = "0.1.0"
+dependencies = [
+ "fparkan-path",
+]
+
+[[package]]
+name = "fparkan-viewer"
+version = "0.1.0"
+dependencies = [
+ "fparkan-msh",
+ "fparkan-nres",
+ "fparkan-render",
+ "fparkan-resource",
+ "fparkan-rsli",
+ "fparkan-terrain-format",
+ "fparkan-texm",
+ "fparkan-vfs",
+]
+
+[[package]]
+name = "fparkan-world"
+version = "0.1.0"
+
+[[package]]
+name = "miniz_oxide"
+version = "0.8.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316"
+dependencies = [
+ "adler2",
+ "simd-adler32",
+]
+
+[[package]]
+name = "simd-adler32"
+version = "0.3.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e320a6c5ad31d271ad523dcf3ad13e2767ad8b1cb8f047f75a8aeaf8da139da2"
+
+[[package]]
+name = "xtask"
+version = "0.1.0"
+dependencies = [
+ "fparkan-corpus",
+]
diff --git a/Cargo.toml b/Cargo.toml
index a14eb8a..7c791db 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -36,7 +36,7 @@ members = [
[workspace.package]
version = "0.1.0"
edition = "2021"
-license = "MIT"
+license = "GPL-2.0-only"
repository = "https://github.com/valentineus/fparkan"
[workspace.lints.rust]
diff --git a/apps/fparkan-game/src/main.rs b/apps/fparkan-game/src/main.rs
index ed12c70..2486cfc 100644
--- a/apps/fparkan-game/src/main.rs
+++ b/apps/fparkan-game/src/main.rs
@@ -262,6 +262,7 @@ mod tests {
}
#[test]
+ #[ignore = "requires licensed corpus"]
fn selected_is_and_is2_missions_produce_approved_render_captures() {
for case in [
RenderCase {
diff --git a/crates/fparkan-assets/src/lib.rs b/crates/fparkan-assets/src/lib.rs
index 78ffb0b..20d08cb 100644
--- a/crates/fparkan-assets/src/lib.rs
+++ b/crates/fparkan-assets/src/lib.rs
@@ -426,6 +426,7 @@ mod tests {
}
#[test]
+ #[ignore = "requires licensed corpus"]
fn prepares_real_unit_asset_plan() {
let root = fixture_root("IS");
let vfs: Arc<dyn Vfs> = Arc::new(DirectoryVfs::new(&root));
@@ -448,6 +449,7 @@ mod tests {
}
#[test]
+ #[ignore = "requires licensed corpus"]
fn repository_plan_deduplicates_duplicate_visuals_but_graph_preserves_requests() {
let root = fixture_root("IS");
let vfs: Arc<dyn Vfs> = Arc::new(DirectoryVfs::new(&root));
diff --git a/crates/fparkan-corpus/src/lib.rs b/crates/fparkan-corpus/src/lib.rs
index ba26c73..1504f01 100644
--- a/crates/fparkan-corpus/src/lib.rs
+++ b/crates/fparkan-corpus/src/lib.rs
@@ -442,6 +442,7 @@ mod tests {
use std::time::{SystemTime, UNIX_EPOCH};
#[test]
+ #[ignore = "requires licensed corpus"]
fn report_for_testdata_roots() {
let root = Path::new(env!("CARGO_MANIFEST_DIR"))
.join("../..")
@@ -457,6 +458,7 @@ mod tests {
}
#[test]
+ #[ignore = "requires licensed corpus"]
fn licensed_part1_manifest_profile_and_counts_match_baseline() {
let root = testdata_root("IS");
let manifest = discover(&root, DiscoverOptions::default()).expect("part 1 manifest");
@@ -473,6 +475,7 @@ mod tests {
}
#[test]
+ #[ignore = "requires licensed corpus"]
fn licensed_part2_manifest_profile_and_counts_match_baseline() {
let root = testdata_root("IS2");
let manifest = discover(&root, DiscoverOptions::default()).expect("part 2 manifest");
@@ -489,6 +492,7 @@ mod tests {
}
#[test]
+ #[ignore = "requires licensed corpus"]
fn licensed_part1_has_no_casefold_relative_path_collisions() {
let root = testdata_root("IS");
let manifest = discover(&root, DiscoverOptions::default()).expect("part 1 manifest");
@@ -497,6 +501,7 @@ mod tests {
}
#[test]
+ #[ignore = "requires licensed corpus"]
fn licensed_part2_has_no_casefold_relative_path_collisions() {
let root = testdata_root("IS2");
let manifest = discover(&root, DiscoverOptions::default()).expect("part 2 manifest");
@@ -505,11 +510,13 @@ mod tests {
}
#[test]
+ #[ignore = "requires licensed corpus"]
fn licensed_part1_paths_stay_under_root() {
assert_discovered_paths_stay_under_root("IS");
}
#[test]
+ #[ignore = "requires licensed corpus"]
fn licensed_part2_paths_stay_under_root() {
assert_discovered_paths_stay_under_root("IS2");
}
diff --git a/crates/fparkan-fx/src/lib.rs b/crates/fparkan-fx/src/lib.rs
index 9675507..fb8adff 100644
--- a/crates/fparkan-fx/src/lib.rs
+++ b/crates/fparkan-fx/src/lib.rs
@@ -838,6 +838,7 @@ mod tests {
}
#[test]
+ #[ignore = "requires licensed corpus"]
fn licensed_corpus_fxid_exact_eof_and_distribution() {
for (corpus, expected_count) in [("IS", 923_usize), ("IS2", 1065_usize)] {
let Some(root) = corpus_root(corpus) else {
@@ -886,6 +887,7 @@ mod tests {
}
#[test]
+ #[ignore = "requires licensed corpus"]
fn licensed_corpus_fxid_emission_captures_are_approved() {
for (corpus, expected_count, expected_emitting, expected_hash) in [
("IS", 923_usize, 467_usize, 10_553_431_922_547_057_702_u64),
diff --git a/crates/fparkan-material/src/lib.rs b/crates/fparkan-material/src/lib.rs
index 780a1ae..a7ec5d7 100644
--- a/crates/fparkan-material/src/lib.rs
+++ b/crates/fparkan-material/src/lib.rs
@@ -1092,6 +1092,7 @@ mod tests {
}
#[test]
+ #[ignore = "requires licensed corpus"]
fn licensed_corpus_mat0_and_wear_parse() {
for (corpus, expected_mat0, expected_archive_wear, expected_standalone_wear) in [
("IS", 905_usize, 439_usize, 95_usize),
diff --git a/crates/fparkan-mission-format/src/lib.rs b/crates/fparkan-mission-format/src/lib.rs
index edbe908..0c85c39 100644
--- a/crates/fparkan-mission-format/src/lib.rs
+++ b/crates/fparkan-mission-format/src/lib.rs
@@ -979,6 +979,7 @@ mod tests {
}
#[test]
+ #[ignore = "requires licensed corpus"]
fn licensed_corpus_tma_validate() {
for (
corpus,
diff --git a/crates/fparkan-msh/src/lib.rs b/crates/fparkan-msh/src/lib.rs
index f06c8d6..3ec3def 100644
--- a/crates/fparkan-msh/src/lib.rs
+++ b/crates/fparkan-msh/src/lib.rs
@@ -1236,6 +1236,7 @@ mod tests {
}
#[test]
+ #[ignore = "requires licensed corpus"]
fn licensed_corpus_msh_assets_validate() {
for (corpus, expected) in [("IS", 435_usize), ("IS2", 511_usize)] {
let Some(root) = corpus_root(corpus) else {
@@ -1279,6 +1280,7 @@ mod tests {
}
#[test]
+ #[ignore = "requires licensed corpus"]
fn licensed_corpus_animation_streams_sample_approved_pose_captures() {
for (
corpus,
diff --git a/crates/fparkan-nres/src/lib.rs b/crates/fparkan-nres/src/lib.rs
index f2bd106..44d9c93 100644
--- a/crates/fparkan-nres/src/lib.rs
+++ b/crates/fparkan-nres/src/lib.rs
@@ -1779,6 +1779,7 @@ mod tests {
}
#[test]
+ #[ignore = "requires licensed corpus"]
fn licensed_corpora_nres_roundtrip_gates() {
let part1 = corpus_gate("IS", 120, 6_804).expect("part 1 NRes gate");
let part2 = corpus_gate("IS2", 134, 8_171).expect("part 2 NRes gate");
diff --git a/crates/fparkan-prototype/src/lib.rs b/crates/fparkan-prototype/src/lib.rs
index 4efafa1..35089b0 100644
--- a/crates/fparkan-prototype/src/lib.rs
+++ b/crates/fparkan-prototype/src/lib.rs
@@ -1826,6 +1826,7 @@ mod tests {
}
#[test]
+ #[ignore = "requires licensed corpus"]
fn licensed_corpora_unit_dat_parse_counts() {
let cases = [("IS", 425, 5_219), ("IS2", 676, 8_145)];
for (corpus, expected_files, expected_records) in cases {
@@ -1859,6 +1860,7 @@ mod tests {
}
#[test]
+ #[ignore = "requires licensed corpus"]
fn licensed_corpora_registry_payloads_are_record_aligned() {
for corpus in ["IS", "IS2"] {
let root = corpus_root(corpus).expect("corpus root");
diff --git a/crates/fparkan-resource/src/lib.rs b/crates/fparkan-resource/src/lib.rs
index aa6de70..7dd90b5 100644
--- a/crates/fparkan-resource/src/lib.rs
+++ b/crates/fparkan-resource/src/lib.rs
@@ -696,6 +696,7 @@ mod tests {
}
#[test]
+ #[ignore = "requires licensed corpus"]
fn licensed_corpora_repository_reads_nres_and_rsli() {
licensed_repository_gate("IS").expect("part 1 repository gate");
licensed_repository_gate("IS2").expect("part 2 repository gate");
diff --git a/crates/fparkan-rsli/src/lib.rs b/crates/fparkan-rsli/src/lib.rs
index 59b4c67..0d315ff 100644
--- a/crates/fparkan-rsli/src/lib.rs
+++ b/crates/fparkan-rsli/src/lib.rs
@@ -1742,6 +1742,7 @@ mod tests {
}
#[test]
+ #[ignore = "requires licensed corpus"]
fn licensed_corpora_rsli_roundtrip_gates() {
let part1 = corpus_gate("IS", 2).expect("part 1 RsLi gate");
let part2 = corpus_gate("IS2", 2).expect("part 2 RsLi gate");
@@ -1751,6 +1752,7 @@ mod tests {
}
#[test]
+ #[ignore = "requires licensed corpus"]
fn licensed_part1_rsli_method_distribution_baseline() {
let stats = corpus_gate("IS", 2).expect("part 1 RsLi gate");
@@ -1770,6 +1772,7 @@ mod tests {
}
#[test]
+ #[ignore = "requires licensed corpus"]
fn licensed_part2_rsli_method_distribution_baseline() {
let stats = corpus_gate("IS2", 2).expect("part 2 RsLi gate");
@@ -1789,6 +1792,7 @@ mod tests {
}
#[test]
+ #[ignore = "requires licensed corpus"]
fn licensed_corpora_rsli_quirk_is_only_approved_interf8_tex() {
let part1 = corpus_gate("IS", 2).expect("part 1 RsLi gate");
let part2 = corpus_gate("IS2", 2).expect("part 2 RsLi gate");
diff --git a/crates/fparkan-runtime/src/lib.rs b/crates/fparkan-runtime/src/lib.rs
index 2a05c4a..4bc9e25 100644
--- a/crates/fparkan-runtime/src/lib.rs
+++ b/crates/fparkan-runtime/src/lib.rs
@@ -695,6 +695,7 @@ mod tests {
}
#[test]
+ #[ignore = "requires licensed corpus"]
fn load_trace_records_preparation_before_registration_and_raw_transforms() {
let root = workspace_root().join("testdata").join("IS");
let vfs: Arc<dyn Vfs> = Arc::new(DirectoryVfs::new(&root));
@@ -736,6 +737,7 @@ mod tests {
}
#[test]
+ #[ignore = "requires licensed corpus"]
fn missing_map_and_missing_reachable_resource_fail_before_registration() {
let root = workspace_root().join("testdata").join("IS");
for (denied, mission) in [
@@ -779,6 +781,7 @@ mod tests {
}
#[test]
+ #[ignore = "requires licensed corpus"]
fn registration_phase_failure_uses_normal_teardown_and_keeps_engine_world() {
let root = workspace_root().join("testdata").join("IS");
let vfs: Arc<dyn Vfs> = Arc::new(DirectoryVfs::new(root));
@@ -816,6 +819,7 @@ mod tests {
}
#[test]
+ #[ignore = "requires licensed corpus"]
fn selected_is_and_is2_missions_execute_10000_deterministic_ticks() {
for case in [
HeadlessCase {
@@ -849,6 +853,7 @@ mod tests {
}
#[test]
+ #[ignore = "requires licensed corpus"]
fn licensed_corpora_load_all_mission_foundations() {
let root = workspace_root();
let part1 = load_all(&root.join("testdata").join("IS"));
diff --git a/crates/fparkan-terrain-format/src/lib.rs b/crates/fparkan-terrain-format/src/lib.rs
index 8b97d79..8fd17ef 100644
--- a/crates/fparkan-terrain-format/src/lib.rs
+++ b/crates/fparkan-terrain-format/src/lib.rs
@@ -1488,6 +1488,7 @@ Generator 1
}
#[test]
+ #[ignore = "requires licensed corpus"]
fn licensed_corpus_land_msh_validate() {
for (corpus, expected_files, expected_vertices, expected_faces) in [
("IS", 33_usize, 299_450_usize, 275_882_usize),
@@ -1536,6 +1537,7 @@ Generator 1
}
#[test]
+ #[ignore = "requires licensed corpus"]
fn licensed_corpus_build_dat_validate() {
for (corpus, expected_ai_prefix) in [("IS", false), ("IS2", true)] {
let Some(root) = corpus_root(corpus) else {
@@ -1583,6 +1585,7 @@ Generator 1
}
#[test]
+ #[ignore = "requires licensed corpus"]
fn licensed_corpus_land_map_validate() {
for (corpus, expected_files, expected_areals, expected_vertices, expected_max_hits) in [
("IS", 33_usize, 34_662_usize, 197_698_usize, 20_usize),
diff --git a/crates/fparkan-terrain/src/lib.rs b/crates/fparkan-terrain/src/lib.rs
index b28fca6..92f36dd 100644
--- a/crates/fparkan-terrain/src/lib.rs
+++ b/crates/fparkan-terrain/src/lib.rs
@@ -794,6 +794,7 @@ mod tests {
}
#[test]
+ #[ignore = "requires licensed corpus"]
fn licensed_corpus_land_maps_build_navigation_worlds() {
for (corpus, expected_files, expected_areals) in [
("IS", 33_usize, 34_662_usize),
@@ -849,6 +850,7 @@ mod tests {
}
#[test]
+ #[ignore = "requires licensed corpus"]
fn licensed_corpus_land_meshes_build_surface_worlds() {
for (corpus, expected_files, expected_faces) in [
("IS", 33_usize, 275_882_usize),
diff --git a/crates/fparkan-texm/src/lib.rs b/crates/fparkan-texm/src/lib.rs
index 6adc8b1..fef5369 100644
--- a/crates/fparkan-texm/src/lib.rs
+++ b/crates/fparkan-texm/src/lib.rs
@@ -1071,6 +1071,7 @@ mod tests {
}
#[test]
+ #[ignore = "requires licensed corpus"]
fn licensed_corpus_texm_assets_validate_and_decode_mip0() {
for (corpus, expected) in [("IS", 518_usize), ("IS2", 631_usize)] {
let Some(root) = corpus_root(corpus) else {
diff --git a/xtask/src/main.rs b/xtask/src/main.rs
index 4141d92..722053a 100644
--- a/xtask/src/main.rs
+++ b/xtask/src/main.rs
@@ -27,8 +27,8 @@ fn run(args: &[String]) -> Result<(), String> {
[cmd] if cmd == "ci" => {
run_rustfmt_check(Path::new("."))?;
run_policy(Path::new("."))?;
- cargo(&["test", "--workspace", "--offline"])?;
- clippy_rustup(&["--workspace", "--offline"])?;
+ cargo(&["test", "--workspace", "--locked", "--offline"])?;
+ clippy_rustup(&["--workspace", "--locked", "--offline"])?;
Ok(())
}
[cmd] if cmd == "policy" => run_policy(Path::new(".")),
@@ -46,12 +46,12 @@ fn run(args: &[String]) -> Result<(), String> {
}
[cmd, suite, rest @ ..] if cmd == "test" && suite == "synthetic" => {
let options = parse_test_options(rest, PathBuf::from("testdata"))?;
- run_stage_tests(options.stage)
+ run_stage_tests(options.stage, TestSuite::Synthetic)
}
[cmd, suite, rest @ ..] if cmd == "test" && suite == "licensed" => {
let options = parse_test_options(rest, PathBuf::from("testdata"))?;
validate_licensed_root(&options.root)?;
- run_stage_tests(options.stage)
+ run_stage_tests(options.stage, TestSuite::Licensed)
}
[cmd, subcmd, rest @ ..] if cmd == "corpus" && subcmd == "baseline" => {
let root = parse_root(rest)?;
@@ -248,6 +248,7 @@ fn run_package(options: &PackageOptions) -> Result<(), String> {
"-p".to_string(),
options.app.package().to_string(),
"--release".to_string(),
+ "--locked".to_string(),
"--offline".to_string(),
"--target".to_string(),
options.target.clone(),
@@ -258,6 +259,8 @@ fn run_policy(root: &Path) -> Result<(), String> {
let mut failures = Vec::new();
scan_policy_dir(root, &mut failures)?;
validate_cargo_metadata(root, &mut failures)?;
+ validate_lockfile(root, &mut failures);
+ validate_workspace_license(root, &mut failures)?;
validate_dependency_boundaries(root, &mut failures)?;
if failures.is_empty() {
Ok(())
@@ -278,6 +281,7 @@ fn validate_cargo_metadata(root: &Path, failures: &mut Vec<String>) -> Result<()
"--format-version",
"1",
"--offline",
+ "--locked",
"--no-deps",
"--manifest-path",
])
@@ -295,6 +299,62 @@ fn validate_cargo_metadata(root: &Path, failures: &mut Vec<String>) -> Result<()
Ok(())
}
+fn validate_lockfile(root: &Path, failures: &mut Vec<String>) {
+ let lockfile = root.join("Cargo.lock");
+ if !lockfile.is_file() {
+ failures.push(format!(
+ "{}: workspace lockfile is required for locked/offline builds",
+ lockfile.display()
+ ));
+ }
+}
+
+fn validate_workspace_license(root: &Path, failures: &mut Vec<String>) -> Result<(), String> {
+ let manifest = root.join("Cargo.toml");
+ let license = fs::read_to_string(root.join("LICENSE.txt"))
+ .map_err(|err| format!("{}: {err}", root.join("LICENSE.txt").display()))?;
+ let expected = if license.contains("GNU GENERAL PUBLIC LICENSE")
+ && license.contains("Version 2, June 1991")
+ {
+ "GPL-2.0-only"
+ } else {
+ failures.push(format!(
+ "{}: unsupported repository license text",
+ root.join("LICENSE.txt").display()
+ ));
+ return Ok(());
+ };
+
+ let mut manifests = Vec::new();
+ collect_cargo_manifests(root, &mut manifests)?;
+ manifests.push(manifest);
+ manifests.sort();
+ manifests.dedup();
+
+ for manifest in manifests {
+ let text = fs::read_to_string(&manifest)
+ .map_err(|err| format!("{}: {err}", manifest.display()))?;
+ let explicit_license = parse_manifest_license(&text);
+ let is_root = manifest == root.join("Cargo.toml");
+ if is_root {
+ if explicit_license.as_deref() != Some(expected) {
+ failures.push(format!(
+ "{}: workspace.package license must be {expected}",
+ manifest.display()
+ ));
+ }
+ } else if let Some(license) = explicit_license {
+ if license != expected {
+ failures.push(format!(
+ "{}: package license {license} does not match repository license {expected}",
+ manifest.display()
+ ));
+ }
+ }
+ }
+ Ok(())
+}
+
fn validate_dependency_boundaries(root: &Path, failures: &mut Vec<String>) -> Result<(), String> {
let mut manifests = Vec::new();
collect_cargo_manifests(root, &mut manifests)?;
@@ -357,6 +417,23 @@ fn collect_cargo_manifests(dir: &Path, out: &mut Vec<PathBuf>) -> Result<(), Str
Ok(())
}
+fn parse_manifest_license(manifest: &str) -> Option<String> {
+ let mut in_package = false;
+ let mut in_workspace_package = false;
+ for line in manifest.lines() {
+ let trimmed = line.trim();
+ if trimmed.starts_with('[') {
+ in_package = trimmed == "[package]";
+ in_workspace_package = trimmed == "[workspace.package]";
+ continue;
+ }
+ if (in_package || in_workspace_package) && trimmed.starts_with("license") {
+ return parse_toml_string_value(trimmed);
+ }
+ }
+ None
+}
+
fn parse_package_name(manifest: &str) -> Option<String> {
let mut in_package = false;
for line in manifest.lines() {
@@ -1082,7 +1159,7 @@ fn run_acceptance_report(options: &AcceptanceOptions) -> Result<(), String> {
if options.suite == TestSuite::Licensed {
validate_licensed_root(&options.root)?;
}
- run_stage_tests(options.stage)?;
+ run_stage_tests(options.stage, options.suite)?;
if let Some(parent) = options.out.parent() {
fs::create_dir_all(parent).map_err(|err| format!("{}: {err}", parent.display()))?;
@@ -1131,12 +1208,22 @@ fn stage_report_packages(stage: Stage) -> Vec<&'static str> {
}
}
-fn run_stage_tests(stage: Stage) -> Result<(), String> {
+fn run_stage_tests(stage: Stage, suite: TestSuite) -> Result<(), String> {
+ let mut suffix = Vec::new();
+ if suite == TestSuite::Licensed {
+ suffix.extend(["--", "--ignored"]);
+ }
match stage {
- Stage::All => cargo(&["test", "--workspace", "--offline"]),
+ Stage::All => {
+ let mut args = vec!["test", "--workspace", "--locked", "--offline"];
+ args.extend(suffix);
+ cargo(&args)
+ }
Stage::Number(number) => {
for package in stage_packages(number)? {
- cargo(&["test", "-p", package, "--offline"])?;
+ let mut args = vec!["test", "-p", package, "--locked", "--offline"];
+ args.extend(suffix.iter().copied());
+ cargo(&args)?;
}
Ok(())
}