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