mercurial/filemerge.py
changeset 34035 96123bdea43e
parent 34034 7558917f291e
child 34036 fe04c018eaac
equal deleted inserted replaced
34034:7558917f291e 34035:96123bdea43e
   491     tool, toolpath, binary, symlink = toolconf
   491     tool, toolpath, binary, symlink = toolconf
   492     if fcd.isabsent() or fco.isabsent():
   492     if fcd.isabsent() or fco.isabsent():
   493         repo.ui.warn(_('warning: %s cannot merge change/delete conflict '
   493         repo.ui.warn(_('warning: %s cannot merge change/delete conflict '
   494                        'for %s\n') % (tool, fcd.path()))
   494                        'for %s\n') % (tool, fcd.path()))
   495         return False, 1, None
   495         return False, 1, None
   496     unused, b, c, back = files
   496     unused, unused, unused, back = files
   497     a = _workingpath(repo, fcd)
   497     a = _workingpath(repo, fcd)
   498     out = ""
   498     b, c = _maketempfiles(repo, fco, fca)
   499     env = {'HG_FILE': fcd.path(),
   499     try:
   500            'HG_MY_NODE': short(mynode),
   500         out = ""
   501            'HG_OTHER_NODE': str(fco.changectx()),
   501         env = {'HG_FILE': fcd.path(),
   502            'HG_BASE_NODE': str(fca.changectx()),
   502                'HG_MY_NODE': short(mynode),
   503            'HG_MY_ISLINK': 'l' in fcd.flags(),
   503                'HG_OTHER_NODE': str(fco.changectx()),
   504            'HG_OTHER_ISLINK': 'l' in fco.flags(),
   504                'HG_BASE_NODE': str(fca.changectx()),
   505            'HG_BASE_ISLINK': 'l' in fca.flags(),
   505                'HG_MY_ISLINK': 'l' in fcd.flags(),
   506            }
   506                'HG_OTHER_ISLINK': 'l' in fco.flags(),
   507 
   507                'HG_BASE_ISLINK': 'l' in fca.flags(),
   508     ui = repo.ui
   508                }
   509 
   509         ui = repo.ui
   510     args = _toolstr(ui, tool, "args", '$local $base $other')
   510 
   511     if "$output" in args:
   511         args = _toolstr(ui, tool, "args", '$local $base $other')
   512         out, a = a, back # read input from backup, write to original
   512         if "$output" in args:
   513     replace = {'local': a, 'base': b, 'other': c, 'output': out}
   513             out, a = a, back # read input from backup, write to original
   514     args = util.interpolate(r'\$', replace, args,
   514         replace = {'local': a, 'base': b, 'other': c, 'output': out}
   515                             lambda s: util.shellquote(util.localpath(s)))
   515         args = util.interpolate(r'\$', replace, args,
   516     cmd = toolpath + ' ' + args
   516                                 lambda s: util.shellquote(util.localpath(s)))
   517     if _toolbool(ui, tool, "gui"):
   517         cmd = toolpath + ' ' + args
   518         repo.ui.status(_('running merge tool %s for file %s\n') %
   518         if _toolbool(ui, tool, "gui"):
   519                        (tool, fcd.path()))
   519             repo.ui.status(_('running merge tool %s for file %s\n') %
   520     repo.ui.debug('launching merge tool: %s\n' % cmd)
   520                            (tool, fcd.path()))
   521     r = ui.system(cmd, cwd=repo.root, environ=env, blockedtag='mergetool')
   521         repo.ui.debug('launching merge tool: %s\n' % cmd)
   522     repo.ui.debug('merge tool returned: %s\n' % r)
   522         r = ui.system(cmd, cwd=repo.root, environ=env, blockedtag='mergetool')
   523     return True, r, False
   523         repo.ui.debug('merge tool returned: %s\n' % r)
       
   524         return True, r, False
       
   525     finally:
       
   526         util.unlink(b)
       
   527         util.unlink(c)
   524 
   528 
   525 def _formatconflictmarker(repo, ctx, template, label, pad):
   529 def _formatconflictmarker(repo, ctx, template, label, pad):
   526     """Applies the given template to the ctx, prefixed by the label.
   530     """Applies the given template to the ctx, prefixed by the label.
   527 
   531 
   528     Pad is the minimum width of the label prefix, so that multiple markers
   532     Pad is the minimum width of the label prefix, so that multiple markers
   601     back = scmutil.origpath(ui, repo, a)
   605     back = scmutil.origpath(ui, repo, a)
   602     if premerge:
   606     if premerge:
   603         util.copyfile(a, back)
   607         util.copyfile(a, back)
   604     return back
   608     return back
   605 
   609 
   606 def _maketempfiles(repo, fcd, fco, fca):
   610 def _maketempfiles(repo, fco, fca):
   607     """Writes out `fco` and `fca` as temporary files, so an external merge
   611     """Writes out `fco` and `fca` as temporary files, so an external merge
   608     tool may use them.
   612     tool may use them.
   609 
       
   610     `fcd` is returned as-is, by convention, because it currently doubles as both
       
   611     the local version and merge destination.
       
   612     """
   613     """
   613     def temp(prefix, ctx):
   614     def temp(prefix, ctx):
   614         fullbase, ext = os.path.splitext(ctx.path())
   615         fullbase, ext = os.path.splitext(ctx.path())
   615         pre = "%s~%s." % (os.path.basename(fullbase), prefix)
   616         pre = "%s~%s." % (os.path.basename(fullbase), prefix)
   616         (fd, name) = tempfile.mkstemp(prefix=pre, suffix=ext)
   617         (fd, name) = tempfile.mkstemp(prefix=pre, suffix=ext)
   618         f = os.fdopen(fd, pycompat.sysstr("wb"))
   619         f = os.fdopen(fd, pycompat.sysstr("wb"))
   619         f.write(data)
   620         f.write(data)
   620         f.close()
   621         f.close()
   621         return name
   622         return name
   622 
   623 
   623     a = repo.wjoin(fcd.path())
       
   624     b = temp("base", fca)
   624     b = temp("base", fca)
   625     c = temp("other", fco)
   625     c = temp("other", fco)
   626 
   626 
   627     return a, b, c
   627     return b, c
   628 
   628 
   629 def _filemerge(premerge, repo, mynode, orig, fcd, fco, fca, labels=None):
   629 def _filemerge(premerge, repo, mynode, orig, fcd, fco, fca, labels=None):
   630     """perform a 3-way merge in the working directory
   630     """perform a 3-way merge in the working directory
   631 
   631 
   632     premerge = whether this is a premerge
   632     premerge = whether this is a premerge
   685         if onfailure:
   685         if onfailure:
   686             ui.warn(onfailure % fd)
   686             ui.warn(onfailure % fd)
   687         return True, 1, False
   687         return True, 1, False
   688 
   688 
   689     back = _makebackup(repo, ui, fcd, premerge)
   689     back = _makebackup(repo, ui, fcd, premerge)
   690     files = _maketempfiles(repo, fcd, fco, fca) + (back,)
   690     files = (None, None, None, back)
   691     r = 1
   691     r = 1
   692     try:
   692     try:
   693         markerstyle = ui.config('ui', 'mergemarkers')
   693         markerstyle = ui.config('ui', 'mergemarkers')
   694         if not labels:
   694         if not labels:
   695             labels = _defaultconflictlabels
   695             labels = _defaultconflictlabels
   713 
   713 
   714         return True, r, deleted
   714         return True, r, deleted
   715     finally:
   715     finally:
   716         if not r and back is not None:
   716         if not r and back is not None:
   717             util.unlink(back)
   717             util.unlink(back)
   718         util.unlink(files[1])
       
   719         util.unlink(files[2])
       
   720 
   718 
   721 def _check(repo, r, ui, tool, fcd, files):
   719 def _check(repo, r, ui, tool, fcd, files):
   722     fd = fcd.path()
   720     fd = fcd.path()
   723     unused, unused, unused, back = files
   721     unused, unused, unused, back = files
   724 
   722