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