changeset 2062:5460f0196f77

merge with crew.
author Vadim Gelfer <vadim.gelfer@gmail.com>
date Thu, 13 Apr 2006 12:44:40 -0700
parents 5987c1eac2ce (current diff) 676f5fd84a94 (diff)
children f1fda71e134e
files mercurial/dirstate.py
diffstat 27 files changed, 674 insertions(+), 228 deletions(-) [+]
line wrap: on
line diff
--- a/.hgtags	Fri Mar 31 17:00:09 2006 -0800
+++ b/.hgtags	Thu Apr 13 12:44:40 2006 -0700
@@ -9,3 +9,4 @@
 eac9c8efcd9bd8244e72fb6821f769f450457a32 0.6c
 979c049974485125e1f9357f6bbe9c1b548a64c3 0.7
 3a56574f329a368d645853e0f9e09472aee62349 0.8
+6a03cff2b0f5d30281e6addefe96b993582f2eac 0.8.1
--- a/MANIFEST.in	Fri Mar 31 17:00:09 2006 -0800
+++ b/MANIFEST.in	Thu Apr 13 12:44:40 2006 -0700
@@ -2,13 +2,13 @@
 recursive-include mercurial *.py
 include hgweb.cgi hgwebdir.cgi
 include hgeditor rewrite-log
-include tests/README tests/run-tests tests/test-*[a-z0-9] tests/*.out
+include tests/README tests/run-tests tests/md5sum.py tests/test-*[a-z0-9] tests/*.out
 prune tests/*.err
 include *.txt
 include templates/map templates/map-*[a-z0-9]
 include templates/*.tmpl
 include templates/static/*
-include doc/README doc/Makefile doc/*.txt doc/*.html doc/*.[0-9]
+include doc/README doc/Makefile doc/gendoc.py doc/*.txt doc/*.html doc/*.[0-9]
 recursive-include contrib *
 include README
 include CONTRIBUTORS
--- a/README	Fri Mar 31 17:00:09 2006 -0800
+++ b/README	Thu Apr 13 12:44:40 2006 -0700
@@ -97,4 +97,3 @@
 
  Documentation in doc/
  Mercurial website at http://selenic.com/mercurial
- Mercurial wiki at http://selenic.com/mercurial/wiki
--- a/contrib/bash_completion	Fri Mar 31 17:00:09 2006 -0800
+++ b/contrib/bash_completion	Thu Apr 13 12:44:40 2006 -0700
@@ -1,17 +1,55 @@
-shopt -s extglob
+# bash completion for the Mercurial distributed SCM
 
-_hg_option_list()
-{
-    "$hg" -v help $1 2>/dev/null | \
-	awk '/^ *-/ {
-		for (i = 1; i <= NF; i ++) {
-		    if (index($i, "-") != 1)
-			break;
-		    print $i;
-		}
-	    }'
-}
+# Docs:
+#
+# If you source this file from your .bashrc, bash should be able to
+# complete a command line that uses hg with all the available commands
+# and options and sometimes even arguments.
+#
+# Mercurial allows you to define additional commands through extensions.
+# Bash should be able to automatically figure out the name of these new
+# commands and their options.  If you also want to tell it how to
+# complete non-option arguments, see below for how to define an
+# _hg_cmd_foo function.
+#
+#
+# Notes about completion for specific commands:
+#
+# - the completion function for the email command from the patchbomb
+#   extension will try to call _hg_emails to get a list of e-mail
+#   addresses.  It's up to the user to define this function.  For
+#   example, put the addresses of the lists that you usually patchbomb
+#   in ~/.patchbomb-to and the addresses that you usually use to send
+#   the patchbombs in ~/.patchbomb-from and use something like this:
+#
+#      _hg_emails()
+#      {
+#          if [ -r ~/.patchbomb-$1 ]; then
+#              cat ~/.patchbomb-$1
+#          fi
+#      }
+# 
+#
+# Writing completion functions for additional commands:
+#
+# If it exists, the function _hg_cmd_foo will be called without
+# arguments to generate the completion candidates for the hg command
+# "foo".
+#
+# In addition to the regular completion variables provided by bash,
+# the following variables are also set:
+# - $hg - the hg program being used (e.g. /usr/bin/hg)
+# - $cmd - the name of the hg command being completed
+# - $cmd_index - the index of $cmd in $COMP_WORDS
+# - $cur - the current argument being completed
+# - $prev - the argument before $cur
+# - $global_args - "|"-separated list of global options that accept
+#                  an argument (e.g. '--cwd|-R|--repository')
+# - $canonical - 1 if we canonicalized $cmd before calling the function
+#                0 otherwise
+# 
 
+shopt -s extglob
 
 _hg_commands()
 {
@@ -42,8 +80,8 @@
 
 _hg_tags()
 {
-    local tags="$("$hg" tags 2>/dev/null |
-	sed -e 's/[0-9]*:[a-f0-9]\{40\}$//; s/ *$//')"
+    local tags="$("$hg" tags -q 2>/dev/null)"
+    local IFS=$'\n'
     COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$tags' -- "$cur"))
 }
 
@@ -67,7 +105,7 @@
 
 _hg()
 {
-    local cur prev cmd opts i
+    local cur prev cmd cmd_index opts i
     # global options that receive an argument
     local global_args='--cwd|-R|--repository'
     local hg="$1"
@@ -83,13 +121,14 @@
 	if [[ ${COMP_WORDS[i]} != -* ]]; then
 	    if [[ ${COMP_WORDS[i-1]} != @($global_args) ]]; then
 		cmd="${COMP_WORDS[i]}"
+		cmd_index=$i
 		break
 	    fi
 	fi
     done
 
     if [[ "$cur" == -* ]]; then
-	opts=$(_hg_option_list $cmd)
+	opts=$("$hg" debugcomplete --options "$cmd" 2>/dev/null)
 
 	COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$opts' -- "$cur"))
 	return
@@ -112,13 +151,43 @@
 	return
     fi
 
-    # canonicalize command name
-    cmd=$("$hg" -q help "$cmd" 2>/dev/null | sed -e 's/^hg //; s/ .*//; 1q')
+    # try to generate completion candidates for whatever command the user typed
+    local help
+    local canonical=0
+    if _hg_command_specific; then
+	return
+    fi
 
-    if [ "$cmd" != status ] && [ "$prev" = -r ] || [ "$prev" = --rev ]; then
-	_hg_tags
+    # canonicalize the command name and try again
+    help=$("$hg" help "$cmd" 2>/dev/null)
+    if [ $? -ne 0 ]; then
+	# Probably either the command doesn't exist or it's ambiguous
 	return
     fi
+    cmd=${help#hg }
+    cmd=${cmd%%[$' \n']*}
+    canonical=1
+    _hg_command_specific
+}
+
+_hg_command_specific()
+{
+    if [ "$(type -t "_hg_cmd_$cmd")" = function ]; then
+	"_hg_cmd_$cmd"
+	return 0
+    fi
+
+    if [ "$cmd" != status ] && [ "$prev" = -r ] || [ "$prev" == --rev ]; then
+	if [ $canonical = 1 ]; then
+	    _hg_tags
+	    return 0
+	elif [[ status != "$cmd"* ]]; then
+	    _hg_tags
+	    return 0
+	else
+	    return 1
+	fi
+    fi
 
     case "$cmd" in
 	help)
@@ -165,9 +234,152 @@
 	debugdata)
 	    COMPREPLY=(${COMPREPLY[@]:-} $(compgen -f -X "!*.d" -- "$cur"))
 	;;
+	*)
+	    return 1
+	;;
     esac
 
