def _picktool()

in eden/scm/edenscm/mercurial/filemerge.py [0:0]


def _picktool(repo, ui, path, binary, symlink, changedelete):
    def supportscd(tool):
        return tool in internals and internals[tool].mergetype == nomerge

    def check(tool, pat, symlink, binary, changedelete):
        tmsg = tool
        if pat:
            tmsg = _("%s (for pattern %s)") % (tool, pat)
        if not _findtool(ui, repo, tool):
            if pat:  # explicitly requested tool deserves a warning
                ui.warn(_("couldn't find merge tool %s\n") % tmsg)
            else:  # configured but non-existing tools are more silent
                ui.note(_("couldn't find merge tool %s\n") % tmsg)
        elif symlink and not _toolbool(ui, tool, "symlink"):
            ui.warn(_("tool %s can't handle symlinks\n") % tmsg)
        elif binary and not _toolbool(ui, tool, "binary"):
            ui.warn(_("tool %s can't handle binary\n") % tmsg)
        elif changedelete and not supportscd(tool):
            # the nomerge tools are the only tools that support change/delete
            # conflicts
            pass
        elif not util.gui() and _toolbool(ui, tool, "gui"):
            ui.warn(_("tool %s requires a GUI\n") % tmsg)
        else:
            return True
        return False

    # internal config: ui.forcemerge
    # forcemerge comes from command line arguments, highest priority
    force = ui.config("ui", "forcemerge")
    if force:
        toolpath = _findtool(ui, repo, force)
        if changedelete and not supportscd(toolpath):
            ui.debug("picktool() forcemerge :prompt\n")
            return ":prompt", None
        else:
            if toolpath:
                ui.debug("picktool() forcemerge toolpath %s\n" % toolpath)
                return (force, util.shellquote(toolpath))
            else:
                # mimic HGMERGE if given tool not found
                ui.debug("picktool() forcemerge toolpath not found %s\n" % force)
                return (force, force)

    # HGMERGE takes next precedence
    hgmerge = encoding.environ.get("HGMERGE")
    if hgmerge:
        if changedelete and not supportscd(hgmerge):
            ui.debug("picktool() hgmerge :prompt %s\n" % hgmerge)
            return ":prompt", None
        else:
            ui.debug("picktool() hgmerge %s\n" % hgmerge)
            return (hgmerge, hgmerge)

    # then patterns
    for pat, tool in ui.configitems("merge-patterns"):
        mf = match.match(repo.root, "", [pat])
        if mf(path) and check(tool, pat, symlink, False, changedelete):
            toolpath = _findtool(ui, repo, tool)
            ui.debug("picktool() merge-patterns tool=%s pat=%s\n" % (toolpath, pat))
            return (tool, util.shellquote(toolpath))

    # then merge tools
    tools = {}
    disabled = set()
    for k, v in ui.configitems("merge-tools"):
        t = k.split(".")[0]
        if t not in tools:
            tools[t] = int(_toolstr(ui, t, "priority"))
        if _toolbool(ui, t, "disabled"):
            disabled.add(t)
    names = tools.keys()
    tools = sorted([(-p, tool) for tool, p in tools.items() if tool not in disabled])
    plain = ui.plain(feature="mergetool")
    interactive = ui.interactive() and not plain
    ui.debug("picktool() interactive=%s plain=%s\n" % (ui.interactive(), plain))
    uimerge = None
    if interactive:
        uimerge = ui.config("ui", "merge:interactive")
    if not uimerge:
        uimerge = ui.config("ui", "merge")
    if uimerge:
        # external tools defined in uimerge won't be able to handle
        # change/delete conflicts
        if uimerge not in names and not changedelete:
            ui.debug(
                "picktool() uimerge merge:interactive=%s merge=%s\n"
                % (ui.config("ui", "merge:interactive"), ui.config("ui", "merge"))
            )
            return (uimerge, uimerge)
        tools.insert(0, (None, uimerge))  # highest priority
    tools.append((None, "hgmerge"))  # the old default, if found
    for p, t in tools:
        if check(t, None, symlink, binary, changedelete):
            toolpath = _findtool(ui, repo, t)
            ui.debug("picktool() tools\n")
            return (t, util.shellquote(toolpath))

    # internal merge or prompt as last resort
    if symlink or binary or changedelete:
        if not changedelete and len(tools):
            # any tool is rejected by capability for symlink or binary
            ui.warn(_("no tool found to merge %s\n") % path)
        return ":prompt", None
    ui.debug("picktool() :merge\n")
    return ":merge", None