-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathcheck.rs
81 lines (72 loc) · 2.82 KB
/
check.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
use crate::{VCSError, VCSResult};
use std::path::Path;
/// Stores the options available for calling [`check_version_control`] and controls which checks if any are run
#[cfg_attr(feature = "clap", derive(clap::Args))]
#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Default)]
pub struct CheckOptions {
/// Does not return an error for dirty files nor generate the list of said files
#[cfg_attr(feature = "clap", arg(long))]
pub allow_dirty: bool,
/// This option basically disables checking. If true no checks are done. (Not even if the `path` exists)
#[cfg_attr(feature = "clap", arg(long))]
pub allow_no_vcs: bool,
/// Does not return an error for staged files nor generate the list of said files
#[cfg_attr(feature = "clap", arg(long))]
pub allow_staged: bool,
}
impl CheckOptions {
/// Creates a [`CheckOptions`] with default values
pub fn new() -> Self {
Default::default()
}
}
/// Based on the [`CheckOptions`] passed it does test on the version control at `path`.
/// See [`CheckOptions`] for more details on what checks do and don't get run depending on what is passed
pub fn check_version_control<P: AsRef<Path>>(path: P, opts: &CheckOptions) -> VCSResult<()> {
if opts.allow_no_vcs {
return Ok(());
}
if !supporting_code::existing_vcs_repo(path.as_ref(), path.as_ref()) {
return VCSResult::Err(VCSError::NoVCS);
}
if opts.allow_dirty && opts.allow_staged {
return Ok(());
}
let mut dirty_files = Vec::new();
let mut staged_files = Vec::new();
if let Ok(repo) = git2::Repository::discover(path.as_ref()) {
let mut repo_opts = git2::StatusOptions::new();
repo_opts.include_ignored(false);
repo_opts.include_untracked(true);
for status in repo.statuses(Some(&mut repo_opts))?.iter() {
if let Some(path) = status.path() {
match status.status() {
git2::Status::CURRENT => (),
git2::Status::INDEX_NEW
| git2::Status::INDEX_MODIFIED
| git2::Status::INDEX_DELETED
| git2::Status::INDEX_RENAMED
| git2::Status::INDEX_TYPECHANGE => {
if !opts.allow_staged {
staged_files.push(path.to_string())
}
}
_ => {
if !opts.allow_dirty {
dirty_files.push(path.to_string())
}
}
};
}
}
}
if dirty_files.is_empty() && staged_files.is_empty() {
Ok(())
} else {
VCSResult::Err(VCSError::NotAllowedFilesFound {
dirty_files,
staged_files,
})
}
}
mod supporting_code;