+    return 0
 }
 
 complete -o bashdefault -o default -F _hg hg 2>/dev/null \
     || complete -o default -F _hg hg
+
+
+# Completion for commands provided by extensions
+
+# mq
+_hg_ext_mq_patchlist()
+{
+    local patches=$("$hg" $1 2>/dev/null)
+    COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$patches' -- "$cur"))
+}
+
+_hg_ext_mq_queues()
+{
+    local root=$("$hg" root 2>/dev/null)
+    local n
+    for n in $(cd "$root"/.hg && compgen -d -- "$cur"); do
+	# I think we're usually not interested in the regular "patches" queue
+	# so just filter it.
+	if [ "$n" != patches ] && [ -e "$root/.hg/$n/series" ]; then
+	    COMPREPLY=(${COMPREPLY[@]:-} "$n")
+	fi
+    done
+}
+
+_hg_cmd_qpop()
+{
+    if [[ "$prev" = @(-n|--name) ]]; then
+	_hg_ext_mq_queues
+	return
+    fi
+    _hg_ext_mq_patchlist qapplied
+}
+
+_hg_cmd_qpush()
+{
+    if [[ "$prev" = @(-n|--name) ]]; then
+	_hg_ext_mq_queues
+	return
+    fi
+    _hg_ext_mq_patchlist qunapplied
+}
+
+_hg_cmd_qdelete()
+{
+    _hg_ext_mq_patchlist qseries
+}
+
+_hg_cmd_qsave()
+{
+    if [[ "$prev" = @(-n|--name) ]]; then
+	_hg_ext_mq_queues
+	return
+    fi
+}
+
+_hg_cmd_strip()
+{
+    _hg_tags
+}
+
+_hg_cmd_qcommit()
+{
+    local root=$("$hg" root 2>/dev/null)
+    # this is run in a sub-shell, so we can't use _hg_status
+    local files=$(cd "$root/.hg/patches" 2>/dev/null &&
+                  "$hg" status -nmar 2>/dev/null)
+    COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$files' -- "$cur"))
+}
+
+
+# hbisect
+_hg_cmd_bisect()
+{
+    local i subcmd
+
+    # find the sub-command
+    for ((i=cmd_index+1; i<=COMP_CWORD; i++)); do
+	if [[ ${COMP_WORDS[i]} != -* ]]; then
+	    if [[ ${COMP_WORDS[i-1]} != @($global_args) ]]; then
+		subcmd="${COMP_WORDS[i]}"
+		break
+	    fi
+	fi
+    done
+
+    if [ -z "$subcmd" ] || [ $COMP_CWORD -eq $i ] || [ "$subcmd" = help ]; then
+	COMPREPLY=(${COMPREPLY[@]:-} 
+		   $(compgen -W 'bad good help init next reset' -- "$cur"))
+	return
+    fi
+
+    case "$subcmd" in
+	good|bad)
+	    _hg_tags
+	    ;;
+    esac
+
+    return
+}
+
+
+# patchbomb
+_hg_cmd_email()
+{
+    case "$prev" in
+	-c|--cc|-t|--to|-f|--from)
+	    # we need an e-mail address. let the user provide a function 
+	    # to get them
+	    if [ "$(type -t _hg_emails)" = function ]; then
+		local arg=to
+		if [[ "$prev" == @(-f|--from) ]]; then
+		    arg=from
+		fi
+		local addresses=$(_hg_emails $arg)
+		COMPREPLY=(${COMPREPLY[@]:-}
+			   $(compgen -W '$addresses' -- "$cur"))
+	    fi
+	    return
+	    ;;
+	-m|--mbox)
+	    # fallback to standard filename completion
+	    return
+	    ;;
+	-s|--subject)
+	    # free form string
+	    return
+	    ;;
+    esac
+
+    _hg_tags
+    return
+}
+
+
+# gpg
+_hg_cmd_sign()
+{
+    _hg_tags
+}
--- a/contrib/hgk	Fri Mar 31 17:00:09 2006 -0800
+++ b/contrib/hgk	Thu Apr 13 12:44:40 2006 -0700
@@ -3448,7 +3448,7 @@
 	return
     }
     if {[catch {
-	set out [exec hg tag $tag $id]
+	set out [exec hg tag -r $id $tag]
     } err]} {
 	error_popup "Error creating tag: $err"
 	return
--- a/doc/hg.1.txt	Fri Mar 31 17:00:09 2006 -0800
+++ b/doc/hg.1.txt	Thu Apr 13 12:44:40 2006 -0700
@@ -210,8 +210,6 @@
 ---------
 http://selenic.com/mercurial[Main Web Site]
 
-http://www.serpentine.com/mercurial[Wiki site]
-
 http://selenic.com/hg[Source code repository]
 
 http://selenic.com/mailman/listinfo/mercurial[Mailing list]
--- a/hgext/mq.py	Fri Mar 31 17:00:09 2006 -0800
+++ b/hgext/mq.py	Thu Apr 13 12:44:40 2006 -0700
@@ -14,6 +14,7 @@
 
 repomap = {}
 
+commands.norepo += " qversion"
 class queue:
     def __init__(self, ui, path, patchdir=None):
         self.basepath = path
--- a/hgmerge	Fri Mar 31 17:00:09 2006 -0800
+++ b/hgmerge	Thu Apr 13 12:44:40 2006 -0700
@@ -47,6 +47,11 @@
 type "$TKDIFF"    >/dev/null 2>&1 || TKDIFF=
 type "$MELD"      >/dev/null 2>&1 || MELD=
 
+# Hack for Solaris
+TEST="/usr/bin/test"
+type "$TEST" >/dev/null 2>&1 || TEST="/bin/test"
+type "$TEST" >/dev/null 2>&1 || TEST="test"
+
 # random part of names
 RAND="$RANDOM$RANDOM"
 
@@ -118,7 +123,7 @@
     # filemerge prefers the right by default
     $FILEMERGE -left "$OTHER" -right "$LOCAL" -ancestor "$BASE" -merge "$LOCAL"
     [ $? -ne 0 ] && echo "FileMerge failed to launch" && failure
-    test "$LOCAL" -nt "$CHGTEST" && success || ask_if_merged
+    $TEST "$LOCAL" -nt "$CHGTEST" && success || ask_if_merged
 fi
 
 if [ -n "$DISPLAY" ]; then
@@ -142,7 +147,7 @@
         # use the file with conflicts
         $MELD "$LOCAL.tmp.$RAND" "$LOCAL" "$OTHER" || failure
         # Also it doesn't return good error code
-        test "$LOCAL" -nt "$CHGTEST" && success || ask_if_merged
+        $TEST "$LOCAL" -nt "$CHGTEST" && success || ask_if_merged
     fi
 fi
 
@@ -153,7 +158,7 @@
     $EDITOR "$LOCAL" || failure
     # Some editors do not return meaningful error codes
     # Do not take any chances
-    test "$LOCAL" -nt "$CHGTEST" && success || ask_if_merged
+    $TEST "$LOCAL" -nt "$CHGTEST" && success || ask_if_merged
 fi
 
 # attempt to manually merge with diff and patch
@@ -170,7 +175,7 @@
     else
         # If rejects are empty after using the editor, merge was ok
         $EDITOR "$LOCAL" "$LOCAL.rej" || failure
-        test -s "$LOCAL.rej" || success
+        $TEST -s "$LOCAL.rej" || success
     fi
     failure
 fi
--- a/mercurial/commands.py	Fri Mar 31 17:00:09 2006 -0800
+++ b/mercurial/commands.py	Thu Apr 13 12:44:40 2006 -0700
@@ -48,7 +48,7 @@
     exact = dict(zip(files, files))
     def walk():
         for src, fn in repo.walk(node=node, files=files, match=matchfn,
-                                 badmatch=None):
+                                 badmatch=badmatch):
             yield src, fn, util.pathto(repo.getcwd(), fn), fn in exact
     return files, matchfn, walk()
 
