hglib/commands/
status.rs

1// This Source Code Form is subject to the terms of the Mozilla Public
2// License, v. 2.0. If a copy of the MPL was not distributed with this file,
3// You can obtain one at http://mozilla.org/MPL/2.0/.
4
5use crate::client::{Client, HglibError, Runner};
6use crate::{runcommand, MkArg};
7
8pub struct Arg<'a> {
9    pub rev: &'a [&'a str],
10    pub change: &'a str,
11    pub all: bool,
12    pub modified: bool,
13    pub added: bool,
14    pub removed: bool,
15    pub deleted: bool,
16    pub clean: bool,
17    pub unknown: bool,
18    pub ignored: bool,
19    pub copies: bool,
20    pub subrepos: bool,
21    pub include: &'a [&'a str],
22    pub exclude: &'a [&'a str],
23}
24
25impl<'a> Default for Arg<'a> {
26    fn default() -> Self {
27        Self {
28            rev: &[],
29            change: "",
30            all: false,
31            modified: false,
32            added: false,
33            removed: false,
34            deleted: false,
35            clean: false,
36            unknown: false,
37            ignored: false,
38            copies: false,
39            subrepos: false,
40            include: &[],
41            exclude: &[],
42        }
43    }
44}
45
46impl<'a> Arg<'a> {
47    fn run(&self, client: &mut Client) -> Result<(Vec<u8>, i32), HglibError> {
48        runcommand!(
49            client,
50            "status",
51            &[""],
52            "--rev",
53            self.rev,
54            "--change",
55            self.change,
56            "-A",
57            self.all,
58            "-m",
59            self.modified,
60            "-a",
61            self.added,
62            "-r",
63            self.removed,
64            "-d",
65            self.deleted,
66            "-c",
67            self.clean,
68            "-u",
69            self.unknown,
70            "-i",
71            self.ignored,
72            "-C",
73            self.copies,
74            "-S",
75            self.subrepos,
76            "-I",
77            self.include,
78            "-X",
79            self.exclude,
80            "--print0",
81            true
82        )
83    }
84}
85
86#[derive(Debug, PartialEq)]
87pub enum Code {
88    Modified,
89    Added,
90    Removed,
91    Clean,
92    Missing,
93    NotTracked,
94    Ignored,
95    Origin,
96}
97
98#[derive(Debug, PartialEq)]
99pub struct Status {
100    pub code: Code,
101    pub filename: String,
102}
103
104impl Client {
105    pub fn status(&mut self, x: Arg) -> Result<Vec<Status>, HglibError> {
106        if !x.rev.is_empty() && !x.change.is_empty() {
107            return Err(HglibError::from("Cannot specify both rev and change"));
108        }
109
110        let (data, _) = x.run(self)?;
111        let mut res = Vec::new();
112        for line in data.split(|c| *c == b'\0').filter(|l| l.len() >= 3) {
113            let c = unsafe { line.get_unchecked(0) };
114            let code = match *c {
115                b'M' => Code::Modified,
116                b'A' => Code::Added,
117                b'R' => Code::Removed,
118                b'C' => Code::Clean,
119                b'!' => Code::Missing,
120                b'?' => Code::NotTracked,
121                b'I' => Code::Ignored,
122                b' ' => Code::Origin,
123                _ => {
124                    return Err(HglibError::from(format!("Invalid code: {}", *c)));
125                }
126            };
127            let filename = unsafe { line.get_unchecked(2..) };
128            let filename = String::from_utf8(filename.to_vec())?;
129            res.push(Status { code, filename });
130        }
131        Ok(res)
132    }
133}