about summary refs log tree commit diff
path: root/clippy_dev/src/setup
diff options
context:
space:
mode:
authorxFrednet <xFrednet@gmail.com>2021-06-27 16:59:17 +0200
committerxFrednet <xFrednet@gmail.com>2021-06-27 22:36:41 +0200
commit2098b27a200152f949bf08946c639d632146fb9b (patch)
tree715b6100dd450ec0cb74e20d1e5faaf9c5dee30b /clippy_dev/src/setup
parent8d427b624f15a5c782c97021c3717451d86b8576 (diff)
Added `cargo dev setup vscode-tasks` for simplicity
Diffstat (limited to 'clippy_dev/src/setup')
-rw-r--r--clippy_dev/src/setup/git_hook.rs6
-rw-r--r--clippy_dev/src/setup/mod.rs21
-rw-r--r--clippy_dev/src/setup/vscode.rs104
3 files changed, 131 insertions, 0 deletions
diff --git a/clippy_dev/src/setup/git_hook.rs b/clippy_dev/src/setup/git_hook.rs
index f27b69a195b..3fbb77d5923 100644
--- a/clippy_dev/src/setup/git_hook.rs
+++ b/clippy_dev/src/setup/git_hook.rs
@@ -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() {
diff --git a/clippy_dev/src/setup/mod.rs b/clippy_dev/src/setup/mod.rs
index 3834f5a1842..a1e4dd103b8 100644
--- a/clippy_dev/src/setup/mod.rs
+++ b/clippy_dev/src/setup/mod.rs
@@ -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
+    }
+}
diff --git a/clippy_dev/src/setup/vscode.rs b/clippy_dev/src/setup/vscode.rs
new file mode 100644
index 00000000000..d59001b2c66
--- /dev/null
+++ b/clippy_dev/src/setup/vscode.rs
@@ -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
+    }
+}