Added cargo dev setup vscode-tasks for simplicity

This commit is contained in:
xFrednet 2021-06-27 16:59:17 +02:00
parent 8d427b624f
commit 2098b27a20
5 changed files with 202 additions and 0 deletions

View file

@ -43,11 +43,13 @@ fn main() {
.expect("this field is mandatory and therefore always valid"),
),
("git-hook", Some(matches)) => setup::git_hook::install_hook(matches.is_present("force-override")),
("vscode-tasks", Some(matches)) => setup::vscode::install_tasks(matches.is_present("force-override")),
_ => {},
},
("remove", Some(sub_command)) => match sub_command.subcommand() {
("git-hook", Some(_)) => setup::git_hook::remove_hook(),
("intellij", Some(_)) => setup::intellij::remove_rustc_src(),
("vscode-tasks", Some(_)) => setup::vscode::remove_tasks(),
_ => {},
},
("serve", Some(matches)) => {
@ -180,6 +182,17 @@ fn get_clap_config<'a>() -> ArgMatches<'a> {
.help("Forces the override of an existing git pre-commit hook")
.required(false),
),
)
.subcommand(
SubCommand::with_name("vscode-tasks")
.about("Add several tasks to vscode for formatting, validation and testing")
.arg(
Arg::with_name("force-override")
.long("force-override")
.short("f")
.help("Forces the override of existing vs code tasks")
.required(false),
),
),
)
.subcommand(
@ -187,6 +200,7 @@ fn get_clap_config<'a>() -> ArgMatches<'a> {
.about("Support for undoing changes done by the setup command")
.setting(AppSettings::ArgRequiredElseHelp)
.subcommand(SubCommand::with_name("git-hook").about("Remove any existing pre-commit git hook"))
.subcommand(SubCommand::with_name("vscode-tasks").about("Remove any existing vscode tasks"))
.subcommand(
SubCommand::with_name("intellij")
.about("Removes rustc source paths added via `cargo dev setup intellij`"),

View file

@ -1,6 +1,8 @@
use std::fs;
use std::path::Path;
use super::verify_inside_clippy_dir;
/// Rusts setup uses `git rev-parse --git-common-dir` to get the root directory of the repo.
/// I've decided against this for the sake of simplicity and to make sure that it doesn't install
/// the hook if `clippy_dev` would be used in the rust tree. The hook also references this tool
@ -36,6 +38,10 @@ pub fn install_hook(force_override: bool) {
}
fn check_precondition(force_override: bool) -> bool {
if !verify_inside_clippy_dir() {
return false;
}
// Make sure that we can find the git repository
let git_path = Path::new(REPO_GIT_DIR);
if !git_path.exists() || !git_path.is_dir() {

View file

@ -1,2 +1,23 @@
pub mod git_hook;
pub mod intellij;
pub mod vscode;
use std::path::Path;
const CLIPPY_DEV_DIR: &str = "clippy_dev";
/// This function verifies that the tool is being executed in the clippy directory.
/// This is useful to ensure that setups only modify Clippys resources. The verification
/// is done by checking that `clippy_dev` is a sub directory of the current directory.
///
/// It will print an error message and return `false` if the directory could not be
/// verified.
fn verify_inside_clippy_dir() -> bool {
let path = Path::new(CLIPPY_DEV_DIR);
if path.exists() && path.is_dir() {
true
} else {
eprintln!("error: unable to verify that the working directory is clippys directory");
false
}
}

View file

@ -0,0 +1,104 @@
use std::fs;
use std::path::Path;
use super::verify_inside_clippy_dir;
const VSCODE_DIR: &str = ".vscode";
const TASK_SOURCE_FILE: &str = "util/etc/vscode-tasks.json";
const TASK_TARGET_FILE: &str = ".vscode/tasks.json";
pub fn install_tasks(force_override: bool) {
if !check_install_precondition(force_override) {
return;
}
match fs::copy(TASK_SOURCE_FILE, TASK_TARGET_FILE) {
Ok(_) => {
println!("info: the task file can be removed with `cargo dev remove vscode-tasks`");
println!("vscode tasks successfully installed");
},
Err(err) => eprintln!(
"error: unable to copy `{}` to `{}` ({})",
TASK_SOURCE_FILE, TASK_TARGET_FILE, err
),
}
}
fn check_install_precondition(force_override: bool) -> bool {
if !verify_inside_clippy_dir() {
return false;
}
let vs_dir_path = Path::new(VSCODE_DIR);
if vs_dir_path.exists() {
// verify the target will be valid
if !vs_dir_path.is_dir() {
eprintln!("error: the `.vscode` path exists but seems to be a file");
return false;
}
// make sure that we don't override any existing tasks by accident
let path = Path::new(TASK_TARGET_FILE);
if path.exists() {
if force_override {
return delete_vs_task_file(path);
}
eprintln!(
"error: there is already a `task.json` file inside the `{}` directory",
VSCODE_DIR
);
println!("info: use the `--force-override` flag to override the existing `task.json` file");
return false;
}
} else {
match fs::create_dir(vs_dir_path) {
Ok(_) => {
println!("info: created `{}` directory for clippy", VSCODE_DIR);
},
Err(err) => {
eprintln!(
"error: the task target directory `{}` could not be created ({})",
VSCODE_DIR, err
);
},
}
}
true
}
pub fn remove_tasks() {
let path = Path::new(TASK_TARGET_FILE);
if path.exists() {
if delete_vs_task_file(path) {
try_delete_vs_directory_if_empty();
println!("vscode tasks successfully removed");
}
} else {
println!("no vscode tasks were found");
}
}
fn delete_vs_task_file(path: &Path) -> bool {
if let Err(err) = fs::remove_file(path) {
eprintln!("error: unable to delete the existing `tasks.json` file ({})", err);
return false;
}
true
}
/// This function will try to delete the `.vscode` directory if it's empty.
/// It may fail silently.
fn try_delete_vs_directory_if_empty() {
let path = Path::new(VSCODE_DIR);
if path.read_dir().map_or(false, |mut iter| iter.next().is_none()) {
// The directory is empty. We just try to delete it but allow a silence
// fail as an empty `.vscode` directory is still valid
let _silence_result = fs::remove_dir(path);
} else {
// The directory is not empty or could not be read. Either way don't take
// any further actions
}
}

View file

@ -0,0 +1,57 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "cargo check",
"type": "shell",
"command": "cargo check",
"problemMatcher": [],
"group": {
"kind": "build",
"isDefault": true,
},
},
{
"label": "cargo fmt",
"type": "shell",
"command": "cargo dev fmt",
"problemMatcher": [],
"group": "none",
},
{
"label": "cargo uitest",
"type": "shell",
"command": "cargo uitest",
"options": {
"env": {
"RUST_BACKTRACE": "1",
// This task will usually execute all UI tests inside `tests/ui` you can
// optionally uncomment the line below and only run a specific test.
//
// See: https://github.com/rust-lang/rust-clippy/blob/master/doc/adding_lints.md#testing
//
// "TESTNAME": "<TODO>",
},
},
"problemMatcher": [],
"group": {
"kind": "test",
"isDefault": true,
}
},
{
"label": "cargo test",
"type": "shell",
"command": "cargo test",
"problemMatcher": [],
"group": "test",
},
{
"label": "cargo dev bless",
"type": "shell",
"command": "cargo dev bless",
"problemMatcher": [],
"group": "none",
},
],
}