@@ -407,15 +407,20 @@
         '''set template string to use'''
         self.t.cache['changeset'] = t
 
-    def write(self, thing):
+    def write(self, thing, header=False):
         '''write expanded template.
         uses in-order recursive traverse of iterators.'''
         for t in thing:
             if hasattr(t, '__iter__'):
-                self.write(t)
+                self.write(t, header=header)
+            elif header:
+                self.ui.write_header(t)
             else:
                 self.ui.write(t)
 
+    def write_header(self, thing):
+        self.write(thing, header=True)
+
     def show(self, rev=0, changenode=None, brinfo=None):
         '''show a single changeset or file revision'''
         log = self.repo.changelog
@@ -549,6 +554,18 @@
             }
 
         try:
+            if self.ui.debugflag and 'header_debug' in self.t:
+                key = 'header_debug'
+            elif self.ui.quiet and 'header_quiet' in self.t:
+                key = 'header_quiet'
+            elif self.ui.verbose and 'header_verbose' in self.t:
+                key = 'header_verbose'
+            elif 'header' in self.t:
+                key = 'header'
+            else:
+                key = ''
+            if key:
+                self.write_header(self.t(key, **props))
             if self.ui.debugflag and 'changeset_debug' in self.t:
                 key = 'changeset_debug'
             elif self.ui.quiet and 'changeset_quiet' in self.t:
@@ -1255,11 +1272,26 @@
     a = r.ancestor(r.lookup(rev1), r.lookup(rev2))
     ui.write("%d:%s\n" % (r.rev(a), hex(a)))
 
-def debugcomplete(ui, cmd):
+def debugcomplete(ui, cmd='', **opts):
     """returns the completion list associated with the given command"""
+
+    if opts['options']:
+        options = []
+        otables = [globalopts]
+        if cmd:
+            aliases, entry = find(cmd)
+            otables.append(entry[1])
+        for t in otables:
+            for o in t:
+                if o[0]:
+                    options.append('-%s' % o[0])
+                options.append('--%s' % o[1])
+        ui.write("%s\n" % "\n".join(options))
+        return
+
     clist = findpossible(cmd).keys()
     clist.sort()
-    ui.write("%s\n" % " ".join(clist))
+    ui.write("%s\n" % "\n".join(clist))
 
 def debugrebuildstate(ui, repo, rev=None):
     """rebuild the dirstate as it would look like for the given revision"""
@@ -1897,9 +1929,11 @@
         def __init__(self, ui):
             self.ui = ui
             self.hunk = {}
+            self.header = {}
         def bump(self, rev):
             self.rev = rev
             self.hunk[rev] = []
+            self.header[rev] = []
         def note(self, *args):
             if self.verbose:
                 self.write(*args)
@@ -1908,6 +1942,8 @@
                 self.write(*args)
         def write(self, *args):
             self.hunk[self.rev].append(args)
+        def write_header(self, *args):
+            self.header[self.rev].append(args)
         def debug(self, *args):
             if self.debugflag:
                 self.write(*args)
@@ -1964,6 +2000,9 @@
                 du.write("\n\n")
         elif st == 'iter':
             if count == limit: break
+            if du.header[rev]:
+                for args in du.header[rev]:
+                    ui.write_header(*args)
             if du.hunk[rev]:
                 count += 1
                 for args in du.hunk[rev]:
@@ -2219,7 +2258,7 @@
     """
     if repo.recover():
         return repo.verify()
-    return False
+    return 1
 
 def remove(ui, repo, pat, *pats, **opts):
     """remove the specified files on the next commit
@@ -2287,9 +2326,8 @@
     to the named files or directories.  This restores the contents of
     the affected files to an unmodified state.
 
-    Modified files have backup copies saved before revert.  To disable
-    backups, use --no-backup.  To change the name of backup files, use
-    --backup to give a format string.
+    Modified files are saved with a .orig suffix before reverting.
+    To disable these backups, use --no-backup.
 
     Using the -r option, it reverts the given files or directories to
     their state as of an earlier revision.  This can be helpful to "roll
@@ -2309,31 +2347,29 @@
     node = opts['rev'] and repo.lookup(opts['rev']) or parent
     mf = repo.manifest.read(repo.changelog.read(node)[0])
 
-    def backup(name, exact):
-        bakname = make_filename(repo, repo.changelog,
-                                opts['backup_name'] or '%p.orig',
-                                node=parent, pathname=name)
-        if os.path.exists(name):
-            # if backup already exists and is same as backup we want
-            # to make, do nothing
-            if os.path.exists(bakname):
-                if repo.wread(name) == repo.wread(bakname):
-                    return
-                raise util.Abort(_('cannot save current version of %s - '
-                                   '%s exists and differs') %
-                                 (name, bakname))
-            ui.status(('saving current version of %s as %s\n') %
-                      (name, bakname))
-            shutil.copyfile(name, bakname)
-            shutil.copymode(name, bakname)
-
     wlock = repo.wlock()
 
-    entries = []
+    # need all matching names in dirstate and manifest of target rev,
+    # so have to walk both. do not print errors if files exist in one
+    # but not other.
+
     names = {}
+    target_only = {}
+
+    # walk dirstate.
+
     for src, abs, rel, exact in walk(repo, pats, opts, badmatch=mf.has_key):
-        names[abs] = True
-        entries.append((abs, rel, exact))
+        names[abs] = (rel, exact)
+        if src == 'b':
+            target_only[abs] = True
+
+    # walk target manifest.
+
+    for src, abs, rel, exact in walk(repo, pats, opts, node=node,
+                                     badmatch=names.has_key):
+        if abs in names: continue
+        names[abs] = (rel, exact)
+        target_only[abs] = True
 
     changes = repo.changes(match=names.has_key, wlock=wlock)
     modified, added, removed, deleted, unknown = map(dict.fromkeys, changes)
@@ -2353,23 +2389,32 @@
         #   make backup if in target manifest
         #   make backup if not in target manifest
         (modified, revert, remove, True, True),
-        (added, revert, forget, True, True),
+        (added, revert, forget, True, False),
         (removed, undelete, None, False, False),
         (deleted, revert, remove, False, False),
         (unknown, add, None, True, False),
+        (target_only, add, None, False, False),
         )
 
-    for abs, rel, exact in entries:
+    entries = names.items()
+    entries.sort()
+
+    for abs, (rel, exact) in entries:
+        in_mf = abs in mf
         def handle(xlist, dobackup):
             xlist[0].append(abs)
-            if dobackup and not opts['no_backup']:
-                backup(rel, exact)
+            if dobackup and not opts['no_backup'] and os.path.exists(rel):
+                bakname = "%s.orig" % rel
+                ui.note(_('saving current version of %s as %s\n') %
+                        (rel, bakname))
+                shutil.copyfile(rel, bakname)
+                shutil.copymode(rel, bakname)
             if ui.verbose or not exact:
                 ui.status(xlist[1] % rel)
         for table, hitlist, misslist, backuphit, backupmiss in disptable:
             if abs not in table: continue
             # file has changed in dirstate
-            if abs in mf:
+            if in_mf:
                 handle(hitlist, backuphit)
             elif misslist is not None:
                 handle(misslist, backupmiss)
