3
3
//! Functions for conducting interactive patch edit session.
4
4
5
5
use std:: {
6
- ffi:: { OsStr , OsString } ,
6
+ ffi:: OsString ,
7
7
fs:: File ,
8
- io:: { BufWriter , Read , Write } ,
8
+ io:: { BufWriter , Write } ,
9
9
path:: Path ,
10
10
} ;
11
11
12
12
use anyhow:: { anyhow, Context , Result } ;
13
- use bstr:: { BString , ByteSlice } ;
13
+ use bstr:: BString ;
14
14
15
15
use super :: description:: { EditablePatchDescription , EditedPatchDescription } ;
16
16
@@ -89,15 +89,25 @@ pub(crate) fn call_editor<P: AsRef<Path>>(
89
89
stderr. flush ( ) ?;
90
90
}
91
91
92
- let result = run_editor ( & editor, path. as_ref ( ) ) ;
92
+ let status_result = gix_command:: prepare ( & editor)
93
+ . arg ( path. as_ref ( ) )
94
+ . with_shell_allow_argument_splitting ( )
95
+ . stdout ( std:: process:: Stdio :: inherit ( ) )
96
+ . spawn ( )
97
+ . with_context ( || format ! ( "running editor: {}" , editor. to_string_lossy( ) ) )
98
+ . and_then ( |mut child| {
99
+ child
100
+ . wait ( )
101
+ . with_context ( || format ! ( "waiting editor: {}" , editor. to_string_lossy( ) ) )
102
+ } ) ;
93
103
94
104
if use_advice && !is_dumb {
95
105
let mut stderr = std:: io:: stderr ( ) ;
96
106
stderr. write_all ( "\r \x1b [K" . as_bytes ( ) ) . unwrap_or ( ( ) ) ;
97
107
stderr. flush ( ) ?;
98
108
}
99
109
100
- let status = result ?;
110
+ let status = status_result ?;
101
111
102
112
if !status. success ( ) {
103
113
return Err ( anyhow ! (
@@ -112,32 +122,6 @@ pub(crate) fn call_editor<P: AsRef<Path>>(
112
122
Ok ( buf)
113
123
}
114
124
115
- fn run_editor < P : AsRef < Path > > ( editor : & OsStr , path : P ) -> Result < std:: process:: ExitStatus > {
116
- let prep = gix_command:: prepare ( editor)
117
- . arg ( path. as_ref ( ) )
118
- . with_shell_allow_argument_splitting ( )
119
- . stdout ( std:: process:: Stdio :: inherit ( ) ) ;
120
-
121
- let mut command = if cfg ! ( windows) && !prep. use_shell {
122
- if let Some ( interpreter) = parse_interpreter ( & prep. command ) {
123
- let mut cmd = std:: process:: Command :: new ( interpreter) ;
124
- cmd. arg ( prep. command ) . arg ( path. as_ref ( ) ) ;
125
- cmd
126
- } else {
127
- std:: process:: Command :: from ( prep)
128
- }
129
- } else {
130
- std:: process:: Command :: from ( prep)
131
- } ;
132
- let mut child = command
133
- . spawn ( )
134
- . with_context ( || format ! ( "running editor: {}" , editor. to_string_lossy( ) ) ) ?;
135
-
136
- child
137
- . wait ( )
138
- . with_context ( || format ! ( "waiting editor: {}" , editor. to_string_lossy( ) ) )
139
- }
140
-
141
125
/// Determine user's editor of choice based on config and environment.
142
126
fn get_editor ( config : & gix:: config:: Snapshot ) -> Result < OsString > {
143
127
let editor = if let Some ( editor) = std:: env:: var_os ( "GIT_EDITOR" ) {
@@ -163,78 +147,3 @@ fn get_editor(config: &gix::config::Snapshot) -> Result<OsString> {
163
147
} ;
164
148
Ok ( editor)
165
149
}
166
-
167
- fn parse_interpreter ( command : & OsStr ) -> Option < OsString > {
168
- let command_path = Path :: new ( command) ;
169
- if command_path. extension ( ) . and_then ( |ext| ext. to_str ( ) ) == Some ( "exe" ) {
170
- return None ;
171
- }
172
-
173
- let mut buffer = [ 0 ; 128 ] ;
174
- if let Some ( n) = std:: fs:: File :: open ( command_path)
175
- . ok ( )
176
- . and_then ( |mut file| file. read ( & mut buffer) . ok ( ) )
177
- {
178
- parse_shebang ( & buffer[ ..n] )
179
- . and_then ( |bytes| bytes. to_os_str ( ) . ok ( ) )
180
- . map ( |osstr| osstr. to_os_string ( ) )
181
- } else {
182
- None
183
- }
184
- }
185
-
186
- fn parse_shebang ( buffer : & [ u8 ] ) -> Option < & [ u8 ] > {
187
- buffer
188
- . as_bstr ( )
189
- . lines ( )
190
- . next ( )
191
- . and_then ( |line| line. strip_prefix ( b"#!" ) )
192
- . and_then ( |shebang| {
193
- shebang. rfind_byteset ( b"/\\ " ) . map ( |index| {
194
- if let Some ( space_index) = shebang[ index..] . find_byte ( b' ' ) {
195
- & shebang[ ..index + space_index]
196
- } else {
197
- shebang
198
- }
199
- } )
200
- } )
201
- }
202
-
203
- #[ cfg( test) ]
204
- mod tests {
205
- use super :: * ;
206
-
207
- #[ test]
208
- fn plain_shebang ( ) {
209
- assert_eq ! ( parse_shebang( b"#!/bin/sh\n some stuff" ) . unwrap( ) , b"/bin/sh" ) ;
210
- }
211
-
212
- #[ test]
213
- fn shebang_with_options ( ) {
214
- assert_eq ! (
215
- parse_shebang( b"#!/bin/sh -i -o -u\n some stuff" ) . unwrap( ) ,
216
- b"/bin/sh"
217
- ) ;
218
- }
219
-
220
- #[ test]
221
- fn shebang_with_backslashes ( ) {
222
- assert_eq ! (
223
- parse_shebang( b"#!C:\\ Program Files\\ Imashell.exe\n some stuff" ) . unwrap( ) ,
224
- b"C:\\ Program Files\\ Imashell.exe"
225
- ) ;
226
- }
227
-
228
- #[ test]
229
- fn shebang_with_trailing_space ( ) {
230
- assert_eq ! (
231
- parse_shebang( b"#!/bin/sh \n some stuff" ) . unwrap( ) ,
232
- b"/bin/sh"
233
- ) ;
234
- }
235
-
236
- #[ test]
237
- fn not_a_shebang ( ) {
238
- assert ! ( parse_shebang( b"/bin/sh\n some stuff" ) . is_none( ) ) ;
239
- }
240
- }
0 commit comments