@@ -3,6 +3,7 @@ use git2::Repository;
33use crate :: { error:: Result , HookResult , HooksError } ;
44
55use std:: {
6+ ffi:: OsString ,
67 path:: { Path , PathBuf } ,
78 process:: Command ,
89 str:: FromStr ,
@@ -121,35 +122,41 @@ impl HookPaths {
121122 let output = if cfg ! ( windows) {
122123 // execute hook in shell
123124 let command = {
124- let mut os_str = std:: ffi:: OsString :: new ( ) ;
125+ // SEE: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_02_02
126+ // Enclosing characters in single-quotes ( '' ) shall preserve the literal value of each character within the single-quotes.
127+ // A single-quote cannot occur within single-quotes.
128+ const REPLACEMENT : & str = concat ! (
129+ "'" , // closing single-quote
130+ "\\ '" , // one escaped single-quote (outside of single-quotes)
131+ "'" , // new single-quote
132+ ) ;
133+
134+ let mut os_str = OsString :: new ( ) ;
125135 os_str. push ( "'" ) ;
126136 if let Some ( hook) = hook. to_str ( ) {
127- // SEE: https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_02_02
128- // Enclosing characters in single-quotes ( '' ) shall preserve the literal value of each character within the single-quotes.
129- // A single-quote cannot occur within single-quotes.
130- const REPLACEMENT : & str = concat ! (
131- "'" , // closing single-quote
132- "\\ '" , // one escaped single-quote (outside of single-quotes)
133- "'" , // new single-quote
134- ) ;
135137 os_str. push ( hook. replace ( '\'' , REPLACEMENT ) ) ;
136138 } else {
137139 #[ cfg( windows) ]
138140 {
139- use std:: os:: windows:: ffi:: OsStrExt ;
140- if hook
141- . as_os_str ( )
142- . encode_wide ( )
143- . into_iter ( )
144- . find ( |x| * x == ( b'\'' as u16 ) )
145- . is_some ( )
146- {
147- // TODO: escape single quotes instead of failing
148- return Err ( HooksError :: PathToString ) ;
141+ use std:: os:: windows:: ffi:: {
142+ OsStrExt , OsStringExt ,
143+ } ;
144+
145+ let mut new_str: Vec < u16 > = vec ! [ ] ;
146+
147+ for ch in hook. as_os_str ( ) . encode_wide ( ) {
148+ if ch == ( b'\'' as u16 ) {
149+ new_str. extend (
150+ std:: ffi:: OsStr :: new ( REPLACEMENT )
151+ . encode_wide ( ) ,
152+ ) ;
153+ } else {
154+ new_str. push ( ch) ;
155+ }
149156 }
150- }
151157
152- os_str. push ( hook. as_os_str ( ) ) ;
158+ os_str. push ( OsString :: from_wide ( & new_str) ) ;
159+ }
153160 }
154161 os_str. push ( "'" ) ;
155162 os_str. push ( " \" $@\" " ) ;
0 commit comments