@@ -2381,8 +2426,8 @@
             if node == parent:
                 if exact: ui.warn(_('no changes needed to %s\n' % rel))
                 continue
-            if abs not in mf:
-                remove[0].append(abs)
+            if not in_mf:
+                handle(remove, False)
         update[abs] = True
 
     repo.dirstate.forget(forget[0])
@@ -2652,7 +2697,10 @@
             r = "%5d:%s" % (repo.changelog.rev(n), hex(n))
         except KeyError:
             r = "    ?:?"
-        ui.write("%-30s %s\n" % (t, r))
+        if ui.quiet:
+            ui.write("%s\n" % t)
+        else:
+            ui.write("%-30s %s\n" % (t, r))
 
 def tip(ui, repo, **opts):
     """show the tip revision
@@ -2708,7 +2756,9 @@
 
     This command is not intended for use on public repositories. Once
     a change is visible for pull by other users, undoing it locally is
-    ineffective.
+    ineffective. Furthemore a race is possible with readers of the
+    repository, for example an ongoing pull from the repository will
+    fail and rollback.
     """
     repo.undo()
 
@@ -2829,7 +2879,10 @@
           ('X', 'exclude', [], _('exclude names matching the given patterns'))],
          _('hg copy [OPTION]... [SOURCE]... DEST')),
     "debugancestor": (debugancestor, [], _('debugancestor INDEX REV1 REV2')),
-    "debugcomplete": (debugcomplete, [], _('debugcomplete CMD')),
+    "debugcomplete":
+        (debugcomplete,
+         [('o', 'options', None, _('show the command options'))],
+         _('debugcomplete [-o] CMD')),
     "debugrebuildstate":
         (debugrebuildstate,
          [('r', 'rev', '', _('revision to rebuild to'))],
@@ -2940,12 +2993,10 @@
          _('hg log [OPTION]... [FILE]')),
     "manifest": (manifest, [], _('hg manifest [REV]')),
     "merge":
-    (merge,
-     [('b', 'branch', '', _('merge with head of a specific branch')),
-      ('', 'style', '', _('display using template map file')),
-      ('f', 'force', None, _('force a merge with outstanding changes')),
-      ('', 'template', '', _('display with template'))],
-     _('hg merge [-b TAG] [-f] [REV]')),
+        (merge,
+         [('b', 'branch', '', _('merge with head of a specific branch')),
+          ('f', 'force', None, _('force a merge with outstanding changes'))],
+         _('hg merge [-b TAG] [-f] [REV]')),
     "outgoing|out": (outgoing,
          [('M', 'no-merges', None, _('do not show merges')),
           ('f', 'force', None,
@@ -3011,7 +3062,6 @@
     "^revert":
         (revert,
          [('r', 'rev', '', _('revision to revert to')),
-          ('', 'backup-name', '', _('save backup with formatted name')),
           ('', 'no-backup', None, _('do not save backup copies of files')),
           ('I', 'include', [], _('include names matching given patterns')),
           ('X', 'exclude', [], _('exclude names matching given patterns'))],
@@ -3072,11 +3122,9 @@
     "^update|up|checkout|co":
         (update,
          [('b', 'branch', '', _('checkout the head of a specific branch')),
-          ('', 'style', '', _('display using template map file')),
           ('m', 'merge', None, _('allow merging of branches')),
           ('C', 'clean', None, _('overwrite locally modified files')),
-          ('f', 'force', None, _('force a merge with outstanding changes')),
-          ('', 'template', '', _('display with template'))],
+          ('f', 'force', None, _('force a merge with outstanding changes'))],
          _('hg update [-b TAG] [-m] [-C] [-f] [REV]')),
     "verify": (verify, [], _('hg verify')),
     "version": (show_version, [], _('hg version')),
@@ -3106,22 +3154,26 @@
 def findpossible(cmd):
     """
     Return cmd -> (aliases, command table entry)
-    for each matching command
+    for each matching command.
+    Return debug commands (or their aliases) only if no normal command matches.
     """
     choice = {}
     debugchoice = {}
     for e in table.keys():
         aliases = e.lstrip("^").split("|")
+        found = None
         if cmd in aliases:
-            choice[cmd] = (aliases, table[e])
-            continue
-        for a in aliases:
-            if a.startswith(cmd):
-                if aliases[0].startswith("debug"):
-                    debugchoice[a] = (aliases, table[e])
-                else:
-                    choice[a] = (aliases, table[e])
-                break
+            found = cmd
+        else:
+            for a in aliases:
+                if a.startswith(cmd):
+                    found = a
+                    break
+        if found is not None:
+            if aliases[0].startswith("debug"):
+                debugchoice[found] = (aliases, table[e])
+            else:
+                choice[found] = (aliases, table[e])
 
     if not choice and debugchoice:
         choice = debugchoice
@@ -3206,38 +3258,32 @@
         u = ui.ui()
     except util.Abort, inst:
         sys.stderr.write(_("abort: %s\n") % inst)
-        sys.exit(1)
+        return -1
 
     external = []
     for x in u.extensions():
-        def on_exception(exc, inst):
-            u.warn(_("*** failed to import extension %s\n") % x[1])
-            u.warn("%s\n" % inst)
-            if "--traceback" in sys.argv[1:]:
-                traceback.print_exc()
-        if x[1]:
-            try:
+        try:
+            if x[1]:
                 mod = imp.load_source(x[0], x[1])
-            except Exception, inst:
-                on_exception(Exception, inst)
-                continue
-        else:
-            def importh(name):
-                mod = __import__(name)
-                components = name.split('.')
-                for comp in components[1:]:
-                    mod = getattr(mod, comp)
-                return mod
-            try:
+            else:
+                def importh(name):
+                    mod = __import__(name)
+                    components = name.split('.')
+                    for comp in components[1:]:
+                        mod = getattr(mod, comp)
+                    return mod
                 try:
                     mod = importh("hgext." + x[0])
                 except ImportError:
                     mod = importh(x[0])
-            except Exception, inst:
-                on_exception(Exception, inst)
-                continue
-
-        external.append(mod)
+            external.append(mod)
+        except Exception, inst:
+            u.warn(_("*** failed to import extension %s: %s\n") % (x[0], inst))
+            if "--traceback" in sys.argv[1:]:
+                traceback.print_exc()
+                return 1
+            continue
+
     for x in external:
         cmdtable = getattr(x, 'cmdtable', {})
         for t in cmdtable:
@@ -3279,14 +3325,11 @@
             repo = path and hg.repository(u, path=path) or None
 
             if options['help']:
-                help_(u, cmd, options['version'])
-                sys.exit(0)
+                return help_(u, cmd, options['version'])
             elif options['version']:
-                show_version(u)
-                sys.exit(0)
+                return show_version(u)
             elif not cmd:
-                help_(u, 'shortlist')
-                sys.exit(0)
+                return help_(u, 'shortlist')
 
             if cmd not in norepo.split():
                 try:
@@ -3341,15 +3384,12 @@
         else:
             u.warn(_("hg: %s\n") % inst.args[1])
             help_(u, 'shortlist')
-        sys.exit(-1)
     except AmbiguousCommand, inst:
         u.warn(_("hg: command '%s' is ambiguous:\n    %s\n") %
                 (inst.args[0], " ".join(inst.args[1])))
-        sys.exit(1)
     except UnknownCommand, inst:
         u.warn(_("hg: unknown command '%s'\n") % inst.args[0])
         help_(u, 'shortlist')
-        sys.exit(1)
     except hg.RepoError, inst:
         u.warn(_("abort: "), inst, "!\n")
     except lock.LockHeld, inst:
@@ -3396,7 +3436,6 @@
             u.warn(_("abort: %s\n") % inst.strerror)
     except util.Abort, inst:
         u.warn(_('abort: '), inst.args[0] % inst.args[1:], '\n')
-        sys.exit(1)
     except TypeError, inst:
         # was this an argument error?
         tb = traceback.extract_tb(sys.exc_info()[2])
@@ -3405,9 +3444,10 @@
         u.debug(inst, "\n")
         u.warn(_("%s: invalid arguments\n") % cmd)
         help_(u, cmd)
-    except SystemExit:
-        # don't catch this in the catch-all below
-        raise
+    except SystemExit, inst:
+        # Commands shouldn't sys.exit directly, but give a return code.
+        # Just in case catch this and and pass exit code to caller.
+        return inst.code
     except:
         u.warn(_("** unknown exception encountered, details follow\n"))
         u.warn(_("** report bug details to mercurial@selenic.com\n"))
@@ -3415,4 +3455,4 @@
                % version.get_version())
         raise
 
-    sys.exit(-1)
+    return -1
--- a/mercurial/dirstate.py	Fri Mar 31 17:00:09 2006 -0800
+++ b/mercurial/dirstate.py	Thu Apr 13 12:44:40 2006 -0700
@@ -294,7 +294,8 @@
                 kind))
         return False
 
