use super::id::ChangeId;
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Status {
pub files: Vec<FileStatus>,
pub has_conflicts: bool,
pub working_copy_change_id: ChangeId,
pub parent_change_id: ChangeId,
}
impl Status {
pub fn is_clean(&self) -> bool {
self.files.is_empty()
}
#[cfg(test)]
pub fn count_by_state(&self, state: &FileState) -> usize {
self.files
.iter()
.filter(|f| std::mem::discriminant(&f.state) == std::mem::discriminant(state))
.count()
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct FileStatus {
pub path: String,
pub state: FileState,
}
impl FileStatus {
pub fn indicator(&self) -> char {
match &self.state {
FileState::Added => 'A',
FileState::Modified => 'M',
FileState::Deleted => 'D',
FileState::Renamed { .. } => 'R',
FileState::Conflicted => 'C',
}
}
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum FileState {
Added,
Modified,
Deleted,
Renamed {
from: String,
},
Conflicted,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_status_is_clean() {
let clean = Status {
files: vec![],
has_conflicts: false,
working_copy_change_id: ChangeId::new("abc".to_string()),
parent_change_id: ChangeId::new("xyz".to_string()),
};
assert!(clean.is_clean());
let dirty = Status {
files: vec![FileStatus {
path: "test.rs".to_string(),
state: FileState::Modified,
}],
has_conflicts: false,
working_copy_change_id: ChangeId::new("abc".to_string()),
parent_change_id: ChangeId::new("xyz".to_string()),
};
assert!(!dirty.is_clean());
}
#[test]
fn test_status_count_by_state() {
let status = Status {
files: vec![
FileStatus {
path: "a.rs".to_string(),
state: FileState::Added,
},
FileStatus {
path: "b.rs".to_string(),
state: FileState::Modified,
},
FileStatus {
path: "c.rs".to_string(),
state: FileState::Added,
},
],
has_conflicts: false,
working_copy_change_id: ChangeId::new("abc".to_string()),
parent_change_id: ChangeId::new("xyz".to_string()),
};
assert_eq!(status.count_by_state(&FileState::Added), 2);
assert_eq!(status.count_by_state(&FileState::Modified), 1);
assert_eq!(status.count_by_state(&FileState::Deleted), 0);
}
#[test]
fn test_file_status_indicator() {
assert_eq!(
FileStatus {
path: "a".to_string(),
state: FileState::Added
}
.indicator(),
'A'
);
assert_eq!(
FileStatus {
path: "b".to_string(),
state: FileState::Modified
}
.indicator(),
'M'
);
assert_eq!(
FileStatus {
path: "c".to_string(),
state: FileState::Deleted
}
.indicator(),
'D'
);
assert_eq!(
FileStatus {
path: "d".to_string(),
state: FileState::Renamed {
from: "old".to_string()
}
}
.indicator(),
'R'
);
assert_eq!(
FileStatus {
path: "e".to_string(),
state: FileState::Conflicted
}
.indicator(),
'C'
);
}
}