1#[cfg(feature = "jj-parse")]
3#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
4pub enum WorkingCopy {
5 #[default]
6 Background,
7 Current,
8}
9
10#[cfg(feature = "jj-parse")]
12#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
13pub enum ConflictState {
14 #[default]
15 Clean,
16 Conflicted,
17}
18
19#[cfg(feature = "jj-parse")]
20impl ConflictState {
21 pub fn is_conflicted(self) -> bool {
22 matches!(self, Self::Conflicted)
23 }
24}
25
26#[cfg(feature = "jj-parse")]
28#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
29pub enum ContentState {
30 #[default]
31 HasContent,
32 Empty,
33}
34
35#[cfg(feature = "jj-parse")]
36impl ContentState {
37 pub fn is_empty(self) -> bool {
38 matches!(self, Self::Empty)
39 }
40}
41
42#[cfg(feature = "jj-parse")]
47#[derive(Debug, Clone)]
48pub struct LogEntry {
49 pub commit_id: String,
50 pub change_id: String,
51 pub author_name: String,
52 pub author_email: String,
53 pub description: String,
54 pub parents: Vec<String>,
55 pub local_bookmarks: Vec<String>,
56 pub remote_bookmarks: Vec<String>,
57 pub working_copy: WorkingCopy,
58 pub conflict: ConflictState,
59 pub content: ContentState,
60}
61
62#[cfg(feature = "jj-parse")]
63impl LogEntry {
64 pub fn summary(&self) -> &str {
66 self.description.lines().next().unwrap_or("")
67 }
68}
69
70#[cfg(feature = "jj-parse")]
72#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
73pub enum RemoteStatus {
74 Local,
76 Unsynced,
78 Synced,
80}
81
82#[cfg(feature = "jj-parse")]
83impl RemoteStatus {
84 pub fn has_remote(self) -> bool {
85 !matches!(self, Self::Local)
86 }
87
88 pub fn is_synced(self) -> bool {
89 matches!(self, Self::Synced)
90 }
91}
92
93#[cfg(feature = "jj-parse")]
95#[derive(Debug, Clone, PartialEq, Eq)]
96pub struct Bookmark {
97 pub name: String,
98 pub commit_id: String,
99 pub change_id: String,
100 pub remote: RemoteStatus,
101}
102
103#[cfg(feature = "jj-parse")]
105#[derive(Debug, Clone, PartialEq, Eq)]
106pub struct GitRemote {
107 pub name: String,
108 pub url: String,
109}
110
111#[cfg(any(feature = "jj-parse", feature = "git-parse"))]
113#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
114pub enum FileChangeKind {
115 Added,
116 Modified,
117 Deleted,
118 Renamed,
119 Copied,
120}
121
122#[cfg(any(feature = "jj-parse", feature = "git-parse"))]
127#[derive(Debug, Clone, PartialEq, Eq)]
128pub struct FileChange {
129 pub kind: FileChangeKind,
130 pub path: std::path::PathBuf,
131 pub from_path: Option<std::path::PathBuf>,
132}
133
134#[cfg(all(test, feature = "jj-parse"))]
135mod tests {
136 use super::*;
137
138 #[test]
139 fn conflict_state() {
140 assert!(!ConflictState::Clean.is_conflicted());
141 assert!(ConflictState::Conflicted.is_conflicted());
142 }
143
144 #[test]
145 fn content_state() {
146 assert!(!ContentState::HasContent.is_empty());
147 assert!(ContentState::Empty.is_empty());
148 }
149
150 #[test]
151 fn working_copy_default() {
152 assert_eq!(WorkingCopy::default(), WorkingCopy::Background);
153 }
154
155 #[test]
156 fn remote_status_local() {
157 assert!(!RemoteStatus::Local.has_remote());
158 assert!(!RemoteStatus::Local.is_synced());
159 }
160
161 #[test]
162 fn remote_status_unsynced() {
163 assert!(RemoteStatus::Unsynced.has_remote());
164 assert!(!RemoteStatus::Unsynced.is_synced());
165 }
166
167 #[test]
168 fn remote_status_synced() {
169 assert!(RemoteStatus::Synced.has_remote());
170 assert!(RemoteStatus::Synced.is_synced());
171 }
172
173 #[test]
174 fn log_entry_summary() {
175 let entry = LogEntry {
176 commit_id: "abc".into(),
177 change_id: "xyz".into(),
178 author_name: "A".into(),
179 author_email: "a@b".into(),
180 description: "first line\nsecond line".into(),
181 parents: vec![],
182 local_bookmarks: vec![],
183 remote_bookmarks: vec![],
184 working_copy: WorkingCopy::Background,
185 conflict: ConflictState::Clean,
186 content: ContentState::HasContent,
187 };
188 assert_eq!(entry.summary(), "first line");
189 }
190
191 #[test]
192 fn log_entry_summary_empty_description() {
193 let entry = LogEntry {
194 commit_id: "abc".into(),
195 change_id: "xyz".into(),
196 author_name: "A".into(),
197 author_email: "a@b".into(),
198 description: String::new(),
199 parents: vec![],
200 local_bookmarks: vec![],
201 remote_bookmarks: vec![],
202 working_copy: WorkingCopy::Background,
203 conflict: ConflictState::Clean,
204 content: ContentState::HasContent,
205 };
206 assert_eq!(entry.summary(), "");
207 }
208}