1+ // Demonstrates the difference between regular commit methods and raw commit methods
2+ // Regular commits update references automatically, raw commits just create the object
3+
4+ use anyhow:: Context ;
5+ use gix:: config:: tree:: { Author , Committer } ;
6+
7+ fn main ( ) -> anyhow:: Result < ( ) > {
8+ let git_dir = std:: env:: args_os ( )
9+ . nth ( 1 )
10+ . context ( "First argument needs to be the directory to initialize the repository in" ) ?;
11+ let mut repo = gix:: init_bare ( git_dir) ?;
12+
13+ println ! ( "Repo (bare): {}" , repo. git_dir( ) . display( ) ) ;
14+
15+ // Set up author/committer
16+ let mut config = repo. config_snapshot_mut ( ) ;
17+ config. set_raw_value ( & Author :: NAME , "Demo User" ) ?;
18+ config. set_raw_value ( & Author :: EMAIL , "demo@example.com" ) ?;
19+ config. set_raw_value ( & Committer :: NAME , "Demo User" ) ?;
20+ config. set_raw_value ( & Committer :: EMAIL , "demo@example.com" ) ?;
21+ let repo = config. commit_auto_rollback ( ) ?;
22+
23+ let empty_tree_id = repo. write_object ( & gix:: objs:: Tree :: empty ( ) ) ?. detach ( ) ;
24+
25+ println ! ( "\n === Demonstrating commit_raw ===" ) ;
26+
27+ // Create a raw commit - this doesn't update any references
28+ let raw_commit = repo. commit_raw ( "Raw commit message" , empty_tree_id, gix:: commit:: NO_PARENT_IDS ) ?;
29+
30+ println ! ( "Created raw commit object (not yet written to database):" ) ;
31+ println ! ( " Message: {}" , raw_commit. message) ;
32+ println ! ( " Tree: {}" , raw_commit. tree) ;
33+ println ! ( " Author: {:?}" , raw_commit. author. name) ;
34+
35+ // HEAD should still be unborn at this point
36+ let head_before = match repo. head ( ) {
37+ Ok ( _) => "exists" ,
38+ Err ( _) => "unborn"
39+ } ;
40+ println ! ( "HEAD status before writing raw commit: {}" , head_before) ;
41+
42+ // Now write the commit object to the database
43+ let raw_commit_id = repo. write_object ( & raw_commit) ?;
44+ println ! ( "Raw commit written to database with ID: {}" , raw_commit_id) ;
45+
46+ // HEAD still shouldn't point to our commit since we didn't update references
47+ let head_after = match repo. head ( ) {
48+ Ok ( _) => "exists" ,
49+ Err ( _) => "unborn"
50+ } ;
51+ println ! ( "HEAD status after writing raw commit: {}" , head_after) ;
52+
53+ println ! ( "\n === Demonstrating commit_as_raw ===" ) ;
54+
55+ // Create specific author/committer signatures
56+ let committer = gix:: actor:: Signature {
57+ name : "Committer Name" . into ( ) ,
58+ email : "committer@example.com" . into ( ) ,
59+ time : gix_date:: Time :: now_local_or_utc ( ) ,
60+ } ;
61+ let author = gix:: actor:: Signature {
62+ name : "Author Name" . into ( ) ,
63+ email : "author@example.com" . into ( ) ,
64+ time : gix_date:: Time :: now_local_or_utc ( ) ,
65+ } ;
66+
67+ let raw_commit2 = repo. commit_as_raw (
68+ committer. to_ref ( & mut Default :: default ( ) ) ,
69+ author. to_ref ( & mut Default :: default ( ) ) ,
70+ "Second raw commit with custom author/committer" ,
71+ empty_tree_id,
72+ [ raw_commit_id. detach ( ) ] ,
73+ ) ?;
74+
75+ println ! ( "Created second raw commit with custom author/committer:" ) ;
76+ println ! ( " Message: {}" , raw_commit2. message) ;
77+ println ! ( " Author: {} <{}>" , raw_commit2. author. name, raw_commit2. author. email) ;
78+ println ! ( " Committer: {} <{}>" , raw_commit2. committer. name, raw_commit2. committer. email) ;
79+
80+ let raw_commit_id2 = repo. write_object ( & raw_commit2) ?;
81+ println ! ( "Second raw commit written with ID: {}" , raw_commit_id2) ;
82+
83+ println ! ( "\n === Comparing with regular commit ===" ) ;
84+
85+ // First, let's update HEAD to point to our second raw commit so we can demonstrate
86+ // the difference. In practice, you might update references manually.
87+ println ! ( "To demonstrate regular commit, we first need to set HEAD manually:" ) ;
88+
89+ // Use the regular commit method which updates HEAD automatically
90+ // For the initial commit, we'll use no parents
91+ let regular_commit_id = repo. commit ( "HEAD" , "Regular commit that updates HEAD" , empty_tree_id, gix:: commit:: NO_PARENT_IDS ) ?;
92+ println ! ( "Regular commit created with ID: {}" , regular_commit_id) ;
93+
94+ // Now HEAD should point to our commit
95+ let head_final = match repo. head ( ) {
96+ Ok ( mut head) => {
97+ match head. try_peel_to_id_in_place ( ) . unwrap_or ( None ) {
98+ Some ( id) => format ! ( "points to {}" , id) ,
99+ None => "exists but unborn" . to_string ( ) ,
100+ }
101+ }
102+ Err ( _) => "unborn" . to_string ( )
103+ } ;
104+ println ! ( "HEAD status after regular commit: {}" , head_final) ;
105+
106+ println ! ( "\n === Summary ===" ) ;
107+ println ! ( "Raw commits allow you to:" ) ;
108+ println ! ( "1. Create commit objects without updating any references" ) ;
109+ println ! ( "2. Write them to the database when you're ready" ) ;
110+ println ! ( "3. Have full control over when and how references are updated" ) ;
111+ println ! ( "4. Batch commit operations for better performance" ) ;
112+
113+ Ok ( ( ) )
114+ }
0 commit comments