--- a/hgext/mq.py Sat Feb 07 18:46:13 2009 +0100
+++ b/hgext/mq.py Sat Feb 07 23:29:12 2009 +0100
@@ -1737,7 +1737,10 @@
if dest is None:
dest = hg.defaultdest(source)
sr = hg.repository(ui, ui.expandpath(source))
- patchespath = opts['patches'] or patchdir(sr)
+ if opts['patches']:
+ patchespath = ui.expandpath(opts['patches'])
+ else:
+ patchespath = patchdir(sr)
try:
pr = hg.repository(ui, patchespath)
except error.RepoError:
--- a/mercurial/commands.py Sat Feb 07 18:46:13 2009 +0100
+++ b/mercurial/commands.py Sat Feb 07 23:29:12 2009 +0100
@@ -645,6 +645,9 @@
elif ui.verbose:
ui.write(_('committed changeset %d:%s\n') % (rev,short(node)))
+ ms = merge_.mergestate(repo)
+ ms.reset(node)
+
def copy(ui, repo, *pats, **opts):
"""mark files as copied for the next commit
--- a/mercurial/dispatch.py Sat Feb 07 18:46:13 2009 +0100
+++ b/mercurial/dispatch.py Sat Feb 07 23:29:12 2009 +0100
@@ -354,6 +354,8 @@
" here (.hg not found)"))
raise
args.insert(0, repo)
+ elif rpath:
+ ui.warn("warning: --repository ignored\n")
d = lambda: util.checksignature(func)(ui, *args, **cmdoptions)
--- a/mercurial/localrepo.py Sat Feb 07 18:46:13 2009 +0100
+++ b/mercurial/localrepo.py Sat Feb 07 23:29:12 2009 +0100
@@ -852,8 +852,6 @@
user = wctx.user()
text = wctx.description()
- if branchname == 'default' and extra.get('close'):
- raise util.Abort(_('closing the default branch is invalid'))
p1, p2 = [p.node() for p in wctx.parents()]
c1 = self.changelog.read(p1)
c2 = self.changelog.read(p2)
--- a/mercurial/patch.py Sat Feb 07 18:46:13 2009 +0100
+++ b/mercurial/patch.py Sat Feb 07 23:29:12 2009 +0100
@@ -1137,7 +1137,7 @@
try:
return internalpatch(patchname, ui, strip, cwd, files)
except NoHunks:
- patcher = util.find_exe('gpatch') or util.find_exe('patch')
+ patcher = util.find_exe('gpatch') or util.find_exe('patch') or 'patch'
ui.debug(_('no valid hunks found; trying with %r instead\n') %
patcher)
if util.needbinarypatch():
--- a/mercurial/util.py Sat Feb 07 18:46:13 2009 +0100
+++ b/mercurial/util.py Sat Feb 07 23:29:12 2009 +0100
@@ -653,7 +653,7 @@
elif main_is_frozen():
set_hgexecutable(sys.executable)
else:
- set_hgexecutable(find_exe('hg', 'hg'))
+ set_hgexecutable(find_exe('hg') or 'hg')
return _hgexecutable
def set_hgexecutable(path):
@@ -1270,29 +1270,33 @@
def isowner(fp, st=None):
return True
- def find_in_path(name, path, default=None):
- '''find name in search path. path can be string (will be split
- with os.pathsep), or iterable thing that returns strings. if name
- found, return path to name. else return default. name is looked up
- using cmd.exe rules, using PATHEXT.'''
- if isinstance(path, str):
- path = path.split(os.pathsep)
-
+ def find_exe(command):
+ '''Find executable for command searching like cmd.exe does.
+ If command is a basename then PATH is searched for command.
+ PATH isn't searched if command is an absolute or relative path.
+ An extension from PATHEXT is found and added if not present.
+ If command isn't found None is returned.'''
pathext = os.environ.get('PATHEXT', '.COM;.EXE;.BAT;.CMD')
- pathext = pathext.lower().split(os.pathsep)
- isexec = os.path.splitext(name)[1].lower() in pathext
+ pathexts = [ext for ext in pathext.lower().split(os.pathsep)]
+ if os.path.splitext(command)[1].lower() in pathexts:
+ pathexts = ['']
+
+ def findexisting(pathcommand):
+ 'Will append extension (if needed) and return existing file'
+ for ext in pathexts:
+ executable = pathcommand + ext
+ if os.path.exists(executable):
+ return executable
+ return None
- for p in path:
- p_name = os.path.join(p, name)
-
- if isexec and os.path.exists(p_name):
- return p_name
-
- for ext in pathext:
- p_name_ext = p_name + ext
- if os.path.exists(p_name_ext):
- return p_name_ext
- return default
+ if os.sep in command:
+ return findexisting(command)
+
+ for path in os.environ.get('PATH', '').split(os.pathsep):
+ executable = findexisting(os.path.join(path, command))
+ if executable is not None:
+ return executable
+ return None
def set_signal_handler():
try:
@@ -1458,33 +1462,32 @@
st = fstat(fp)
return st.st_uid == os.getuid()
- def find_in_path(name, path, default=None):
- '''find name in search path. path can be string (will be split
- with os.pathsep), or iterable thing that returns strings. if name
- found, return path to name. else return default.'''
- if isinstance(path, str):
- path = path.split(os.pathsep)
- for p in path:
- p_name = os.path.join(p, name)
- if os.path.exists(p_name):
- return p_name
- return default
+ def find_exe(command):
+ '''Find executable for command searching like which does.
+ If command is a basename then PATH is searched for command.
+ PATH isn't searched if command is an absolute or relative path.
+ If command isn't found None is returned.'''
+ if sys.platform == 'OpenVMS':
+ return command
+
+ def findexisting(executable):
+ 'Will return executable if existing file'
+ if os.path.exists(executable):
+ return executable
+ return None
+
+ if os.sep in command:
+ return findexisting(command)
+
+ for path in os.environ.get('PATH', '').split(os.pathsep):
+ executable = findexisting(os.path.join(path, command))
+ if executable is not None:
+ return executable
+ return None
def set_signal_handler():
pass
-def find_exe(name, default=None):
- '''find path of an executable.
- if name contains a path component, return it as is. otherwise,
- use normal executable search path.'''
-
- if os.sep in name or sys.platform == 'OpenVMS':
- # don't check the executable bit. if the file isn't
- # executable, whoever tries to actually run it will give a
- # much more useful error message.
- return name
- return find_in_path(name, os.environ.get('PATH', ''), default=default)
-
def mktempcopy(name, emptyok=False, createmode=None):
"""Create a temporary file with the same contents from name
--- a/tests/run-tests.py Sat Feb 07 18:46:13 2009 +0100
+++ b/tests/run-tests.py Sat Feb 07 23:29:12 2009 +0100
@@ -465,7 +465,8 @@
os.environ['CDPATH'] = ''
TESTDIR = os.environ["TESTDIR"] = os.getcwd()
-HGTMP = os.environ['HGTMP'] = tempfile.mkdtemp('', 'hgtests.', options.tmpdir)
+HGTMP = os.environ['HGTMP'] = os.path.realpath(tempfile.mkdtemp('', 'hgtests.',
+ options.tmpdir))
DAEMON_PIDS = None
HGRCPATH = None
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-merge-tools Sat Feb 07 23:29:12 2009 +0100
@@ -0,0 +1,150 @@
+#!/bin/sh
+
+# test merge-tools configuration - mostly exercising filemerge.py
+
+unset HGMERGE # make sure HGMERGE doesn't interfere with the test
+
+hg init
+
+echo "# revision 0"
+echo "revision 0" > f
+echo "space" >> f
+hg commit -Am "revision 0" -d "1000000 0"
+
+echo "# revision 1"
+echo "revision 1" > f
+echo "space" >> f
+hg commit -Am "revision 1" -d "1000000 0"
+
+hg update 0 > /dev/null
+echo "# revision 2"
+echo "revision 2" > f
+echo "space" >> f
+hg commit -Am "revision 2" -d "1000000 0"
+
+hg update 0 > /dev/null
+echo "# revision 3 - simple to merge"
+echo "revision 3" >> f
+hg commit -Am "revision 3" -d "1000000 0"
+
+
+echo "[merge-tools]" > .hg/hgrc
+echo
+
+beforemerge() {
+ cat .hg/hgrc
+ echo "# hg update -C 1"
+ hg update -C 1 > /dev/null
+}
+
+aftermerge() {
+ echo "# cat f"
+ cat f
+ echo "# hg stat"
+ hg stat
+ rm -f f.orig
+ echo
+}
+
+domerge() {
+ beforemerge
+ echo "# hg merge $*"
+ hg merge $*
+ aftermerge
+}
+
+echo
+echo Tool selection
+echo
+
+echo "# default is internal merge:"
+domerge -r 2
+
+echo "# simplest hgrc using false for merge:"
+echo "false.whatever=" >> .hg/hgrc
+domerge -r 2
+
+echo "# true with higher .priority gets precedence:"
+echo "true.priority=1" >> .hg/hgrc
+domerge -r 2
+
+echo "# unless lowered on command line:"
+domerge -r 2 --config merge-tools.true.priority=-7
+
+echo "# or false set higher on command line:"
+domerge -r 2 --config merge-tools.false.priority=117
+
+echo "# or true.executable not found in PATH:"
+domerge -r 2 --config merge-tools.true.executable=nonexistingmergetool
+
+echo "# or true.executable with bogus path:"
+domerge -r 2 --config merge-tools.true.executable=/bin/nonexistingmergetool
+
+echo "# but true.executable set to cat found in PATH works:"
+echo "true.executable=cat" >> .hg/hgrc
+domerge -r 2
+
+echo "# and true.executable set to cat with path works:"
+domerge -r 2 --config merge-tools.true.executable=/bin/cat
+
+
+echo
+echo Tool selection and merge-patterns
+echo
+
+echo "# merge-patterns specifies new tool tac:"
+domerge -r 2 --config merge-patterns.f=tac
+
+echo "# merge-patterns specifies executable not found in PATH and gets warning:"
+domerge -r 2 --config merge-patterns.f=true --config merge-tools.true.executable=nonexistingmergetool
+
+echo "# merge-patterns specifies executable with bogus path and gets warning:"
+domerge -r 2 --config merge-patterns.f=true --config merge-tools.true.executable=/bin/nonexistingmergetool
+
+
+echo
+echo Premerge
+echo
+
+echo "# Default is silent simplemerge:"
+domerge -r 3
+
+echo "# .premerge=True is same:"
+domerge -r 3 --config merge-tools.true.premerge=True
+
+echo "# .premerge=False executes merge-tool:"
+domerge -r 3 --config merge-tools.true.premerge=False
+
+
+echo
+echo Tool execution
+echo
+
+echo '# set tools.args explicit to include $base $local $other $output:' # default '$local $base $other'
+beforemerge
+hg merge -r 2 --config merge-tools.true.executable=head --config merge-tools.true.args='$base $local $other $output' \
+ | sed 's,==> .* <==,==> ... <==,g'
+aftermerge
+
+echo '# Merge with "echo mergeresult > $local":'
+beforemerge
+hg merge -r 2 --config merge-tools.true.executable=echo --config merge-tools.true.args='mergeresult > $local'
+aftermerge
+
+echo '# - and $local is the file f:'
+beforemerge
+hg merge -r 2 --config merge-tools.true.executable=echo --config merge-tools.true.args='mergeresult > f'
+aftermerge
+
+echo '# Merge with "echo mergeresult > $output" - the variable is a bit magic:'
+beforemerge
+hg merge -r 2 --config merge-tools.true.executable=echo --config merge-tools.true.args='mergeresult > $output'
+aftermerge
+
+
+echo
+echo Merge post-processing
+echo
+
+echo "# cat is a bad merge-tool and doesn't change:"
+domerge -r 2 --config merge-tools.true.checkchanged=1
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-merge-tools.out Sat Feb 07 23:29:12 2009 +0100
@@ -0,0 +1,399 @@
+# revision 0
+adding f
+# revision 1
+# revision 2
+created new head
+# revision 3 - simple to merge
+created new head
+
+
+Tool selection
+
+# default is internal merge:
+[merge-tools]
+# hg update -C 1
+# hg merge -r 2
+merging f
+warning: conflicts during merge.
+merging f failed!
+0 files updated, 0 files merged, 0 files removed, 1 files unresolved
+use 'hg resolve' to retry unresolved file merges
+# cat f
+<<<<<<< local
+revision 1
+=======
+revision 2
+>>>>>>> other
+space
+# hg stat
+M f
+? f.orig
+
+# simplest hgrc using false for merge:
+[merge-tools]
+false.whatever=
+# hg update -C 1
+# hg merge -r 2
+merging f
+merging f failed!
+0 files updated, 0 files merged, 0 files removed, 1 files unresolved
+use 'hg resolve' to retry unresolved file merges
+# cat f
+revision 1
+space
+# hg stat
+M f
+? f.orig
+
+# true with higher .priority gets precedence:
+[merge-tools]
+false.whatever=
+true.priority=1
+# hg update -C 1
+# hg merge -r 2
+merging f
+0 files updated, 1 files merged, 0 files removed, 0 files unresolved
+(branch merge, don't forget to commit)
+# cat f
+revision 1
+space
+# hg stat
+M f
+
+# unless lowered on command line:
+[merge-tools]
+false.whatever=
+true.priority=1
+# hg update -C 1
+# hg merge -r 2 --config merge-tools.true.priority=-7
+merging f
+merging f failed!
+0 files updated, 0 files merged, 0 files removed, 1 files unresolved
+use 'hg resolve' to retry unresolved file merges
+# cat f
+revision 1
+space
+# hg stat
+M f
+? f.orig
+
+# or false set higher on command line:
+[merge-tools]
+false.whatever=
+true.priority=1
+# hg update -C 1
+# hg merge -r 2 --config merge-tools.false.priority=117
+merging f
+merging f failed!
+0 files updated, 0 files merged, 0 files removed, 1 files unresolved
+use 'hg resolve' to retry unresolved file merges
+# cat f
+revision 1
+space
+# hg stat
+M f
+? f.orig
+
+# or true.executable not found in PATH:
+[merge-tools]
+false.whatever=
+true.priority=1
+# hg update -C 1
+# hg merge -r 2 --config merge-tools.true.executable=nonexistingmergetool
+merging f
+merging f failed!
+0 files updated, 0 files merged, 0 files removed, 1 files unresolved
+use 'hg resolve' to retry unresolved file merges
+# cat f
+revision 1
+space
+# hg stat
+M f
+? f.orig
+
+# or true.executable with bogus path:
+[merge-tools]
+false.whatever=
+true.priority=1
+# hg update -C 1
+# hg merge -r 2 --config merge-tools.true.executable=/bin/nonexistingmergetool
+merging f
+merging f failed!
+0 files updated, 0 files merged, 0 files removed, 1 files unresolved
+use 'hg resolve' to retry unresolved file merges
+# cat f
+revision 1
+space
+# hg stat
+M f
+? f.orig
+
+# but true.executable set to cat found in PATH works:
+[merge-tools]
+false.whatever=
+true.priority=1
+true.executable=cat
+# hg update -C 1
+# hg merge -r 2
+revision 1
+space
+revision 0
+space
+revision 2
+space
+merging f
+0 files updated, 1 files merged, 0 files removed, 0 files unresolved
+(branch merge, don't forget to commit)
+# cat f
+revision 1
+space
+# hg stat
+M f
+
+# and true.executable set to cat with path works:
+[merge-tools]
+false.whatever=
+true.priority=1
+true.executable=cat
+# hg update -C 1
+# hg merge -r 2 --config merge-tools.true.executable=/bin/cat
+revision 1
+space
+revision 0
+space
+revision 2
+space
+merging f
+0 files updated, 1 files merged, 0 files removed, 0 files unresolved
+(branch merge, don't forget to commit)
+# cat f
+revision 1
+space
+# hg stat
+M f
+
+
+Tool selection and merge-patterns
+
+# merge-patterns specifies new tool tac:
+[merge-tools]
+false.whatever=
+true.priority=1
+true.executable=cat
+# hg update -C 1
+# hg merge -r 2 --config merge-patterns.f=tac
+space
+revision 1
+space
+revision 0
+space
+revision 2
+merging f
+0 files updated, 1 files merged, 0 files removed, 0 files unresolved
+(branch merge, don't forget to commit)
+# cat f
+revision 1
+space
+# hg stat
+M f
+
+# merge-patterns specifies executable not found in PATH and gets warning:
+[merge-tools]
+false.whatever=
+true.priority=1
+true.executable=cat
+# hg update -C 1
+# hg merge -r 2 --config merge-patterns.f=true --config merge-tools.true.executable=nonexistingmergetool
+couldn't find merge tool true specified for f
+merging f
+merging f failed!
+0 files updated, 0 files merged, 0 files removed, 1 files unresolved
+use 'hg resolve' to retry unresolved file merges
+# cat f
+revision 1
+space
+# hg stat
+M f
+? f.orig
+
+# merge-patterns specifies executable with bogus path and gets warning:
+[merge-tools]
+false.whatever=
+true.priority=1
+true.executable=cat
+# hg update -C 1
+# hg merge -r 2 --config merge-patterns.f=true --config merge-tools.true.executable=/bin/nonexistingmergetool
+couldn't find merge tool true specified for f
+merging f
+merging f failed!
+0 files updated, 0 files merged, 0 files removed, 1 files unresolved
+use 'hg resolve' to retry unresolved file merges
+# cat f
+revision 1
+space
+# hg stat
+M f
+? f.orig
+
+
+Premerge
+
+# Default is silent simplemerge:
+[merge-tools]
+false.whatever=
+true.priority=1
+true.executable=cat
+# hg update -C 1
+# hg merge -r 3
+merging f
+0 files updated, 1 files merged, 0 files removed, 0 files unresolved
+(branch merge, don't forget to commit)
+# cat f
+revision 1
+space
+revision 3
+# hg stat
+M f
+
+# .premerge=True is same:
+[merge-tools]
+false.whatever=
+true.priority=1
+true.executable=cat
+# hg update -C 1
+# hg merge -r 3 --config merge-tools.true.premerge=True
+merging f
+0 files updated, 1 files merged, 0 files removed, 0 files unresolved
+(branch merge, don't forget to commit)
+# cat f
+revision 1
+space
+revision 3
+# hg stat
+M f
+
+# .premerge=False executes merge-tool:
+[merge-tools]
+false.whatever=
+true.priority=1
+true.executable=cat
+# hg update -C 1
+# hg merge -r 3 --config merge-tools.true.premerge=False
+revision 1
+space
+revision 0
+space
+revision 0
+space
+revision 3
+merging f
+0 files updated, 1 files merged, 0 files removed, 0 files unresolved
+(branch merge, don't forget to commit)
+# cat f
+revision 1
+space
+# hg stat
+M f
+
+
+Tool execution
+
+# set tools.args explicit to include $base $local $other $output:
+[merge-tools]
+false.whatever=
+true.priority=1
+true.executable=cat
+# hg update -C 1
+==> ... <==
+revision 0
+space
+
+==> ... <==
+revision 1
+space
+
+==> ... <==
+revision 2
+space
+
+==> ... <==
+revision 1
+space
+merging f
+0 files updated, 1 files merged, 0 files removed, 0 files unresolved
+(branch merge, don't forget to commit)
+# cat f
+revision 1
+space
+# hg stat
+M f
+
+# Merge with "echo mergeresult > $local":
+[merge-tools]
+false.whatever=
+true.priority=1
+true.executable=cat
+# hg update -C 1
+merging f
+0 files updated, 1 files merged, 0 files removed, 0 files unresolved
+(branch merge, don't forget to commit)
+# cat f
+mergeresult
+# hg stat
+M f
+
+# - and $local is the file f:
+[merge-tools]
+false.whatever=
+true.priority=1
+true.executable=cat
+# hg update -C 1
+merging f
+0 files updated, 1 files merged, 0 files removed, 0 files unresolved
+(branch merge, don't forget to commit)
+# cat f
+mergeresult
+# hg stat
+M f
+
+# Merge with "echo mergeresult > $output" - the variable is a bit magic:
+[merge-tools]
+false.whatever=
+true.priority=1
+true.executable=cat
+# hg update -C 1
+merging f
+0 files updated, 1 files merged, 0 files removed, 0 files unresolved
+(branch merge, don't forget to commit)
+# cat f
+mergeresult
+# hg stat
+M f
+
+
+Merge post-processing
+
+# cat is a bad merge-tool and doesn't change:
+[merge-tools]
+false.whatever=
+true.priority=1
+true.executable=cat
+# hg update -C 1
+# hg merge -r 2 --config merge-tools.true.checkchanged=1
+revision 1
+space
+revision 0
+space
+revision 2
+space
+merging f
+merging f failed!
+0 files updated, 0 files merged, 0 files removed, 1 files unresolved
+use 'hg resolve' to retry unresolved file merges
+# cat f
+revision 1
+space
+# hg stat
+M f
+? f.orig
+
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-resolve Sat Feb 07 23:29:12 2009 +0100
@@ -0,0 +1,27 @@
+#!/bin/sh
+
+# test that a commit clears the merge state.
+
+hg init repo
+cd repo
+
+echo foo > file
+hg commit -Am 'add file' -d '0 0'
+
+echo bar >> file
+hg commit -Am 'append bar' -d '0 0'
+
+echo % create a second head
+hg up -C 0
+echo baz >> file
+hg commit -Am 'append baz' -d '0 0'
+
+echo % failing merge
+HGMERGE=internal:fail hg merge
+
+echo resolved > file
+hg resolve -m file
+hg commit -m 'resolved' -d '0 0'
+
+echo % resolve -l, should be empty
+hg resolve -l
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-resolve.out Sat Feb 07 23:29:12 2009 +0100
@@ -0,0 +1,8 @@
+adding file
+% create a second head
+1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+created new head
+% failing merge
+0 files updated, 0 files merged, 0 files removed, 1 files unresolved
+use 'hg resolve' to retry unresolved file merges
+% resolve -l, should be empty