Skip to main content

cargo_uv/git/
git_file.rs

1use std::{path::PathBuf, str::FromStr};
2
3use tracing::instrument;
4
5#[allow(dead_code)]
6#[derive(Debug, Clone)]
7pub struct GitFile {
8    pub mode: String,
9    pub path: PathBuf,
10}
11
12impl std::fmt::Display for GitFile {
13    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
14        write!(f, "{}", self.path.display())
15    }
16}
17
18impl GitFile {
19    #[instrument]
20    pub fn parse(line: impl ToString + std::fmt::Debug) -> Option<GitFile> {
21        let line = line.to_string();
22        let (mode, path_str) = line.trim().split_once(" ")?;
23        let path = PathBuf::from_str(path_str).ok()?;
24        if mode.trim().is_empty() {
25            None
26        } else {
27            Some(GitFile {
28                mode: mode.trim().to_string(),
29                path,
30            })
31        }
32    }
33}
34
35#[derive(Debug, Clone, Default)]
36pub struct GitFiles(Vec<GitFile>);
37
38impl GitFiles {
39    /// Creates an empty GitFiles object.
40    pub fn new() -> Self {
41        Self::default()
42    }
43}
44
45impl std::ops::Deref for GitFiles {
46    type Target = Vec<GitFile>;
47
48    fn deref(&self) -> &Vec<GitFile> {
49        &self.0
50    }
51}
52
53impl std::ops::DerefMut for GitFiles {
54    fn deref_mut(&mut self) -> &mut Self::Target {
55        &mut self.0
56    }
57}
58
59impl AsRef<Vec<GitFile>> for GitFiles {
60    fn as_ref(&self) -> &Vec<GitFile> {
61        &self.0
62    }
63}
64
65impl AsMut<Vec<GitFile>> for GitFiles {
66    fn as_mut(&mut self) -> &mut Vec<GitFile> {
67        &mut self.0
68    }
69}
70
71impl std::fmt::Display for GitFiles {
72    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
73        for file in self.0.iter() {
74            write!(f, "\n{}", file)?;
75        }
76        Ok(())
77    }
78}
79
80impl GitFiles {
81    #[instrument]
82    /// Mutates the git output for `git status --short` to a vec of files.
83    /// Returns None if [Vec] is empty.
84    pub fn parse(lines: String) -> Option<Self> {
85        let lines = lines.lines();
86        let mut ret = Vec::new();
87        for line in lines {
88            if let Some(gfile) = GitFile::parse(line) {
89                ret.push(gfile);
90            }
91        }
92        if ret.is_empty() {
93            None
94        } else {
95            Some(GitFiles(ret))
96        }
97    }
98}