##// END OF EJS Templates
windows: add a method to convert Unix style command lines to Windows style...
Matt Harbison -
r38502:3efadf23 default
parent child Browse files
Show More
@@ -12,6 +12,7 b' import msvcrt'
12 import os
12 import os
13 import re
13 import re
14 import stat
14 import stat
15 import string
15 import sys
16 import sys
16
17
17 from .i18n import _
18 from .i18n import _
@@ -253,6 +254,108 b' normcasefallback = encoding.upperfallbac'
253 def samestat(s1, s2):
254 def samestat(s1, s2):
254 return False
255 return False
255
256
257 def shelltocmdexe(path, env):
258 r"""Convert shell variables in the form $var and ${var} inside ``path``
259 to %var% form. Existing Windows style variables are left unchanged.
260
261 The variables are limited to the given environment. Unknown variables are
262 left unchanged.
263
264 >>> e = {b'var1': b'v1', b'var2': b'v2', b'var3': b'v3'}
265 >>> # Only valid values are expanded
266 >>> shelltocmdexe(b'cmd $var1 ${var2} %var3% $missing ${missing} %missing%',
267 ... e)
268 'cmd %var1% %var2% %var3% $missing ${missing} %missing%'
269 >>> # Single quote prevents expansion, as does \$ escaping
270 >>> shelltocmdexe(b"cmd '$var1 ${var2} %var3%' \$var1 \${var2} \\", e)
271 "cmd '$var1 ${var2} %var3%' $var1 ${var2} \\"
272 >>> # $$ -> $, %% is not special, but can be the end and start of variables
273 >>> shelltocmdexe(b"cmd $$ %% %var1%%var2%", e)
274 'cmd $ %% %var1%%var2%'
275 >>> # No double substitution
276 >>> shelltocmdexe(b"$var1 %var1%", {b'var1': b'%var2%', b'var2': b'boom'})
277 '%var1% %var1%'
278 """
279 if b'$' not in path:
280 return path
281
282 varchars = pycompat.sysbytes(string.ascii_letters + string.digits) + b'_-'
283
284 res = b''
285 index = 0
286 pathlen = len(path)
287 while index < pathlen:
288 c = path[index]
289 if c == b'\'': # no expansion within single quotes
290 path = path[index + 1:]
291 pathlen = len(path)
292 try:
293 index = path.index(b'\'')
294 res += b'\'' + path[:index + 1]
295 except ValueError:
296 res += c + path
297 index = pathlen - 1
298 elif c == b'%': # variable
299 path = path[index + 1:]
300 pathlen = len(path)
301 try:
302 index = path.index(b'%')
303 except ValueError:
304 res += b'%' + path
305 index = pathlen - 1
306 else:
307 var = path[:index]
308 res += b'%' + var + b'%'
309 elif c == b'$': # variable or '$$'
310 if path[index + 1:index + 2] == b'$':
311 res += c
312 index += 1
313 elif path[index + 1:index + 2] == b'{':
314 path = path[index + 2:]
315 pathlen = len(path)
316 try:
317 index = path.index(b'}')
318 var = path[:index]
319
320 # See below for why empty variables are handled specially
321 if env.get(var, '') != '':
322 res += b'%' + var + b'%'
323 else:
324 res += b'${' + var + b'}'
325 except ValueError:
326 res += b'${' + path
327 index = pathlen - 1
328 else:
329 var = b''
330 index += 1
331 c = path[index:index + 1]
332 while c != b'' and c in varchars:
333 var += c
334 index += 1
335 c = path[index:index + 1]
336 # Some variables (like HG_OLDNODE) may be defined, but have an
337 # empty value. Those need to be skipped because when spawning
338 # cmd.exe to run the hook, it doesn't replace %VAR% for an empty
339 # VAR, and that really confuses things like revset expressions.
340 # OTOH, if it's left in Unix format and the hook runs sh.exe, it
341 # will substitute to an empty string, and everything is happy.
342 if env.get(var, '') != '':
343 res += b'%' + var + b'%'
344 else:
345 res += b'$' + var
346
347 if c != '':
348 index -= 1
349 elif c == b'\\' and index + 1 < pathlen and path[index + 1] == b'$':
350 # Skip '\', but only if it is escaping $
351 res += b'$'
352 index += 1
353 else:
354 res += c
355
356 index += 1
357 return res
358
256 # A sequence of backslashes is special iff it precedes a double quote:
359 # A sequence of backslashes is special iff it precedes a double quote:
257 # - if there's an even number of backslashes, the double quote is not
360 # - if there's an even number of backslashes, the double quote is not
258 # quoted (i.e. it ends the quoted region)
361 # quoted (i.e. it ends the quoted region)
General Comments 0
You need to be logged in to leave comments. Login now