Skip to content

Commit e51166b

Browse files
committed
Detect rebase state
1 parent 3e61357 commit e51166b

File tree

3 files changed

+80
-1
lines changed

3 files changed

+80
-1
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 & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ mod history;
136136
mod line;
137137
mod line_parser;
138138
mod search;
139+
mod state;
139140
#[cfg(not(tarpaulin_include))]
140141
pub mod testutil;
141142
mod utils;
@@ -147,9 +148,10 @@ use std::{
147148
slice::Iter,
148149
};
149150

151+
use state::detect_state;
150152
pub use version_track::Version;
151153

152-
pub use self::{action::Action, edit_content::EditContext, line::Line, search::Search};
154+
pub use self::{action::Action, edit_content::EditContext, line::Line, search::Search, state::State};
153155
use self::{
154156
history::{History, HistoryItem},
155157
utils::{remove_range, swap_range_down, swap_range_up},
@@ -166,6 +168,7 @@ pub struct TodoFile {
166168
lines: Vec<Line>,
167169
selected_line_index: usize,
168170
version: Version,
171+
state: State,
169172
}
170173

171174
impl TodoFile {
@@ -181,6 +184,7 @@ impl TodoFile {
181184
is_noop: false,
182185
selected_line_index: 0,
183186
version: Version::new(),
187+
state: State::Initial,
184188
}
185189
}
186190

@@ -231,6 +235,7 @@ impl TodoFile {
231235
})
232236
.collect();
233237
self.set_lines(lines?);
238+
self.state = detect_state(&self.filepath)?;
234239
Ok(())
235240
}
236241

@@ -408,6 +413,13 @@ impl TodoFile {
408413
&self.version
409414
}
410415

416+
/// Get the current state
417+
#[must_use]
418+
#[inline]
419+
pub const fn state(&self) -> &State {
420+
&self.state
421+
}
422+
411423
/// Get the selected line.
412424
#[must_use]
413425
#[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)