-    def statwalk(self, files=None, match=util.always, dc=None, ignored=False):
+    def statwalk(self, files=None, match=util.always, dc=None, ignored=False,
+                 badmatch=None):
         self.lazyread()
 
         # walk all files by default
@@ -311,11 +312,12 @@
                 return False
             return match(file_)
 
-        return self.walkhelper(files=files, statmatch=statmatch, dc=dc)
+        return self.walkhelper(files=files, statmatch=statmatch, dc=dc,
+                               badmatch=badmatch)
 
-    def walk(self, files=None, match=util.always, dc=None):
+    def walk(self, files=None, match=util.always, dc=None, badmatch=None):
         # filter out the stat
-        for src, f, st in self.statwalk(files, match, dc):
+        for src, f, st in self.statwalk(files, match, dc, badmatch=badmatch):
             yield src, f
 
     # walk recursively through the directory tree, finding all files
@@ -330,7 +332,7 @@
     # dc is an optional arg for the current dirstate.  dc is not modified
     # directly by this function, but might be modified by your statmatch call.
     #
-    def walkhelper(self, files, statmatch, dc):
+    def walkhelper(self, files, statmatch, dc, badmatch=None):
         # recursion free walker, faster than os.walk.
         def findfiles(s):
             work = [s]
@@ -385,9 +387,12 @@
                         found = True
                         break
                 if not found:
-                    self.ui.warn('%s: %s\n' % (
-                                 util.pathto(self.getcwd(), ff),
-                                 inst.strerror))
+                    if inst.errno != errno.ENOENT or not badmatch:
+                        self.ui.warn('%s: %s\n' % (
+                            util.pathto(self.getcwd(), ff),
+                            inst.strerror))
+                    elif badmatch and badmatch(ff) and statmatch(ff, None):
+                        yield 'b', ff, None
                 continue
             if stat.S_ISDIR(st.st_mode):
                 cmp1 = (lambda x, y: cmp(x[1], y[1]))
--- a/mercurial/localrepo.py	Fri Mar 31 17:00:09 2006 -0800
+++ b/mercurial/localrepo.py	Thu Apr 13 12:44:40 2006 -0700
@@ -498,7 +498,7 @@
                     self.ui.warn(_('%s: No such file in rev %s\n') % (
                         util.pathto(self.getcwd(), fn), short(node)))
         else:
-            for src, fn in self.dirstate.walk(files, match):
+            for src, fn in self.dirstate.walk(files, match, badmatch=badmatch):
                 yield src, fn
 
     def changes(self, node1=None, node2=None, files=[], match=util.always,
@@ -1662,7 +1662,7 @@
                     self.ui.status(" %s%s\n" % (f, cf))
                 self.ui.warn(_("aborting update spanning branches!\n"))
                 self.ui.status(_("(use 'hg merge' to merge across branches"
-                                 " or '-C' to lose changes)\n"))
+                                 " or 'hg update -C' to lose changes)\n"))
                 return 1
             branch_merge = True
 
--- a/mercurial/mpatch.c	Fri Mar 31 17:00:09 2006 -0800
+++ b/mercurial/mpatch.c	Thu Apr 13 12:44:40 2006 -0700
@@ -61,12 +61,12 @@
 	a = (struct flist *)malloc(sizeof(struct flist));
 	if (a) {
 		a->base = (struct frag *)malloc(sizeof(struct frag) * size);
-		if (!a->base) {
-			free(a);
-			a = NULL;
-		} else
+		if (a->base) {
 			a->head = a->tail = a->base;
-		return a;
+			return a;
+		}
+		free(a);
+		a = NULL;
 	}
 	if (!PyErr_Occurred())
 		PyErr_NoMemory();
--- a/mercurial/sshrepo.py	Fri Mar 31 17:00:09 2006 -0800
+++ b/mercurial/sshrepo.py	Thu Apr 13 12:44:40 2006 -0700
@@ -39,12 +39,21 @@
         # skip any noise generated by remote shell
         r = self.do_cmd("between", pairs=("%s-%s" % ("0"*40, "0"*40)))
         l1 = ""
-        while 1:
+        l2 = "dummy"
+        max_noise = 500
+        while l2 and max_noise:
             l2 = r.readline()
             self.readerr()
             if l1 == "1\n" and l2 == "\n":
                 break
+            if l1:
+                ui.debug(_("remote: "), l1)
             l1 = l2
+            max_noise -= 1
+        else:
+            if l1:
+                ui.debug(_("remote: "), l1)
+            raise hg.RepoError(_("no response from remote hg"))
 
     def readerr(self):
         while 1:
--- a/mercurial/ui.py	Fri Mar 31 17:00:09 2006 -0800
+++ b/mercurial/ui.py	Thu Apr 13 12:44:40 2006 -0700
@@ -27,6 +27,8 @@
 
             self.updateopts(verbose, debug, quiet, interactive)
             self.diffcache = None
+            self.header = []
+            self.prev_header = []
         else:
             # parentui may point to an ui object which is already a child
             self.parentui = parentui.parentui or parentui
@@ -184,9 +186,18 @@
         return self.config("paths", loc, loc)
 
     def write(self, *args):
+        if self.header:
+            if self.header != self.prev_header:
+                self.prev_header = self.header
+                self.write(*self.header)
+            self.header = []
         for a in args:
             sys.stdout.write(str(a))
 
+    def write_header(self, *args):
+        for a in args:
+            self.header.append(str(a))
+
     def write_err(self, *args):
         try:
             if not sys.stdout.closed: sys.stdout.flush()
--- a/mercurial/util.py	Fri Mar 31 17:00:09 2006 -0800
+++ b/mercurial/util.py	Thu Apr 13 12:44:40 2006 -0700
@@ -393,7 +393,7 @@
         if hardlink:
             try:
                 os_link(src, dst)
-            except:
+            except (IOError, OSError):
                 hardlink = False
                 shutil.copy(src, dst)
         else:
@@ -515,18 +515,13 @@
 
     sys.stdout = winstdout(sys.stdout)
 
+    def system_rcpath():
+        return [r'c:\mercurial\mercurial.ini']
+
     def os_rcpath():
         '''return default os-specific hgrc search path'''
