diff --git a/crates/xtask/src/fetch.rs b/crates/xtask/src/fetch.rs index 13ae8faa..5023691e 100644 --- a/crates/xtask/src/fetch.rs +++ b/crates/xtask/src/fetch.rs @@ -1,33 +1,24 @@ -use crate::{bail_on_err, root_dir, EMSCRIPTEN_VERSION}; +use crate::{bail_on_err, root_dir, FetchFixtures, EMSCRIPTEN_VERSION}; use anyhow::Result; -use std::process::Command; +use std::{ + fs, + process::{Command, Stdio}, +}; -pub fn run_fixtures() -> Result<()> { - let grammars_dir = root_dir().join("test").join("fixtures").join("grammars"); +pub fn run_fixtures(args: &FetchFixtures) -> Result<()> { + let fixtures_dir = root_dir().join("test").join("fixtures"); + let grammars_dir = fixtures_dir.join("grammars"); + let fixtures_path = fixtures_dir.join("fixtures.json"); - [ - ("bash", "master"), - ("c", "master"), - ("cpp", "master"), - ("embedded-template", "master"), - ("go", "master"), - ("html", "master"), - ("java", "master"), - ("javascript", "master"), - ("jsdoc", "master"), - ("json", "master"), - ("php", "master"), - ("python", "master"), - ("ruby", "master"), - ("rust", "master"), - ("typescript", "master"), - ] - .iter() - .try_for_each(|(grammar, r#ref)| { - let grammar_dir = grammars_dir.join(grammar); + // grammar name, tag + let mut fixtures: Vec<(String, String)> = + serde_json::from_str(&fs::read_to_string(&fixtures_path)?)?; + + for (grammar, tag) in &mut fixtures { + let grammar_dir = grammars_dir.join(&grammar); let grammar_url = format!("https://github.com/tree-sitter/tree-sitter-{grammar}"); - println!("Updating the {grammar} grammar..."); + println!("Fetching the {grammar} grammar..."); if !grammar_dir.exists() { let mut command = Command::new("git"); @@ -47,21 +38,54 @@ pub fn run_fixtures() -> Result<()> { std::env::set_current_dir(&grammar_dir)?; let mut command = Command::new("git"); - command.args(["fetch", "origin", r#ref, "--depth", "1"]); + command.args(["fetch", "origin", "--tags"]); bail_on_err( &command.spawn()?.wait_with_output()?, - &format!("Failed to fetch the {grammar} grammar"), + &format!("Failed to fetch the {grammar} grammar's tags"), )?; + if args.update { + let mut command = Command::new("git"); + command + .args(["tag", "--sort=-creatordate"]) + .stdout(Stdio::piped()); + let update_out = command.spawn()?.wait_with_output()?; + bail_on_err( + &update_out, + &format!("Failed to parse the {grammar} grammar's latest commit"), + )?; + let new_tag = String::from_utf8(update_out.stdout)? + .lines() + .next() + .expect("No tags found") + .trim() + .to_string(); + if !new_tag.eq(tag) { + println!("Updating the {grammar} grammar from {tag} to {new_tag}..."); + *tag = new_tag; + } + } let mut command = Command::new("git"); - command.args(["reset", "--hard", "FETCH_HEAD"]); + command.args(["reset", "--hard", tag]); bail_on_err( &command.spawn()?.wait_with_output()?, &format!("Failed to reset the {grammar} grammar"), )?; + } - Ok(()) - }) + if args.update { + println!("Updating the fixtures lock file"); + fs::write( + &fixtures_path, + // format the JSON without extra newlines + serde_json::to_string(&fixtures)? + .replace("[[", "[\n [") + .replace("],", "],\n ") + .replace("]]", "]\n]"), + )?; + } + + Ok(()) } pub fn run_emscripten() -> Result<()> { diff --git a/crates/xtask/src/main.rs b/crates/xtask/src/main.rs index feba36d4..600ae83e 100644 --- a/crates/xtask/src/main.rs +++ b/crates/xtask/src/main.rs @@ -35,7 +35,7 @@ enum Commands { /// Fetches emscripten. FetchEmscripten, /// Fetches the fixtures for testing tree-sitter. - FetchFixtures, + FetchFixtures(FetchFixtures), /// Generate the Rust bindings from the C library. GenerateBindings, /// Generates the fixtures for testing tree-sitter. @@ -115,6 +115,13 @@ struct Clippy { package: Option, } +#[derive(Args)] +struct FetchFixtures { + /// Update all fixtures to the latest tag + #[arg(long, short)] + update: bool, +} + #[derive(Args)] struct GenerateFixtures { /// Generates the parser to Wasm @@ -222,7 +229,9 @@ fn run() -> Result<()> { Commands::CheckWasmExports(check_options) => check_wasm_exports::run(&check_options)?, Commands::Clippy(clippy_options) => clippy::run(&clippy_options)?, Commands::FetchEmscripten => fetch::run_emscripten()?, - Commands::FetchFixtures => fetch::run_fixtures()?, + Commands::FetchFixtures(fetch_fixture_options) => { + fetch::run_fixtures(&fetch_fixture_options)?; + } Commands::GenerateBindings => generate::run_bindings()?, Commands::GenerateFixtures(generate_fixtures_options) => { generate::run_fixtures(&generate_fixtures_options)?; diff --git a/test/fixtures/fixtures.json b/test/fixtures/fixtures.json new file mode 100644 index 00000000..7f4a385d --- /dev/null +++ b/test/fixtures/fixtures.json @@ -0,0 +1,17 @@ +[ + ["bash","v0.25.0"], + ["c","v0.24.1"], + ["cpp","v0.23.4"], + ["embedded-template","v0.25.0"], + ["go","v0.25.0"], + ["html","v0.23.2"], + ["java","v0.23.5"], + ["javascript","v0.23.1"], + ["jsdoc","v0.23.2"], + ["json","v0.24.8"], + ["php","v0.24.2"], + ["python","v0.23.6"], + ["ruby","v0.23.1"], + ["rust","v0.24.0"], + ["typescript","v0.23.2"] +] \ No newline at end of file