278 def quote(match): |
279 def quote(match): |
279 pre = match.group(2) |
280 pre = match.group(2) |
280 key = match.group(3) |
281 key = match.group(3) |
281 if not do3way and key == 'parent2': |
282 if not do3way and key == 'parent2': |
282 return pre |
283 return pre |
283 return pre + util.shellquote(replace[key]) |
284 return pre + procutil.shellquote(replace[key]) |
284 |
285 |
285 # Match parent2 first, so 'parent1?' will match both parent1 and parent |
286 # Match parent2 first, so 'parent1?' will match both parent1 and parent |
286 regex = (br'''(['"]?)([^\s'"$]*)''' |
287 regex = (br'''(['"]?)([^\s'"$]*)''' |
287 br'\$(parent2|parent1?|child|plabel1|plabel2|clabel|root)\1') |
288 br'\$(parent2|parent1?|child|plabel1|plabel2|clabel|root)\1') |
288 if not do3way and not re.search(regex, cmdline): |
289 if not do3way and not re.search(regex, cmdline): |
347 program = opts.get('program') |
348 program = opts.get('program') |
348 option = opts.get('option') |
349 option = opts.get('option') |
349 if not program: |
350 if not program: |
350 program = 'diff' |
351 program = 'diff' |
351 option = option or ['-Npru'] |
352 option = option or ['-Npru'] |
352 cmdline = ' '.join(map(util.shellquote, [program] + option)) |
353 cmdline = ' '.join(map(procutil.shellquote, [program] + option)) |
353 return dodiff(ui, repo, cmdline, pats, opts) |
354 return dodiff(ui, repo, cmdline, pats, opts) |
354 |
355 |
355 class savedcmd(object): |
356 class savedcmd(object): |
356 """use external program to diff repository (or selected files) |
357 """use external program to diff repository (or selected files) |
357 |
358 |
374 self.__doc__ %= {r'path': pycompat.sysstr(stringutil.uirepr(docpath))} |
375 self.__doc__ %= {r'path': pycompat.sysstr(stringutil.uirepr(docpath))} |
375 self._cmdline = cmdline |
376 self._cmdline = cmdline |
376 |
377 |
377 def __call__(self, ui, repo, *pats, **opts): |
378 def __call__(self, ui, repo, *pats, **opts): |
378 opts = pycompat.byteskwargs(opts) |
379 opts = pycompat.byteskwargs(opts) |
379 options = ' '.join(map(util.shellquote, opts['option'])) |
380 options = ' '.join(map(procutil.shellquote, opts['option'])) |
380 if options: |
381 if options: |
381 options = ' ' + options |
382 options = ' ' + options |
382 return dodiff(ui, repo, self._cmdline + options, pats, opts) |
383 return dodiff(ui, repo, self._cmdline + options, pats, opts) |
383 |
384 |
384 def uisetup(ui): |
385 def uisetup(ui): |
385 for cmd, path in ui.configitems('extdiff'): |
386 for cmd, path in ui.configitems('extdiff'): |
386 path = util.expandpath(path) |
387 path = util.expandpath(path) |
387 if cmd.startswith('cmd.'): |
388 if cmd.startswith('cmd.'): |
388 cmd = cmd[4:] |
389 cmd = cmd[4:] |
389 if not path: |
390 if not path: |
390 path = util.findexe(cmd) |
391 path = procutil.findexe(cmd) |
391 if path is None: |
392 if path is None: |
392 path = filemerge.findexternaltool(ui, cmd) or cmd |
393 path = filemerge.findexternaltool(ui, cmd) or cmd |
393 diffopts = ui.config('extdiff', 'opts.' + cmd) |
394 diffopts = ui.config('extdiff', 'opts.' + cmd) |
394 cmdline = util.shellquote(path) |
395 cmdline = procutil.shellquote(path) |
395 if diffopts: |
396 if diffopts: |
396 cmdline += ' ' + diffopts |
397 cmdline += ' ' + diffopts |
397 elif cmd.startswith('opts.'): |
398 elif cmd.startswith('opts.'): |
398 continue |
399 continue |
399 else: |
400 else: |
401 # case "cmd = path opts" |
402 # case "cmd = path opts" |
402 cmdline = path |
403 cmdline = path |
403 diffopts = len(pycompat.shlexsplit(cmdline)) > 1 |
404 diffopts = len(pycompat.shlexsplit(cmdline)) > 1 |
404 else: |
405 else: |
405 # case "cmd =" |
406 # case "cmd =" |
406 path = util.findexe(cmd) |
407 path = procutil.findexe(cmd) |
407 if path is None: |
408 if path is None: |
408 path = filemerge.findexternaltool(ui, cmd) or cmd |
409 path = filemerge.findexternaltool(ui, cmd) or cmd |
409 cmdline = util.shellquote(path) |
410 cmdline = procutil.shellquote(path) |
410 diffopts = False |
411 diffopts = False |
411 # look for diff arguments in [diff-tools] then [merge-tools] |
412 # look for diff arguments in [diff-tools] then [merge-tools] |
412 if not diffopts: |
413 if not diffopts: |
413 args = ui.config('diff-tools', cmd+'.diffargs') or \ |
414 args = ui.config('diff-tools', cmd+'.diffargs') or \ |
414 ui.config('merge-tools', cmd+'.diffargs') |
415 ui.config('merge-tools', cmd+'.diffargs') |