reference_transaction/
reference_transaction.rs1use girt::refs::{Expected, RefEdit, RefName, Reflog, TransactionError};
3use girt::{Commit, CommitFields, Repository, Signature};
4
5fn main() -> Result<(), Box<dyn std::error::Error>> {
6 let directory = tempfile::tempdir()?;
7 let repo = Repository::init(
8 girt::ObjectFormat::Sha256,
9 directory.path().join("repository"),
10 girt::InitKind::Bare,
11 )?;
12
13 let objects = repo.loose_objects();
14 let tree = objects.write_tree(&repo.new_tree(Vec::new())?)?;
15
16 let committer = Signature {
17 name: b"Example Writer".to_vec(),
18 email: b"writer@example.com".to_vec(),
19 seconds: 1700000000,
20 offset_minutes: 0,
21 };
22
23 let commit = Commit::new(CommitFields {
24 tree,
25 parents: Vec::new(),
26 author: committer.clone(),
27 committer: committer.clone(),
28 extra_headers: Vec::new(),
29 message: b"Initial commit\n".to_vec(),
30 })?;
31 let id = objects.write_commit(&commit)?;
32
33 let head = RefName::HEAD;
34 let tag = RefName::tag("initial")?;
35 let edits = [
36 {
37 let input = RefEdit::new(
38 head.clone(),
39 Some(girt::refs::Target::Direct(id)),
40 Expected::Absent,
41 Reflog::Append {
42 committer: committer.clone(),
43 message: b"initial publication".to_vec(),
44 },
45 );
46 input.with_dereference(girt::refs::Dereference::Follow)
47 },
48 RefEdit::create(
49 tag.clone(),
50 id,
51 Reflog::Append {
52 committer: committer.clone(),
53 message: b"mark initial".to_vec(),
54 },
55 ),
56 ];
57
58 let refs = repo.references()?;
59 match refs.transaction(&edits) {
60 Ok(outcomes) => println!("Published: {outcomes:?}"),
61 Err(TransactionError::Prepare { operation, source }) => {
62 eprintln!("No refs or logs changed; operation {operation:?}: {source}");
63 return Err(source.into());
64 }
65 Err(error @ TransactionError::Publish { .. }) => {
66 eprintln!("Partial publication: {error:?}");
68 return Err(error.into());
69 }
70 Err(error) => return Err(error.into()),
71 }
72
73 refs.transaction(&[RefEdit::delete(
74 tag.clone(),
75 id,
76 Reflog::Append {
77 committer,
78 message: b"remove temporary tag".to_vec(),
79 },
80 )])?;
81
82 assert_eq!(refs.reflog(&head)?.unwrap().len(), 1);
83 assert_eq!(refs.reflog(&tag)?.unwrap().len(), 2);
84 assert_eq!(refs.read(&tag)?, None);
85
86 let keep = RefName::new("refs/jj/keep-example")?;
88 refs.transaction(&[RefEdit::new(
89 keep.clone(),
90 Some(girt::refs::Target::Direct(id)),
91 Expected::AbsentOr(girt::refs::Target::Direct(id)),
92 Reflog::Preserve,
93 )])?;
94 refs.transaction(&[RefEdit::new(keep, None, Expected::Exists, Reflog::Delete)])?;
95 Ok(())
96}