1use bstr::{BStr, BString, ByteSlice};
2
3#[derive(Default, Debug, Clone, Copy, Ord, PartialOrd, Eq, PartialEq, Hash)]
5pub enum Ignore {
6 All,
8 Dirty,
11 Untracked,
14 #[default]
17 None,
18}
19
20impl TryFrom<&BStr> for Ignore {
21 type Error = ();
22
23 fn try_from(value: &BStr) -> Result<Self, Self::Error> {
24 Ok(match value.as_bytes() {
25 b"all" => Ignore::All,
26 b"dirty" => Ignore::Dirty,
27 b"untracked" => Ignore::Untracked,
28 b"none" => Ignore::None,
29 _ => return Err(()),
30 })
31 }
32}
33
34#[derive(Default, Debug, Clone, Copy, Ord, PartialOrd, Eq, PartialEq, Hash)]
41pub enum FetchRecurse {
42 #[default]
44 OnDemand,
45 Always,
50 Never,
52}
53
54impl FetchRecurse {
55 pub fn new(boolean: Result<Option<bool>, gix_config::value::Error>) -> Result<Option<Self>, BString> {
59 Ok(match boolean {
60 Ok(Some(value)) => Some(if value {
61 FetchRecurse::Always
62 } else {
63 FetchRecurse::Never
64 }),
65 Ok(None) => None,
66 Err(err) => {
67 if err.input != "on-demand" {
68 return Err(err.input);
69 }
70 Some(FetchRecurse::OnDemand)
71 }
72 })
73 }
74}
75
76#[derive(Debug, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
78pub enum Branch {
79 CurrentInSuperproject,
81 Name(BString),
83}
84
85impl Default for Branch {
86 fn default() -> Self {
87 Branch::Name("HEAD".into())
88 }
89}
90
91impl TryFrom<&BStr> for Branch {
92 type Error = gix_refspec::parse::Error;
93
94 fn try_from(value: &BStr) -> Result<Self, Self::Error> {
95 if value == "." {
96 return Ok(Branch::CurrentInSuperproject);
97 }
98
99 gix_refspec::parse(value, gix_refspec::parse::Operation::Fetch)
100 .map(|spec| Branch::Name(spec.source().expect("no object").to_owned()))
101 }
102}
103
104#[derive(Default, Debug, Clone, Hash, PartialOrd, PartialEq, Ord, Eq)]
107pub enum Update {
108 #[default]
110 Checkout,
111 Rebase,
113 Merge,
115 Command(BString),
121 None,
123}
124
125impl TryFrom<&BStr> for Update {
126 type Error = ();
127
128 fn try_from(value: &BStr) -> Result<Self, Self::Error> {
129 Ok(match value.as_bstr().as_bytes() {
130 b"checkout" => Update::Checkout,
131 b"rebase" => Update::Rebase,
132 b"merge" => Update::Merge,
133 b"none" => Update::None,
134 command if command.first() == Some(&b'!') => Update::Command(command[1..].to_owned().into()),
135 _ => return Err(()),
136 })
137 }
138}
139
140#[derive(Debug, thiserror::Error)]
142#[expect(missing_docs)]
143#[error("The '{field}' field of submodule '{submodule}' was invalid: '{actual}'")]
144pub struct Error {
145 pub field: &'static str,
146 pub submodule: BString,
147 pub actual: BString,
148}
149
150pub mod branch {
152 use bstr::BString;
153
154 #[derive(Debug, thiserror::Error)]
156 #[expect(missing_docs)]
157 #[error(
158 "The value '{actual}' of the 'branch' field of submodule '{submodule}' couldn't be turned into a valid fetch refspec"
159 )]
160 pub struct Error {
161 pub submodule: BString,
162 pub actual: BString,
163 pub source: gix_refspec::parse::Error,
164 }
165}
166
167pub mod update {
169 use bstr::BString;
170
171 #[derive(Debug, thiserror::Error)]
173 #[expect(missing_docs)]
174 pub enum Error {
175 #[error("The 'update' field of submodule '{submodule}' tried to set command '{actual}' to be shared")]
176 CommandForbiddenInModulesConfiguration { submodule: BString, actual: BString },
177 #[error("The 'update' field of submodule '{submodule}' was invalid: '{actual}'")]
178 Invalid { submodule: BString, actual: BString },
179 }
180}
181
182pub mod url {
184 use bstr::BString;
185
186 #[derive(Debug, thiserror::Error)]
188 #[expect(missing_docs)]
189 pub enum Error {
190 #[error("The url of submodule '{submodule}' could not be parsed")]
191 Parse {
192 submodule: BString,
193 source: gix_url::parse::Error,
194 },
195 #[error("The submodule '{submodule}' was missing its 'url' field or it was empty")]
196 Missing { submodule: BString },
197 }
198}
199
200pub mod path {
202 use bstr::BString;
203
204 #[derive(Debug, thiserror::Error)]
206 #[expect(missing_docs)]
207 pub enum Error {
208 #[error("The path '{actual}' of submodule '{submodule}' needs to be relative")]
209 Absolute { actual: BString, submodule: BString },
210 #[error("The submodule '{submodule}' was missing its 'path' field or it was empty")]
211 Missing { submodule: BString },
212 #[error("The path '{actual}' would lead outside of the repository worktree")]
213 OutsideOfWorktree { actual: BString, submodule: BString },
214 }
215}