1use super::json_record::{ObjectWriter, string_array};
19use super::transaction_journal::{
21 AddedPath, Base, Conclusion, FileIdentity, IndexLockRecord, JOURNAL_SCHEMA_VERSION,
22 LandingOperation, LandingRecord, LockIdentity, PreparedRecord, PreparingRecord, RefFormat,
23 SymbolicHead, TransactionMode,
24};
25
26fn encode_base(base: &Base) -> String {
36 let mut writer: ObjectWriter = ObjectWriter::new();
37 match base {
38 Base::Unborn => {
39 writer.string("kind", "unborn");
40 }
41 Base::Commit(oid) => {
42 writer.string("kind", "commit").string("oid", oid.as_str());
43 }
44 }
45 return writer.finish();
46}
47
48fn encode_identity(identity: &FileIdentity) -> String {
58 let mut writer: ObjectWriter = ObjectWriter::new();
59 writer
60 .string("device", identity.device.as_str())
61 .string("inode", identity.inode.as_str());
62 return writer.finish();
63}
64
65fn encode_lock(lock: &LockIdentity) -> String {
75 let mut writer: ObjectWriter = ObjectWriter::new();
76 writer
77 .string("device", lock.file.device.as_str())
78 .string("inode", lock.file.inode.as_str())
79 .string("fsId", lock.fs_id.as_str());
80 return writer.finish();
81}
82
83fn encode_added_paths(records: &[AddedPath]) -> String {
93 let mut text: String = String::from("[");
94 for (index, record) in records.iter().enumerate() {
95 if index > 0 {
96 text.push(',');
97 }
98 let mut writer: ObjectWriter = ObjectWriter::new();
99 writer
100 .string("path", record.path.as_str())
101 .string("gitMode", record.git_mode.as_str())
102 .string("originalOid", record.original_oid.as_str())
103 .string("intendedOid", record.intended_oid.as_str());
104 text.push_str(writer.finish().as_str());
105 }
106 text.push(']');
107 return text;
108}
109
110fn record_head(state: &str) -> ObjectWriter {
121 let mut writer: ObjectWriter = ObjectWriter::new();
122 writer
123 .integer("schemaVersion", JOURNAL_SCHEMA_VERSION)
124 .string("state", state);
125 return writer;
126}
127
128pub fn mode_name(mode: TransactionMode) -> &'static str {
138 match mode {
139 TransactionMode::ExplicitPath => return "explicit-path",
140 TransactionMode::Index => return "index",
141 }
142}
143
144pub fn conclusion_name(conclusion: Conclusion) -> &'static str {
154 match conclusion {
155 Conclusion::None => return "none",
156 Conclusion::Amend => return "amend",
157 Conclusion::Merge => return "merge",
158 Conclusion::CherryPick => return "cherry-pick",
159 Conclusion::Revert => return "revert",
160 }
161}
162
163pub fn ref_format_name(format: RefFormat) -> &'static str {
173 match format {
174 RefFormat::Files => return "files",
175 RefFormat::Reftable => return "reftable",
176 }
177}
178
179pub fn encode_preparing(record: &PreparingRecord) -> String {
189 let mut writer: ObjectWriter = record_head("preparing");
190 writer
191 .string("transactionId", record.transaction_id.as_str())
192 .string("mode", mode_name(record.mode))
193 .raw("base", encode_base(&record.base).as_str());
194 let head: String = match &record.symbolic_head {
195 SymbolicHead::Branch(name) => {
196 let mut nested: ObjectWriter = ObjectWriter::new();
197 nested.string("kind", "branch").string("ref", name.as_str());
198 nested.finish()
199 }
200 SymbolicHead::Detached => String::from("{\"kind\":\"detached\"}"),
201 };
202 writer
203 .raw("symbolicHead", head.as_str())
204 .string("targetRef", record.target_ref.as_str())
205 .string("conclusion", conclusion_name(record.conclusion))
206 .string("repositoryRoot", record.repository_root.as_str())
207 .string("gitDir", record.git_dir.as_str())
208 .string("commonDir", record.common_dir.as_str())
209 .string("realIndexPath", record.real_index_path.as_str())
210 .string("objectDirectory", record.object_directory.as_str())
211 .string("refFormat", ref_format_name(record.ref_format))
212 .string("emptyTreeOid", record.empty_tree_oid.as_str())
213 .string("shadowPath", record.shadow_path.as_str())
214 .raw(
215 "selectedPathspecs",
216 string_array(record.selected_pathspecs.as_slice()).as_str(),
217 )
218 .string("invokedAt", record.invoked_at.as_str());
219 return format!("{}\n", writer.finish());
220}
221
222pub fn encode_prepared(record: &PreparedRecord) -> String {
232 let mut writer: ObjectWriter = record_head("prepared");
233 writer
234 .string("shadowPath", record.shadow_path.as_str())
235 .string("preparedOid", record.prepared_oid.as_str())
236 .boolean("signed", record.signed)
237 .string("intendedTreeOid", record.intended_tree_oid.as_str())
238 .raw(
239 "committedPaths",
240 string_array(record.committed_paths.as_slice()).as_str(),
241 )
242 .raw(
243 "addedPaths",
244 encode_added_paths(record.added_paths.as_slice()).as_str(),
245 )
246 .raw(
247 "selectedWorktreePaths",
248 encode_added_paths(record.selected_worktree_paths.as_slice()).as_str(),
249 );
250 return format!("{}\n", writer.finish());
251}
252
253pub fn encode_index_lock(record: &IndexLockRecord) -> String {
263 let mut writer: ObjectWriter = record_head("index-locked");
264 writer
265 .integer("attempt", record.attempt)
266 .raw("lock", encode_lock(&record.lock).as_str());
267 return format!("{}\n", writer.finish());
268}
269
270pub fn encode_landing(record: &LandingRecord) -> String {
283 let mut writer: ObjectWriter = record_head("landing");
284 writer.integer("attempt", record.attempt).string(
285 "operation",
286 match record.operation {
287 LandingOperation::Commit => "commit",
288 LandingOperation::NormalizeOnly => "normalize-only",
289 },
290 );
291 writer.raw("expectedOld", encode_base(&record.expected_old).as_str());
292 if let Some(oid) = &record.new_oid {
293 writer.string("newOid", oid.as_str());
294 }
295 writer
296 .string("landedTreeOid", record.landed_tree_oid.as_str())
297 .raw(
298 "preLandingIndex",
299 encode_identity(&record.pre_landing_index).as_str(),
300 )
301 .raw("postIndex", encode_identity(&record.post_index).as_str())
302 .raw("lock", encode_lock(&record.lock).as_str());
303 if let Some(pack) = &record.pack_name {
304 writer.string("packName", pack.as_str());
305 }
306 writer
307 .raw(
308 "addedPaths",
309 encode_added_paths(record.added_paths.as_slice()).as_str(),
310 )
311 .raw(
312 "selectedWorktreePaths",
313 encode_added_paths(record.selected_worktree_paths.as_slice()).as_str(),
314 );
315 return format!("{}\n", writer.finish());
316}
317
318pub fn encode_ref_updated(landed_oid: &str) -> String {
328 let mut writer: ObjectWriter = record_head("ref-updated");
329 writer.string("landedOid", landed_oid);
330 return format!("{}\n", writer.finish());
331}
332
333#[cfg(test)]
335#[path = "transaction_journal_encode_tests.rs"]
336pub(crate) mod tests;