[PATCH 1 of 4] hgmerge: add new hgmerge package under mercurial
Matt Mackall
mpm at selenic.com
Tue Jan 8 11:49:20 CST 2008
On Mon, 2008-01-07 at 15:20 -0600, Steve Borho wrote:
> # HG changeset patch
> # User Steve Borho <steve at borho.org>
> # Date 1199739435 21600
> # Node ID 1dabe5c4867c4f1d855494ecd0f76d6436882c6e
> # Parent 3ef279074c77c3cf3f6b35f0f73dee2fdba5aa41
> hgmerge: add new hgmerge package under mercurial
>
> diff --git a/mercurial/hgmerge/README.txt b/mercurial/hgmerge/README.txt
> new file mode 100644
> --- /dev/null
> +++ b/mercurial/hgmerge/README.txt
> @@ -0,0 +1,96 @@
> +Cross-platform merging for Mercurial.
> +
> +The purpose of hgmerge is to provide a file revision merging interface, with
> +good default behavior and user configurability. It is the default merge
> +behavior for Mercurial when HGMERGE is not set in your environmant and ui.merge
> +is not set in your hgrc file(s).
> +
> +When unconfigured, hgmerge will attempt to perform a 3-way merge using an
> +included simplemerge script that runs without user interaction. If no conflicts
> +are found, the merge is successful. When conflicts are found, hgmerge will
> +search for interactive 3-way merge tools on your computer and use the first one
> +it finds. If no tools are detected (or if requested tool is not found), the
> +partially merged file with conflict markers is left in the working directory to
> +be resolved manually. Note that Mercurial does not track 'conflict' file
> +status, so users have to be diligent to not check in partially merged files.
> +
> +The 'hg debuginstall' command will report the list of plug-ins that are detected
> +on your machine.
> +
> +By adding entries in their hgrc files, users can:
> +* completely override the search by specifying a default plug-in
> +* specify plugins to use for specific file extensions
> +* modify the built-in plug-ins (override characteristics)
> +* define search precedence for plug-ins
> +* define entirely new plug-ins.
> +
> +Hgmerge defines two new hgrc sections. [hgmerge] is used to define default and
> +file extension based plug-ins. [hgmerge-plugins] is used to configure built-in
> +plugins and to define entirely new plugins.
> +
> +Example hgmerge section:
> +[hgmerge]
> +default = kdiff3
> +ext.png = mypngmerge
> +ext.lib = takemine
> +
> +When a file extension plug-in is specified (e.g., .png), hgmerge will bypass the
> +initial simplemerge step and directly call the specified plug-in. This is
> +useful for e.g. binary formats that cannot be merged as text. There are two
> +special plug-ins intended for file extension use: 'takemine' and 'takeother'
> +(with predictable behaviors). These two will not show up in the list of
> +installed plug-ins but are always available.
> +
> +Note that unless the plug-in was selected by a file extension match, hgmerge
> +will specially handle file types which are unmergeable by most merge tools
> +(symlinks, binary files, etc). Unmergeable files bypass the entire simplemerge
> +and plugin architecture and instead the user will be asked to chose between the
> +'local' and 'other' versions of the file.
> +
> +Plug-In Configuration
> +=====================
> +Merge plug-ins can be configured through Mercurial's configuration system
> +(hgrc). One may modify existing plug-ins or define new ones. Plug-in
> +configurations exist in the section [hgmerge-plugins].
> +
> +Plug-ins can be of one of two types: tool and custom. The default type is tool.
> +
> +Tool Plug-Ins
> +-------------
> +A tool definition represents an external program and parameters for running
> +that, such as its arguments. The argument line can contain variables, the
> +following are supported: $base, $local, $other, $output.
> +
> +The following options can be set for a tool:
> + executable: Either just the name of the executable or its pathname. Per
> + default the same as the plug-in's name.
> + arguments: The arguments to pass to the tool (default: $base $local $other
> + $output)
> + priority: The priority in which to evaluate this plug-in.
> + stdout: Should the tool's standard output be used as the merge result?
> + check_conflicts: Check whether there are conflicts even though the tool
> + reported none?
> + win.regpath_installdir: Specify a pathname in the Windows registry defining
> + the tool's installation directory. The format of this option is like this:
> + <key name>\<value name>. If the key itself actually holds the value, end
> + the pathname with a backslash, so it's clear there is no value name
> + component.
> + win.regpath_installpath: Like the former, except that the registry value
> + is taken to specify the installation path of the tool's executable.
> +
> +Example tool configuration:
> +[hgmerge-plugins]
> +gvimdiff.type = tool
> +gvimdiff.arguments = --nofork -d -g -O $output $other $base
> +gvimdiff.priority = 1
> +gvimdiff.win.regpath_installpath = Software\Vim\GVim\path
> +kdiff3.executable = ~/bin/kdiff3 # override built in plug-in value
> +
> +Note that the plugin type defaults to tool and can be left unspecified, and the
> +priority defaults to 0 (higher priority tools are detected first).
> +
> +Custom Plug-Ins
> +---------------
> +A "custom" plug-in is defined by a Python class. TODO ...
> +
> +# vim: textwidth=80
> diff --git a/mercurial/hgmerge/TODO.txt b/mercurial/hgmerge/TODO.txt
> new file mode 100644
> --- /dev/null
> +++ b/mercurial/hgmerge/TODO.txt
> @@ -0,0 +1,5 @@
> +* Allow user to turn off automatic invocation of merge tool
> +* Port tests to standard Mercurial system
> +
> +MacOS - needs wrappers for more OSX tools
> + - needs testing
Let's not have a TODO file. I'd prefer not to have a separate directory
too, but let's see..
> diff --git a/mercurial/hgmerge/__init__.py b/mercurial/hgmerge/__init__.py
> new file mode 100644
> --- /dev/null
> +++ b/mercurial/hgmerge/__init__.py
> @@ -0,0 +1,544 @@
> +# -*- coding: utf-8 -*-
> +""" Logic for merging changes in two versions of a file.
> + at var stockplugins: Sequence of stock plug-in representations.
> +"""
> +import shutil
> +import StringIO
> +import filecmp
> +import random
> +import traceback
> +
> +from mercurial.hgmerge._common import *
> +import mercurial.util as hgutil
> +import _simplemerge
> +import _plugins as hgmergeplugs
> +import _pluginapi as hgpluginapi
> +
> +stockplugins = hgmergeplugs.plugins
> +
> +# Initially not defined
> +plugins = None
> +
> +class filedesc(object):
> + ''' Describe properties of a file.
> + @ivar name: The file's name.
> + @ivar islink: Is the file a symlink?
> + '''
I detect design overkill.
> +class _pluginopts(object):
> + ''' Plug-in options handler baseclass.
> + '''
> + def __init__(self, ui, sectname, name):
> + self.attrs = {}
> + self.__ui, self.__sect, self.__name = ui, sectname, name
> + self._set_int('priority', default=0)
> +
> + def _set_string(self, prop, **kwds):
> + self._set_opt(prop, self.__ui.config, **kwds)
> +
> + def _set_bool(self, prop, **kwds):
> + self._set_opt(prop, self.__ui.configbool, **kwds)
Yes, looks like someone's a Java fan.
This code is about 5 times as long as it needs to be. Needs a few rounds
of simplifying.
> +def _is_mergeable(base, local, other):
> + ''' Are the files mergeable?
> + @return: Success?
> + '''
> + mergetypes = ('dos', 'unix', 'mac')
> +
> + for eoltp in (local.eoltype, other.eoltype, base.eoltype):
> + if eoltp not in mergetypes:
> + return False
Hmmm. Don't really like this. Does it apply to user-defined tools?
> +def _readfile(fname):
> + f = file(fname, 'rb')
> + try: data = f.read()
> + finally: f.close()
> + return data
This function should be taken out and shot.
> +
> +def _ask_unmergeable(ui, local, other, output):
> + ''' File is not mergeable, ask user which version to keep.
> + @return: Success?
> + '''
> + def _describe(fdesc):
> + '''Describe a file to the user'''
> + if not fdesc.islink:
> + eoltp = fdesc.eoltype
> + if eoltp in ('dos', 'unix', 'mac'):
> + return 'is a %s style text file browsable here\n%s' % (
Browsable?
> +def eoltype(name):
> + ''' Get the EOL type for a file.
> + '''
util.py
> +def lookup_reg(path):
> + ''' Look up a path in the Windows registry.
> + @return: The value for the path if found, else None.
> + '''
util_win32.py
> +# -*- coding: utf-8 -*-s
No thanks.
> \ No newline at end of file
Oops.
> diff --git a/contrib/simplemerge b/mercurial/hgmerge/_simplemerge.py
> old mode 100755
> new mode 100644
> copy from contrib/simplemerge
> copy to mercurial/hgmerge/_simplemerge.py
I think we have tests that want to use this.
> --- /dev/null
> +++ b/mercurial/hgmerge/design.txt
> @@ -0,0 +1,26 @@
> +Hgmerge's design explained
Put this in a file docstring.
> +# vim: textwidth=80
No thanks.
--
Mathematics is the supreme nostalgia of our time.
More information about the Mercurial-devel
mailing list