-        try:
-            import win32api, win32process
-            proc = win32api.GetCurrentProcess()
-            filename = win32process.GetModuleFileNameEx(proc, 0)
-            systemrc = os.path.join(os.path.dirname(filename), 'mercurial.ini')
-        except ImportError:
-            systemrc = r'c:\mercurial\mercurial.ini'
-
-        return [systemrc,
-                os.path.join(os.path.expanduser('~'), 'mercurial.ini')]
+        return system_rcpath() + [os.path.join(os.path.expanduser('~'),
+                                               'mercurial.ini')]
 
     def parse_patch_output(output_line):
         """parses the output produced by patch and returns the file name"""
@@ -535,43 +530,9 @@
             pf = pf[1:-1] # Remove the quotes
         return pf
 
-    try: # Mark Hammond's win32all package allows better functionality on Windows
-        import win32api, win32con, win32file, pywintypes
-
-        # create hard links using win32file module
-        def os_link(src, dst): # NB will only succeed on NTFS
-            win32file.CreateHardLink(dst, src)
-
-        def nlinks(pathname):
-            """Return number of hardlinks for the given file."""
-            try:
-                fh = win32file.CreateFile(pathname,
-                    win32file.GENERIC_READ, win32file.FILE_SHARE_READ,
-                    None, win32file.OPEN_EXISTING, 0, None)
-                res = win32file.GetFileInformationByHandle(fh)
-                fh.Close()
-                return res[7]
-            except:
-                return os.stat(pathname).st_nlink
-
-        def testpid(pid):
-            '''return True if pid is still running or unable to
-            determine, False otherwise'''
-            try:
-                import win32process, winerror
-                handle = win32api.OpenProcess(
-                    win32con.PROCESS_QUERY_INFORMATION, False, pid)
-                if handle:
-                    status = win32process.GetExitCodeProcess(handle)
-                    return status == win32con.STILL_ACTIVE
-            except pywintypes.error, details:
-                return details[0] != winerror.ERROR_INVALID_PARAMETER
-            return True
-
-    except ImportError:
-        def testpid(pid):
-            '''return False if pid dead, True if running or not known'''
-            return True
+    def testpid(pid):
+        '''return False if pid dead, True if running or not known'''
+        return True
 
     def is_exec(f, last):
         return last
@@ -597,6 +558,12 @@
     def explain_exit(code):
         return _("exited with status %d") % code, code
 
