mercurial/filemerge.py
changeset 27039 d7517deedf86
parent 27038 58a4eb16e722
child 27040 1bde66b89bb2
equal deleted inserted replaced
27038:58a4eb16e722 27039:d7517deedf86
   118             if p:
   118             if p:
   119                 return p
   119                 return p
   120     exe = _toolstr(ui, tool, "executable", tool)
   120     exe = _toolstr(ui, tool, "executable", tool)
   121     return util.findexe(util.expandpath(exe))
   121     return util.findexe(util.expandpath(exe))
   122 
   122 
   123 def _picktool(repo, ui, path, binary, symlink):
   123 def _picktool(repo, ui, path, binary, symlink, changedelete):
   124     def check(tool, pat, symlink, binary):
   124     def supportscd(tool):
       
   125         return tool in internals and internals[tool].mergetype == nomerge
       
   126 
       
   127     def check(tool, pat, symlink, binary, changedelete):
   125         tmsg = tool
   128         tmsg = tool
   126         if pat:
   129         if pat:
   127             tmsg += " specified for " + pat
   130             tmsg += " specified for " + pat
   128         if not _findtool(ui, tool):
   131         if not _findtool(ui, tool):
   129             if pat: # explicitly requested tool deserves a warning
   132             if pat: # explicitly requested tool deserves a warning
   132                 ui.note(_("couldn't find merge tool %s\n") % tmsg)
   135                 ui.note(_("couldn't find merge tool %s\n") % tmsg)
   133         elif symlink and not _toolbool(ui, tool, "symlink"):
   136         elif symlink and not _toolbool(ui, tool, "symlink"):
   134             ui.warn(_("tool %s can't handle symlinks\n") % tmsg)
   137             ui.warn(_("tool %s can't handle symlinks\n") % tmsg)
   135         elif binary and not _toolbool(ui, tool, "binary"):
   138         elif binary and not _toolbool(ui, tool, "binary"):
   136             ui.warn(_("tool %s can't handle binary\n") % tmsg)
   139             ui.warn(_("tool %s can't handle binary\n") % tmsg)
       
   140         elif changedelete and not supportscd(tool):
       
   141             # the nomerge tools are the only tools that support change/delete
       
   142             # conflicts
       
   143             pass
   137         elif not util.gui() and _toolbool(ui, tool, "gui"):
   144         elif not util.gui() and _toolbool(ui, tool, "gui"):
   138             ui.warn(_("tool %s requires a GUI\n") % tmsg)
   145             ui.warn(_("tool %s requires a GUI\n") % tmsg)
   139         else:
   146         else:
   140             return True
   147             return True
   141         return False
   148         return False
   143     # internal config: ui.forcemerge
   150     # internal config: ui.forcemerge
   144     # forcemerge comes from command line arguments, highest priority
   151     # forcemerge comes from command line arguments, highest priority
   145     force = ui.config('ui', 'forcemerge')
   152     force = ui.config('ui', 'forcemerge')
   146     if force:
   153     if force:
   147         toolpath = _findtool(ui, force)
   154         toolpath = _findtool(ui, force)
   148         if toolpath:
   155         if changedelete and not supportscd(toolpath):
   149             return (force, util.shellquote(toolpath))
   156             return ":prompt", None
   150         else:
   157         else:
   151             # mimic HGMERGE if given tool not found
   158             if toolpath:
   152             return (force, force)
   159                 return (force, util.shellquote(toolpath))
       
   160             else:
       
   161                 # mimic HGMERGE if given tool not found
       
   162                 return (force, force)
   153 
   163 
   154     # HGMERGE takes next precedence
   164     # HGMERGE takes next precedence
   155     hgmerge = os.environ.get("HGMERGE")
   165     hgmerge = os.environ.get("HGMERGE")
   156     if hgmerge:
   166     if hgmerge:
   157         return (hgmerge, hgmerge)
   167         if changedelete and not supportscd(hgmerge):
       
   168             return ":prompt", None
       
   169         else:
       
   170             return (hgmerge, hgmerge)
   158 
   171 
   159     # then patterns
   172     # then patterns
   160     for pat, tool in ui.configitems("merge-patterns"):
   173     for pat, tool in ui.configitems("merge-patterns"):
   161         mf = match.match(repo.root, '', [pat])
   174         mf = match.match(repo.root, '', [pat])
   162         if mf(path) and check(tool, pat, symlink, False):
   175         if mf(path) and check(tool, pat, symlink, False, changedelete):
   163             toolpath = _findtool(ui, tool)
   176             toolpath = _findtool(ui, tool)
   164             return (tool, util.shellquote(toolpath))
   177             return (tool, util.shellquote(toolpath))
   165 
   178 
   166     # then merge tools
   179     # then merge tools
   167     tools = {}
   180     tools = {}
   174             disabled.add(t)
   187             disabled.add(t)
   175     names = tools.keys()
   188     names = tools.keys()
   176     tools = sorted([(-p, t) for t, p in tools.items() if t not in disabled])
   189     tools = sorted([(-p, t) for t, p in tools.items() if t not in disabled])
   177     uimerge = ui.config("ui", "merge")
   190     uimerge = ui.config("ui", "merge")
   178     if uimerge:
   191     if uimerge:
   179         if uimerge not in names:
   192         # external tools defined in uimerge won't be able to handle
       
   193         # change/delete conflicts
       
   194         if uimerge not in names and not changedelete:
   180             return (uimerge, uimerge)
   195             return (uimerge, uimerge)
   181         tools.insert(0, (None, uimerge)) # highest priority
   196         tools.insert(0, (None, uimerge)) # highest priority
   182     tools.append((None, "hgmerge")) # the old default, if found
   197     tools.append((None, "hgmerge")) # the old default, if found
   183     for p, t in tools:
   198     for p, t in tools:
   184         if check(t, None, symlink, binary):
   199         if check(t, None, symlink, binary, changedelete):
   185             toolpath = _findtool(ui, t)
   200             toolpath = _findtool(ui, t)
   186             return (t, util.shellquote(toolpath))
   201             return (t, util.shellquote(toolpath))
   187 
   202 
   188     # internal merge or prompt as last resort
   203     # internal merge or prompt as last resort
   189     if symlink or binary:
   204     if symlink or binary or changedelete:
   190         return ":prompt", None
   205         return ":prompt", None
   191     return ":merge", None
   206     return ":merge", None
   192 
   207 
   193 def _eoltype(data):
   208 def _eoltype(data):
   194     "Guess the EOL type of a file"
   209     "Guess the EOL type of a file"
   533 
   548 
   534     ui = repo.ui
   549     ui = repo.ui
   535     fd = fcd.path()
   550     fd = fcd.path()
   536     binary = fcd.isbinary() or fco.isbinary() or fca.isbinary()
   551     binary = fcd.isbinary() or fco.isbinary() or fca.isbinary()
   537     symlink = 'l' in fcd.flags() + fco.flags()
   552     symlink = 'l' in fcd.flags() + fco.flags()
   538     tool, toolpath = _picktool(repo, ui, fd, binary, symlink)
   553     changedelete = fcd.isabsent() or fco.isabsent()
       
   554     tool, toolpath = _picktool(repo, ui, fd, binary, symlink, changedelete)
   539     if tool in internals and tool.startswith('internal:'):
   555     if tool in internals and tool.startswith('internal:'):
   540         # normalize to new-style names (':merge' etc)
   556         # normalize to new-style names (':merge' etc)
   541         tool = tool[len('internal'):]
   557         tool = tool[len('internal'):]
   542     ui.debug("picked tool '%s' for %s (binary %s symlink %s)\n" %
   558     ui.debug("picked tool '%s' for %s (binary %s symlink %s)\n" %
   543                (tool, fd, binary, symlink))
   559                (tool, fd, binary, symlink))