Skip to content

Commit e2fa7fa

Browse files
committed
Detect rebase state
1 parent dd950ed commit e2fa7fa

File tree

3 files changed

+80
-0
lines changed

3 files changed

+80
-0
lines changed

src/todo_file/src/errors/io.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ pub enum FileReadErrorCause {
1515
/// Caused by a parse error
1616
#[error(transparent)]
1717
ParseError(#[from] ParseError),
18+
/// Caused by the file path returning None for parent()
19+
#[error("NoParentDir")]
20+
NoParentDir(),
1821
}
1922

2023
impl PartialEq for FileReadErrorCause {
@@ -24,6 +27,7 @@ impl PartialEq for FileReadErrorCause {
2427
match (self, other) {
2528
(Self::IoError(self_err), Self::IoError(other_err)) => self_err.kind() == other_err.kind(),
2629
(Self::ParseError(self_err), Self::ParseError(other_err)) => self_err == other_err,
30+
(Self::NoParentDir(), Self::NoParentDir()) => true,
2731
_ => false,
2832
}
2933
}

src/todo_file/src/lib.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ mod history;
131131
mod line;
132132
mod line_parser;
133133
mod search;
134+
mod state;
134135
#[cfg(not(tarpaulin_include))]
135136
pub mod testutil;
136137
mod todo_file_options;
@@ -143,13 +144,15 @@ use std::{
143144
slice::Iter,
144145
};
145146

147+
use state::detect_state;
146148
pub use version_track::Version;
147149

148150
pub use self::{
149151
action::Action,
150152
edit_content::EditContext,
151153
line::Line,
152154
search::Search,
155+
state::State,
153156
todo_file_options::TodoFileOptions,
154157
};
155158
use self::{
@@ -171,6 +174,7 @@ pub struct TodoFile {
171174
options: TodoFileOptions,
172175
selected_line_index: usize,
173176
version: Version,
177+
state: State,
174178
}
175179

176180
impl TodoFile {
@@ -188,6 +192,7 @@ impl TodoFile {
188192
options,
189193
selected_line_index: 0,
190194
version: Version::new(),
195+
state: State::Initial,
191196
}
192197
}
193198

@@ -238,6 +243,7 @@ impl TodoFile {
238243
})
239244
.collect();
240245
self.set_lines(lines?);
246+
self.state = detect_state(&self.filepath)?;
241247
Ok(())
242248
}
243249

@@ -457,6 +463,13 @@ impl TodoFile {
457463
&self.version
458464
}
459465

466+
/// Get the current state
467+
#[must_use]
468+
#[inline]
469+
pub const fn state(&self) -> &State {
470+
&self.state
471+
}
472+
460473
/// Get the selected line.
461474
#[must_use]
462475
#[inline]

src/todo_file/src/state.rs

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
use std::{
2+
fmt::{Display, Formatter},
3+
path::{Path, PathBuf},
4+
};
5+
6+
use crate::errors::{FileReadErrorCause, IoError};
7+
8+
/// Describes the state of rebase when editing the rebase todo file.
9+
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
10+
#[allow(clippy::exhaustive_enums)]
11+
pub enum State {
12+
/// Editing todo at start of a rebase.
13+
Initial,
14+
/// Editing todo in the middle of a rebase with --edit.
15+
Edit,
16+
/// Editing the todo file for git-revise
17+
Revise,
18+
}
19+
20+
pub(crate) fn detect_state(filepath: &Path) -> Result<State, IoError> {
21+
if filepath.ends_with("git-revise-todo") {
22+
return Ok(State::Revise);
23+
}
24+
if let Some(parent) = filepath.parent() {
25+
if parent.join("stopped-sha").try_exists().map_err(|err| {
26+
IoError::FileRead {
27+
file: PathBuf::from(parent),
28+
cause: FileReadErrorCause::from(err),
29+
}
30+
})? {
31+
return Ok(State::Edit);
32+
}
33+
}
34+
return Ok(State::Initial);
35+
}
36+
37+
impl State {}
38+
39+
impl Display for State {
40+
#[inline]
41+
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
42+
write!(f, "{}", match *self {
43+
Self::Initial => "initial",
44+
Self::Edit => "edit",
45+
Self::Revise => "revise",
46+
})
47+
}
48+
}
49+
50+
#[cfg(test)]
51+
mod tests {
52+
use rstest::rstest;
53+
54+
use super::*;
55+
56+
#[rstest]
57+
#[case::edit(State::Initial, "initial")]
58+
#[case::edit(State::Edit, "edit")]
59+
#[case::edit(State::Revise, "revise")]
60+
fn to_string(#[case] action: State, #[case] expected: &str) {
61+
assert_eq!(format!("{action}"), expected);
62+
}
63+
}

0 commit comments

Comments
 (0)