def resolve()

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


def resolve(ui, repo, *pats, **opts):
    """redo merges or set/view the merge status of files

    Merges with unresolved conflicts are often the result of
    non-interactive merging using the ``internal:merge`` configuration
    setting, or a command-line merge tool like ``diff3``. The resolve
    command is used to manage the files involved in a merge, after
    :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
    working directory must have two parents). See :hg:`help
    merge-tools` for information on configuring merge tools.

    The resolve command can be used in the following ways:

    - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
      files, discarding any previous merge attempts. Re-merging is not
      performed for files already marked as resolved. Use ``--all/-a``
      to select all unresolved files. ``--tool`` can be used to specify
      the merge tool used for the given files. It overrides the HGMERGE
      environment variable and your configuration files.  Previous file
      contents are saved with a ``.orig`` suffix.

    - :hg:`resolve -m [FILE]`: mark a file as having been resolved
      (e.g. after having manually fixed-up the files). The default is
      to mark all unresolved files.

    - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
      default is to mark all resolved files.

    - :hg:`resolve -l`: list files which had or still have conflicts.
      In the printed list, ``U`` = unresolved and ``R`` = resolved.
      You can use ``set:unresolved()`` or ``set:resolved()`` to filter
      the list. See :hg:`help filesets` for details.

    .. note::

       Mercurial will not let you commit files with unresolved merge
       conflicts. You must use :hg:`resolve -m ...` before you can
       commit after a conflicting merge.

    Returns 0 on success, 1 if any files fail a resolve attempt.
    """

    flaglist = "all mark unmark list no_status root_relative".split()
    all, mark, unmark, show, nostatus, rootrel = [opts.get(o) for o in flaglist]

    # Enable --root-relative by default if HGPLAIN is set, for compatibility.
    if rootrel is None and ui.plain():
        rootrel = True

    if (show and (mark or unmark)) or (mark and unmark):
        raise error.Abort(_("too many options specified"))
    if pats and all:
        raise error.Abort(_("can't specify --all and patterns"))
    if not (all or pats or show or mark or unmark):
        raise error.Abort(
            _("no files or directories specified"),
            hint=_("use --all to re-merge all unresolved files"),
        )

    if show:
        ui.pager("resolve")
        fm = ui.formatter("resolve", opts)
        ms = mergemod.mergestate.read(repo)
        m = scmutil.match(repo[None], pats, opts)

        # Labels and keys based on merge state.  Unresolved path conflicts show
        # as 'P'.  Resolved path conflicts show as 'R', the same as normal
        # resolved conflicts.
        mergestateinfo = {
            "u": ("resolve.unresolved", "U"),
            "r": ("resolve.resolved", "R"),
            "pu": ("resolve.unresolved", "P"),
            "pr": ("resolve.resolved", "R"),
            "d": ("resolve.driverresolved", "D"),
        }

        cwd = "" if rootrel else repo.getcwd()

        for f in ms:
            if not m(f):
                continue

            label, key = mergestateinfo[ms[f]]
            fm.startitem()
            fm.condwrite(not nostatus, "status", "%s ", key, label=label)
            # User-friendly paths
            f = repo.pathto(f, cwd)
            fm.write("path", "%s\n", f, label=label)
        fm.end()
        return 0

    with repo.wlock():
        ms = mergemod.mergestate.read(repo)

        if not (ms.active() or repo.dirstate.p2() != nullid):
            raise error.Abort(_("resolve command not applicable when not merging"))

        wctx = repo[None]

        if ms.mergedriver and ms.mdstate() == "u":
            proceed = mergemod.driverpreprocess(repo, ms, wctx)
            ms.commit()
            # allow mark and unmark to go through
            if not mark and not unmark and not proceed:
                return 1

        m = scmutil.match(wctx, pats, opts)
        ret = 0
        didwork = False
        runconclude = False

        tocomplete = []
        for f in ms:
            if not m(f):
                continue

            didwork = True

            # don't let driver-resolved files be marked, and run the conclude
            # step if asked to resolve
            if ms[f] == "d":
                exact = m.exact(f)
                if mark:
                    if exact:
                        ui.warn(_("not marking %s as it is driver-resolved\n") % f)
                elif unmark:
                    if exact:
                        ui.warn(_("not unmarking %s as it is driver-resolved\n") % f)
                else:
                    runconclude = True
                continue

            # path conflicts must be resolved manually
            if ms[f] in ("pu", "pr"):
                if mark:
                    ms.mark(f, "pr")
                elif unmark:
                    ms.mark(f, "pu")
                elif ms[f] == "pu":
                    ui.warn(_("%s: path conflict must be resolved manually\n") % f)
                continue

            if mark:
                ms.mark(f, "r")
            elif unmark:
                ms.mark(f, "u")
            else:
                # backup pre-resolve (merge uses .orig for its own purposes)
                a = repo.wjoin(f)
                try:
                    util.copyfile(a, a + ".resolve")
                except (IOError, OSError) as inst:
                    if inst.errno != errno.ENOENT:
                        raise

                try:
                    # preresolve file
                    ui.setconfig("ui", "forcemerge", opts.get("tool", ""), "resolve")
                    complete, r = ms.preresolve(f, wctx)
                    if not complete:
                        tocomplete.append(f)
                    elif r:
                        ret = 1
                finally:
                    ui.setconfig("ui", "forcemerge", "", "resolve")
                    ms.commit()

                # replace filemerge's .orig file with our resolve file, but only
                # for merges that are complete
                if complete:
                    try:
                        util.rename(a + ".resolve", scmutil.origpath(ui, repo, a))
                    except OSError as inst:
                        if inst.errno != errno.ENOENT:
                            raise

        for f in tocomplete:
            try:
                # resolve file
                ui.setconfig("ui", "forcemerge", opts.get("tool", ""), "resolve")
                r = ms.resolve(f, wctx)
                if r:
                    ret = 1
            finally:
                ui.setconfig("ui", "forcemerge", "", "resolve")
                ms.commit()

            # replace filemerge's .orig file with our resolve file
            a = repo.wjoin(f)
            try:
                util.rename(a + ".resolve", scmutil.origpath(ui, repo, a))
            except OSError as inst:
                if inst.errno != errno.ENOENT:
                    raise

        ms.commit()
        ms.recordactions()

        if not didwork and pats:
            hint = None
            if not any([p for p in pats if p.find(":") >= 0]):
                pats = ["path:%s" % p for p in pats]
                m = scmutil.match(wctx, pats, opts)
                for f in ms:
                    if not m(f):
                        continue
                    flags = "".join(["-%s " % o[0] for o in flaglist if opts.get(o)])
                    hint = _("(try: hg resolve %s%s)\n") % (flags, " ".join(pats))
                    break
            ui.warn(_("arguments do not match paths that need resolving\n"))
            if hint:
                ui.warn(hint)
        elif ms.mergedriver and ms.mdstate() != "s":
            # run conclude step when either a driver-resolved file is requested
            # or there are no driver-resolved files
            # we can't use 'ret' to determine whether any files are unresolved
            # because we might not have tried to resolve some
            if (runconclude or not list(ms.driverresolved())) and not list(
                ms.unresolved()
            ):
                proceed = mergemod.driverconclude(repo, ms, wctx)
                ms.commit()
                ms.recordactions()
                if not proceed:
                    return 1

    # Nudge users into finishing an unfinished operation
    unresolvedf = list(ms.unresolved())
    driverresolvedf = list(ms.driverresolved())
    if not unresolvedf and not driverresolvedf:
        ui.status(_("(no more unresolved files)\n"))
        cmdutil.checkafterresolved(repo)
    elif not unresolvedf:
        ui.status(
            _("(no more unresolved files -- " 'run "hg resolve --all" to conclude)\n')
        )

    return ret