diff --git a/.cargo/config b/.cargo/config index c0be661fd6..c319d33f24 100644 --- a/.cargo/config +++ b/.cargo/config @@ -1,9 +1,10 @@ [alias] # Automatically generates the ast and syntax kinds files -gen-syntax = "run --package tools -- gen-syntax" -gen-tests = "run --package tools -- gen-tests" -install-code = "run --package tools -- install-code" -format = "run --package tools -- format" +gen-syntax = "run --package tools --bin tools -- gen-syntax" +gen-tests = "run --package tools --bin tools -- gen-tests" +install-code = "run --package tools --bin tools -- install-code" +format = "run --package tools --bin tools -- format" +format-hook = "run --package tools --bin tools -- format-hook" -render-test = "run --package ra_cli -- render-test" -parse = "run --package ra_cli -- parse" +render-test = "run --package ra_cli -- render-test" +parse = "run --package ra_cli -- parse" diff --git a/crates/ra_editor/src/typing.rs b/crates/ra_editor/src/typing.rs index 9703e03712..01acdda7c3 100644 --- a/crates/ra_editor/src/typing.rs +++ b/crates/ra_editor/src/typing.rs @@ -20,7 +20,7 @@ pub fn join_lines(file: &SourceFileNode, range: TextRange) -> LocalEdit { return LocalEdit { edit: EditBuilder::new().finish(), cursor_position: None, - } + }; } Some(pos) => pos, }; diff --git a/crates/tools/src/bin/pre-commit.rs b/crates/tools/src/bin/pre-commit.rs new file mode 100644 index 0000000000..ca19094795 --- /dev/null +++ b/crates/tools/src/bin/pre-commit.rs @@ -0,0 +1,37 @@ +use std::{ + process::{Command}, +}; + +use tools::{Result, run_rustfmt, run, project_root}; +use failure::bail; + +fn main() -> tools::Result<()> { + run_rustfmt(tools::Overwrite)?; + update_staged() +} + +fn update_staged() -> Result<()> { + let root = project_root(); + let output = Command::new("git") + .arg("diff") + .arg("--name-only") + .arg("--cached") + .current_dir(&root) + .output()?; + if !output.status.success() { + bail!( + "`git diff --name-only --cached` exited with {}", + output.status + ); + } + for line in String::from_utf8(output.stdout)?.lines() { + run( + &format!( + "git update-index --add {}", + root.join(line).to_string_lossy() + ), + ".", + )?; + } + Ok(()) +} diff --git a/crates/tools/src/lib.rs b/crates/tools/src/lib.rs index 674b9d11fe..95d6e08f04 100644 --- a/crates/tools/src/lib.rs +++ b/crates/tools/src/lib.rs @@ -1,6 +1,8 @@ use std::{ path::{Path, PathBuf}, process::{Command, Stdio}, + fs::copy, + io::{Error, ErrorKind} }; use failure::bail; @@ -39,7 +41,7 @@ pub fn collect_tests(s: &str) -> Vec<(usize, Test)> { let (start_line, name) = loop { match block.next() { Some((idx, line)) if line.starts_with("test ") => { - break (idx, line["test ".len()..].to_string()) + break (idx, line["test ".len()..].to_string()); } Some(_) => (), None => continue 'outer, @@ -65,7 +67,7 @@ pub fn generate(mode: Mode) -> Result<()> { } pub fn project_root() -> PathBuf { - Path::new(&std::env::var("CARGO_MANIFEST_DIR").unwrap()) + Path::new(&env!("CARGO_MANIFEST_DIR")) .ancestors() .nth(2) .unwrap() @@ -116,3 +118,18 @@ fn install_rustfmt() -> Result<()> { ".", ) } + +pub fn install_format_hook() -> Result<()> { + let result_path = Path::new("./.git/hooks/pre-commit"); + if !result_path.exists() { + run("cargo build --package tools --bin pre-commit", ".")?; + if cfg!(windows) { + copy("./target/debug/pre-commit.exe", result_path)?; + } else { + copy("./target/debug/pre-commit", result_path)?; + } + } else { + return Err(Error::new(ErrorKind::AlreadyExists, "Git hook already created").into()); + } + Ok(()) +} diff --git a/crates/tools/src/main.rs b/crates/tools/src/main.rs index 36a7c83e22..9e90ac5c21 100644 --- a/crates/tools/src/main.rs +++ b/crates/tools/src/main.rs @@ -7,7 +7,7 @@ use std::{ use clap::{App, Arg, SubCommand}; use failure::bail; -use tools::{collect_tests, generate, run, run_rustfmt, Mode, Overwrite, Result, Test, Verify}; +use tools::{collect_tests, generate, install_format_hook, run, run_rustfmt, Mode, Overwrite, Result, Test, Verify}; const GRAMMAR_DIR: &str = "./crates/ra_syntax/src/grammar"; const INLINE_TESTS_DIR: &str = "./crates/ra_syntax/tests/data/parser/inline"; @@ -25,17 +25,22 @@ fn main() -> Result<()> { .subcommand(SubCommand::with_name("gen-tests")) .subcommand(SubCommand::with_name("install-code")) .subcommand(SubCommand::with_name("format")) + .subcommand(SubCommand::with_name("format-hook")) .get_matches(); let mode = if matches.is_present("verify") { Verify } else { Overwrite }; - match matches.subcommand() { - ("install-code", _) => install_code_extension()?, - ("gen-tests", _) => gen_tests(mode)?, - ("gen-syntax", _) => generate(Overwrite)?, - ("format", _) => run_rustfmt(Overwrite)?, + match matches + .subcommand_name() + .expect("Subcommand must be specified") + { + "install-code" => install_code_extension()?, + "gen-tests" => gen_tests(mode)?, + "gen-syntax" => generate(Overwrite)?, + "format" => run_rustfmt(mode)?, + "format-hook" => install_format_hook()?, _ => unreachable!(), } Ok(())