@@ -5,6 +5,7 @@ use crate::{
55} ;
66use git2:: { ErrorCode , ObjectType , Repository , Signature } ;
77use scopetime:: scope_time;
8+ use ssh_key:: { HashAlg , LineEnding , PrivateKey } ;
89
910///
1011pub fn amend (
@@ -61,7 +62,11 @@ pub(crate) fn signature_allow_undefined_name(
6162}
6263
6364/// this does not run any git hooks, git-hooks have to be executed manually, checkout `hooks_commit_msg` for example
64- pub fn commit ( repo_path : & RepoPath , msg : & str ) -> Result < CommitId > {
65+ pub fn commit (
66+ repo_path : & RepoPath ,
67+ msg : & str ,
68+ sk : Option < & PrivateKey > ,
69+ ) -> Result < CommitId > {
6570 scope_time ! ( "commit" ) ;
6671
6772 let repo = repo ( repo_path) ?;
@@ -78,17 +83,49 @@ pub fn commit(repo_path: &RepoPath, msg: &str) -> Result<CommitId> {
7883 } ;
7984
8085 let parents = parents. iter ( ) . collect :: < Vec < _ > > ( ) ;
81-
82- Ok ( repo
83- . commit (
84- Some ( "HEAD" ) ,
86+ if let Some ( sk) = sk {
87+ let buffer = repo. commit_create_buffer (
8588 & signature,
8689 & signature,
8790 msg,
8891 & tree,
8992 parents. as_slice ( ) ,
90- ) ?
91- . into ( ) )
93+ ) ?;
94+ let content = String :: from_utf8 ( buffer. to_vec ( ) ) ?;
95+ let sig = sk
96+ . sign ( "git" , HashAlg :: Sha256 , & buffer) ?
97+ . to_pem ( LineEnding :: LF ) ?;
98+ let commit_id = repo. commit_signed ( & content, & sig, None ) ?;
99+ match repo. head ( ) {
100+ Ok ( mut head) => {
101+ head. set_target ( commit_id, msg) ?;
102+ }
103+ Err ( _) => {
104+ let config = repo. config ( ) ?;
105+ let default_branch_name = config
106+ . get_str ( "init.defaultBranch" )
107+ . unwrap_or ( "master" ) ;
108+ repo. reference (
109+ & format ! ( "refs/heads/{}" , default_branch_name) ,
110+ commit_id,
111+ true ,
112+ msg,
113+ ) ?;
114+ }
115+ }
116+ Ok ( commit_id. into ( ) )
117+ } else {
118+ Ok ( repo
119+ . commit (
120+ Some ( "HEAD" ) ,
121+ & signature,
122+ & signature,
123+ msg,
124+ & tree,
125+ parents. as_slice ( ) ,
126+ ) ?
127+ . into ( ) )
128+ }
92129}
93130
94131/// Tag a commit.
@@ -162,7 +199,7 @@ mod tests {
162199
163200 assert_eq ! ( get_statuses( repo_path) , ( 0 , 1 ) ) ;
164201
165- commit ( repo_path, "commit msg" ) . unwrap ( ) ;
202+ commit ( repo_path, "commit msg" , None ) . unwrap ( ) ;
166203
167204 assert_eq ! ( get_statuses( repo_path) , ( 0 , 0 ) ) ;
168205 }
@@ -188,7 +225,7 @@ mod tests {
188225
189226 assert_eq ! ( get_statuses( repo_path) , ( 0 , 1 ) ) ;
190227
191- commit ( repo_path, "commit msg" ) . unwrap ( ) ;
228+ commit ( repo_path, "commit msg" , None ) . unwrap ( ) ;
192229
193230 assert_eq ! ( get_statuses( repo_path) , ( 0 , 0 ) ) ;
194231 }
@@ -205,7 +242,7 @@ mod tests {
205242 File :: create ( root. join ( file_path1) ) ?. write_all ( b"test1" ) ?;
206243
207244 stage_add_file ( repo_path, file_path1) ?;
208- let id = commit ( repo_path, "commit msg" ) ?;
245+ let id = commit ( repo_path, "commit msg" , None ) ?;
209246
210247 assert_eq ! ( count_commits( & repo, 10 ) , 1 ) ;
211248
@@ -244,7 +281,7 @@ mod tests {
244281
245282 stage_add_file ( repo_path, file_path) ?;
246283
247- let new_id = commit ( repo_path, "commit msg" ) ?;
284+ let new_id = commit ( repo_path, "commit msg" , None ) ?;
248285
249286 tag_commit ( repo_path, & new_id, "tag" , None ) ?;
250287
@@ -286,7 +323,7 @@ mod tests {
286323
287324 stage_add_file ( repo_path, file_path) ?;
288325
289- let new_id = commit ( repo_path, "commit msg" ) ?;
326+ let new_id = commit ( repo_path, "commit msg" , None ) ?;
290327
291328 tag_commit ( repo_path, & new_id, "tag" , Some ( "tag-message" ) ) ?;
292329
@@ -322,13 +359,13 @@ mod tests {
322359
323360 repo. config ( ) ?. remove ( "user.email" ) ?;
324361
325- let error = commit ( repo_path, "commit msg" ) ;
362+ let error = commit ( repo_path, "commit msg" , None ) ;
326363
327364 assert ! ( matches!( error, Err ( _) ) ) ;
328365
329366 repo. config ( ) ?. set_str ( "user.email" , "email" ) ?;
330367
331- let success = commit ( repo_path, "commit msg" ) ;
368+ let success = commit ( repo_path, "commit msg" , None ) ;
332369
333370 assert ! ( matches!( success, Ok ( _) ) ) ;
334371 assert_eq ! ( count_commits( & repo, 10 ) , 1 ) ;
@@ -358,7 +395,7 @@ mod tests {
358395
359396 repo. config ( ) ?. remove ( "user.name" ) ?;
360397
361- let mut success = commit ( repo_path, "commit msg" ) ;
398+ let mut success = commit ( repo_path, "commit msg" , None ) ;
362399
363400 assert ! ( matches!( success, Ok ( _) ) ) ;
364401 assert_eq ! ( count_commits( & repo, 10 ) , 1 ) ;
@@ -371,7 +408,7 @@ mod tests {
371408
372409 repo. config ( ) ?. set_str ( "user.name" , "name" ) ?;
373410
374- success = commit ( repo_path, "commit msg" ) ;
411+ success = commit ( repo_path, "commit msg" , None ) ;
375412
376413 assert ! ( matches!( success, Ok ( _) ) ) ;
377414 assert_eq ! ( count_commits( & repo, 10 ) , 2 ) ;
0 commit comments