@@ -108,8 +108,10 @@ pub struct Commit {
108108 pub created_at : i128 ,
109109 /// The author of the commit.
110110 pub author : Author ,
111- /// The GitButler change-id associated with this commit, if available.
112- pub change_id : Option < String > ,
111+ /// The GitButler change-id associated with this commit.
112+ /// It always exists as we either read it from the [headers][but_core::commit::Headers], or we
113+ /// synthesize one from [the commit id][but_core::commit::Headers::synthetic_change_id_from_commit_id()].
114+ pub change_id : String ,
113115 /// Optional URL to the Gerrit review for this commit, if applicable.
114116 /// Only populated if Gerrit mode is enabled and the commit has an associated review.
115117 pub gerrit_review_url : Option < String > ,
@@ -123,17 +125,22 @@ impl TryFrom<gix::Commit<'_>> for Commit {
123125 let commit_id = commit. id ;
124126 let commit = commit. decode ( ) ?;
125127 let headers = but_core:: commit:: Headers :: try_from_commit_headers ( || commit. extra_headers ( ) ) ;
128+ let has_conflicts = headers. as_ref ( ) . is_some_and ( |hdr| hdr. is_conflicted ( ) ) ;
129+ let change_id = headers
130+ . unwrap_or_default ( )
131+ . ensure_change_id ( commit_id)
132+ . change_id
133+ . expect ( "change-id is ensured" )
134+ . to_string ( ) ;
126135 Ok ( Commit {
127136 id : commit_id,
128137 parent_ids : commit. parents ( ) . collect ( ) ,
129138 message : commit. message . to_owned ( ) ,
130- has_conflicts : headers . as_ref ( ) . is_some_and ( |hdr| hdr . is_conflicted ( ) ) ,
139+ has_conflicts,
131140 state : CommitState :: LocalAndRemote ( commit_id) ,
132141 created_at : i128:: from ( commit. time ( ) ?. seconds ) * 1000 ,
133142 author : commit. author ( ) ?. into ( ) ,
134- change_id : headers
135- . and_then ( |headers| headers. change_id )
136- . map ( |id| id. to_string ( ) ) ,
143+ change_id,
137144 gerrit_review_url : None ,
138145 } )
139146 }
@@ -144,8 +151,11 @@ impl From<but_core::CommitOwned> for Commit {
144151 let headers = commit:: Headers :: try_from_commit ( & inner) ;
145152 let has_conflicts = headers. as_ref ( ) . is_some_and ( |hdr| hdr. is_conflicted ( ) ) ;
146153 let change_id = headers
147- . and_then ( |hdr| hdr. change_id )
148- . map ( |id| id. to_string ( ) ) ;
154+ . unwrap_or_default ( )
155+ . ensure_change_id ( id)
156+ . change_id
157+ . expect ( "change-id is ensured" )
158+ . to_string ( ) ;
149159 let gix:: objs:: Commit {
150160 tree : _,
151161 parents,
@@ -439,7 +449,12 @@ impl From<&LocalCommit> for ui::Commit {
439449 author : author
440450 . to_ref ( & mut gix:: date:: parse:: TimeBuf :: default ( ) )
441451 . into ( ) ,
442- change_id : change_id. as_ref ( ) . map ( ToString :: to_string) ,
452+ change_id : change_id
453+ . as_ref ( )
454+ . map ( ToString :: to_string)
455+ . unwrap_or_else ( || {
456+ but_core:: commit:: Headers :: synthetic_change_id_from_commit_id ( * id) . to_string ( )
457+ } ) ,
443458 gerrit_review_url : None ,
444459 }
445460 }
0 commit comments