contrib/simplemerge
author Anton Shestakov <av6@dwimlabs.net>
Sat, 15 Jan 2022 09:08:41 +0300
changeset 48689 fbf7e383e961
parent 48578 77e24ee8994b
child 48749 9ee70e175fed
permissions -rw-r--r--
destutil: if wdp is obsolete, update to the closest non-obsolete ancestor As the original comments suggest, using prune as a model here was an existing idea, and now this patch implements it. I think it would be even better to do what solveobswdp() from evolve does (in short, it allows to update to a successor of the closest ancestor even if that ancestor is obsolete), but that is outside of this series' scope. Differential Revision: https://phab.mercurial-scm.org/D12099

#!/usr/bin/env python3
from __future__ import absolute_import

import getopt
import sys

import hgdemandimport

hgdemandimport.enable()

from mercurial.i18n import _
from mercurial import (
    context,
    error,
    fancyopts,
    pycompat,
    simplemerge,
    ui as uimod,
)
from mercurial.utils import procutil, stringutil

options = [
    (b'L', b'label', [], _(b'labels to use on conflict markers')),
    (b'a', b'text', None, _(b'treat all files as text')),
    (b'p', b'print', None, _(b'print results instead of overwriting LOCAL')),
    (b'', b'no-minimal', None, _(b'no effect (DEPRECATED)')),
    (b'h', b'help', None, _(b'display help and exit')),
    (b'q', b'quiet', None, _(b'suppress output')),
]

usage = _(
    b'''simplemerge [OPTS] LOCAL BASE OTHER

    Simple three-way file merge utility with a minimal feature set.

    Apply to LOCAL the changes necessary to go from BASE to OTHER.

    By default, LOCAL is overwritten with the results of this operation.
'''
)


class ParseError(Exception):
    """Exception raised on errors in parsing the command line."""


def showhelp():
    procutil.stdout.write(usage)
    procutil.stdout.write(b'\noptions:\n')

    out_opts = []
    for shortopt, longopt, default, desc in options:
        out_opts.append(
            (
                b'%2s%s'
                % (
                    shortopt and b'-%s' % shortopt,
                    longopt and b' --%s' % longopt,
                ),
                b'%s' % desc,
            )
        )
    opts_len = max([len(opt[0]) for opt in out_opts])
    for first, second in out_opts:
        procutil.stdout.write(b' %-*s  %s\n' % (opts_len, first, second))


try:
    for fp in (sys.stdin, procutil.stdout, sys.stderr):
        procutil.setbinary(fp)

    opts = {}
    try:
        bargv = [a.encode('utf8') for a in sys.argv[1:]]
        args = fancyopts.fancyopts(bargv, options, opts)
    except getopt.GetoptError as e:
        raise ParseError(e)
    if opts[b'help']:
        showhelp()
        sys.exit(0)
    if len(args) != 3:
        raise ParseError(_(b'wrong number of arguments').decode('utf8'))
    if len(opts[b'label']) > 2:
        opts[b'mode'] = b'merge3'
    local, base, other = args
    overrides = opts[b'label']
    if len(overrides) > 3:
        raise error.InputError(b'can only specify three labels.')
    labels = [local, other, base]
    labels[: len(overrides)] = overrides
    local_input = simplemerge.MergeInput(
        context.arbitraryfilectx(local), labels[0]
    )
    other_input = simplemerge.MergeInput(
        context.arbitraryfilectx(other), labels[1]
    )
    base_input = simplemerge.MergeInput(
        context.arbitraryfilectx(base), labels[2]
    )
    sys.exit(
        simplemerge.simplemerge(
            uimod.ui.load(),
            local_input,
            base_input,
            other_input,
            **pycompat.strkwargs(opts)
        )
    )
except ParseError as e:
    e = stringutil.forcebytestr(e)
    procutil.stdout.write(b"%s: %s\n" % (sys.argv[0].encode('utf8'), e))
    showhelp()
    sys.exit(1)
except error.Abort as e:
    procutil.stderr.write(b"abort: %s\n" % e)
    sys.exit(255)
except KeyboardInterrupt:
    sys.exit(255)