+    try:
+        # override functions with win32 versions if possible
+        from util_win32 import *
+    except ImportError:
+        pass
+
 else:
     nulldev = '/dev/null'
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial/util_win32.py	Thu Apr 13 12:44:40 2006 -0700
@@ -0,0 +1,171 @@
+# util_win32.py - utility functions that use win32 API
+#
+# Copyright 2005 Matt Mackall <mpm@selenic.com>
+# Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
+#
+# This software may be used and distributed according to the terms of
+# the GNU General Public License, incorporated herein by reference.
+
+# Mark Hammond's win32all package allows better functionality on
+# Windows.  this module overrides definitions in util.py.  if not
+# available, import of this module will fail, and generic code will be
+# used.
+
+import win32api
+
+from demandload import *
+from i18n import gettext as _
+demandload(globals(), 'errno os pywintypes win32con win32file win32process')
+demandload(globals(), 'winerror')
+
+class WinError(OSError):
+    winerror_map = {
+        winerror.ERROR_ACCESS_DENIED: errno.EACCES,
+        winerror.ERROR_ACCOUNT_DISABLED: errno.EACCES,
+        winerror.ERROR_ACCOUNT_RESTRICTION: errno.EACCES,
+        winerror.ERROR_ALREADY_ASSIGNED: errno.EBUSY,
+        winerror.ERROR_ALREADY_EXISTS: errno.EEXIST,
+        winerror.ERROR_ARITHMETIC_OVERFLOW: errno.ERANGE,
+        winerror.ERROR_BAD_COMMAND: errno.EIO,
+        winerror.ERROR_BAD_DEVICE: errno.ENODEV,
+        winerror.ERROR_BAD_DRIVER_LEVEL: errno.ENXIO,
+        winerror.ERROR_BAD_EXE_FORMAT: errno.ENOEXEC,
+        winerror.ERROR_BAD_FORMAT: errno.ENOEXEC,
+        winerror.ERROR_BAD_LENGTH: errno.EINVAL,
+        winerror.ERROR_BAD_PATHNAME: errno.ENOENT,
+        winerror.ERROR_BAD_PIPE: errno.EPIPE,
+        winerror.ERROR_BAD_UNIT: errno.ENODEV,
+        winerror.ERROR_BAD_USERNAME: errno.EINVAL,
+        winerror.ERROR_BROKEN_PIPE: errno.EPIPE,
+        winerror.ERROR_BUFFER_OVERFLOW: errno.ENAMETOOLONG,
+        winerror.ERROR_BUSY: errno.EBUSY,
+        winerror.ERROR_BUSY_DRIVE: errno.EBUSY,
+        winerror.ERROR_CALL_NOT_IMPLEMENTED: errno.ENOSYS,
+        winerror.ERROR_CANNOT_MAKE: errno.EACCES,
+        winerror.ERROR_CANTOPEN: errno.EIO,
+        winerror.ERROR_CANTREAD: errno.EIO,
+        winerror.ERROR_CANTWRITE: errno.EIO,
+        winerror.ERROR_CRC: errno.EIO,
+        winerror.ERROR_CURRENT_DIRECTORY: errno.EACCES,
+        winerror.ERROR_DEVICE_IN_USE: errno.EBUSY,
+        winerror.ERROR_DEV_NOT_EXIST: errno.ENODEV,
+        winerror.ERROR_DIRECTORY: errno.EINVAL,
+        winerror.ERROR_DIR_NOT_EMPTY: errno.ENOTEMPTY,
+        winerror.ERROR_DISK_CHANGE: errno.EIO,
+        winerror.ERROR_DISK_FULL: errno.ENOSPC,
+        winerror.ERROR_DRIVE_LOCKED: errno.EBUSY,
+        winerror.ERROR_ENVVAR_NOT_FOUND: errno.EINVAL,
+        winerror.ERROR_EXE_MARKED_INVALID: errno.ENOEXEC,
+        winerror.ERROR_FILENAME_EXCED_RANGE: errno.ENAMETOOLONG,
+        winerror.ERROR_FILE_EXISTS: errno.EEXIST,
+        winerror.ERROR_FILE_INVALID: errno.ENODEV,
+        winerror.ERROR_FILE_NOT_FOUND: errno.ENOENT,
+        winerror.ERROR_GEN_FAILURE: errno.EIO,
+        winerror.ERROR_HANDLE_DISK_FULL: errno.ENOSPC,
+        winerror.ERROR_INSUFFICIENT_BUFFER: errno.ENOMEM,
+        winerror.ERROR_INVALID_ACCESS: errno.EACCES,
+        winerror.ERROR_INVALID_ADDRESS: errno.EFAULT,
+        winerror.ERROR_INVALID_BLOCK: errno.EFAULT,
+        winerror.ERROR_INVALID_DATA: errno.EINVAL,
+        winerror.ERROR_INVALID_DRIVE: errno.ENODEV,
+        winerror.ERROR_INVALID_EXE_SIGNATURE: errno.ENOEXEC,
+        winerror.ERROR_INVALID_FLAGS: errno.EINVAL,
+        winerror.ERROR_INVALID_FUNCTION: errno.ENOSYS,
+        winerror.ERROR_INVALID_HANDLE: errno.EBADF,
+        winerror.ERROR_INVALID_LOGON_HOURS: errno.EACCES,
+        winerror.ERROR_INVALID_NAME: errno.EINVAL,
+        winerror.ERROR_INVALID_OWNER: errno.EINVAL,
+        winerror.ERROR_INVALID_PARAMETER: errno.EINVAL,
+        winerror.ERROR_INVALID_PASSWORD: errno.EPERM,
+        winerror.ERROR_INVALID_PRIMARY_GROUP: errno.EINVAL,
+        winerror.ERROR_INVALID_SIGNAL_NUMBER: errno.EINVAL,
+        winerror.ERROR_INVALID_TARGET_HANDLE: errno.EIO,
+        winerror.ERROR_INVALID_WORKSTATION: errno.EACCES,
+        winerror.ERROR_IO_DEVICE: errno.EIO,
+        winerror.ERROR_IO_INCOMPLETE: errno.EINTR,
+        winerror.ERROR_LOCKED: errno.EBUSY,
+        winerror.ERROR_LOCK_VIOLATION: errno.EACCES,
+        winerror.ERROR_LOGON_FAILURE: errno.EACCES,
+        winerror.ERROR_MAPPED_ALIGNMENT: errno.EINVAL,
+        winerror.ERROR_META_EXPANSION_TOO_LONG: errno.E2BIG,
+        winerror.ERROR_MORE_DATA: errno.EPIPE,
+        winerror.ERROR_NEGATIVE_SEEK: errno.ESPIPE,
+        winerror.ERROR_NOACCESS: errno.EFAULT,
+        winerror.ERROR_NONE_MAPPED: errno.EINVAL,
+        winerror.ERROR_NOT_ENOUGH_MEMORY: errno.ENOMEM,
+        winerror.ERROR_NOT_READY: errno.EAGAIN,
+        winerror.ERROR_NOT_SAME_DEVICE: errno.EXDEV,
+        winerror.ERROR_NO_DATA: errno.EPIPE,
+        winerror.ERROR_NO_MORE_SEARCH_HANDLES: errno.EIO,
+        winerror.ERROR_NO_PROC_SLOTS: errno.EAGAIN,
+        winerror.ERROR_NO_SUCH_PRIVILEGE: errno.EACCES,
+        winerror.ERROR_OPEN_FAILED: errno.EIO,
+        winerror.ERROR_OPEN_FILES: errno.EBUSY,
+        winerror.ERROR_OPERATION_ABORTED: errno.EINTR,
+        winerror.ERROR_OUTOFMEMORY: errno.ENOMEM,
+        winerror.ERROR_PASSWORD_EXPIRED: errno.EACCES,
+        winerror.ERROR_PATH_BUSY: errno.EBUSY,
+        winerror.ERROR_PATH_NOT_FOUND: errno.ENOTDIR,
+        winerror.ERROR_PIPE_BUSY: errno.EBUSY,
+        winerror.ERROR_PIPE_CONNECTED: errno.EPIPE,
+        winerror.ERROR_PIPE_LISTENING: errno.EPIPE,
+        winerror.ERROR_PIPE_NOT_CONNECTED: errno.EPIPE,
+        winerror.ERROR_PRIVILEGE_NOT_HELD: errno.EACCES,
+        winerror.ERROR_READ_FAULT: errno.EIO,
+        winerror.ERROR_SEEK: errno.EIO,
+        winerror.ERROR_SEEK_ON_DEVICE: errno.ESPIPE,
+        winerror.ERROR_SHARING_BUFFER_EXCEEDED: errno.ENFILE,
+        winerror.ERROR_SHARING_VIOLATION: errno.EACCES,
+        winerror.ERROR_STACK_OVERFLOW: errno.ENOMEM,
+        winerror.ERROR_SWAPERROR: errno.ENOENT,
+        winerror.ERROR_TOO_MANY_MODULES: errno.EMFILE,
+        winerror.ERROR_TOO_MANY_OPEN_FILES: errno.EMFILE,
+        winerror.ERROR_UNRECOGNIZED_MEDIA: errno.ENXIO,
+        winerror.ERROR_UNRECOGNIZED_VOLUME: errno.ENODEV,
+        winerror.ERROR_WAIT_NO_CHILDREN: errno.ECHILD,
+        winerror.ERROR_WRITE_FAULT: errno.EIO,
+        winerror.ERROR_WRITE_PROTECT: errno.EROFS,
+        }
+
+    def __init__(self, err):
+        self.win_errno, self.win_function, self.win_strerror = err
+        OSError.__init__(self, self.winerror_map.get(self.win_errno, 0),
+                         self.win_strerror)
+
+def os_link(src, dst):
+    # NB will only succeed on NTFS
+    try:
+        win32file.CreateHardLink(dst, src)
+    except pywintypes.error, details:
+        raise WinError(details)
+
+def nlinks(pathname):
+    """Return number of hardlinks for the given file."""
+    try:
+        fh = win32file.CreateFile(pathname,
+            win32file.GENERIC_READ, win32file.FILE_SHARE_READ,
+            None, win32file.OPEN_EXISTING, 0, None)
+        res = win32file.GetFileInformationByHandle(fh)
+        fh.Close()
+        return res[7]
+    except pywintypes.error:
+        return os.stat(pathname).st_nlink
+
+def testpid(pid):
+    '''return True if pid is still running or unable to
+    determine, False otherwise'''
+    try:
+        handle = win32api.OpenProcess(
+            win32con.PROCESS_QUERY_INFORMATION, False, pid)
+        if handle:
+            status = win32process.GetExitCodeProcess(handle)
+            return status == win32con.STILL_ACTIVE
+    except pywintypes.error, details:
+        return details[0] != winerror.ERROR_INVALID_PARAMETER
+    return True
+
+def system_rcpath():
+    '''return default os-specific hgrc search path'''
+    proc = win32api.GetCurrentProcess()
+    filename = win32process.GetModuleFileNameEx(proc, 0)
+    return [os.path.join(os.path.dirname(filename), 'mercurial.ini')]
--- a/templates/map-cmdline.changelog	Fri Mar 31 17:00:09 2006 -0800
+++ b/templates/map-cmdline.changelog	Thu Apr 13 12:44:40 2006 -0700
@@ -1,15 +1,14 @@
-changeset = '{date|shortdate}  {author|person}  <{author|email}>  ({node|short}{tags})\n\n\t* {files|stringify|fill68|tabindent}{desc|fill68|tabindent|strip}\n\n'
-changeset_quiet = '{date|shortdate}  {author|person}  <{author|email}>\n\n\t* {desc|firstline|fill68|tabindent|strip}\n\n'
+header = '{date|shortdate}  {author|person}  <{author|email}>\n\n'
+header_verbose = ''
+changeset = '\t* {files|stringify|fill68|tabindent}{desc|fill68|tabindent|strip}\n\t[{node|short}]{tags}\n\n'
+changeset_quiet = '\t* {desc|firstline|fill68|tabindent|strip}\n\n'
 changeset_verbose = '{date|isodate}  {author|person}  <{author|email}>  ({node|short}{tags})\n\n\t* {file_adds|stringify|fill68|tabindent}{file_dels|stringify|fill68|tabindent}{files|stringify|fill68|tabindent}{desc|fill68|tabindent|strip}\n\n'
 start_tags = ' ['
 tag = '{tag}, '
 last_tag = '{tag}]'
-start_files = '('
 file = '{file}, '
-last_file = '{file}):\n\t'
-start_file_adds = '('
+last_file = '{file}:\n\t'
 file_add = '{file_add}, '
