1use 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}