1
- use super :: { utils:: repo, CommitId } ;
1
+ use super :: { get_head , utils:: repo, CommitId } ;
2
2
use crate :: error:: Result ;
3
+ use git2:: { ErrorCode , Repository , Signature } ;
3
4
use scopetime:: scope_time;
4
5
5
6
///
@@ -29,13 +30,65 @@ pub fn amend(
29
30
Ok ( CommitId :: new ( new_id) )
30
31
}
31
32
33
+ /// Wrap Repository::signature to allow unknown user.name.
34
+ ///
35
+ /// See <https://github.com/extrawurst/gitui/issues/79>.
36
+ fn signature_allow_undefined_name (
37
+ repo : & Repository ,
38
+ ) -> std:: result:: Result < Signature < ' _ > , git2:: Error > {
39
+ match repo. signature ( ) {
40
+ Err ( e) if e. code ( ) == ErrorCode :: NotFound => {
41
+ let config = repo. config ( ) ?;
42
+ Signature :: now (
43
+ config. get_str ( "user.name" ) . unwrap_or ( "unknown" ) ,
44
+ config. get_str ( "user.email" ) ?,
45
+ )
46
+ }
47
+
48
+ v => v,
49
+ }
50
+ }
51
+
52
+ /// this does not run any git hooks
53
+ pub fn commit ( repo_path : & str , msg : & str ) -> Result < CommitId > {
54
+ scope_time ! ( "commit" ) ;
55
+
56
+ let repo = repo ( repo_path) ?;
57
+
58
+ let signature = signature_allow_undefined_name ( & repo) ?;
59
+ let mut index = repo. index ( ) ?;
60
+ let tree_id = index. write_tree ( ) ?;
61
+ let tree = repo. find_tree ( tree_id) ?;
62
+
63
+ let parents = if let Ok ( id) = get_head ( repo_path) {
64
+ vec ! [ repo. find_commit( id. into( ) ) ?]
65
+ } else {
66
+ Vec :: new ( )
67
+ } ;
68
+
69
+ let parents = parents. iter ( ) . collect :: < Vec < _ > > ( ) ;
70
+
71
+ Ok ( repo
72
+ . commit (
73
+ Some ( "HEAD" ) ,
74
+ & signature,
75
+ & signature,
76
+ msg,
77
+ & tree,
78
+ parents. as_slice ( ) ,
79
+ ) ?
80
+ . into ( ) )
81
+ }
82
+
32
83
#[ cfg( test) ]
33
84
mod tests {
34
85
35
86
use crate :: error:: Result ;
36
87
use crate :: sync:: {
37
88
commit, get_commit_details, get_commit_files, stage_add_file,
38
- tests:: repo_init_empty, utils:: get_head, LogWalker ,
89
+ tests:: { get_statuses, repo_init, repo_init_empty} ,
90
+ utils:: get_head,
91
+ LogWalker ,
39
92
} ;
40
93
use commit:: amend;
41
94
use git2:: Repository ;
@@ -48,6 +101,54 @@ mod tests {
48
101
items. len ( )
49
102
}
50
103
104
+ #[ test]
105
+ fn test_commit ( ) {
106
+ let file_path = Path :: new ( "foo" ) ;
107
+ let ( _td, repo) = repo_init ( ) . unwrap ( ) ;
108
+ let root = repo. path ( ) . parent ( ) . unwrap ( ) ;
109
+ let repo_path = root. as_os_str ( ) . to_str ( ) . unwrap ( ) ;
110
+
111
+ File :: create ( & root. join ( file_path) )
112
+ . unwrap ( )
113
+ . write_all ( b"test\n foo" )
114
+ . unwrap ( ) ;
115
+
116
+ assert_eq ! ( get_statuses( repo_path) , ( 1 , 0 ) ) ;
117
+
118
+ stage_add_file ( repo_path, file_path) . unwrap ( ) ;
119
+
120
+ assert_eq ! ( get_statuses( repo_path) , ( 0 , 1 ) ) ;
121
+
122
+ commit ( repo_path, "commit msg" ) . unwrap ( ) ;
123
+
124
+ assert_eq ! ( get_statuses( repo_path) , ( 0 , 0 ) ) ;
125
+ }
126
+
127
+ #[ test]
128
+ fn test_commit_in_empty_repo ( ) {
129
+ let file_path = Path :: new ( "foo" ) ;
130
+ let ( _td, repo) = repo_init_empty ( ) . unwrap ( ) ;
131
+ let root = repo. path ( ) . parent ( ) . unwrap ( ) ;
132
+ let repo_path = root. as_os_str ( ) . to_str ( ) . unwrap ( ) ;
133
+
134
+ assert_eq ! ( get_statuses( repo_path) , ( 0 , 0 ) ) ;
135
+
136
+ File :: create ( & root. join ( file_path) )
137
+ . unwrap ( )
138
+ . write_all ( b"test\n foo" )
139
+ . unwrap ( ) ;
140
+
141
+ assert_eq ! ( get_statuses( repo_path) , ( 1 , 0 ) ) ;
142
+
143
+ stage_add_file ( repo_path, file_path) . unwrap ( ) ;
144
+
145
+ assert_eq ! ( get_statuses( repo_path) , ( 0 , 1 ) ) ;
146
+
147
+ commit ( repo_path, "commit msg" ) . unwrap ( ) ;
148
+
149
+ assert_eq ! ( get_statuses( repo_path) , ( 0 , 0 ) ) ;
150
+ }
151
+
51
152
#[ test]
52
153
fn test_amend ( ) -> Result < ( ) > {
53
154
let file_path1 = Path :: new ( "foo" ) ;
0 commit comments