pre_commit_sort/
pre_commit_config.rs1use std::collections::BTreeMap;
3
4use crate::{ConfigHook, Local, Meta, PreCommit, Remote, Repo, CI};
5
6#[serde_with::skip_serializing_none]
7#[derive(serde::Serialize, serde::Deserialize, Debug, Eq, Ord, PartialEq, PartialOrd, Clone)]
8pub struct PreCommitConfig {
9 ci: Option<CI>,
10 repos: Vec<Repo>,
11 default_install_hook_types: Option<Vec<String>>,
12 default_language_version: Option<BTreeMap<String, String>>,
13 default_stages: Option<Vec<String>>,
14 files: Option<String>,
15 exclude: Option<String>,
16 fail_fast: Option<bool>,
17 minimum_pre_commit_version: Option<String>,
18}
19
20impl PreCommitConfig {
21 #[must_use]
22 pub const fn new() -> Self {
23 Self {
24 ci: None,
25 repos: Vec::new(),
26 default_install_hook_types: None,
27 default_language_version: None,
28 default_stages: None,
29 files: None,
30 exclude: None,
31 fail_fast: None,
32 minimum_pre_commit_version: None,
33 }
34 }
35
36 pub fn add_remote(&mut self, remote: Remote) {
37 self.repos.push(Repo::Remote(remote));
38 }
39
40 pub fn add_local(&mut self, local: Local) {
41 self.repos.push(Repo::Local(local));
42 }
43
44 pub fn add_meta(&mut self, meta: Meta) {
45 self.repos.push(Repo::Meta(meta));
46 }
47
48 pub fn sort(&mut self) {
50 for repo in &mut self.repos {
51 repo.sort();
52 }
53 self.repos.sort();
54 self.repos.dedup();
55 self.dedup_rev();
56 }
57
58 fn dedup_rev(&mut self) {
60 while let Some(i) = self.find_first_rev_dup() {
61 self.repos.remove(i);
62 }
63 }
64
65 fn find_first_rev_dup(&self) -> Option<usize> {
66 for (i, w) in self.repos.windows(2).enumerate() {
68 if w[0].equal_but_rev(&w[1]) {
69 return Some(i);
70 }
71 }
72 None
73 }
74
75 pub fn install(&mut self) {
77 const VERSION: &str = env!("CARGO_PKG_VERSION");
78 let mut remote = Remote::new(
79 env!("CARGO_PKG_REPOSITORY").to_string(),
80 format!("v{VERSION}"),
81 );
82 let hook = ConfigHook::new(env!("CARGO_PKG_NAME").to_string());
83 remote.add_hook(hook);
84 self.add_remote(remote);
85 }
86}
87
88impl PreCommit for PreCommitConfig {
89 const PATH: &'static str = ".pre-commit-config.yaml";
90
91 fn process(&mut self, install: bool) {
92 if install {
93 self.install();
94 }
95 self.sort();
96 }
97}
98
99impl Default for PreCommitConfig {
100 fn default() -> Self {
101 Self::new()
102 }
103}