]> git.lizzy.rs Git - rust.git/blob - src/tools/clippy/clippy_dev/src/setup/vscode.rs
Merge commit '7248d06384c6a90de58c04c1f46be88821278d8b' into sync-from-clippy
[rust.git] / src / tools / clippy / clippy_dev / src / setup / vscode.rs
1 use std::fs;
2 use std::path::Path;
3
4 use super::verify_inside_clippy_dir;
5
6 const VSCODE_DIR: &str = ".vscode";
7 const TASK_SOURCE_FILE: &str = "util/etc/vscode-tasks.json";
8 const TASK_TARGET_FILE: &str = ".vscode/tasks.json";
9
10 pub fn install_tasks(force_override: bool) {
11     if !check_install_precondition(force_override) {
12         return;
13     }
14
15     match fs::copy(TASK_SOURCE_FILE, TASK_TARGET_FILE) {
16         Ok(_) => {
17             println!("info: the task file can be removed with `cargo dev remove vscode-tasks`");
18             println!("vscode tasks successfully installed");
19         },
20         Err(err) => eprintln!(
21             "error: unable to copy `{}` to `{}` ({})",
22             TASK_SOURCE_FILE, TASK_TARGET_FILE, err
23         ),
24     }
25 }
26
27 fn check_install_precondition(force_override: bool) -> bool {
28     if !verify_inside_clippy_dir() {
29         return false;
30     }
31
32     let vs_dir_path = Path::new(VSCODE_DIR);
33     if vs_dir_path.exists() {
34         // verify the target will be valid
35         if !vs_dir_path.is_dir() {
36             eprintln!("error: the `.vscode` path exists but seems to be a file");
37             return false;
38         }
39
40         // make sure that we don't override any existing tasks by accident
41         let path = Path::new(TASK_TARGET_FILE);
42         if path.exists() {
43             if force_override {
44                 return delete_vs_task_file(path);
45             }
46
47             eprintln!(
48                 "error: there is already a `task.json` file inside the `{}` directory",
49                 VSCODE_DIR
50             );
51             println!("info: use the `--force-override` flag to override the existing `task.json` file");
52             return false;
53         }
54     } else {
55         match fs::create_dir(vs_dir_path) {
56             Ok(_) => {
57                 println!("info: created `{}` directory for clippy", VSCODE_DIR);
58             },
59             Err(err) => {
60                 eprintln!(
61                     "error: the task target directory `{}` could not be created ({})",
62                     VSCODE_DIR, err
63                 );
64             },
65         }
66     }
67
68     true
69 }
70
71 pub fn remove_tasks() {
72     let path = Path::new(TASK_TARGET_FILE);
73     if path.exists() {
74         if delete_vs_task_file(path) {
75             try_delete_vs_directory_if_empty();
76             println!("vscode tasks successfully removed");
77         }
78     } else {
79         println!("no vscode tasks were found");
80     }
81 }
82
83 fn delete_vs_task_file(path: &Path) -> bool {
84     if let Err(err) = fs::remove_file(path) {
85         eprintln!("error: unable to delete the existing `tasks.json` file ({})", err);
86         return false;
87     }
88
89     true
90 }
91
92 /// This function will try to delete the `.vscode` directory if it's empty.
93 /// It may fail silently.
94 fn try_delete_vs_directory_if_empty() {
95     let path = Path::new(VSCODE_DIR);
96     if path.read_dir().map_or(false, |mut iter| iter.next().is_none()) {
97         // The directory is empty. We just try to delete it but allow a silence
98         // fail as an empty `.vscode` directory is still valid
99         let _silence_result = fs::remove_dir(path);
100     } else {
101         // The directory is not empty or could not be read. Either way don't take
102         // any further actions
103     }
104 }