@@ -5,6 +5,7 @@ use crate::{
5
5
} ;
6
6
use git2:: { ErrorCode , ObjectType , Repository , Signature } ;
7
7
use scopetime:: scope_time;
8
+ use ssh_key:: { HashAlg , LineEnding , PrivateKey } ;
8
9
9
10
///
10
11
pub fn amend (
@@ -61,7 +62,11 @@ pub(crate) fn signature_allow_undefined_name(
61
62
}
62
63
63
64
/// 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 > {
65
70
scope_time ! ( "commit" ) ;
66
71
67
72
let repo = repo ( repo_path) ?;
@@ -78,17 +83,49 @@ pub fn commit(repo_path: &RepoPath, msg: &str) -> Result<CommitId> {
78
83
} ;
79
84
80
85
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 (
85
88
& signature,
86
89
& signature,
87
90
msg,
88
91
& tree,
89
92
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
+ }
92
129
}
93
130
94
131
/// Tag a commit.
@@ -162,7 +199,7 @@ mod tests {
162
199
163
200
assert_eq ! ( get_statuses( repo_path) , ( 0 , 1 ) ) ;
164
201
165
- commit ( repo_path, "commit msg" ) . unwrap ( ) ;
202
+ commit ( repo_path, "commit msg" , None ) . unwrap ( ) ;
166
203
167
204
assert_eq ! ( get_statuses( repo_path) , ( 0 , 0 ) ) ;
168
205
}
@@ -188,7 +225,7 @@ mod tests {
188
225
189
226
assert_eq ! ( get_statuses( repo_path) , ( 0 , 1 ) ) ;
190
227
191
- commit ( repo_path, "commit msg" ) . unwrap ( ) ;
228
+ commit ( repo_path, "commit msg" , None ) . unwrap ( ) ;
192
229
193
230
assert_eq ! ( get_statuses( repo_path) , ( 0 , 0 ) ) ;
194
231
}
@@ -205,7 +242,7 @@ mod tests {
205
242
File :: create ( root. join ( file_path1) ) ?. write_all ( b"test1" ) ?;
206
243
207
244
stage_add_file ( repo_path, file_path1) ?;
208
- let id = commit ( repo_path, "commit msg" ) ?;
245
+ let id = commit ( repo_path, "commit msg" , None ) ?;
209
246
210
247
assert_eq ! ( count_commits( & repo, 10 ) , 1 ) ;
211
248
@@ -244,7 +281,7 @@ mod tests {
244
281
245
282
stage_add_file ( repo_path, file_path) ?;
246
283
247
- let new_id = commit ( repo_path, "commit msg" ) ?;
284
+ let new_id = commit ( repo_path, "commit msg" , None ) ?;
248
285
249
286
tag_commit ( repo_path, & new_id, "tag" , None ) ?;
250
287
@@ -286,7 +323,7 @@ mod tests {
286
323
287
324
stage_add_file ( repo_path, file_path) ?;
288
325
289
- let new_id = commit ( repo_path, "commit msg" ) ?;
326
+ let new_id = commit ( repo_path, "commit msg" , None ) ?;
290
327
291
328
tag_commit ( repo_path, & new_id, "tag" , Some ( "tag-message" ) ) ?;
292
329
@@ -322,13 +359,13 @@ mod tests {
322
359
323
360
repo. config ( ) ?. remove ( "user.email" ) ?;
324
361
325
- let error = commit ( repo_path, "commit msg" ) ;
362
+ let error = commit ( repo_path, "commit msg" , None ) ;
326
363
327
364
assert ! ( matches!( error, Err ( _) ) ) ;
328
365
329
366
repo. config ( ) ?. set_str ( "user.email" , "email" ) ?;
330
367
331
- let success = commit ( repo_path, "commit msg" ) ;
368
+ let success = commit ( repo_path, "commit msg" , None ) ;
332
369
333
370
assert ! ( matches!( success, Ok ( _) ) ) ;
334
371
assert_eq ! ( count_commits( & repo, 10 ) , 1 ) ;
@@ -358,7 +395,7 @@ mod tests {
358
395
359
396
repo. config ( ) ?. remove ( "user.name" ) ?;
360
397
361
- let mut success = commit ( repo_path, "commit msg" ) ;
398
+ let mut success = commit ( repo_path, "commit msg" , None ) ;
362
399
363
400
assert ! ( matches!( success, Ok ( _) ) ) ;
364
401
assert_eq ! ( count_commits( & repo, 10 ) , 1 ) ;
@@ -371,7 +408,7 @@ mod tests {
371
408
372
409
repo. config ( ) ?. set_str ( "user.name" , "name" ) ?;
373
410
374
- success = commit ( repo_path, "commit msg" ) ;
411
+ success = commit ( repo_path, "commit msg" , None ) ;
375
412
376
413
assert ! ( matches!( success, Ok ( _) ) ) ;
377
414
assert_eq ! ( count_commits( & repo, 10 ) , 2 ) ;
0 commit comments