##// 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 12 import os
13 13 import re
14 14 import stat
15 import string
15 16 import sys
16 17
17 18 from .i18n import _
@@ -253,6 +254,108 b' normcasefallback = encoding.upperfallbac'
253 254 def samestat(s1, s2):
254 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 359 # A sequence of backslashes is special iff it precedes a double quote:
257 360 # - if there's an even number of backslashes, the double quote is not
258 361 # quoted (i.e. it ends the quoted region)
General Comments 0
You need to be logged in to leave comments. Login now