-last_file_add = '{file_add}): new file.\n* '
-start_file_dels = '('
+last_file_add = '{file_add}: new file.\n* '
 file_del = '{file_del}, '
-last_file_del = '{file_del}): deleted file.\n* '
+last_file_del = '{file_del}: deleted file.\n* '
--- a/tests/run-tests	Fri Mar 31 17:00:09 2006 -0800
+++ b/tests/run-tests	Thu Apr 13 12:44:40 2006 -0700
@@ -19,6 +19,16 @@
 HGMERGE=true; export HGMERGE
 HGUSER="test"; export HGUSER
 HGRCPATH=""; export HGRCPATH
+OS=`uname`
+
+case "$OS" in
+  HP-UX|SunOS)
+    DIFFOPTS=
+    ;;
+  *)
+    DIFFOPTS=-u
+    ;;
+esac
 
 if [ `echo -n HG` = "-n HG" ]
 then
@@ -101,13 +111,13 @@
 	cat "$ERR"
 	fail=1
     elif [ -r "$OUTOK" ]; then
-	if diff -u "$OUTOK" "$OUT" > /dev/null; then
+	if diff $DIFFOPTS "$OUTOK" "$OUT" > /dev/null; then
 	    : no differences
 	else
 	    cp "$OUT" "$ERR"
 	    echo
 	    echo "$1 output changed:"
-	    diff -u "$OUTOK" "$ERR" || true
+	    diff $DIFFOPTS "$OUTOK" "$ERR" || true
 	    fail=1
 	fi
     fi
--- a/tests/test-clone-failure.out	Fri Mar 31 17:00:09 2006 -0800
+++ b/tests/test-clone-failure.out	Thu Apr 13 12:44:40 2006 -0700
@@ -6,7 +6,7 @@
 abort: repository a not found!
 255
 abort: destination '../a' already exists
-1
+255
 abort: repository a not found!
 255
 abort: destination 'q' already exists
--- a/tests/test-confused-revert.out	Fri Mar 31 17:00:09 2006 -0800
+++ b/tests/test-confused-revert.out	Thu Apr 13 12:44:40 2006 -0700
@@ -2,24 +2,20 @@
 A b
 R a
 reverting...
-saving current version of b as b.orig
+undeleting a
 forgetting b
-undeleting a
 %%% should show b unknown and a back to normal
 ? b
-? b.orig
 merging a
 %%% should show foo-b
 foo-b
 %%% should show a removed and b added
 A b
 R a
-? b.orig
 reverting...
+undeleting a
 forgetting b
-undeleting a
 %%% should show b unknown and a marked modified (merged)
 ? b
-? b.orig
 %%% should show foo-b
 foo-b
--- a/tests/test-merge-revert.out	Fri Mar 31 17:00:09 2006 -0800
+++ b/tests/test-merge-revert.out	Thu Apr 13 12:44:40 2006 -0700
@@ -3,7 +3,6 @@
 016807e6fdaf tip
 eb43f19ff115
 eb43f19ff115+
-saving current version of file1 as file1.orig
 reverting file1
 ? file1.orig
 eb43f19ff115
--- a/tests/test-merge5.out	Fri Mar 31 17:00:09 2006 -0800
+++ b/tests/test-merge5.out	Thu Apr 13 12:44:40 2006 -0700
@@ -2,4 +2,4 @@
 this update spans a branch affecting the following files:
  b
 aborting update spanning branches!
-(use 'hg merge' to merge across branches or '-C' to lose changes)
+(use 'hg merge' to merge across branches or 'hg update -C' to lose changes)
--- a/tests/test-revert	Fri Mar 31 17:00:09 2006 -0800
+++ b/tests/test-revert	Thu Apr 13 12:44:40 2006 -0700
@@ -22,22 +22,36 @@
 echo %% should show b added, copy saved, and c modified
 hg status
 hg revert b
-echo %% should show b unknown, b.bak unknown, and c modified
+echo %% should show b unknown, and c modified
 hg status
 hg revert --no-backup c
-echo %% should show unknown: b b.bak
+echo %% should show unknown: b
 hg status
-echo %% should show a b b.bak c e
+echo %% should show a b c e
 ls
-echo %% should save backup to e.0
+echo %% should verbosely save backup to e.orig
 echo z > e
-hg revert --backup='%p.%R'
+hg revert -v
 echo %% should say no changes needed
 hg revert a
 echo %% should say file not managed
 echo q > q
 hg revert q
+rm q
 echo %% should say file not found
 hg revert notfound
+hg rm a
+hg commit -m "second" -d "1000000 0"
+echo z > z
+hg add z
+hg st
+echo %% should add a, forget z
+hg revert -r0
+echo %% should forget a
+hg revert -rtip
+rm -f a *.orig
+echo %% should silently add a
+hg revert -r0 a
+hg st a
 
 true
--- a/tests/test-revert-unknown.out	Fri Mar 31 17:00:09 2006 -0800
+++ b/tests/test-revert-unknown.out	Thu Apr 13 12:44:40 2006 -0700
@@ -1,5 +1,6 @@
 %% Should show unknown
 ? unknown
+removing b
 %% Should show unknown and b removed
 R b
 ? unknown
--- a/tests/test-revert.out	Fri Mar 31 17:00:09 2006 -0800
+++ b/tests/test-revert.out	Thu Apr 13 12:44:40 2006 -0700
@@ -13,26 +13,35 @@
 %% should show b added, copy saved, and c modified
 M c
 A b
-saving current version of b as b.orig
-%% should show b unknown, b.bak unknown, and c modified
+%% should show b unknown, and c modified
 M c
 ? b
-? b.orig
-%% should show unknown: b b.bak
+%% should show unknown: b
 ? b
-? b.orig
-%% should show a b b.bak c e
+%% should show a b c e
 a
 b
-b.orig
 c
 e
-%% should save backup to e.0
-saving current version of e as e.0
+%% should verbosely save backup to e.orig
+saving current version of e as e.orig
 reverting e
+resolving manifests
+getting e
+1 files updated, 0 files merged, 0 files removed, 0 files unresolved
 %% should say no changes needed
 no changes needed to a
 %% should say file not managed
 file not managed: q
 %% should say file not found
-notfound: No such file or directory
+notfound: No such file in rev 095eacd0c0d7
+A z
+? b
+? e.orig
+%% should add a, forget z
+adding a
+forgetting z
+%% should forget a
+forgetting a
+%% should silently add a
+A a
--- a/tests/test-tag.out	Fri Mar 31 17:00:09 2006 -0800
+++ b/tests/test-tag.out	Thu Apr 13 12:44:40 2006 -0700
@@ -21,7 +21,6 @@
 use of 'hg tag NAME [REV]' is deprecated, please use 'hg tag [-r REV] NAME' instead
 abort: use only one form to specify the revision
 failed
-saving current version of .hgtags as .hgtags.orig
 use of 'hg tag NAME [REV]' is deprecated, please use 'hg tag [-r REV] NAME' instead
 0acdaf8983679e0aac16e811534eb49d7ee1f2b4 bleah
 0acdaf8983679e0aac16e811534eb49d7ee1f2b4 bleah0
--- a/tests/test-up-local-change.out	Fri Mar 31 17:00:09 2006 -0800
+++ b/tests/test-up-local-change.out	Thu Apr 13 12:44:40 2006 -0700
@@ -101,7 +101,7 @@
  a (resolve)
  b (resolve)
 aborting update spanning branches!
-(use 'hg merge' to merge across branches or '-C' to lose changes)
+(use 'hg merge' to merge across branches or 'hg update -C' to lose changes)
 failed
 abort: outstanding uncommitted changes
 failed