merge with i18n stable 2.9-rc
authorMatt Mackall <mpm@selenic.com>
Tue, 21 Jan 2014 14:44:01 -0600
branchstable
changeset 20308 8862469e16f9
parent 20306 fe8e254c7ad6 (diff)
parent 20307 b49f7022cd76 (current diff)
child 20309 fe302a0f116c
merge with i18n
--- a/.hgignore	Mon Jan 20 11:16:26 2014 -0200
+++ b/.hgignore	Tue Jan 21 14:44:01 2014 -0600
@@ -1,6 +1,7 @@
 syntax: glob
 
 *.elc
+*.tmp
 *.orig
 *.rej
 *~
--- a/Makefile	Mon Jan 20 11:16:26 2014 -0200
+++ b/Makefile	Tue Jan 21 14:44:01 2014 -0600
@@ -53,7 +53,8 @@
 
 clean:
 	-$(PYTHON) setup.py clean --all # ignore errors from this command
-	find . \( -name '*.py[cdo]' -o -name '*.so' \) -exec rm -f '{}' ';'
+	find contrib doc hgext i18n mercurial tests \
+		\( -name '*.py[cdo]' -o -name '*.so' \) -exec rm -f '{}' ';'
 	rm -f $(addprefix mercurial/,$(notdir $(wildcard mercurial/pure/[a-z]*.py)))
 	rm -f MANIFEST MANIFEST.in mercurial/__version__.py tests/*.err
 	rm -rf build mercurial/locale
@@ -107,7 +108,7 @@
 	  mercurial/fileset.py mercurial/revset.py \
 	  mercurial/templatefilters.py mercurial/templatekw.py \
 	  mercurial/filemerge.py \
-	  $(DOCFILES) > i18n/hg.pot
+	  $(DOCFILES) > i18n/hg.pot.tmp
         # All strings marked for translation in Mercurial contain
         # ASCII characters only. But some files contain string
         # literals like this '\037\213'. xgettext thinks it has to
@@ -119,11 +120,17 @@
 	  --msgid-bugs-address "<mercurial-devel@selenic.com>" \
 	  --copyright-holder "Matt Mackall <mpm@selenic.com> and others" \
 	  --from-code ISO-8859-1 --join --sort-by-file --add-comments=i18n: \
-	  -d hg -p i18n -o hg.pot
-	$(PYTHON) i18n/posplit i18n/hg.pot
+	  -d hg -p i18n -o hg.pot.tmp
+	$(PYTHON) i18n/posplit i18n/hg.pot.tmp
+        # The target file is not created before the last step. So it never is in
+        # an intermediate state.
+	mv -f i18n/hg.pot.tmp i18n/hg.pot
 
 %.po: i18n/hg.pot
-	msgmerge --no-location --update $@ $^
+        # work on a temporary copy for never having a half completed target
+	cp $@ $@.tmp
+	msgmerge --no-location --update $@.tmp $^
+	mv -f $@.tmp $@
 
 .PHONY: help all local build doc clean install install-bin install-doc \
 	install-home install-home-bin install-home-doc dist dist-notests tests \
--- a/contrib/bash_completion	Mon Jan 20 11:16:26 2014 -0200
+++ b/contrib/bash_completion	Tue Jan 21 14:44:01 2014 -0600
@@ -76,7 +76,7 @@
 {
     local i
     for i in $(compgen -d -- "$cur"); do
-	test ! -d "$i"/.hg || COMPREPLY=(${COMPREPLY[@]:-} "$i")
+        test ! -d "$i"/.hg || COMPREPLY=(${COMPREPLY[@]:-} "$i")
     done
 }
 
@@ -84,7 +84,6 @@
 {
     local files="$(_hg_cmd debugpathcomplete $1 "$cur")"
     local IFS=$'\n'
-    compopt -o filenames 2>/dev/null
     COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$files' -- "$cur"))
 }
 
@@ -92,10 +91,16 @@
 {
     local files="$(_hg_cmd status -n$1 "glob:$cur**")"
     local IFS=$'\n'
-    compopt -o filenames 2>/dev/null
     COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$files' -- "$cur"))
 }
 
+_hg_branches()
+{
+    local branches="$(_hg_cmd branches -q)"
+    local IFS=$'\n'
+    COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$branches' -- "$cur"))
+}
+
 _hg_bookmarks()
 {
     local bookmarks="$(_hg_cmd bookmarks -q)"
@@ -117,25 +122,45 @@
     local filters="$1"
 
     for ((i=1; $i<=$COMP_CWORD; i++)); do
-	if [[ "${COMP_WORDS[i]}" != -* ]]; then
-	    if [[ ${COMP_WORDS[i-1]} == @($filters|$global_args) ]]; then
-		continue
-	    fi
-	    count=$(($count + 1))
-	fi
+        if [[ "${COMP_WORDS[i]}" != -* ]]; then
+            if [[ ${COMP_WORDS[i-1]} == @($filters|$global_args) ]]; then
+                continue
+            fi
+            count=$(($count + 1))
+        fi
     done
 
     echo $(($count - 1))
 }
 
+_hg_fix_wordlist()
+{
+    local LASTCHAR=' '
+    if [ ${#COMPREPLY[@]} = 1 ]; then
+        [ -d "$COMPREPLY" ] && LASTCHAR=/
+        COMPREPLY=$(printf %q%s "$COMPREPLY" "$LASTCHAR")
+    else
+        for ((i=0; i < ${#COMPREPLY[@]}; i++)); do
+            [ -d "${COMPREPLY[$i]}" ] && COMPREPLY[$i]=${COMPREPLY[$i]}/
+        done
+    fi
+}
+
 _hg()
 {
-    local cur prev cmd cmd_index opts i
+    local cur prev cmd cmd_index opts i aliashg
     # global options that receive an argument
     local global_args='--cwd|-R|--repository'
     local hg="$1"
     local canonical=0
 
+    aliashg=$(alias $hg 2>/dev/null)
+    if [[ -n "$aliashg" ]]; then
+      aliashg=${aliashg#"alias $hg='"}
+      aliashg=${aliashg%"'"}
+      hg=$aliashg
+    fi
+
     COMPREPLY=()
     cur="$2"
     prev="$3"
@@ -144,145 +169,169 @@
     # (first non-option argument that doesn't follow a global option that
     #  receives an argument)
     for ((i=1; $i<=$COMP_CWORD; i++)); do
-	if [[ ${COMP_WORDS[i]} != -* ]]; then
-	    if [[ ${COMP_WORDS[i-1]} != @($global_args) ]]; then
-		cmd="${COMP_WORDS[i]}"
-		cmd_index=$i
-		break
-	    fi
-	fi
+        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
-	if [ "$(type -t "_hg_opt_$cmd")" = function ] && "_hg_opt_$cmd"; then
-	    return
-	fi
+        if [ "$(type -t "_hg_opt_$cmd")" = function ] && "_hg_opt_$cmd"; then
+            _hg_fix_wordlist
+            return
+        fi
 
-	opts=$(_hg_cmd debugcomplete --options "$cmd")
+        opts=$(_hg_cmd debugcomplete --options "$cmd")
 
-	COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$opts' -- "$cur"))
-	return
+        COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$opts' -- "$cur"))
+        _hg_fix_wordlist
+        return
     fi
 
     # global options
     case "$prev" in
-	-R|--repository)
-	    _hg_paths
-	    _hg_repos
-	    return
-	;;
-	--cwd)
-	    # Stick with default bash completion
-	    return
-	;;
+        -R|--repository)
+            _hg_paths
+            _hg_repos
+            _hg_fix_wordlist
+            return
+        ;;
+        --cwd)
+            # Stick with default bash completion
+            _hg_fix_wordlist
+            return
+        ;;
     esac
 
     if [ -z "$cmd" ] || [ $COMP_CWORD -eq $i ]; then
-	_hg_commands
-	return
+        _hg_commands
+        _hg_fix_wordlist
+        return
     fi
 
     # try to generate completion candidates for whatever command the user typed
     local help
     if _hg_command_specific; then
-	return
+        _hg_fix_wordlist
+        return
     fi
 
     # canonicalize the command name and try again
     help=$(_hg_cmd help "$cmd")
     if [ $? -ne 0 ]; then
-	# Probably either the command doesn't exist or it's ambiguous
-	return
+        # 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_fix_wordlist
 }
 
 _hg_command_specific()
 {
     if [ "$(type -t "_hg_cmd_$cmd")" = function ]; then
-	"_hg_cmd_$cmd"
-	return 0
+        "_hg_cmd_$cmd"
+        return 0
     fi
 
-    if [ "$cmd" != status ] && [ "$prev" = -r ] || [ "$prev" == --rev ]; then
-	if [ $canonical = 1 ]; then
-	    _hg_labels
-	    return 0
-	elif [[ status != "$cmd"* ]]; then
-            _hg_labels
-	    return 0
-	else
-	    return 1
-	fi
+    if [ "$cmd" != status ]; then
+        case "$prev" in
+            -r|--rev)
+                if [[ $canonical = 1 || status != "$cmd"* ]]; then
+                    _hg_labels
+                    return 0
+                fi
+                return 1
+            ;;
+            -B|--bookmark)
+                if [[ $canonical = 1 || status != "$cmd"* ]]; then
+                    _hg_bookmarks
+                    return 0
+                fi
+                return 1
+            ;;
+            -b|--branch)
+                if [[ $canonical = 1 || status != "$cmd"* ]]; then
+                    _hg_branches
+                    return 0
+                fi
+                return 1
+            ;;
+        esac
     fi
 
+    local aliascmd=$(_hg_cmd showconfig alias.$cmd | awk '{print $1}')
+    [ -n "$aliascmd" ] && cmd=$aliascmd
+
     case "$cmd" in
-	help)
-	    _hg_commands
-	;;
-	export)
-	    if _hg_ext_mq_patchlist qapplied && [ "${COMPREPLY[*]}" ]; then
-		return 0
-	    fi
-	    _hg_labels
-	;;
-	manifest|update|up|checkout|co)
-	    _hg_labels
-	;;
-	pull|push|outgoing|incoming)
-	    _hg_paths
-	    _hg_repos
-	;;
-	paths)
-	    _hg_paths
-	;;
-	add)
-	    _hg_status "u"
-	;;
-	merge)
-	    _hg_labels
-	;;
-	commit|ci|record)
-	    _hg_status "mar"
-	;;
-	remove|rm)
-	    _hg_debugpathcomplete -n
-	;;
-	forget)
-	    _hg_debugpathcomplete -fa
-	;;
-	diff)
-	    _hg_status "mar"
-	;;
-	revert)
-	    _hg_debugpathcomplete
-	;;
-	clone)
-	    local count=$(_hg_count_non_option)
-	    if [ $count = 1 ]; then
-		_hg_paths
-	    fi
-	    _hg_repos
-	;;
-	debugindex|debugindexdot)
-	    COMPREPLY=(${COMPREPLY[@]:-} $(compgen -f -X "!*.i" -- "$cur"))
-	;;
-	debugdata)
-	    COMPREPLY=(${COMPREPLY[@]:-} $(compgen -f -X "!*.d" -- "$cur"))
-	;;
-	*)
-	    return 1
-	;;
+        help)
+            _hg_commands
+        ;;
+        export)
+            if _hg_ext_mq_patchlist qapplied && [ "${COMPREPLY[*]}" ]; then
+                return 0
+            fi
+            _hg_labels
+        ;;
+        manifest|update|up|checkout|co)
+            _hg_labels
+        ;;
+        pull|push|outgoing|incoming)
+            _hg_paths
+            _hg_repos
+        ;;
+        paths)
+            _hg_paths
+        ;;
+        add)
+            _hg_status "u"
+        ;;
+        merge)
+            _hg_labels
+        ;;
+        commit|ci|record)
+            _hg_status "mar"
+        ;;
+        remove|rm)
+            _hg_debugpathcomplete -n
+        ;;
+        forget)
+            _hg_debugpathcomplete -fa
+        ;;
+        diff)
+            _hg_status "mar"
+        ;;
+        revert)
+            _hg_debugpathcomplete
+        ;;
+        clone)
+            local count=$(_hg_count_non_option)
+            if [ $count = 1 ]; then
+                _hg_paths
+            fi
+            _hg_repos
+        ;;
+        debugindex|debugindexdot)
+            COMPREPLY=(${COMPREPLY[@]:-} $(compgen -f -X "!*.i" -- "$cur"))
+        ;;
+        debugdata)
+            COMPREPLY=(${COMPREPLY[@]:-} $(compgen -f -X "!*.d" -- "$cur"))
+        ;;
+        *)
+            return 1
+        ;;
     esac
 
     return 0
 }
 
-complete -o bashdefault -o default -F _hg hg \
-    || complete -o default -F _hg hg
+complete -o bashdefault -o default -o nospace -F _hg hg \
+    || complete -o default -o nospace -F _hg hg
 
 
 # Completion for commands provided by extensions
@@ -290,10 +339,8 @@
 # bookmarks
 _hg_cmd_bookmarks()
 {
-    if [[ "$prev" = @(-d|--delete|-m|--rename) ]]; then
-        _hg_bookmarks
-        return
-    fi
+    _hg_bookmarks
+    return
 }
 
 # mq
@@ -302,8 +349,8 @@
     local patches
     patches=$(_hg_cmd $1)
     if [ $? -eq 0 ] && [ "$patches" ]; then
-	COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$patches' -- "$cur"))
-	return 0
+        COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$patches' -- "$cur"))
+        return 0
     fi
     return 1
 }
@@ -313,19 +360,19 @@
     local root=$(_hg_cmd root)
     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
+        # 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
+        _hg_ext_mq_queues
+        return
     fi
     _hg_ext_mq_patchlist qapplied
 }
@@ -333,8 +380,8 @@
 _hg_cmd_qpush()
 {
     if [[ "$prev" = @(-n|--name) ]]; then
-	_hg_ext_mq_queues
-	return
+        _hg_ext_mq_queues
+        return
     fi
     _hg_ext_mq_patchlist qunapplied
 }
@@ -342,8 +389,8 @@
 _hg_cmd_qgoto()
 {
     if [[ "$prev" = @(-n|--name) ]]; then
-	_hg_ext_mq_queues
-	return
+        _hg_ext_mq_queues
+        return
     fi
     _hg_ext_mq_patchlist qseries
 }
@@ -352,7 +399,7 @@
 {
     local qcmd=qunapplied
     if [[ "$prev" = @(-r|--rev) ]]; then
-	qcmd=qapplied
+        qcmd=qapplied
     fi
     _hg_ext_mq_patchlist $qcmd
 }
@@ -360,7 +407,7 @@
 _hg_cmd_qfinish()
 {
     if [[ "$prev" = @(-a|--applied) ]]; then
-	return
+        return
     fi
     _hg_ext_mq_patchlist qapplied
 }
@@ -368,8 +415,8 @@
 _hg_cmd_qsave()
 {
     if [[ "$prev" = @(-n|--name) ]]; then
-	_hg_ext_mq_queues
-	return
+        _hg_ext_mq_queues
+        return
     fi
 }
 
@@ -382,6 +429,10 @@
 
 _hg_cmd_strip()
 {
+    if [[ "$prev" = @(-B|--bookmark) ]]; then
+        _hg_bookmarks
+        return
+    fi
     _hg_labels
 }
 
@@ -412,7 +463,7 @@
 {
     local count=$(_hg_count_non_option)
     if [ $count = 1 ]; then
-	_hg_paths
+        _hg_paths
     fi
     _hg_repos
 }
@@ -433,15 +484,15 @@
     local prefix=''
 
     if [[ "$cur" == +* ]]; then
-	prefix=+
+        prefix=+
     elif [[ "$cur" == -* ]]; then
-	prefix=-
+        prefix=-
     fi
     local ncur=${cur#[-+]}
 
     if ! [ "$prefix" ]; then
-	_hg_ext_mq_patchlist qseries
-	return
+        _hg_ext_mq_patchlist qseries
+        return
     fi
 
     local guards=$(_hg_ext_mq_guards)
@@ -452,15 +503,15 @@
 {
     local i
     for ((i=cmd_index+1; i<=COMP_CWORD; i++)); do
-	if [[ ${COMP_WORDS[i]} != -* ]]; then
-	    if [[ ${COMP_WORDS[i-1]} != @($global_args) ]]; then
-		_hg_cmd_qguard
-		return 0
-	    fi
-	elif [ "${COMP_WORDS[i]}" = -- ]; then
-	    _hg_cmd_qguard
-	    return 0
-	fi
+        if [[ ${COMP_WORDS[i]} != -* ]]; then
+            if [[ ${COMP_WORDS[i-1]} != @($global_args) ]]; then
+                _hg_cmd_qguard
+                return 0
+            fi
+        elif [ "${COMP_WORDS[i]}" = -- ]; then
+            _hg_cmd_qguard
+            return 0
+        fi
     done
     return 1
 }
@@ -484,24 +535,24 @@
 
     # 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
+        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
+        COMPREPLY=(${COMPREPLY[@]:-}
+                   $(compgen -W 'bad good help init next reset' -- "$cur"))
+        return
     fi
 
     case "$subcmd" in
-	good|bad)
-	    _hg_labels
-	    ;;
+        good|bad)
+            _hg_labels
+            ;;
     esac
 
     return
@@ -512,28 +563,28 @@
 _hg_cmd_email()
 {
     case "$prev" in
-	-c|--cc|-t|--to|-f|--from|--bcc)
-	    # 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
-	    ;;
+        -c|--cc|-t|--to|-f|--from|--bcc)
+            # 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_labels
@@ -552,15 +603,15 @@
 _hg_cmd_transplant()
 {
     case "$prev" in
-	-s|--source)
-	    _hg_paths
-	    _hg_repos
-	    return
-	    ;;
-	--filter)
-	    # standard filename completion
-	    return
-	    ;;
+        -s|--source)
+            _hg_paths
+            _hg_repos
+            return
+            ;;
+        --filter)
+            # standard filename completion
+            return
+            ;;
     esac
 
     # all other transplant options values and command parameters are revisions
@@ -571,14 +622,18 @@
 # shelve
 _hg_shelves()
 {
-    local shelves="$(_hg_cmd unshelve -l .)"
+    local shelves="$(_hg_cmd shelve -ql)"
     local IFS=$'\n'
     COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$shelves' -- "$cur"))
 }
 
 _hg_cmd_shelve()
 {
-    _hg_status "mard"
+    if [[ "$prev" = @(-d|--delete) ]]; then
+        _hg_shelves
+    else
+        _hg_status "mard"
+    fi
 }
 
 _hg_cmd_unshelve()
--- a/contrib/check-code.py	Mon Jan 20 11:16:26 2014 -0200
+++ b/contrib/check-code.py	Tue Jan 21 14:44:01 2014 -0600
@@ -7,6 +7,18 @@
 # This software may be used and distributed according to the terms of the
 # GNU General Public License version 2 or any later version.
 
+"""style and portability checker for Mercurial
+
+when a rule triggers wrong, do one of the following (prefer one from top):
+ * do the work-around the rule suggests
+ * doublecheck that it is a false match
+ * improve the rule pattern
+ * add an ignore pattern to the rule (3rd arg) which matches your good line
+   (you can append a short comment and match this, like: #re-raises, # no-py24)
+ * change the pattern to a warning and list the exception in test-check-code-hg
+ * ONLY use no--check-code for skipping entire files from external sources
+"""
+
 import re, glob, os, sys
 import keyword
 import optparse
@@ -141,17 +153,15 @@
     (r'^  saved backup bundle to \$TESTTMP.*\.hg$', winglobmsg),
     (r'^  changeset .* references (corrupted|missing) \$TESTTMP/.*[^)]$',
      winglobmsg),
-    (r'^  pulling from \$TESTTMP/.*[^)]$', winglobmsg, '\$TESTTMP/unix-repo$'),
-    (r'^  reverting .*/.*[^)]$', winglobmsg, '\$TESTTMP/unix-repo$'),
-    (r'^  cloning subrepo \S+/.*[^)]$', winglobmsg, '\$TESTTMP/unix-repo$'),
-    (r'^  pushing to \$TESTTMP/.*[^)]$', winglobmsg, '\$TESTTMP/unix-repo$'),
-    (r'^  pushing subrepo \S+/\S+ to.*[^)]$', winglobmsg,
-     '\$TESTTMP/unix-repo$'),
+    (r'^  pulling from \$TESTTMP/.*[^)]$', winglobmsg,
+     '\$TESTTMP/unix-repo$'), # in test-issue1802.t which skipped on windows
+    (r'^  reverting .*/.*[^)]$', winglobmsg),
+    (r'^  cloning subrepo \S+/.*[^)]$', winglobmsg),
+    (r'^  pushing to \$TESTTMP/.*[^)]$', winglobmsg),
+    (r'^  pushing subrepo \S+/\S+ to.*[^)]$', winglobmsg),
     (r'^  moving \S+/.*[^)]$', winglobmsg),
-    (r'^  no changes made to subrepo since.*/.*[^)]$',
-     winglobmsg, '\$TESTTMP/unix-repo$'),
-    (r'^  .*: largefile \S+ not available from file:.*/.*[^)]$',
-     winglobmsg, '\$TESTTMP/unix-repo$'),
+    (r'^  no changes made to subrepo since.*/.*[^)]$', winglobmsg),
+    (r'^  .*: largefile \S+ not available from file:.*/.*[^)]$', winglobmsg),
   ],
   # warnings
   [
@@ -227,7 +237,7 @@
     (r'^\s*except.* as .*:', "except as not available in Python 2.4"),
     (r'^\s*os\.path\.relpath', "relpath not available in Python 2.4"),
     (r'(?<!def)\s+(any|all|format)\(',
-     "any/all/format not available in Python 2.4"),
+     "any/all/format not available in Python 2.4", 'no-py24'),
     (r'(?<!def)\s+(callable)\(',
      "callable not available in Python 3, use getattr(f, '__call__', None)"),
     (r'if\s.*\selse', "if ... else form not available in Python 2.4"),
@@ -264,7 +274,7 @@
     (r'[\s\(](open|file)\([^)]*\)\.read\(',
      "use util.readfile() instead"),
     (r'[\s\(](open|file)\([^)]*\)\.write\(',
-     "use util.readfile() instead"),
+     "use util.writefile() instead"),
     (r'^[\s\(]*(open(er)?|file)\([^)]*\)',
      "always assign an opened file to a variable, and close it afterwards"),
     (r'[\s\(](open|file)\([^)]*\)\.',
@@ -443,10 +453,8 @@
         pre = post = fp.read()
         fp.close()
         if "no-" "check-code" in pre:
-            if debug:
-                print "Skipping %s for %s it has no-" "check-code" % (
-                       name, f)
-            break
+            print "Skipping %s it has no-" "check-code" % f
+            return "Skip" # skip checking this file
         for p, r in filters:
             post = re.sub(p, r, post)
         nerrs = len(pats[0]) # nerr elements are errors
@@ -486,13 +494,11 @@
                     n += 1
                 l = prelines[n]
 
-                if "check-code" "-ignore" in l:
+                if ignore and re.search(ignore, l, re.MULTILINE):
                     if debug:
-                        print "Skipping %s for %s:%s (check-code" "-ignore)" % (
+                        print "Skipping %s for %s:%s (ignore pattern)" % (
                             name, f, n)
                     continue
-                elif ignore and re.search(ignore, l, re.MULTILINE):
-                    continue
                 bd = ""
                 if blame:
                     bd = 'working directory'
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/editmerge	Tue Jan 21 14:44:01 2014 -0600
@@ -0,0 +1,58 @@
+#!/bin/bash
+# A simple script for opening merge conflicts in the editor.
+# Use the following Mercurial settings to enable it.
+#
+# [ui]
+# merge = editmerge
+#
+# [merge-tools]
+# editmerge.args=$output
+# editmerge.check=changed
+# editmerge.premerge=keep
+
+FILE=$1
+
+getlines() {
+  grep -n "<<<<<<" $FILE | cut -f1 -d:
+}
+
+# editor preference loosely based on http://mercurial.selenic.com/wiki/editor
+# hg showconfig is at the bottom though, since it's slow to run (0.15 seconds)
+ED=$HGEDITOR
+if [ "$ED" = "" ] ; then
+  ED=$VISUAL
+fi
+if [ "$ED" = "" ] ; then
+  ED=$EDITOR
+fi
+if [ "$ED" = "" ] ; then
+  ED=$(hg showconfig ui.editor)
+fi
+if [ "$ED" = "" ] ; then
+  echo "merge failed - unable to find editor"
+  exit 1
+fi
+
+if [ "$ED" = "emacs" ] || [ "$ED" = "nano" ] || [ "$ED" = "vim" ] ; then
+  FIRSTLINE=$(getlines | head -n 1)
+  PREVIOUSLINE=""
+
+  # open the editor to the first conflict until there are no more
+  # or the user stops editing the file
+  while [ ! "$FIRSTLINE" = "" ] && [ ! "$FIRSTLINE" = "$PREVIOUSLINE" ] ; do
+    $ED +$FIRSTLINE $FILE
+    PREVIOUSLINE=$FIRSTLINE
+    FIRSTLINE=$(getlines | head -n 1)
+  done
+else
+  $ED $FILE
+fi
+
+# get the line numbers of the remaining conflicts
+CONFLICTS=$(getlines | sed ':a;N;$!ba;s/\n/, /g')
+if [ ! "$CONFLICTS" = "" ] ; then
+  echo "merge failed - resolve the conflicts (line $CONFLICTS) then use 'hg resolve --mark'"
+  exit 1
+fi
+
+exit 0
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/contrib/import-checker.py	Tue Jan 21 14:44:01 2014 -0600
@@ -0,0 +1,244 @@
+import ast
+import os
+import sys
+
+# Import a minimal set of stdlib modules needed for list_stdlib_modules()
+# to work when run from a virtualenv.  The modules were chosen empirically
+# so that the return value matches the return value without virtualenv.
+import BaseHTTPServer
+import zlib
+
+def dotted_name_of_path(path):
+    """Given a relative path to a source file, return its dotted module name.
+
+
+    >>> dotted_name_of_path('mercurial/error.py')
+    'mercurial.error'
+    """
+    parts = path.split('/')
+    parts[-1] = parts[-1][:-3] # remove .py
+    return '.'.join(parts)
+
+
+def list_stdlib_modules():
+    """List the modules present in the stdlib.
+
+    >>> mods = set(list_stdlib_modules())
+    >>> 'BaseHTTPServer' in mods
+    True
+
+    os.path isn't really a module, so it's missing:
+
+    >>> 'os.path' in mods
+    False
+
+    sys requires special treatment, because it's baked into the
+    interpreter, but it should still appear:
+
+    >>> 'sys' in mods
+    True
+
+    >>> 'collections' in mods
+    True
+
+    >>> 'cStringIO' in mods
+    True
+    """
+    for m in sys.builtin_module_names:
+        yield m
+    # These modules only exist on windows, but we should always
+    # consider them stdlib.
+    for m in ['msvcrt', '_winreg']:
+        yield m
+    # These get missed too
+    for m in 'ctypes', 'email':
+        yield m
+    yield 'builtins' # python3 only
+    stdlib_prefixes = set([sys.prefix, sys.exec_prefix])
+    # We need to supplement the list of prefixes for the search to work
+    # when run from within a virtualenv.
+    for mod in (BaseHTTPServer, zlib):
+        try:
+            # Not all module objects have a __file__ attribute.
+            filename = mod.__file__
+        except AttributeError:
+            continue
+        dirname = os.path.dirname(filename)
+        for prefix in stdlib_prefixes:
+            if dirname.startswith(prefix):
+                # Then this directory is redundant.
+                break
+        else:
+            stdlib_prefixes.add(dirname)
+    for libpath in sys.path:
+        # We want to walk everything in sys.path that starts with
+        # something in stdlib_prefixes. check-code suppressed because
+        # the ast module used by this script implies the availability
+        # of any().
+        if not any(libpath.startswith(p) for p in stdlib_prefixes): # no-py24
+            continue
+        if 'site-packages' in libpath:
+            continue
+        for top, dirs, files in os.walk(libpath):
+            for name in files:
+                if name == '__init__.py':
+                    continue
+                if not (name.endswith('.py') or name.endswith('.so')):
+                    continue
+                full_path = os.path.join(top, name)
+                if 'site-packages' in full_path:
+                    continue
+                rel_path = full_path[len(libpath) + 1:]
+                mod = dotted_name_of_path(rel_path)
+                yield mod
+
+stdlib_modules = set(list_stdlib_modules())
+
+def imported_modules(source, ignore_nested=False):
+    """Given the source of a file as a string, yield the names
+    imported by that file.
+
+    Args:
+      source: The python source to examine as a string.
+      ignore_nested: If true, import statements that do not start in
+                     column zero will be ignored.
+
+    Returns:
+      A list of module names imported by the given source.
+
+    >>> sorted(imported_modules(
+    ...         'import foo ; from baz import bar; import foo.qux'))
+    ['baz.bar', 'foo', 'foo.qux']
+    >>> sorted(imported_modules(
+    ... '''import foo
+    ... def wat():
+    ...     import bar
+    ... ''', ignore_nested=True))
+    ['foo']
+    """
+    for node in ast.walk(ast.parse(source)):
+        if ignore_nested and getattr(node, 'col_offset', 0) > 0:
+            continue
+        if isinstance(node, ast.Import):
+            for n in node.names:
+                yield n.name
+        elif isinstance(node, ast.ImportFrom):
+            prefix = node.module + '.'
+            for n in node.names:
+                yield prefix + n.name
+
+def verify_stdlib_on_own_line(source):
+    """Given some python source, verify that stdlib imports are done
+    in separate statements from relative local module imports.
+
+    Observing this limitation is important as it works around an
+    annoying lib2to3 bug in relative import rewrites:
+    http://bugs.python.org/issue19510.
+
+    >>> list(verify_stdlib_on_own_line('import sys, foo'))
+    ['mixed stdlib and relative imports:\\n   foo, sys']
+    >>> list(verify_stdlib_on_own_line('import sys, os'))
+    []
+    >>> list(verify_stdlib_on_own_line('import foo, bar'))
+    []
+    """
+    for node in ast.walk(ast.parse(source)):
+        if isinstance(node, ast.Import):
+            from_stdlib = {}
+            for n in node.names:
+                from_stdlib[n.name] = n.name in stdlib_modules
+            num_std = len([x for x in from_stdlib.values() if x])
+            if num_std not in (len(from_stdlib.values()), 0):
+                yield ('mixed stdlib and relative imports:\n   %s' %
+                       ', '.join(sorted(from_stdlib.iterkeys())))
+
+class CircularImport(Exception):
+    pass
+
+
+def cyclekey(names):
+    return tuple(sorted(set(names)))
+
+def check_one_mod(mod, imports, path=None, ignore=None):
+    if path is None:
+        path = []
+    if ignore is None:
+        ignore = []
+    path = path + [mod]
+    for i in sorted(imports.get(mod, [])):
+        if i not in stdlib_modules:
+            i = mod.rsplit('.', 1)[0] + '.' + i
+        if i in path:
+            firstspot = path.index(i)
+            cycle = path[firstspot:] + [i]
+            if cyclekey(cycle) not in ignore:
+                raise CircularImport(cycle)
+            continue
+        check_one_mod(i, imports, path=path, ignore=ignore)
+
+def rotatecycle(cycle):
+    """arrange a cycle so that the lexicographically first module listed first
+
+    >>> rotatecycle(['foo', 'bar', 'foo'])
+    ['bar', 'foo', 'bar']
+    """
+    lowest = min(cycle)
+    idx = cycle.index(lowest)
+    return cycle[idx:] + cycle[1:idx] + [lowest]
+
+def find_cycles(imports):
+    """Find cycles in an already-loaded import graph.
+
+    >>> imports = {'top.foo': ['bar', 'os.path', 'qux'],
+    ...            'top.bar': ['baz', 'sys'],
+    ...            'top.baz': ['foo'],
+    ...            'top.qux': ['foo']}
+    >>> print '\\n'.join(sorted(find_cycles(imports)))
+    top.bar -> top.baz -> top.foo -> top.bar -> top.bar
+    top.foo -> top.qux -> top.foo -> top.foo
+    """
+    cycles = {}
+    for mod in sorted(imports.iterkeys()):
+        try:
+            check_one_mod(mod, imports, ignore=cycles)
+        except CircularImport, e:
+            cycle = e.args[0]
+            cycles[cyclekey(cycle)] = ' -> '.join(rotatecycle(cycle))
+    return cycles.values()
+
+def _cycle_sortkey(c):
+    return len(c), c
+
+def main(argv):
+    if len(argv) < 2:
+        print 'Usage: %s file [file] [file] ...'
+        return 1
+    used_imports = {}
+    any_errors = False
+    for source_path in argv[1:]:
+        f = open(source_path)
+        modname = dotted_name_of_path(source_path)
+        src = f.read()
+        used_imports[modname] = sorted(
+            imported_modules(src, ignore_nested=True))
+        for error in verify_stdlib_on_own_line(src):
+            any_errors = True
+            print source_path, error
+        f.close()
+    cycles = find_cycles(used_imports)
+    if cycles:
+        firstmods = set()
+        for c in sorted(cycles, key=_cycle_sortkey):
+            first = c.split()[0]
+            # As a rough cut, ignore any cycle that starts with the
+            # same module as some other cycle. Otherwise we see lots
+            # of cycles that are effectively duplicates.
+            if first in firstmods:
+                continue
+            print 'Import cycle:', c
+            firstmods.add(first)
+        any_errors = True
+    return not any_errors
+
+if __name__ == '__main__':
+    sys.exit(int(main(sys.argv)))
--- a/contrib/lock-checker.py	Mon Jan 20 11:16:26 2014 -0200
+++ b/contrib/lock-checker.py	Tue Jan 21 14:44:01 2014 -0600
@@ -7,21 +7,12 @@
 This currently only checks store locks, not working copy locks.
 """
 import os
-import traceback
-
-def _warnstack(ui, msg, skip=1):
-    '''issue warning with the message and the current stack, skipping the
-    skip last entries'''
-    ui.warn('%s at:\n' % msg)
-    entries = traceback.extract_stack()[:-skip]
-    fnmax = max(len(entry[0]) for entry in entries)
-    for fn, ln, func, _text in entries:
-        ui.warn(' %*s:%-4s in %s\n' % (fnmax, fn, ln, func))
+from mercurial import util
 
 def _checklock(repo):
     l = repo._lockref and repo._lockref()
     if l is None or not l.held:
-        _warnstack(repo.ui, 'missing lock', skip=2)
+        util.debugstacktrace('missing lock', skip=1)
 
 def reposetup(ui, repo):
     orig = repo.__class__
--- a/contrib/perf.py	Mon Jan 20 11:16:26 2014 -0200
+++ b/contrib/perf.py	Tue Jan 21 14:44:01 2014 -0600
@@ -243,6 +243,18 @@
                                copies=opts.get('rename')))
     ui.popbuffer()
 
+@command('perfmoonwalk')
+def perfmoonwalk(ui, repo):
+    """benchmark walking the changelog backwards
+
+    This also loads the changelog data for each revision in the changelog.
+    """
+    def moonwalk():
+        for i in xrange(len(repo), -1, -1):
+            ctx = repo[i]
+            ctx.branch() # read changelog data (in addition to the index)
+    timer(moonwalk)
+
 @command('perftemplating')
 def perftemplating(ui, repo):
     ui.pushbuffer()
@@ -349,7 +361,7 @@
     def getfiltered(name):
         def d():
             repo.invalidatevolatilesets()
-            repoview.filteredrevs(repo, name)
+            repoview.filterrevs(repo, name)
         return d
 
     allfilter = sorted(repoview.filtertable)
@@ -386,7 +398,7 @@
     allfilters = []
     while possiblefilters:
         for name in possiblefilters:
-            subset = repoview.subsettable.get(name)
+            subset = branchmap.subsettable.get(name)
             if subset not in possiblefilters:
                 break
         else:
--- a/contrib/win32/ReadMe.html	Mon Jan 20 11:16:26 2014 -0200
+++ b/contrib/win32/ReadMe.html	Tue Jan 21 14:44:01 2014 -0600
@@ -140,7 +140,7 @@
     </p>
 
     <p>
-      Mercurial is Copyright 2005-2013 Matt Mackall and others. See
+      Mercurial is Copyright 2005-2014 Matt Mackall and others. See
       the <tt>Contributors.txt</tt> file for a list of contributors.
     </p>
 
--- a/doc/gendoc.py	Mon Jan 20 11:16:26 2014 -0200
+++ b/doc/gendoc.py	Tue Jan 21 14:44:01 2014 -0600
@@ -40,11 +40,16 @@
             shortopt, longopt, default, desc, optlabel = opt
         else:
             shortopt, longopt, default, desc = opt
+            optlabel = _("VALUE")
         allopts = []
         if shortopt:
             allopts.append("-%s" % shortopt)
         if longopt:
             allopts.append("--%s" % longopt)
+        if isinstance(default, list):
+            allopts[-1] += " <%s[+]>" % optlabel
+        elif (default is not None) and not isinstance(default, bool):
+            allopts[-1] += " <%s>" % optlabel
         desc += default and _(" (default: %s)") % default or ""
         yield (", ".join(allopts), desc)
 
@@ -71,8 +76,14 @@
 def showdoc(ui):
     # print options
     ui.write(minirst.section(_("Options")))
+    multioccur = False
     for optstr, desc in get_opts(globalopts):
         ui.write("%s\n    %s\n\n" % (optstr, desc))
+        if optstr.endswith("[+]>"):
+            multioccur = True
+    if multioccur:
+        ui.write(_("\n[+] marked option can be specified multiple times\n"))
+        ui.write("\n")
 
     # print cmds
     ui.write(minirst.section(_("Commands")))
@@ -157,12 +168,18 @@
         if opt_output:
             opts_len = max([len(line[0]) for line in opt_output])
             ui.write(_("Options:\n\n"))
+            multioccur = False
             for optstr, desc in opt_output:
                 if desc:
                     s = "%-*s  %s" % (opts_len, optstr, desc)
                 else:
                     s = optstr
                 ui.write("%s\n" % s)
+                if optstr.endswith("[+]>"):
+                    multioccur = True
+            if multioccur:
+                ui.write(_("\n[+] marked option can be specified"
+                           " multiple times\n"))
             ui.write("\n")
         # aliases
         if d['aliases']:
--- a/hgext/convert/filemap.py	Mon Jan 20 11:16:26 2014 -0200
+++ b/hgext/convert/filemap.py	Tue Jan 21 14:44:01 2014 -0600
@@ -10,12 +10,20 @@
 from mercurial import util, error
 from common import SKIPREV, converter_source
 
-def rpairs(name):
-    e = len(name)
-    while e != -1:
-        yield name[:e], name[e + 1:]
-        e = name.rfind('/', 0, e)
-    yield '.', name
+def rpairs(path):
+    '''Yield tuples with path split at '/', starting with the full path.
+    No leading, trailing or double '/', please.
+    >>> for x in rpairs('foo/bar/baz'): print x
+    ('foo/bar/baz', '')
+    ('foo/bar', 'baz')
+    ('foo', 'bar/baz')
+    ('.', 'foo/bar/baz')
+    '''
+    i = len(path)
+    while i != -1:
+        yield path[:i], path[i + 1:]
+        i = path.rfind('/', 0, i)
+    yield '.', path
 
 def normalize(path):
     ''' We use posixpath.normpath to support cross-platform path format.
--- a/hgext/graphlog.py	Mon Jan 20 11:16:26 2014 -0200
+++ b/hgext/graphlog.py	Tue Jan 21 14:44:01 2014 -0600
@@ -5,7 +5,10 @@
 # This software may be used and distributed according to the terms of the
 # GNU General Public License version 2 or any later version.
 
-'''command to view revision graphs from a shell
+'''command to view revision graphs from a shell (DEPRECATED)
+
+The functionality of this extension has been include in core Mercurial
+since version 2.3.
 
 This extension adds a --graph option to the incoming, outgoing and log
 commands. When this options is given, an ASCII representation of the
--- a/hgext/keyword.py	Mon Jan 20 11:16:26 2014 -0200
+++ b/hgext/keyword.py	Tue Jan 21 14:44:01 2014 -0600
@@ -84,7 +84,7 @@
 
 from mercurial import commands, context, cmdutil, dispatch, filelog, extensions
 from mercurial import localrepo, match, patch, templatefilters, templater, util
-from mercurial import scmutil
+from mercurial import scmutil, pathutil
 from mercurial.hgweb import webcommands
 from mercurial.i18n import _
 import os, re, shutil, tempfile
@@ -439,12 +439,16 @@
     repo[None].add([fn])
     ui.note(_('\nkeywords written to %s:\n') % fn)
     ui.note(keywords)
-    repo.dirstate.setbranch('demobranch')
+    wlock = repo.wlock()
+    try:
+        repo.dirstate.setbranch('demobranch')
+    finally:
+        wlock.release()
     for name, cmd in ui.configitems('hooks'):
         if name.split('.', 1)[0].find('commit') > -1:
             repo.ui.setconfig('hooks', name, '')
     msg = _('hg keyword configuration and expansion example')
-    ui.note("hg ci -m '%s'\n" % msg) # check-code-ignore
+    ui.note(("hg ci -m '%s'\n" % msg))
     repo.commit(text=msg)
     ui.status(_('\n\tkeywords expanded\n'))
     ui.write(repo.wread(fn))
@@ -673,7 +677,7 @@
                 expansion. '''
                 source = repo.dirstate.copied(dest)
                 if 'l' in wctx.flags(source):
-                    source = scmutil.canonpath(repo.root, cwd,
+                    source = pathutil.canonpath(repo.root, cwd,
                                                os.path.realpath(source))
                 return kwt.match(source)
 
--- a/hgext/largefiles/overrides.py	Mon Jan 20 11:16:26 2014 -0200
+++ b/hgext/largefiles/overrides.py	Tue Jan 21 14:44:01 2014 -0600
@@ -12,7 +12,7 @@
 import copy
 
 from mercurial import hg, commands, util, cmdutil, scmutil, match as match_, \
-    node, archival, error, merge, discovery
+    node, archival, error, merge, discovery, pathutil
 from mercurial.i18n import _
 from mercurial.node import hex
 from hgext import rebase
@@ -415,47 +415,23 @@
     return processed
 
 # Override filemerge to prompt the user about how they wish to merge
-# largefiles. This will handle identical edits, and copy/rename +
-# edit without prompting the user.
+# largefiles. This will handle identical edits without prompting the user.
 def overridefilemerge(origfn, repo, mynode, orig, fcd, fco, fca):
-    # Use better variable names here. Because this is a wrapper we cannot
-    # change the variable names in the function declaration.
-    fcdest, fcother, fcancestor = fcd, fco, fca
     if not lfutil.isstandin(orig):
-        return origfn(repo, mynode, orig, fcdest, fcother, fcancestor)
-    else:
-        if not fcother.cmp(fcdest): # files identical?
-            return None
+        return origfn(repo, mynode, orig, fcd, fco, fca)
 
-        # backwards, use working dir parent as ancestor
-        if fcancestor == fcother:
-            fcancestor = fcdest.parents()[0]
+    if not fco.cmp(fcd): # files identical?
+        return None
 
-        if orig != fcother.path():
-            repo.ui.status(_('merging %s and %s to %s\n')
-                           % (lfutil.splitstandin(orig),
-                              lfutil.splitstandin(fcother.path()),
-                              lfutil.splitstandin(fcdest.path())))
-        else:
-            repo.ui.status(_('merging %s\n')
-                           % lfutil.splitstandin(fcdest.path()))
-
-        if fcancestor.path() != fcother.path() and fcother.data() == \
-                fcancestor.data():
-            return 0
-        if fcancestor.path() != fcdest.path() and fcdest.data() == \
-                fcancestor.data():
-            repo.wwrite(fcdest.path(), fcother.data(), fcother.flags())
-            return 0
-
-        if repo.ui.promptchoice(_('largefile %s has a merge conflict\n'
-                                  'keep (l)ocal or take (o)ther?'
-                                  '$$ &Local $$ &Other') %
-                                lfutil.splitstandin(orig), 0) == 0:
-            return 0
-        else:
-            repo.wwrite(fcdest.path(), fcother.data(), fcother.flags())
-            return 0
+    if repo.ui.promptchoice(
+        _('largefile %s has a merge conflict\nancestor was %s\n'
+          'keep (l)ocal %s or\ntake (o)ther %s?'
+          '$$ &Local $$ &Other') %
+          (lfutil.splitstandin(orig),
+           fca.data().strip(), fcd.data().strip(), fco.data().strip()),
+        0) == 1:
+        repo.wwrite(fcd.path(), fco.data(), fco.flags())
+    return 0
 
 # Copy first changes the matchers to match standins instead of
 # largefiles.  Then it overrides util.copyfile in that function it
@@ -469,7 +445,7 @@
         return orig(ui, repo, pats, opts, rename)
 
     def makestandin(relpath):
-        path = scmutil.canonpath(repo.root, repo.getcwd(), relpath)
+        path = pathutil.canonpath(repo.root, repo.getcwd(), relpath)
         return os.path.join(repo.wjoin(lfutil.standin(path)))
 
     fullpats = scmutil.expandpats(pats)
--- a/hgext/largefiles/reposetup.py	Mon Jan 20 11:16:26 2014 -0200
+++ b/hgext/largefiles/reposetup.py	Tue Jan 21 14:44:01 2014 -0600
@@ -445,8 +445,8 @@
                              for f in files
                              if lfutil.isstandin(f) and f in ctx]))
                 lfcommands.uploadlfiles(ui, self, remote, toupload)
-            return super(lfilesrepo, self).push(remote, force, revs,
-                newbranch)
+            return super(lfilesrepo, self).push(remote, force=force, revs=revs,
+                newbranch=newbranch)
 
         def _subdirlfs(self, files, lfiles):
             '''
--- a/hgext/mq.py	Mon Jan 20 11:16:26 2014 -0200
+++ b/hgext/mq.py	Tue Jan 21 14:44:01 2014 -0600
@@ -1204,7 +1204,9 @@
         diffopts = self.diffopts()
         wlock = repo.wlock()
         try:
-            heads = [h for hs in repo.branchmap().itervalues() for h in hs]
+            heads = []
+            for hs in repo.branchmap().itervalues():
+                heads.extend(hs)
             if not heads:
                 heads = [nullid]
             if repo.dirstate.p1() not in heads and not exact:
@@ -2565,8 +2567,10 @@
         ph = patchheader(q.join(parent), q.plainmode)
         message, user = ph.message, ph.user
         for msg in messages:
-            message.append('* * *')
-            message.extend(msg)
+            if msg:
+                if message:
+                    message.append('* * *')
+                message.extend(msg)
         message = '\n'.join(message)
 
     if opts.get('edit'):
--- a/hgext/rebase.py	Mon Jan 20 11:16:26 2014 -0200
+++ b/hgext/rebase.py	Tue Jan 21 14:44:01 2014 -0600
@@ -221,46 +221,73 @@
 
             if revf:
                 rebaseset = scmutil.revrange(repo, revf)
+                if not rebaseset:
+                    raise util.Abort(_('empty "rev" revision set - '
+                                       'nothing to rebase'))
             elif srcf:
                 src = scmutil.revrange(repo, [srcf])
+                if not src:
+                    raise util.Abort(_('empty "source" revision set - '
+                                       'nothing to rebase'))
                 rebaseset = repo.revs('(%ld)::', src)
+                assert rebaseset
             else:
                 base = scmutil.revrange(repo, [basef or '.'])
+                if not base:
+                    raise util.Abort(_('empty "base" revision set - '
+                                       "can't compute rebase set"))
                 rebaseset = repo.revs(
                     '(children(ancestor(%ld, %d)) and ::(%ld))::',
                     base, dest, base)
-            if rebaseset:
-                root = min(rebaseset)
-            else:
-                root = None
+                if not rebaseset:
+                    if base == [dest.rev()]:
+                        if basef:
+                            ui.status(_('nothing to rebase - %s is both "base"'
+                                        ' and destination\n') % dest)
+                        else:
+                            ui.status(_('nothing to rebase - working directory '
+                                        'parent is also destination\n'))
+                    elif not repo.revs('%ld - ::%d', base, dest):
+                        if basef:
+                            ui.status(_('nothing to rebase - "base" %s is '
+                                        'already an ancestor of destination '
+                                        '%s\n') %
+                                      ('+'.join(str(repo[r]) for r in base),
+                                       dest))
+                        else:
+                            ui.status(_('nothing to rebase - working '
+                                        'directory parent is already an '
+                                        'ancestor of destination %s\n') % dest)
+                    else: # can it happen?
+                        ui.status(_('nothing to rebase from %s to %s\n') %
+                                  ('+'.join(str(repo[r]) for r in base), dest))
+                    return 1
 
-            if not rebaseset:
-                repo.ui.debug('base is ancestor of destination\n')
-                result = None
-            elif (not (keepf or obsolete._enabled)
+            if (not (keepf or obsolete._enabled)
                   and repo.revs('first(children(%ld) - %ld)',
                                 rebaseset, rebaseset)):
                 raise util.Abort(
                     _("can't remove original changesets with"
                       " unrebased descendants"),
                     hint=_('use --keep to keep original changesets'))
-            else:
-                result = buildstate(repo, dest, rebaseset, collapsef)
 
+            result = buildstate(repo, dest, rebaseset, collapsef)
             if not result:
                 # Empty state built, nothing to rebase
                 ui.status(_('nothing to rebase\n'))
                 return 1
-            elif not keepf and not repo[root].mutable():
+
+            root = min(rebaseset)
+            if not keepf and not repo[root].mutable():
                 raise util.Abort(_("can't rebase immutable changeset %s")
                                  % repo[root],
                                  hint=_('see hg help phases for details'))
-            else:
-                originalwd, target, state = result
-                if collapsef:
-                    targetancestors = repo.changelog.ancestors([target],
-                                                               inclusive=True)
-                    external = externalparent(repo, state, targetancestors)
+
+            originalwd, target, state = result
+            if collapsef:
+                targetancestors = repo.changelog.ancestors([target],
+                                                           inclusive=True)
+                external = externalparent(repo, state, targetancestors)
 
         if keepbranchesf:
             # insert _savebranch at the start of extrafns so if
@@ -275,7 +302,6 @@
                         raise util.Abort(_('cannot collapse multiple named '
                             'branches'))
 
-
         # Rebase
         if not targetancestors:
             targetancestors = repo.changelog.ancestors([target], inclusive=True)
--- a/hgext/record.py	Mon Jan 20 11:16:26 2014 -0200
+++ b/hgext/record.py	Tue Jan 21 14:44:01 2014 -0600
@@ -7,7 +7,7 @@
 
 '''commands to interactively select changes for commit/qrefresh'''
 
-from mercurial.i18n import gettext, _
+from mercurial.i18n import _
 from mercurial import cmdutil, commands, extensions, hg, patch
 from mercurial import util
 import copy, cStringIO, errno, os, re, shutil, tempfile
@@ -18,15 +18,6 @@
 
 lines_re = re.compile(r'@@ -(\d+),(\d+) \+(\d+),(\d+) @@\s*(.*)')
 
-diffopts = [
-    ('w', 'ignore-all-space', False,
-     _('ignore white space when comparing lines')),
-    ('b', 'ignore-space-change', None,
-     _('ignore changes in the amount of white space')),
-    ('B', 'ignore-blank-lines', None,
-     _('ignore changes whose lines are all blank')),
-]
-
 def scanpatch(fp):
     """like patch.iterhunks, but yield different events
 
@@ -286,21 +277,18 @@
             resps = _('[Ynesfdaq?]'
                       '$$ &Yes, record this change'
                       '$$ &No, skip this change'
-                      '$$ &Edit the change manually'
+                      '$$ &Edit this change manually'
                       '$$ &Skip remaining changes to this file'
                       '$$ Record remaining changes to this &file'
                       '$$ &Done, skip remaining changes and files'
                       '$$ Record &all changes to all remaining files'
                       '$$ &Quit, recording no changes'
-                      '$$ &?')
+                      '$$ &? (display help)')
             r = ui.promptchoice("%s %s" % (query, resps))
             ui.write("\n")
             if r == 8: # ?
-                doc = gettext(record.__doc__)
-                c = doc.find('::') + 2
-                for l in doc[c:].splitlines():
-                    if l.startswith('      '):
-                        ui.write(l.strip(), '\n')
+                for c, t in ui.extractchoices(resps)[1]:
+                    ui.write('%s - %s\n' % (c, t.lower()))
                 continue
             elif r == 0: # yes
                 ret = True
@@ -423,7 +411,7 @@
 
 @command("record",
          # same options as commit + white space diff options
-         commands.table['^commit|ci'][1][:] + diffopts,
+         commands.table['^commit|ci'][1][:] + commands.diffwsopts,
           _('hg record [OPTION]... [FILE]...'))
 def record(ui, repo, *pats, **opts):
     '''interactively select changes to commit
@@ -502,7 +490,8 @@
                          cmdsuggest)
 
     # make sure username is set before going interactive
-    ui.username()
+    if not opts.get('user'):
+        ui.username() # raise exception, username not provided
 
     def recordfunc(ui, repo, message, match, opts):
         """This is generic record driver.
@@ -526,11 +515,10 @@
                                '(use "hg commit" instead)'))
 
         changes = repo.status(match=match)[:3]
-        diffopts = patch.diffopts(ui, opts=dict(
-            git=True, nodates=True,
-            ignorews=opts.get('ignore_all_space'),
-            ignorewsamount=opts.get('ignore_space_change'),
-            ignoreblanklines=opts.get('ignore_blank_lines')))
+        diffopts = opts.copy()
+        diffopts['nodates'] = True
+        diffopts['git'] = True
+        diffopts = patch.diffopts(ui, opts=diffopts)
         chunks = patch.diff(repo, changes=changes, opts=diffopts)
         fp = cStringIO.StringIO()
         fp.write(''.join(chunks))
@@ -667,7 +655,7 @@
         (qrecord,
          # same options as qnew, but copy them so we don't get
          # -i/--interactive for qrecord and add white space diff options
-         mq.cmdtable['^qnew'][1][:] + diffopts,
+         mq.cmdtable['^qnew'][1][:] + commands.diffwsopts,
          _('hg qrecord [OPTION]... PATCH [FILE]...'))
 
     _wrapcmd('qnew', mq.cmdtable, qnew, _("interactively record a new patch"))
--- a/hgext/relink.py	Mon Jan 20 11:16:26 2014 -0200
+++ b/hgext/relink.py	Tue Jan 21 14:44:01 2014 -0600
@@ -48,6 +48,10 @@
         ui.status(_('there is nothing to relink\n'))
         return
 
+    if not util.samedevice(src.store.path, repo.store.path):
+        # No point in continuing
+        raise util.Abort(_('source and destination are on different devices'))
+
     locallock = repo.lock()
     try:
         remotelock = src.lock()
--- a/hgext/strip.py	Mon Jan 20 11:16:26 2014 -0200
+++ b/hgext/strip.py	Tue Jan 21 14:44:01 2014 -0600
@@ -182,37 +182,32 @@
 
         revs = sorted(rootnodes)
         if update and opts.get('keep'):
-            wlock = repo.wlock()
-            try:
-                urev, p2 = repo.changelog.parents(revs[0])
-                if (util.safehasattr(repo, 'mq') and p2 != nullid
-                    and p2 in [x.node for x in repo.mq.applied]):
-                    urev = p2
-                uctx = repo[urev]
+            urev, p2 = repo.changelog.parents(revs[0])
+            if (util.safehasattr(repo, 'mq') and p2 != nullid
+                and p2 in [x.node for x in repo.mq.applied]):
+                urev = p2
+            uctx = repo[urev]
 
-                # only reset the dirstate for files that would actually change
-                # between the working context and uctx
-                descendantrevs = repo.revs("%s::." % uctx.rev())
-                changedfiles = []
-                for rev in descendantrevs:
-                    # blindly reset the files, regardless of what actually
-                    # changed
-                    changedfiles.extend(repo[rev].files())
+            # only reset the dirstate for files that would actually change
+            # between the working context and uctx
+            descendantrevs = repo.revs("%s::." % uctx.rev())
+            changedfiles = []
+            for rev in descendantrevs:
+                # blindly reset the files, regardless of what actually changed
+                changedfiles.extend(repo[rev].files())
 
-                # reset files that only changed in the dirstate too
-                dirstate = repo.dirstate
-                dirchanges = [f for f in dirstate if dirstate[f] != 'n']
-                changedfiles.extend(dirchanges)
+            # reset files that only changed in the dirstate too
+            dirstate = repo.dirstate
+            dirchanges = [f for f in dirstate if dirstate[f] != 'n']
+            changedfiles.extend(dirchanges)
 
-                repo.dirstate.rebuild(urev, uctx.manifest(), changedfiles)
-                repo.dirstate.write()
-                update = False
-            finally:
-                wlock.release()
+            repo.dirstate.rebuild(urev, uctx.manifest(), changedfiles)
+            repo.dirstate.write()
+            update = False
 
         if opts.get('bookmark'):
             if mark == repo._bookmarkcurrent:
-                bookmarks.setcurrent(repo, None)
+                bookmarks.unsetcurrent(repo)
             del marks[mark]
             marks.write()
             ui.write(_("bookmark '%s' deleted\n") % mark)
--- a/hgext/transplant.py	Mon Jan 20 11:16:26 2014 -0200
+++ b/hgext/transplant.py	Tue Jan 21 14:44:01 2014 -0600
@@ -154,7 +154,7 @@
                     # transplants before them fail.
                     domerge = True
                     if not hasnode(repo, node):
-                        repo.pull(source, heads=[node])
+                        repo.pull(source.peer(), heads=[node])
 
                 skipmerge = False
                 if parents[1] != revlog.nullid:
@@ -451,34 +451,31 @@
 
 def browserevs(ui, repo, nodes, opts):
     '''interactively transplant changesets'''
-    def browsehelp(ui):
-        ui.write(_('y: transplant this changeset\n'
-                   'n: skip this changeset\n'
-                   'm: merge at this changeset\n'
-                   'p: show patch\n'
-                   'c: commit selected changesets\n'
-                   'q: cancel transplant\n'
-                   '?: show this help\n'))
-
     displayer = cmdutil.show_changeset(ui, repo, opts)
     transplants = []
     merges = []
+    prompt = _('apply changeset? [ynmpcq?]:'
+               '$$ &yes, transplant this changeset'
+               '$$ &no, skip this changeset'
+               '$$ &merge at this changeset'
+               '$$ show &patch'
+               '$$ &commit selected changesets'
+               '$$ &quit and cancel transplant'
+               '$$ &? (show this help)')
     for node in nodes:
         displayer.show(repo[node])
         action = None
         while not action:
-            action = ui.prompt(_('apply changeset? [ynmpcq?]:'))
+            action = 'ynmpcq?'[ui.promptchoice(prompt)]
             if action == '?':
-                browsehelp(ui)
+                for c, t in ui.extractchoices(prompt)[1]:
+                    ui.write('%s: %s\n' % (c, t))
                 action = None
             elif action == 'p':
                 parent = repo.changelog.parents(node)[0]
                 for chunk in patch.diff(repo, parent, node):
                     ui.write(chunk)
                 action = None
-            elif action not in ('y', 'n', 'm', 'c', 'q'):
-                ui.write(_('no such option\n'))
-                action = None
         if action == 'y':
             transplants.append(node)
         elif action == 'm':
--- a/mercurial/ancestor.py	Mon Jan 20 11:16:26 2014 -0200
+++ b/mercurial/ancestor.py	Tue Jan 21 14:44:01 2014 -0600
@@ -5,7 +5,8 @@
 # This software may be used and distributed according to the terms of the
 # GNU General Public License version 2 or any later version.
 
-import heapq, util
+import heapq
+import util
 from node import nullrev
 
 def ancestors(pfunc, *orignodes):
--- a/mercurial/bookmarks.py	Mon Jan 20 11:16:26 2014 -0200
+++ b/mercurial/bookmarks.py	Tue Jan 21 14:44:01 2014 -0600
@@ -6,7 +6,7 @@
 # GNU General Public License version 2 or any later version.
 
 from mercurial.i18n import _
-from mercurial.node import hex
+from mercurial.node import hex, bin
 from mercurial import encoding, error, util, obsolete
 import errno
 
@@ -58,7 +58,7 @@
         '''
         repo = self._repo
         if repo._bookmarkcurrent not in self:
-            setcurrent(repo, None)
+            unsetcurrent(repo)
 
         wlock = repo.wlock()
         try:
@@ -106,13 +106,13 @@
     Set the name of the bookmark that we are on (hg update <bookmark>).
     The name is recorded in .hg/bookmarks.current
     '''
+    if mark not in repo._bookmarks:
+        raise AssertionError('bookmark %s does not exist!' % mark)
+
     current = repo._bookmarkcurrent
     if current == mark:
         return
 
-    if mark not in repo._bookmarks:
-        mark = ''
-
     wlock = repo.wlock()
     try:
         file = repo.opener('bookmarks.current', 'w', atomictemp=True)
@@ -192,13 +192,12 @@
         return False
 
     if marks[cur] in parents:
-        old = repo[marks[cur]]
         new = repo[node]
         divs = [repo[b] for b in marks
                 if b.split('@', 1)[0] == cur.split('@', 1)[0]]
         anc = repo.changelog.ancestors([new.rev()])
         deletefrom = [b.node() for b in divs if b.rev() in anc or b == new]
-        if old.descendant(new):
+        if validdest(repo, repo[marks[cur]], new):
             marks[cur] = new.node()
             update = True
 
@@ -239,49 +238,176 @@
     finally:
         w.release()
 
+def compare(repo, srcmarks, dstmarks,
+            srchex=None, dsthex=None, targets=None):
+    '''Compare bookmarks between srcmarks and dstmarks
+
+    This returns tuple "(addsrc, adddst, advsrc, advdst, diverge,
+    differ, invalid)", each are list of bookmarks below:
+
+    :addsrc:  added on src side (removed on dst side, perhaps)
+    :adddst:  added on dst side (removed on src side, perhaps)
+    :advsrc:  advanced on src side
+    :advdst:  advanced on dst side
+    :diverge: diverge
+    :differ:  changed, but changeset referred on src is unknown on dst
+    :invalid: unknown on both side
+
+    Each elements of lists in result tuple is tuple "(bookmark name,
+    changeset ID on source side, changeset ID on destination
+    side)". Each changeset IDs are 40 hexadecimal digit string or
+    None.
+
+    Changeset IDs of tuples in "addsrc", "adddst", "differ" or
+     "invalid" list may be unknown for repo.
+
+    This function expects that "srcmarks" and "dstmarks" return
+    changeset ID in 40 hexadecimal digit string for specified
+    bookmark. If not so (e.g. bmstore "repo._bookmarks" returning
+    binary value), "srchex" or "dsthex" should be specified to convert
+    into such form.
+
+    If "targets" is specified, only bookmarks listed in it are
+    examined.
+    '''
+    if not srchex:
+        srchex = lambda x: x
+    if not dsthex:
+        dsthex = lambda x: x
+
+    if targets:
+        bset = set(targets)
+    else:
+        srcmarkset = set(srcmarks)
+        dstmarkset = set(dstmarks)
+        bset = srcmarkset ^ dstmarkset
+        for b in srcmarkset & dstmarkset:
+            if srchex(srcmarks[b]) != dsthex(dstmarks[b]):
+                bset.add(b)
+
+    results = ([], [], [], [], [], [], [])
+    addsrc = results[0].append
+    adddst = results[1].append
+    advsrc = results[2].append
+    advdst = results[3].append
+    diverge = results[4].append
+    differ = results[5].append
+    invalid = results[6].append
+
+    for b in sorted(bset):
+        if b not in srcmarks:
+            if b in dstmarks:
+                adddst((b, None, dsthex(dstmarks[b])))
+            else:
+                invalid((b, None, None))
+        elif b not in dstmarks:
+            addsrc((b, srchex(srcmarks[b]), None))
+        else:
+            scid = srchex(srcmarks[b])
+            dcid = dsthex(dstmarks[b])
+            if scid in repo and dcid in repo:
+                sctx = repo[scid]
+                dctx = repo[dcid]
+                if sctx.rev() < dctx.rev():
+                    if validdest(repo, sctx, dctx):
+                        advdst((b, scid, dcid))
+                    else:
+                        diverge((b, scid, dcid))
+                else:
+                    if validdest(repo, dctx, sctx):
+                        advsrc((b, scid, dcid))
+                    else:
+                        diverge((b, scid, dcid))
+            else:
+                # it is too expensive to examine in detail, in this case
+                differ((b, scid, dcid))
+
+    return results
+
+def _diverge(ui, b, path, localmarks):
+    if b == '@':
+        b = ''
+    # find a unique @ suffix
+    for x in range(1, 100):
+        n = '%s@%d' % (b, x)
+        if n not in localmarks:
+            break
+    # try to use an @pathalias suffix
+    # if an @pathalias already exists, we overwrite (update) it
+    for p, u in ui.configitems("paths"):
+        if path == u:
+            n = '%s@%s' % (b, p)
+    return n
+
 def updatefromremote(ui, repo, remotemarks, path):
     ui.debug("checking for updated bookmarks\n")
-    changed = False
     localmarks = repo._bookmarks
-    for k in sorted(remotemarks):
-        if k in localmarks:
-            nr, nl = remotemarks[k], localmarks[k]
-            if nr in repo:
-                cr = repo[nr]
-                cl = repo[nl]
-                if cl.rev() >= cr.rev():
-                    continue
-                if validdest(repo, cl, cr):
-                    localmarks[k] = cr.node()
-                    changed = True
-                    ui.status(_("updating bookmark %s\n") % k)
-                else:
-                    if k == '@':
-                        kd = ''
-                    else:
-                        kd = k
-                    # find a unique @ suffix
-                    for x in range(1, 100):
-                        n = '%s@%d' % (kd, x)
-                        if n not in localmarks:
-                            break
-                    # try to use an @pathalias suffix
-                    # if an @pathalias already exists, we overwrite (update) it
-                    for p, u in ui.configitems("paths"):
-                        if path == u:
-                            n = '%s@%s' % (kd, p)
+    (addsrc, adddst, advsrc, advdst, diverge, differ, invalid
+     ) = compare(repo, remotemarks, localmarks, dsthex=hex)
+
+    changed = []
+    for b, scid, dcid in addsrc:
+        if scid in repo: # add remote bookmarks for changes we already have
+            changed.append((b, bin(scid), ui.status,
+                            _("adding remote bookmark %s\n") % (b)))
+    for b, scid, dcid in advsrc:
+        changed.append((b, bin(scid), ui.status,
+                        _("updating bookmark %s\n") % (b)))
+    for b, scid, dcid in diverge:
+        db = _diverge(ui, b, path, localmarks)
+        changed.append((db, bin(scid), ui.warn,
+                        _("divergent bookmark %s stored as %s\n") % (b, db)))
+    if changed:
+        for b, node, writer, msg in sorted(changed):
+            localmarks[b] = node
+            writer(msg)
+        localmarks.write()
+
+def updateremote(ui, repo, remote, revs):
+    ui.debug("checking for updated bookmarks\n")
+    revnums = map(repo.changelog.rev, revs or [])
+    ancestors = [a for a in repo.changelog.ancestors(revnums, inclusive=True)]
+    (addsrc, adddst, advsrc, advdst, diverge, differ, invalid
+     ) = compare(repo, repo._bookmarks, remote.listkeys('bookmarks'),
+                 srchex=hex)
 
-                    localmarks[n] = cr.node()
-                    changed = True
-                    ui.warn(_("divergent bookmark %s stored as %s\n") % (k, n))
-        elif remotemarks[k] in repo:
-            # add remote bookmarks for changes we already have
-            localmarks[k] = repo[remotemarks[k]].node()
-            changed = True
-            ui.status(_("adding remote bookmark %s\n") % k)
+    for b, scid, dcid in advsrc:
+        if ancestors and repo[scid].rev() not in ancestors:
+            continue
+        if remote.pushkey('bookmarks', b, dcid, scid):
+            ui.status(_("updating bookmark %s\n") % b)
+        else:
+            ui.warn(_('updating bookmark %s failed!\n') % b)
+
+def pushtoremote(ui, repo, remote, targets):
+    (addsrc, adddst, advsrc, advdst, diverge, differ, invalid
+     ) = compare(repo, repo._bookmarks, remote.listkeys('bookmarks'),
+                 srchex=hex, targets=targets)
+    if invalid:
+        b, scid, dcid = invalid[0]
+        ui.warn(_('bookmark %s does not exist on the local '
+                  'or remote repository!\n') % b)
+        return 2
 
-    if changed:
-        localmarks.write()
+    def push(b, old, new):
+        r = remote.pushkey('bookmarks', b, old, new)
+        if not r:
+            ui.warn(_('updating bookmark %s failed!\n') % b)
+            return 1
+        return 0
+    failed = 0
+    for b, scid, dcid in sorted(addsrc + advsrc + advdst + diverge + differ):
+        ui.status(_("exporting bookmark %s\n") % b)
+        if dcid is None:
+            dcid = ''
+        failed += push(b, dcid, scid)
+    for b, scid, dcid in adddst:
+        # treat as "deleted locally"
+        ui.status(_("deleting remote bookmark %s\n") % b)
+        failed += push(b, dcid, '')
+
+    if failed:
+        return 1
 
 def diff(ui, dst, src):
     ui.status(_("searching for changed bookmarks\n"))
--- a/mercurial/branchmap.py	Mon Jan 20 11:16:26 2014 -0200
+++ b/mercurial/branchmap.py	Tue Jan 21 14:44:01 2014 -0600
@@ -7,11 +7,11 @@
 
 from node import bin, hex, nullid, nullrev
 import encoding
-import util, repoview
+import util
 
 def _filename(repo):
     """name of a branchcache file for a given repo or repoview"""
-    filename = "cache/branchheads"
+    filename = "cache/branch2"
     if repo.filtername:
         filename = '%s-%s' % (filename, repo.filtername)
     return filename
@@ -39,11 +39,16 @@
         for l in lines:
             if not l:
                 continue
-            node, label = l.split(" ", 1)
+            node, state, label = l.split(" ", 2)
+            if state not in 'oc':
+                raise ValueError('invalid branch state')
             label = encoding.tolocal(label.strip())
             if not node in repo:
                 raise ValueError('node %s does not exist' % node)
-            partial.setdefault(label, []).append(bin(node))
+            node = bin(node)
+            partial.setdefault(label, []).append(node)
+            if state == 'c':
+                partial._closednodes.add(node)
     except KeyboardInterrupt:
         raise
     except Exception, inst:
@@ -58,6 +63,17 @@
 
 
 
+### Nearest subset relation
+# Nearest subset of filter X is a filter Y so that:
+# * Y is included in X,
+# * X - Y is as small as possible.
+# This create and ordering used for branchmap purpose.
+# the ordering may be partial
+subsettable = {None: 'visible',
+               'visible': 'served',
+               'served': 'immutable',
+               'immutable': 'base'}
+
 def updatecache(repo):
     cl = repo.changelog
     filtername = repo.filtername
@@ -67,7 +83,7 @@
     if partial is None or not partial.validfor(repo):
         partial = read(repo)
         if partial is None:
-            subsetname = repoview.subsettable.get(filtername)
+            subsetname = subsettable.get(filtername)
             if subsetname is None:
                 partial = branchcache()
             else:
@@ -83,14 +99,40 @@
     repo._branchcaches[repo.filtername] = partial
 
 class branchcache(dict):
-    """A dict like object that hold branches heads cache"""
+    """A dict like object that hold branches heads cache.
+
+    This cache is used to avoid costly computations to determine all the
+    branch heads of a repo.
+
+    The cache is serialized on disk in the following format:
+
+    <tip hex node> <tip rev number> [optional filtered repo hex hash]
+    <branch head hex node> <open/closed state> <branch name>
+    <branch head hex node> <open/closed state> <branch name>
+    ...
+
+    The first line is used to check if the cache is still valid. If the
+    branch cache is for a filtered repo view, an optional third hash is
+    included that hashes the hashes of all filtered revisions.
+
+    The open/closed state is represented by a single letter 'o' or 'c'.
+    This field can be used to avoid changelog reads when determining if a
+    branch head closes a branch or not.
+    """
 
     def __init__(self, entries=(), tipnode=nullid, tiprev=nullrev,
-                 filteredhash=None):
+                 filteredhash=None, closednodes=None):
         super(branchcache, self).__init__(entries)
         self.tipnode = tipnode
         self.tiprev = tiprev
         self.filteredhash = filteredhash
+        # closednodes is a set of nodes that close their branch. If the branch
+        # cache has been updated, it may contain nodes that are no longer
+        # heads.
+        if closednodes is None:
+            self._closednodes = set()
+        else:
+            self._closednodes = closednodes
 
     def _hashfiltered(self, repo):
         """build hash of revision filtered in the current cache
@@ -124,9 +166,38 @@
         except IndexError:
             return False
 
+    def _branchtip(self, heads):
+        '''Return tuple with last open head in heads and false,
+        otherwise return last closed head and true.'''
+        tip = heads[-1]
+        closed = True
+        for h in reversed(heads):
+            if h not in self._closednodes:
+                tip = h
+                closed = False
+                break
+        return tip, closed
+
+    def branchtip(self, branch):
+        '''Return the tipmost open head on branch head, otherwise return the
+        tipmost closed head on branch.
+        Raise KeyError for unknown branch.'''
+        return self._branchtip(self[branch])[0]
+
+    def branchheads(self, branch, closed=False):
+        heads = self[branch]
+        if not closed:
+            heads = [h for h in heads if h not in self._closednodes]
+        return heads
+
+    def iterbranches(self):
+        for bn, heads in self.iteritems():
+            yield (bn, heads) + self._branchtip(heads)
+
     def copy(self):
         """return an deep copy of the branchcache object"""
-        return branchcache(self, self.tipnode, self.tiprev, self.filteredhash)
+        return branchcache(self, self.tipnode, self.tiprev, self.filteredhash,
+                           self._closednodes)
 
     def write(self, repo):
         try:
@@ -137,7 +208,12 @@
             f.write(" ".join(cachekey) + '\n')
             for label, nodes in sorted(self.iteritems()):
                 for node in nodes:
-                    f.write("%s %s\n" % (hex(node), encoding.fromlocal(label)))
+                    if node in self._closednodes:
+                        state = 'c'
+                    else:
+                        state = 'o'
+                    f.write("%s %s %s\n" % (hex(node), state,
+                                            encoding.fromlocal(label)))
             f.close()
         except (IOError, OSError, util.Abort):
             # Abort may be raise by read only opener
@@ -145,55 +221,43 @@
 
     def update(self, repo, revgen):
         """Given a branchhead cache, self, that may have extra nodes or be
-        missing heads, and a generator of nodes that are at least a superset of
+        missing heads, and a generator of nodes that are strictly a superset of
         heads missing, this function updates self to be correct.
         """
         cl = repo.changelog
         # collect new branch entries
         newbranches = {}
-        getbranch = cl.branch
+        getbranchinfo = cl.branchinfo
         for r in revgen:
-            newbranches.setdefault(getbranch(r), []).append(cl.node(r))
+            branch, closesbranch = getbranchinfo(r)
+            newbranches.setdefault(branch, []).append(r)
+            if closesbranch:
+                self._closednodes.add(cl.node(r))
         # if older branchheads are reachable from new ones, they aren't
         # really branchheads. Note checking parents is insufficient:
         # 1 (branch a) -> 2 (branch b) -> 3 (branch a)
-        for branch, newnodes in newbranches.iteritems():
+        for branch, newheadrevs in newbranches.iteritems():
             bheads = self.setdefault(branch, [])
-            # Remove candidate heads that no longer are in the repo (e.g., as
-            # the result of a strip that just happened).  Avoid using 'node in
-            # self' here because that dives down into branchcache code somewhat
-            # recursively.
-            bheadrevs = [cl.rev(node) for node in bheads
-                         if cl.hasnode(node)]
-            newheadrevs = [cl.rev(node) for node in newnodes
-                           if cl.hasnode(node)]
-            ctxisnew = bheadrevs and min(newheadrevs) > max(bheadrevs)
-            # Remove duplicates - nodes that are in newheadrevs and are already
-            # in bheadrevs.  This can happen if you strip a node whose parent
-            # was already a head (because they're on different branches).
-            bheadrevs = sorted(set(bheadrevs).union(newheadrevs))
+            bheadset = set(cl.rev(node) for node in bheads)
 
-            # Starting from tip means fewer passes over reachable.  If we know
-            # the new candidates are not ancestors of existing heads, we don't
-            # have to examine ancestors of existing heads
-            if ctxisnew:
-                iterrevs = sorted(newheadrevs)
-            else:
-                iterrevs = list(bheadrevs)
+            # This have been tested True on all internal usage of this function.
+            # run it again in case of doubt
+            # assert not (set(bheadrevs) & set(newheadrevs))
+            newheadrevs.sort()
+            bheadset.update(newheadrevs)
 
             # This loop prunes out two kinds of heads - heads that are
             # superseded by a head in newheadrevs, and newheadrevs that are not
             # heads because an existing head is their descendant.
-            while iterrevs:
-                latest = iterrevs.pop()
-                if latest not in bheadrevs:
+            while newheadrevs:
+                latest = newheadrevs.pop()
+                if latest not in bheadset:
                     continue
-                ancestors = set(cl.ancestors([latest],
-                                                         bheadrevs[0]))
-                if ancestors:
-                    bheadrevs = [b for b in bheadrevs if b not in ancestors]
+                ancestors = set(cl.ancestors([latest], min(bheadset)))
+                bheadset -= ancestors
+            bheadrevs = sorted(bheadset)
             self[branch] = [cl.node(rev) for rev in bheadrevs]
-            tiprev = max(bheadrevs)
+            tiprev = bheadrevs[-1]
             if tiprev > self.tiprev:
                 self.tipnode = cl.node(tiprev)
                 self.tiprev = tiprev
--- a/mercurial/changelog.py	Mon Jan 20 11:16:26 2014 -0200
+++ b/mercurial/changelog.py	Tue Jan 21 14:44:01 2014 -0600
@@ -342,9 +342,10 @@
         text = "\n".join(l)
         return self.addrevision(text, transaction, len(self), p1, p2)
 
-    def branch(self, rev):
-        """return the branch of a revision
+    def branchinfo(self, rev):
+        """return the branch name and open/close state of a revision
 
         This function exists because creating a changectx object
         just to access this is costly."""
-        return encoding.tolocal(self.read(rev)[5].get("branch"))
+        extra = self.read(rev)[5]
+        return encoding.tolocal(extra.get("branch")), 'close' in extra
--- a/mercurial/cmdutil.py	Mon Jan 20 11:16:26 2014 -0200
+++ b/mercurial/cmdutil.py	Tue Jan 21 14:44:01 2014 -0600
@@ -10,7 +10,7 @@
 import os, sys, errno, re, tempfile
 import util, scmutil, templater, patch, error, templatekw, revlog, copies
 import match as matchmod
-import subrepo, context, repair, graphmod, revset, phases, obsolete
+import subrepo, context, repair, graphmod, revset, phases, obsolete, pathutil
 import changelog
 import bookmarks
 import lock as lockmod
@@ -274,7 +274,7 @@
     # relsrc: ossep
     # otarget: ossep
     def copyfile(abssrc, relsrc, otarget, exact):
-        abstarget = scmutil.canonpath(repo.root, cwd, otarget)
+        abstarget = pathutil.canonpath(repo.root, cwd, otarget)
         if '/' in abstarget:
             # We cannot normalize abstarget itself, this would prevent
             # case only renames, like a => A.
@@ -367,7 +367,7 @@
     # return: function that takes hgsep and returns ossep
     def targetpathfn(pat, dest, srcs):
         if os.path.isdir(pat):
-            abspfx = scmutil.canonpath(repo.root, cwd, pat)
+            abspfx = pathutil.canonpath(repo.root, cwd, pat)
             abspfx = util.localpath(abspfx)
             if destdirexists:
                 striplen = len(os.path.split(abspfx)[0])
@@ -393,7 +393,7 @@
             res = lambda p: os.path.join(dest,
                                          os.path.basename(util.localpath(p)))
         else:
-            abspfx = scmutil.canonpath(repo.root, cwd, pat)
+            abspfx = pathutil.canonpath(repo.root, cwd, pat)
             if len(abspfx) < len(srcs[0][0]):
                 # A directory. Either the target path contains the last
                 # component of the source path or it does not.
@@ -2063,7 +2063,7 @@
                 fc = ctx[f]
                 repo.wwrite(f, fc.data(), fc.flags())
 
-            audit_path = scmutil.pathauditor(repo.root)
+            audit_path = pathutil.pathauditor(repo.root)
             for f in remove[0]:
                 if repo.dirstate[f] == 'a':
                     repo.dirstate.drop(f)
--- a/mercurial/commands.py	Mon Jan 20 11:16:26 2014 -0200
+++ b/mercurial/commands.py	Tue Jan 21 14:44:01 2014 -0600
@@ -17,7 +17,8 @@
 import merge as mergemod
 import minirst, revset, fileset
 import dagparser, context, simplemerge, graphmod
-import random, setdiscovery, treediscovery, dagutil, pvec, localrepo
+import random
+import setdiscovery, treediscovery, dagutil, pvec, localrepo
 import phases, obsolete
 
 table = {}
@@ -460,16 +461,29 @@
     try:
         branch = repo.dirstate.branch()
         bheads = repo.branchheads(branch)
-        hg.clean(repo, node, show_stats=False)
-        repo.dirstate.setbranch(branch)
         rctx = scmutil.revsingle(repo, hex(parent))
-        cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
         if not opts.get('merge') and op1 != node:
             try:
                 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
-                return hg.update(repo, op1)
+                stats = mergemod.update(repo, parent, True, True, False,
+                                        node, False)
+                repo.setparents(op1, op2)
+                hg._showstats(repo, stats)
+                if stats[3]:
+                    repo.ui.status(_("use 'hg resolve' to retry unresolved "
+                                     "file merges\n"))
+                else:
+                    msg = _("changeset %s backed out, "
+                            "don't forget to commit.\n")
+                    ui.status(msg % short(node))
+                return stats[3] > 0
             finally:
                 ui.setconfig('ui', 'forcemerge', '')
+        else:
+            hg.clean(repo, node, show_stats=False)
+            repo.dirstate.setbranch(branch)
+            cmdutil.revert(ui, repo, rctx, repo.dirstate.parents())
+
 
         e = cmdutil.commiteditor
         if not opts['message'] and not opts['logfile']:
@@ -666,12 +680,13 @@
 
     if command:
         changesets = 1
-        try:
-            node = state['current'][0]
-        except LookupError:
-            if noupdate:
+        if noupdate:
+            try:
+                node = state['current'][0]
+            except LookupError:
                 raise util.Abort(_('current bisect revision is unknown - '
                                    'start a new bisect to fix'))
+        else:
             node, p2 = repo.dirstate.parents()
             if p2 != nullid:
                 raise util.Abort(_('current bisect revision is a merge'))
@@ -700,7 +715,7 @@
                 ui.status(_('changeset %d:%s: %s\n') % (ctx, ctx, transition))
                 check_state(state, interactive=False)
                 # bisect
-                nodes, changesets, good = hbisect.bisect(repo.changelog, state)
+                nodes, changesets, bgood = hbisect.bisect(repo.changelog, state)
                 # update to next check
                 node = nodes[0]
                 if not noupdate:
@@ -709,7 +724,7 @@
         finally:
             state['current'] = [node]
             hbisect.save_state(repo, state)
-        print_result(nodes, good)
+        print_result(nodes, bgood)
         return
 
     # update state
@@ -806,10 +821,6 @@
     rename = opts.get('rename')
     inactive = opts.get('inactive')
 
-    hexfn = ui.debugflag and hex or short
-    marks = repo._bookmarks
-    cur   = repo.changectx('.').node()
-
     def checkformat(mark):
         mark = mark.strip()
         if not mark:
@@ -818,7 +829,7 @@
         scmutil.checknewlabel(repo, mark, 'bookmark')
         return mark
 
-    def checkconflict(repo, mark, force=False, target=None):
+    def checkconflict(repo, mark, cur, force=False, target=None):
         if mark in marks and not force:
             if target:
                 if marks[mark] == target and target == cur:
@@ -836,12 +847,10 @@
                     bookmarks.deletedivergent(repo, [target], mark)
                     return
 
-                # consider successor changesets as well
-                foreground = obsolete.foreground(repo, [marks[mark]])
                 deletefrom = [b for b in divs
                               if repo[b].rev() in anc or b == target]
                 bookmarks.deletedivergent(repo, deletefrom, mark)
-                if bmctx.rev() in anc or target in foreground:
+                if bookmarks.validdest(repo, bmctx, repo[target]):
                     ui.status(_("moving bookmark '%s' forward from %s\n") %
                               (mark, short(bmctx.node())))
                     return
@@ -861,75 +870,84 @@
     if not names and (delete or rev):
         raise util.Abort(_("bookmark name required"))
 
-    if delete:
-        for mark in names:
-            if mark not in marks:
-                raise util.Abort(_("bookmark '%s' does not exist") % mark)
-            if mark == repo._bookmarkcurrent:
-                bookmarks.setcurrent(repo, None)
-            del marks[mark]
-        marks.write()
-
-    elif rename:
-        if not names:
-            raise util.Abort(_("new bookmark name required"))
-        elif len(names) > 1:
-            raise util.Abort(_("only one new bookmark name allowed"))
-        mark = checkformat(names[0])
-        if rename not in marks:
-            raise util.Abort(_("bookmark '%s' does not exist") % rename)
-        checkconflict(repo, mark, force)
-        marks[mark] = marks[rename]
-        if repo._bookmarkcurrent == rename and not inactive:
-            bookmarks.setcurrent(repo, mark)
-        del marks[rename]
-        marks.write()
-
-    elif names:
-        newact = None
-        for mark in names:
-            mark = checkformat(mark)
-            if newact is None:
-                newact = mark
-            if inactive and mark == repo._bookmarkcurrent:
-                bookmarks.setcurrent(repo, None)
-                return
-            tgt = cur
-            if rev:
-                tgt = scmutil.revsingle(repo, rev).node()
-            checkconflict(repo, mark, force, tgt)
-            marks[mark] = tgt
-        if not inactive and cur == marks[newact] and not rev:
-            bookmarks.setcurrent(repo, newact)
-        elif cur != tgt and newact == repo._bookmarkcurrent:
-            bookmarks.setcurrent(repo, None)
-        marks.write()
-
-    # Same message whether trying to deactivate the current bookmark (-i
-    # with no NAME) or listing bookmarks
-    elif len(marks) == 0:
-        ui.status(_("no bookmarks set\n"))
-
-    elif inactive:
-        if not repo._bookmarkcurrent:
-            ui.status(_("no active bookmark\n"))
+    if delete or rename or names or inactive:
+        wlock = repo.wlock()
+        try:
+            cur = repo.changectx('.').node()
+            marks = repo._bookmarks
+            if delete:
+                for mark in names:
+                    if mark not in marks:
+                        raise util.Abort(_("bookmark '%s' does not exist") %
+                                         mark)
+                    if mark == repo._bookmarkcurrent:
+                        bookmarks.unsetcurrent(repo)
+                    del marks[mark]
+                marks.write()
+
+            elif rename:
+                if not names:
+                    raise util.Abort(_("new bookmark name required"))
+                elif len(names) > 1:
+                    raise util.Abort(_("only one new bookmark name allowed"))
+                mark = checkformat(names[0])
+                if rename not in marks:
+                    raise util.Abort(_("bookmark '%s' does not exist") % rename)
+                checkconflict(repo, mark, cur, force)
+                marks[mark] = marks[rename]
+                if repo._bookmarkcurrent == rename and not inactive:
+                    bookmarks.setcurrent(repo, mark)
+                del marks[rename]
+                marks.write()
+
+            elif names:
+                newact = None
+                for mark in names:
+                    mark = checkformat(mark)
+                    if newact is None:
+                        newact = mark
+                    if inactive and mark == repo._bookmarkcurrent:
+                        bookmarks.unsetcurrent(repo)
+                        return
+                    tgt = cur
+                    if rev:
+                        tgt = scmutil.revsingle(repo, rev).node()
+                    checkconflict(repo, mark, cur, force, tgt)
+                    marks[mark] = tgt
+                if not inactive and cur == marks[newact] and not rev:
+                    bookmarks.setcurrent(repo, newact)
+                elif cur != tgt and newact == repo._bookmarkcurrent:
+                    bookmarks.unsetcurrent(repo)
+                marks.write()
+
+            elif inactive:
+                if len(marks) == 0:
+                    ui.status(_("no bookmarks set\n"))
+                elif not repo._bookmarkcurrent:
+                    ui.status(_("no active bookmark\n"))
+                else:
+                    bookmarks.unsetcurrent(repo)
+        finally:
+            wlock.release()
+    else: # show bookmarks
+        hexfn = ui.debugflag and hex or short
+        marks = repo._bookmarks
+        if len(marks) == 0:
+            ui.status(_("no bookmarks set\n"))
         else:
-            bookmarks.setcurrent(repo, None)
-
-    else: # show bookmarks
-        for bmark, n in sorted(marks.iteritems()):
-            current = repo._bookmarkcurrent
-            if bmark == current:
-                prefix, label = '*', 'bookmarks.current'
-            else:
-                prefix, label = ' ', ''
-
-            if ui.quiet:
-                ui.write("%s\n" % bmark, label=label)
-            else:
-                ui.write(" %s %-25s %d:%s\n" % (
-                    prefix, bmark, repo.changelog.rev(n), hexfn(n)),
-                    label=label)
+            for bmark, n in sorted(marks.iteritems()):
+                current = repo._bookmarkcurrent
+                if bmark == current:
+                    prefix, label = '*', 'bookmarks.current'
+                else:
+                    prefix, label = ' ', ''
+
+                if ui.quiet:
+                    ui.write("%s\n" % bmark, label=label)
+                else:
+                    ui.write(" %s %-25s %d:%s\n" % (
+                        prefix, bmark, repo.changelog.rev(n), hexfn(n)),
+                        label=label)
 
 @command('branch',
     [('f', 'force', None,
@@ -1012,23 +1030,15 @@
 
     hexfunc = ui.debugflag and hex or short
 
-    activebranches = set([repo[n].branch() for n in repo.heads()])
+    allheads = set(repo.heads())
     branches = []
-    for tag, heads in repo.branchmap().iteritems():
-        for h in reversed(heads):
-            ctx = repo[h]
-            isopen = not ctx.closesbranch()
-            if isopen:
-                tip = ctx
-                break
-        else:
-            tip = repo[heads[-1]]
-        isactive = tag in activebranches and isopen
-        branches.append((tip, isactive, isopen))
-    branches.sort(key=lambda i: (i[1], i[0].rev(), i[0].branch(), i[2]),
+    for tag, heads, tip, isclosed in repo.branchmap().iterbranches():
+        isactive = not isclosed and bool(set(heads) & allheads)
+        branches.append((tag, repo[tip], isactive, not isclosed))
+    branches.sort(key=lambda i: (i[2], i[1].rev(), i[0], i[3]),
                   reverse=True)
 
-    for ctx, isactive, isopen in branches:
+    for tag, ctx, isactive, isopen in branches:
         if (not active) or isactive:
             if isactive:
                 label = 'branches.active'
@@ -1041,16 +1051,16 @@
             else:
                 label = 'branches.inactive'
                 notice = _(' (inactive)')
-            if ctx.branch() == repo.dirstate.branch():
+            if tag == repo.dirstate.branch():
                 label = 'branches.current'
-            rev = str(ctx.rev()).rjust(31 - encoding.colwidth(ctx.branch()))
+            rev = str(ctx.rev()).rjust(31 - encoding.colwidth(tag))
             rev = ui.label('%s:%s' % (rev, hexfunc(ctx.node())),
                            'log.changeset changeset.%s' % ctx.phasestr())
-            tag = ui.label(ctx.branch(), label)
+            labeledtag = ui.label(tag, label)
             if ui.quiet:
-                ui.write("%s\n" % tag)
+                ui.write("%s\n" % labeledtag)
             else:
-                ui.write("%s %s%s\n" % (tag, rev, notice))
+                ui.write("%s %s%s\n" % (labeledtag, rev, notice))
 
 @command('bundle',
     [('f', 'force', None, _('run even when the destination is unrelated')),
@@ -1158,14 +1168,28 @@
     ctx = scmutil.revsingle(repo, opts.get('rev'))
     err = 1
     m = scmutil.match(ctx, (file1,) + pats, opts)
-    for abs in ctx.walk(m):
+
+    def write(path):
         fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
-                                 pathname=abs)
-        data = ctx[abs].data()
+                                 pathname=path)
+        data = ctx[path].data()
         if opts.get('decode'):
-            data = repo.wwritedata(abs, data)
+            data = repo.wwritedata(path, data)
         fp.write(data)
         fp.close()
+
+    # Automation often uses hg cat on single files, so special case it
+    # for performance to avoid the cost of parsing the manifest.
+    if len(m.files()) == 1 and not m.anypats():
+        file = m.files()[0]
+        mf = repo.manifest
+        mfnode = ctx._changeset[0]
+        if mf.find(mfnode, file)[0]:
+            write(file)
+            return 0
+
+    for abs in ctx.walk(m):
+        write(abs)
         err = 0
     return err
 
@@ -2142,11 +2166,8 @@
     labels = set()
     labels.update(t[0] for t in repo.tagslist())
     labels.update(repo._bookmarks.keys())
-    for heads in repo.branchmap().itervalues():
-        for h in heads:
-            ctx = repo[h]
-            if not ctx.closesbranch():
-                labels.add(ctx.branch())
+    labels.update(tag for (tag, heads, tip, closed)
+                  in repo.branchmap().iterbranches() if not closed)
     completions = set()
     if not args:
         args = ['']
@@ -2244,7 +2265,7 @@
                     continue
                 s = f.find(os.sep, speclen)
                 if s >= 0:
-                    adddir(f[:s + 1])
+                    adddir(f[:s])
                 else:
                     addfile(f)
         return files, dirs
@@ -2265,10 +2286,6 @@
         f, d = complete(spec, acceptable or 'nmar')
         files.update(f)
         dirs.update(d)
-    if not files and len(dirs) == 1:
-        # force the shell to consider a completion that matches one
-        # directory and zero files to be ambiguous
-        dirs.add(iter(dirs).next() + '.')
     files.update(dirs)
     ui.write('\n'.join(repo.pathto(p, cwd) for p in sorted(files)))
     ui.write('\n')
@@ -3762,12 +3779,12 @@
                                         files, eolmode=None)
                     except patch.PatchError, e:
                         raise util.Abort(str(e))
-                    memctx = patch.makememctx(repo, (p1.node(), p2.node()),
-                                              message,
-                                              opts.get('user') or user,
-                                              opts.get('date') or date,
-                                              branch, files, store,
-                                              editor=cmdutil.commiteditor)
+                    memctx = context.makememctx(repo, (p1.node(), p2.node()),
+                                                message,
+                                                opts.get('user') or user,
+                                                opts.get('date') or date,
+                                                branch, files, store,
+                                                editor=cmdutil.commiteditor)
                     repo.savecommitmessage(memctx.description())
                     n = memctx.commit()
                 finally:
@@ -4680,6 +4697,7 @@
     """
 
     if opts.get('bookmark'):
+        ui.setconfig('bookmarks', 'pushing', opts['bookmark'])
         for b in opts['bookmark']:
             # translate -B options to -r so changesets get pushed
             if b in repo._bookmarks:
@@ -4713,25 +4731,11 @@
     result = not result
 
     if opts.get('bookmark'):
-        rb = other.listkeys('bookmarks')
-        for b in opts['bookmark']:
-            # explicit push overrides remote bookmark if any
-            if b in repo._bookmarks:
-                ui.status(_("exporting bookmark %s\n") % b)
-                new = repo[b].hex()
-            elif b in rb:
-                ui.status(_("deleting remote bookmark %s\n") % b)
-                new = '' # delete
-            else:
-                ui.warn(_('bookmark %s does not exist on the local '
-                          'or remote repository!\n') % b)
-                return 2
-            old = rb.get(b, '')
-            r = other.pushkey('bookmarks', b, old, new)
-            if not r:
-                ui.warn(_('updating bookmark %s failed!\n') % b)
-                if not result:
-                    result = 2
+        bresult = bookmarks.pushtoremote(ui, repo, other, opts['bookmark'])
+        if bresult == 2:
+            return 2
+        if not result and bresult:
+            result = 2
 
     return result
 
@@ -5915,7 +5919,7 @@
              % util.version())
     ui.status(_(
         "(see http://mercurial.selenic.com for more information)\n"
-        "\nCopyright (C) 2005-2013 Matt Mackall and others\n"
+        "\nCopyright (C) 2005-2014 Matt Mackall and others\n"
         "This is free software; see the source for copying conditions. "
         "There is NO\nwarranty; "
         "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
--- a/mercurial/commandserver.py	Mon Jan 20 11:16:26 2014 -0200
+++ b/mercurial/commandserver.py	Tue Jan 21 14:44:01 2014 -0600
@@ -184,7 +184,10 @@
         # persist between requests
         copiedui = self.ui.copy()
         self.repo.baseui = copiedui
-        self.repo.ui = self.repo.dirstate._ui = self.repoui.copy()
+        # clone ui without using ui.copy because this is protected
+        repoui = self.repoui.__class__(self.repoui)
+        repoui.copy = copiedui.copy # redo copy protection
+        self.repo.ui = self.repo.dirstate._ui = repoui
         self.repo.invalidate()
         self.repo.invalidatedirstate()
 
--- a/mercurial/context.py	Mon Jan 20 11:16:26 2014 -0200
+++ b/mercurial/context.py	Tue Jan 21 14:44:01 2014 -0600
@@ -8,7 +8,6 @@
 from node import nullid, nullrev, short, hex, bin
 from i18n import _
 import ancestor, mdiff, error, util, scmutil, subrepo, patch, encoding, phases
-import copies
 import match as matchmod
 import os, errno, stat
 import obsolete as obsmod
@@ -195,6 +194,21 @@
     def dirty(self):
         return False
 
+def makememctx(repo, parents, text, user, date, branch, files, store,
+               editor=None):
+    def getfilectx(repo, memctx, path):
+        data, (islink, isexec), copied = store.getfile(path)
+        return memfilectx(path, data, islink=islink, isexec=isexec,
+                                  copied=copied)
+    extra = {}
+    if branch:
+        extra['branch'] = encoding.fromlocal(branch)
+    ctx =  memctx(repo, parents, text, files, getfilectx, user,
+                          date, extra)
+    if editor:
+        ctx._text = editor(repo, ctx, [])
+    return ctx
+
 class changectx(basectx):
     """A changecontext object makes access to data related to a particular
     changeset convenient. It represents a read-only context already present in
@@ -396,6 +410,15 @@
         # for dirstate.walk, files=['.'] means "walk the whole tree".
         # follow that here, too
         fset.discard('.')
+
+        # avoid the entire walk if we're only looking for specific files
+        if fset and not match.anypats():
+            if util.all([fn in self for fn in fset]):
+                for fn in sorted(fset):
+                    if match(fn):
+                        yield fn
+                raise StopIteration
+
         for fn in self:
             if fn in fset:
                 # specified pattern is the exact name
@@ -722,14 +745,6 @@
             c = visit.pop(max(visit))
             yield c
 
-    def copies(self, c2):
-        if not util.safehasattr(self, "_copycache"):
-            self._copycache = {}
-        sc2 = str(c2)
-        if sc2 not in self._copycache:
-            self._copycache[sc2] = copies.pathcopies(c2)
-        return self._copycache[sc2]
-
 class filectx(basefilectx):
     """A filecontext object makes access to data related to a particular
        filerevision convenient."""
--- a/mercurial/copies.py	Mon Jan 20 11:16:26 2014 -0200
+++ b/mercurial/copies.py	Tue Jan 21 14:44:01 2014 -0600
@@ -98,15 +98,14 @@
 
     return t
 
-def _tracefile(fctx, actx):
-    '''return file context that is the ancestor of fctx present in actx'''
-    stop = actx.rev()
-    am = actx.manifest()
+def _tracefile(fctx, am, limit=-1):
+    '''return file context that is the ancestor of fctx present in ancestor
+    manifest am, stopping after the first ancestor lower than limit'''
 
     for f in fctx.ancestors():
         if am.get(f.path(), None) == f.filenode():
             return f
-        if f.rev() < stop:
+        if f.rev() < limit:
             return None
 
 def _dirstatecopies(d):
@@ -129,6 +128,13 @@
             # short-circuit to avoid issues with merge states
             return _dirstatecopies(w)
 
+    # files might have to be traced back to the fctx parent of the last
+    # one-side-only changeset, but not further back than that
+    limit = _findlimit(a._repo, a.rev(), b.rev())
+    if limit is None:
+        limit = -1
+    am = a.manifest()
+
     # find where new files came from
     # we currently don't try to find where old files went, too expensive
     # this means we can miss a case like 'hg rm b; hg cp a b'
@@ -137,7 +143,7 @@
     missing.difference_update(a.manifest().iterkeys())
 
     for f in missing:
-        ofctx = _tracefile(b[f], a)
+        ofctx = _tracefile(b[f], am, limit)
         if ofctx:
             cm[f] = ofctx.path()
 
--- a/mercurial/dagutil.py	Mon Jan 20 11:16:26 2014 -0200
+++ b/mercurial/dagutil.py	Tue Jan 21 14:44:01 2014 -0600
@@ -141,7 +141,9 @@
         rl = self._revlog
         if filterunknown:
             return [r for r in map(rl.nodemap.get, ids)
-                    if r is not None and r != nullrev]
+                    if (r is not None
+                        and r != nullrev
+                        and r not in rl.filteredrevs)]
         return map(self._internalize, ids)
 
 
@@ -149,7 +151,7 @@
     '''dag interface to a revlog'''
 
     def __init__(self, revlog):
-        revlogbaseddag.__init__(self, revlog, set(xrange(len(revlog))))
+        revlogbaseddag.__init__(self, revlog, set(revlog))
 
     def _getheads(self):
         return [r for r in self._revlog.headrevs() if r != nullrev]
--- a/mercurial/dirstate.py	Mon Jan 20 11:16:26 2014 -0200
+++ b/mercurial/dirstate.py	Tue Jan 21 14:44:01 2014 -0600
@@ -8,7 +8,7 @@
 
 from node import nullid
 from i18n import _
-import scmutil, util, ignore, osutil, parsers, encoding
+import scmutil, util, ignore, osutil, parsers, encoding, pathutil
 import os, stat, errno, gc
 
 propertycache = util.propertycache
@@ -736,7 +736,7 @@
                 # unknown == True means we walked the full directory tree above.
                 # So if a file is not seen it was either a) not matching matchfn
                 # b) ignored, c) missing, or d) under a symlink directory.
-                audit_path = scmutil.pathauditor(self._root)
+                audit_path = pathutil.pathauditor(self._root)
 
                 for nf in iter(visit):
                     # Report ignored items in the dmap as long as they are not
--- a/mercurial/discovery.py	Mon Jan 20 11:16:26 2014 -0200
+++ b/mercurial/discovery.py	Tue Jan 21 14:44:01 2014 -0600
@@ -34,9 +34,9 @@
 
     if heads:
         allknown = True
-        nm = repo.changelog.nodemap
+        knownnode = repo.changelog.hasnode # no nodemap until it is filtered
         for h in heads:
-            if nm.get(h) is None:
+            if not knownnode(h):
                 allknown = False
                 break
         if allknown:
@@ -172,8 +172,9 @@
         remotebranches.add(branch)
         known = []
         unsynced = []
+        knownnode = cl.hasnode # do not use nodemap until it is filtered
         for h in heads:
-            if h in cl.nodemap:
+            if knownnode(h):
                 known.append(h)
             else:
                 unsynced.append(h)
@@ -204,11 +205,11 @@
 def _oldheadssummary(repo, remoteheads, outgoing, inc=False):
     """Compute branchmapsummary for repo without branchmap support"""
 
-    cl = repo.changelog
     # 1-4b. old servers: Check for new topological heads.
     # Construct {old,new}map with branch = None (topological branch).
     # (code based on update)
-    oldheads = set(h for h in remoteheads if h in cl.nodemap)
+    knownnode = repo.changelog.hasnode # no nodemap until it is filtered
+    oldheads = set(h for h in remoteheads if knownnode(h))
     # all nodes in outgoing.missing are children of either:
     # - an element of oldheads
     # - another element of outgoing.missing
@@ -219,7 +220,8 @@
     unsynced = inc and set([None]) or set()
     return {None: (oldheads, newheads, unsynced)}
 
-def checkheads(repo, remote, outgoing, remoteheads, newbranch=False, inc=False):
+def checkheads(repo, remote, outgoing, remoteheads, newbranch=False, inc=False,
+               newbookmarks=[]):
     """Check that a push won't add any outgoing head
 
     raise Abort error and display ui message as needed.
@@ -259,6 +261,9 @@
             lctx, rctx = repo[bm], repo[rnode]
             if bookmarks.validdest(repo, rctx, lctx):
                 bookmarkedheads.add(lctx.node())
+        else:
+            if bm in newbookmarks:
+                bookmarkedheads.add(repo[bm].node())
 
     # 3. Check for new heads.
     # If there are more heads after the push than before, a suitable
@@ -313,8 +318,8 @@
             if 1 < len(newhs):
                 dhs = list(newhs)
                 if error is None:
-                    error = (_("push creates multiple headed new branch '%s'")
-                             % (branch))
+                    error = (_("push creates new branch '%s' "
+                               "with multiple heads") % (branch))
                     hint = _("merge or"
                              " see \"hg help push\" for details about"
                              " pushing new heads")
@@ -337,10 +342,12 @@
                     hint = _("merge or"
                              " see \"hg help push\" for details about"
                              " pushing new heads")
-            if branch is not None:
-                repo.ui.note(_("new remote heads on branch '%s'\n") % branch)
+            if branch is None:
+                repo.ui.note(_("new remote heads:\n"))
+            else:
+                repo.ui.note(_("new remote heads on branch '%s':\n") % branch)
             for h in dhs:
-                repo.ui.note(_("new remote head %s\n") % short(h))
+                repo.ui.note((" %s\n") % short(h))
     if error:
         raise util.Abort(error, hint=hint)
 
--- a/mercurial/dispatch.py	Mon Jan 20 11:16:26 2014 -0200
+++ b/mercurial/dispatch.py	Tue Jan 21 14:44:01 2014 -0600
@@ -106,8 +106,9 @@
                 for cfg in cfgs:
                     req.repo.ui.setconfig(*cfg)
 
+            # if we are in HGPLAIN mode, then disable custom debugging
             debugger = ui.config("ui", "debugger")
-            if not debugger:
+            if not debugger or ui.plain():
                 debugger = 'pdb'
 
             try:
--- a/mercurial/fancyopts.py	Mon Jan 20 11:16:26 2014 -0200
+++ b/mercurial/fancyopts.py	Tue Jan 21 14:44:01 2014 -0600
@@ -5,7 +5,8 @@
 # This software may be used and distributed according to the terms of the
 # GNU General Public License version 2 or any later version.
 
-import getopt, util
+import getopt
+import util
 from i18n import _
 
 def gnugetopt(args, options, longoptions):
--- a/mercurial/fileset.py	Mon Jan 20 11:16:26 2014 -0200
+++ b/mercurial/fileset.py	Tue Jan 21 14:44:01 2014 -0600
@@ -5,7 +5,8 @@
 # This software may be used and distributed according to the terms of the
 # GNU General Public License version 2 or any later version.
 
-import parser, error, util, merge, re
+import re
+import parser, error, util, merge
 from i18n import _
 
 elements = {
--- a/mercurial/hbisect.py	Mon Jan 20 11:16:26 2014 -0200
+++ b/mercurial/hbisect.py	Tue Jan 21 14:44:01 2014 -0600
@@ -8,7 +8,8 @@
 # This software may be used and distributed according to the terms of the
 # GNU General Public License version 2 or any later version.
 
-import os, error
+import os
+import error
 from i18n import _
 from node import short, hex
 import util
--- a/mercurial/help.py	Mon Jan 20 11:16:26 2014 -0200
+++ b/mercurial/help.py	Tue Jan 21 14:44:01 2014 -0600
@@ -6,7 +6,8 @@
 # GNU General Public License version 2 or any later version.
 
 from i18n import gettext, _
-import itertools, sys, os, error
+import itertools, sys, os
+import error
 import extensions, revset, fileset, templatekw, templatefilters, filemerge
 import encoding, util, minirst
 import cmdutil
--- a/mercurial/help/config.txt	Mon Jan 20 11:16:26 2014 -0200
+++ b/mercurial/help/config.txt	Tue Jan 21 14:44:01 2014 -0600
@@ -945,6 +945,15 @@
     Phase of newly-created commits.
     Default: draft
 
+``checksubrepos``
+
+    Check phase of state in each subrepositories, allowed values are
+    "ignore", "follow" or "abort". For settings other than "ignore",
+    the phase of each subrepository commit is checked before committing
+    in the parent repository. If there is any greater phase than the parent
+    ("secret" vs "draft", for example), the commit is either aborted
+    with "abort" or the higher phase is used with "follow". Default: "follow".
+
 ``profiling``
 -------------
 
--- a/mercurial/help/hg.1.txt	Mon Jan 20 11:16:26 2014 -0200
+++ b/mercurial/help/hg.1.txt	Tue Jan 21 14:44:01 2014 -0600
@@ -112,7 +112,7 @@
 
 Copying
 """""""
-Copyright (C) 2005-2013 Matt Mackall.
+Copyright (C) 2005-2014 Matt Mackall.
 Free use of this software is granted under the terms of the GNU General
 Public License version 2 or any later version.
 
--- a/mercurial/help/hgignore.5.txt	Mon Jan 20 11:16:26 2014 -0200
+++ b/mercurial/help/hgignore.5.txt	Tue Jan 21 14:44:01 2014 -0600
@@ -26,7 +26,7 @@
 Copying
 =======
 This manual page is copyright 2006 Vadim Gelfer.
-Mercurial is copyright 2005-2013 Matt Mackall.
+Mercurial is copyright 2005-2014 Matt Mackall.
 Free use of this software is granted under the terms of the GNU General
 Public License version 2 or any later version.
 
--- a/mercurial/help/hgrc.5.txt	Mon Jan 20 11:16:26 2014 -0200
+++ b/mercurial/help/hgrc.5.txt	Tue Jan 21 14:44:01 2014 -0600
@@ -34,7 +34,7 @@
 Copying
 =======
 This manual page is copyright 2005 Bryan O'Sullivan.
-Mercurial is copyright 2005-2013 Matt Mackall.
+Mercurial is copyright 2005-2014 Matt Mackall.
 Free use of this software is granted under the terms of the GNU General
 Public License version 2 or any later version.
 
--- a/mercurial/help/patterns.txt	Mon Jan 20 11:16:26 2014 -0200
+++ b/mercurial/help/patterns.txt	Tue Jan 21 14:44:01 2014 -0600
@@ -29,6 +29,11 @@
 feeds. Each string read from the file is itself treated as a file
 pattern.
 
+All patterns, except for ``glob:`` specified in command line (not for
+``-I`` or ``-X`` options) or ``.hgignore`` file, can match also
+against directories: files under matched directories are treated as
+matched.
+
 Plain examples::
 
   path:foo/bar   a name bar in a directory named foo in the root
--- a/mercurial/help/phases.txt	Mon Jan 20 11:16:26 2014 -0200
+++ b/mercurial/help/phases.txt	Tue Jan 21 14:44:01 2014 -0600
@@ -58,6 +58,13 @@
   Servers running older versions of Mercurial are treated as
   publishing.
 
+.. note::
+   Changesets in secret phase are not exchanged with the server. This
+   applies to their content: file names, file contents, and changeset
+   metadata. For technical reasons, the identifier (e.g. d825e4025e39)
+   of the secret changeset may be communicated to the server.
+
+
 Examples
 ========
 
--- a/mercurial/help/revisions.txt	Mon Jan 20 11:16:26 2014 -0200
+++ b/mercurial/help/revisions.txt	Tue Jan 21 14:44:01 2014 -0600
@@ -14,9 +14,9 @@
 
 Any other string is treated as a bookmark, tag, or branch name. A
 bookmark is a movable pointer to a revision. A tag is a permanent name
-associated with a revision. A branch name denotes the tipmost revision
-of that branch. Bookmark, tag, and branch names must not contain the ":"
-character.
+associated with a revision. A branch name denotes the tipmost open branch head
+of that branch - or if they are all closed, the tipmost closed head of the
+branch. Bookmark, tag, and branch names must not contain the ":" character.
 
 The reserved name "tip" always identifies the most recent revision.
 
--- a/mercurial/help/templates.txt	Mon Jan 20 11:16:26 2014 -0200
+++ b/mercurial/help/templates.txt	Tue Jan 21 14:44:01 2014 -0600
@@ -102,3 +102,7 @@
 - Invert the firstline filter, i.e. everything but the first line::
 
    $ hg log -r 0 --template "{sub(r'^.*\n?\n?', '', desc)}\n"
+
+- Display the contents of the 'extra' field, one per line::
+
+   $ hg log -r 0 --template "{join(extras, '\n')}\n"
--- a/mercurial/hg.py	Mon Jan 20 11:16:26 2014 -0200
+++ b/mercurial/hg.py	Tue Jan 21 14:44:01 2014 -0600
@@ -202,19 +202,20 @@
         hardlink = None
         num = 0
         srcpublishing = srcrepo.ui.configbool('phases', 'publish', True)
+        srcvfs = scmutil.vfs(srcrepo.sharedpath)
+        dstvfs = scmutil.vfs(destpath)
         for f in srcrepo.store.copylist():
             if srcpublishing and f.endswith('phaseroots'):
                 continue
-            src = os.path.join(srcrepo.sharedpath, f)
-            dst = os.path.join(destpath, f)
-            dstbase = os.path.dirname(dst)
-            if dstbase and not os.path.exists(dstbase):
-                os.mkdir(dstbase)
-            if os.path.exists(src):
-                if dst.endswith('data'):
+            dstbase = os.path.dirname(f)
+            if dstbase and not dstvfs.exists(dstbase):
+                dstvfs.mkdir(dstbase)
+            if srcvfs.exists(f):
+                if f.endswith('data'):
                     # lock to avoid premature writing to the target
-                    destlock = lock.lock(os.path.join(dstbase, "lock"))
-                hardlink, n = util.copyfiles(src, dst, hardlink)
+                    destlock = lock.lock(dstvfs, dstbase + "/lock")
+                hardlink, n = util.copyfiles(srcvfs.join(f), dstvfs.join(f),
+                                             hardlink)
                 num += n
         if hardlink:
             ui.debug("linked %d files\n" % num)
@@ -337,8 +338,8 @@
             # Recomputing branch cache might be slow on big repos,
             # so just copy it
             dstcachedir = os.path.join(destpath, 'cache')
-            srcbranchcache = srcrepo.sjoin('cache/branchheads')
-            dstbranchcache = os.path.join(dstcachedir, 'branchheads')
+            srcbranchcache = srcrepo.sjoin('cache/branch2')
+            dstbranchcache = os.path.join(dstcachedir, 'branch2')
             if os.path.exists(srcbranchcache):
                 if not os.path.exists(dstcachedir):
                     os.mkdir(dstcachedir)
@@ -511,11 +512,7 @@
             return subreporecurse()
 
         displayer = cmdutil.show_changeset(ui, other, opts, buffered)
-
-        # XXX once graphlog extension makes it into core,
-        # should be replaced by a if graph/else
         displaychlist(other, chlist, displayer)
-
         displayer.close()
     finally:
         cleanupfn()
--- a/mercurial/hgweb/hgweb_mod.py	Mon Jan 20 11:16:26 2014 -0200
+++ b/mercurial/hgweb/hgweb_mod.py	Tue Jan 21 14:44:01 2014 -0600
@@ -6,7 +6,7 @@
 # This software may be used and distributed according to the terms of the
 # GNU General Public License version 2 or any later version.
 
-import os
+import os, re
 from mercurial import ui, hg, hook, error, encoding, templater, util, repoview
 from mercurial.templatefilters import websub
 from mercurial.i18n import _
@@ -14,7 +14,7 @@
 from common import HTTP_OK, HTTP_NOT_MODIFIED, HTTP_BAD_REQUEST
 from common import HTTP_NOT_FOUND, HTTP_SERVER_ERROR
 from request import wsgirequest
-import webcommands, protocol, webutil, re
+import webcommands, protocol, webutil
 
 perms = {
     'changegroup': 'pull',
@@ -373,6 +373,7 @@
                                              "motd": motd,
                                              "sessionvars": sessionvars,
                                              "pathdef": makebreadcrumb(req.url),
+                                             "style": style,
                                             })
         return tmpl
 
--- a/mercurial/hgweb/hgwebdir_mod.py	Mon Jan 20 11:16:26 2014 -0200
+++ b/mercurial/hgweb/hgwebdir_mod.py	Tue Jan 21 14:44:01 2014 -0600
@@ -448,7 +448,9 @@
                                              "logourl": logourl,
                                              "logoimg": logoimg,
                                              "staticurl": staticurl,
-                                             "sessionvars": sessionvars})
+                                             "sessionvars": sessionvars,
+                                             "style": style,
+                                             })
         return tmpl
 
     def updatereqenv(self, env):
--- a/mercurial/hgweb/webcommands.py	Mon Jan 20 11:16:26 2014 -0200
+++ b/mercurial/hgweb/webcommands.py	Tue Jan 21 14:44:01 2014 -0600
@@ -537,18 +537,18 @@
     tips = []
     heads = web.repo.heads()
     parity = paritygen(web.stripecount)
-    sortkey = lambda ctx: (not ctx.closesbranch(), ctx.rev())
+    sortkey = lambda item: (not item[1], item[0].rev())
 
     def entries(limit, **map):
         count = 0
         if not tips:
-            for t, n in web.repo.branchtags().iteritems():
-                tips.append(web.repo[n])
-        for ctx in sorted(tips, key=sortkey, reverse=True):
+            for tag, hs, tip, closed in web.repo.branchmap().iterbranches():
+                tips.append((web.repo[tip], closed))
+        for ctx, closed in sorted(tips, key=sortkey, reverse=True):
             if limit > 0 and count >= limit:
                 return
             count += 1
-            if not web.repo.branchheads(ctx.branch()):
+            if closed:
                 status = 'closed'
             elif ctx.node() not in heads:
                 status = 'inactive'
@@ -596,8 +596,9 @@
     def branches(**map):
         parity = paritygen(web.stripecount)
 
-        b = web.repo.branchtags()
-        l = [(-web.repo.changelog.rev(n), n, t) for t, n in b.iteritems()]
+        b = web.repo.branchmap()
+        l = [(-web.repo.changelog.rev(tip), tip, tag)
+             for tag, heads, tip, closed in b.iterbranches()]
         for r, n, t in sorted(l):
             yield {'parity': parity.next(),
                    'branch': t,
@@ -845,15 +846,11 @@
     end = min(count, start + revcount) # last rev on this page
     parity = paritygen(web.stripecount, offset=start - end)
 
-    def entries(latestonly, **map):
+    def entries():
         l = []
 
         repo = web.repo
-        revs = repo.changelog.revs(start, end - 1)
-        if latestonly:
-            for r in revs:
-                pass
-            revs = (r,)
+        revs = fctx.filelog().revs(start, end - 1)
         for i in revs:
             iterfctx = fctx.filectx(i)
 
@@ -877,11 +874,14 @@
         for e in reversed(l):
             yield e
 
+    entries = list(entries())
+    latestentry = entries[:1]
+
     revnav = webutil.filerevnav(web.repo, fctx.path())
     nav = revnav.gen(end - 1, revcount, count)
     return tmpl("filelog", file=f, node=fctx.hex(), nav=nav,
-                entries=lambda **x: entries(latestonly=False, **x),
-                latestentry=lambda **x: entries(latestonly=True, **x),
+                entries=entries,
+                latestentry=latestentry,
                 revcount=revcount, morevars=morevars, lessvars=lessvars)
 
 def archive(web, req, tmpl):
--- a/mercurial/hgweb/webutil.py	Mon Jan 20 11:16:26 2014 -0200
+++ b/mercurial/hgweb/webutil.py	Tue Jan 21 14:44:01 2014 -0600
@@ -7,7 +7,7 @@
 # GNU General Public License version 2 or any later version.
 
 import os, copy
-from mercurial import match, patch, scmutil, error, ui, util
+from mercurial import match, patch, error, ui, util, pathutil
 from mercurial.i18n import _
 from mercurial.node import hex, nullid
 from common import ErrorResponse
@@ -196,7 +196,7 @@
 
 def cleanpath(repo, path):
     path = path.lstrip('/')
-    return scmutil.canonpath(repo.root, '', path)
+    return pathutil.canonpath(repo.root, '', path)
 
 def changeidctx (repo, changeid):
     try:
--- a/mercurial/localrepo.py	Mon Jan 20 11:16:26 2014 -0200
+++ b/mercurial/localrepo.py	Tue Jan 21 14:44:01 2014 -0600
@@ -8,14 +8,15 @@
 from i18n import _
 import peer, changegroup, subrepo, discovery, pushkey, obsolete, repoview
 import changelog, dirstate, filelog, manifest, context, bookmarks, phases
-import lock, transaction, store, encoding
+import lock as lockmod
+import transaction, store, encoding
 import scmutil, util, extensions, hook, error, revset
 import match as matchmod
 import merge as mergemod
 import tags as tagsmod
 from lock import release
 import weakref, errno, os, time, inspect
-import branchmap
+import branchmap, pathutil
 propertycache = util.propertycache
 filecache = scmutil.filecache
 
@@ -166,11 +167,12 @@
         self.root = self.wvfs.base
         self.path = self.wvfs.join(".hg")
         self.origroot = path
-        self.auditor = scmutil.pathauditor(self.root, self._checknested)
+        self.auditor = pathutil.pathauditor(self.root, self._checknested)
         self.vfs = scmutil.vfs(self.path)
         self.opener = self.vfs
         self.baseui = baseui
         self.ui = baseui.copy()
+        self.ui.copy = baseui.copy # prevent copying repo configuration
         # A list of callback to shape the phase if no data were found.
         # Callback are in the form: func(repo, roots) --> processed root.
         # This list it to be filled by extension during repo setup
@@ -279,6 +281,9 @@
         self.requirements = requirements
         self.sopener.options = dict((r, 1) for r in requirements
                                            if r in self.openerreqs)
+        chunkcachesize = self.ui.configint('format', 'chunkcachesize')
+        if chunkcachesize is not None:
+            self.sopener.options['chunkcachesize'] = chunkcachesize
 
     def _writerequirements(self):
         reqfile = self.opener("requires", "w")
@@ -650,33 +655,17 @@
         return sorted(marks)
 
     def branchmap(self):
-        '''returns a dictionary {branch: [branchheads]}'''
+        '''returns a dictionary {branch: [branchheads]} with branchheads
+        ordered by increasing revision number'''
         branchmap.updatecache(self)
         return self._branchcaches[self.filtername]
 
-
-    def _branchtip(self, heads):
-        '''return the tipmost branch head in heads'''
-        tip = heads[-1]
-        for h in reversed(heads):
-            if not self[h].closesbranch():
-                tip = h
-                break
-        return tip
-
     def branchtip(self, branch):
         '''return the tip node for a given branch'''
-        if branch not in self.branchmap():
+        try:
+            return self.branchmap().branchtip(branch)
+        except KeyError:
             raise error.RepoLookupError(_("unknown branch '%s'") % branch)
-        return self._branchtip(self.branchmap()[branch])
-
-    def branchtags(self):
-        '''return a dict where branch names map to the tipmost head of
-        the branch, open heads come before closed'''
-        bt = {}
-        for bn, heads in self.branchmap().iteritems():
-            bt[bn] = self._branchtip(heads)
-        return bt
 
     def lookup(self, key):
         return self[key].node()
@@ -832,7 +821,7 @@
         renames = [(vfs, x, undoname(x)) for vfs, x in self._journalfiles()]
         rp = report and report or self.ui.warn
         tr = transaction.transaction(rp, self.sopener,
-                                     self.sjoin("journal"),
+                                     "journal",
                                      aftertrans(renames),
                                      self.store.createmode)
         self._transref = weakref.ref(tr)
@@ -866,7 +855,7 @@
         try:
             if self.svfs.exists("journal"):
                 self.ui.status(_("rolling back interrupted transaction\n"))
-                transaction.rollback(self.sopener, self.sjoin("journal"),
+                transaction.rollback(self.sopener, "journal",
                                      self.ui.warn)
                 self.invalidate()
                 return True
@@ -922,7 +911,7 @@
 
         parents = self.dirstate.parents()
         self.destroying()
-        transaction.rollback(self.sopener, self.sjoin('undo'), ui.warn)
+        transaction.rollback(self.sopener, 'undo', ui.warn)
         if self.vfs.exists('undo.bookmarks'):
             self.vfs.rename('undo.bookmarks', 'bookmarks')
         if self.svfs.exists('undo.phaseroots'):
@@ -998,17 +987,18 @@
                 pass
         self.invalidatecaches()
 
-    def _lock(self, lockname, wait, releasefn, acquirefn, desc):
+    def _lock(self, vfs, lockname, wait, releasefn, acquirefn, desc):
         try:
-            l = lock.lock(lockname, 0, releasefn, desc=desc)
+            l = lockmod.lock(vfs, lockname, 0, releasefn, desc=desc)
         except error.LockHeld, inst:
             if not wait:
                 raise
             self.ui.warn(_("waiting for lock on %s held by %r\n") %
                          (desc, inst.locker))
             # default to 600 seconds timeout
-            l = lock.lock(lockname, int(self.ui.config("ui", "timeout", "600")),
-                          releasefn, desc=desc)
+            l = lockmod.lock(vfs, lockname,
+                             int(self.ui.config("ui", "timeout", "600")),
+                             releasefn, desc=desc)
         if acquirefn:
             acquirefn()
         return l
@@ -1041,7 +1031,7 @@
                     continue
                 ce.refresh()
 
-        l = self._lock(self.sjoin("lock"), wait, unlock,
+        l = self._lock(self.svfs, "lock", wait, unlock,
                        self.invalidate, _('repository %s') % self.origroot)
         self._lockref = weakref.ref(l)
         return l
@@ -1059,7 +1049,7 @@
             self.dirstate.write()
             self._filecache['dirstate'].refresh()
 
-        l = self._lock(self.join("wlock"), wait, unlock,
+        l = self._lock(self.vfs, "wlock", wait, unlock,
                        self.invalidatedirstate, _('working directory of %s') %
                        self.origroot)
         self._wlockref = weakref.ref(l)
@@ -1379,7 +1369,7 @@
                       parent2=xp2, pending=p)
             self.changelog.finalize(trp)
             # set the new commit is proper phase
-            targetphase = phases.newcommitphase(self.ui)
+            targetphase = subrepo.newcommitphase(self.ui, ctx)
             if targetphase:
                 # retract boundary do not alter parent changeset.
                 # if a parent have higher the resulting phase will
@@ -1621,13 +1611,11 @@
         if branch not in branches:
             return []
         # the cache returns heads ordered lowest to highest
-        bheads = list(reversed(branches[branch]))
+        bheads = list(reversed(branches.branchheads(branch, closed=closed)))
         if start is not None:
             # filter out the heads that cannot be reached from startrev
             fbheads = set(self.changelog.nodesbetween([start], bheads)[2])
             bheads = [h for h in bheads if h in fbheads]
-        if not closed:
-            bheads = [h for h in bheads if not self[h].closesbranch()]
         return bheads
 
     def branches(self, nodes):
@@ -1678,12 +1666,11 @@
         trname = 'pull\n' + util.hidepassword(remote.url())
         lock = self.lock()
         try:
-            tmp = discovery.findcommonincoming(self, remote, heads=heads,
-                                               force=force)
+            tmp = discovery.findcommonincoming(self.unfiltered(), remote,
+                                               heads=heads, force=force)
             common, fetch, rheads = tmp
             if not fetch:
                 self.ui.status(_("no changes found\n"))
-                added = []
                 result = 0
             else:
                 tr = self.transaction(trname)
@@ -1705,20 +1692,13 @@
                                            "changegroupsubset."))
                 else:
                     cg = remote.changegroupsubset(fetch, heads, 'pull')
-                # we use unfiltered changelog here because hidden revision must
-                # be taken in account for phase synchronization. They may
-                # becomes public and becomes visible again.
-                cl = self.unfiltered().changelog
-                clstart = len(cl)
                 result = self.addchangegroup(cg, 'pull', remote.url())
-                clend = len(cl)
-                added = [cl.node(r) for r in xrange(clstart, clend)]
 
             # compute target subset
             if heads is None:
                 # We pulled every thing possible
                 # sync on everything common
-                subset = common + added
+                subset = common + rheads
             else:
                 # We pulled a specific subset
                 # sync on this subset
@@ -1861,14 +1841,16 @@
                                     raise util.Abort(_(mst)
                                                      % (ctx.troubles()[0],
                                                         ctx))
+                        newbm = self.ui.configlist('bookmarks', 'pushing')
                         discovery.checkheads(unfi, remote, outgoing,
                                              remoteheads, newbranch,
-                                             bool(inc))
+                                             bool(inc), newbm)
 
                     # TODO: get bundlecaps from remote
                     bundlecaps = None
                     # create a changegroup from local
-                    if revs is None and not outgoing.excluded:
+                    if revs is None and not (outgoing.excluded
+                                             or self.changelog.filteredrevs):
                         # push everything,
                         # use the fast path, no race possible on push
                         bundler = changegroup.bundle10(self, bundlecaps)
@@ -1976,27 +1958,7 @@
             if locallock is not None:
                 locallock.release()
 
-        self.ui.debug("checking for updated bookmarks\n")
-        rb = remote.listkeys('bookmarks')
-        revnums = map(unfi.changelog.rev, revs or [])
-        ancestors = [
-            a for a in unfi.changelog.ancestors(revnums, inclusive=True)]
-        for k in rb.keys():
-            if k in unfi._bookmarks:
-                nr, nl = rb[k], hex(self._bookmarks[k])
-                if nr in unfi:
-                    cr = unfi[nr]
-                    cl = unfi[nl]
-                    if bookmarks.validdest(unfi, cr, cl):
-                        if ancestors and cl.rev() not in ancestors:
-                            continue
-                        r = remote.pushkey('bookmarks', k, nr, nl)
-                        if r:
-                            self.ui.status(_("updating bookmark %s\n") % k)
-                        else:
-                            self.ui.warn(_('updating bookmark %s'
-                                           ' failed!\n') % k)
-
+        bookmarks.updateremote(self.ui, unfi, remote, revs)
         return ret
 
     def changegroupinfo(self, nodes, source):
@@ -2025,8 +1987,10 @@
             bases = [nullid]
         # TODO: remove call to nodesbetween.
         csets, bases, heads = cl.nodesbetween(bases, heads)
-        bases = [p for n in bases for p in cl.parents(n) if p != nullid]
-        outgoing = discovery.outgoing(cl, bases, heads)
+        discbases = []
+        for n in bases:
+            discbases.extend([p for p in cl.parents(n) if p != nullid])
+        outgoing = discovery.outgoing(cl, discbases, heads)
         bundler = changegroup.bundle10(self)
         return self._changegroupsubset(outgoing, bundler, source)
 
--- a/mercurial/lock.py	Mon Jan 20 11:16:26 2014 -0200
+++ b/mercurial/lock.py	Tue Jan 21 14:44:01 2014 -0600
@@ -29,7 +29,8 @@
 
     _host = None
 
-    def __init__(self, file, timeout=-1, releasefn=None, desc=None):
+    def __init__(self, vfs, file, timeout=-1, releasefn=None, desc=None):
+        self.vfs = vfs
         self.f = file
         self.held = 0
         self.timeout = timeout
@@ -75,13 +76,14 @@
         lockname = '%s:%s' % (lock._host, self.pid)
         while not self.held:
             try:
-                util.makelock(lockname, self.f)
+                self.vfs.makelock(lockname, self.f)
                 self.held = 1
             except (OSError, IOError), why:
                 if why.errno == errno.EEXIST:
                     locker = self.testlock()
                     if locker is not None:
-                        raise error.LockHeld(errno.EAGAIN, self.f, self.desc,
+                        raise error.LockHeld(errno.EAGAIN,
+                                             self.vfs.join(self.f), self.desc,
                                              locker)
                 else:
                     raise error.LockUnavailable(why.errno, why.strerror,
@@ -99,7 +101,7 @@
 
         """
         try:
-            locker = util.readlock(self.f)
+            locker = self.vfs.readlock(self.f)
         except (OSError, IOError), why:
             if why.errno == errno.ENOENT:
                 return None
@@ -119,8 +121,8 @@
         # if locker dead, break lock.  must do this with another lock
         # held, or can race and break valid lock.
         try:
-            l = lock(self.f + '.break', timeout=0)
-            util.unlink(self.f)
+            l = lock(self.vfs, self.f + '.break', timeout=0)
+            self.vfs.unlink(self.f)
             l.release()
         except error.LockError:
             return locker
@@ -140,7 +142,7 @@
             if self.releasefn:
                 self.releasefn()
             try:
-                util.unlink(self.f)
+                self.vfs.unlink(self.f)
             except OSError:
                 pass
             for callback in self.postrelease:
--- a/mercurial/manifest.py	Mon Jan 20 11:16:26 2014 -0200
+++ b/mercurial/manifest.py	Tue Jan 21 14:44:01 2014 -0600
@@ -30,8 +30,9 @@
 
 class manifest(revlog.revlog):
     def __init__(self, opener):
-        # we expect to deal with not more than three revs at a time in merge
-        self._mancache = util.lrucachedict(3)
+        # we expect to deal with not more than four revs at a time,
+        # during a commit --amend
+        self._mancache = util.lrucachedict(4)
         revlog.revlog.__init__(self, opener, "00manifest.i")
 
     def parse(self, lines):
--- a/mercurial/match.py	Mon Jan 20 11:16:26 2014 -0200
+++ b/mercurial/match.py	Tue Jan 21 14:44:01 2014 -0600
@@ -6,7 +6,7 @@
 # GNU General Public License version 2 or any later version.
 
 import re
-import scmutil, util, fileset
+import util, fileset, pathutil
 from i18n import _
 
 def _rematcher(pat):
@@ -317,7 +317,7 @@
     pats = []
     for kind, name in [_patsplit(p, default) for p in names]:
         if kind in ('glob', 'relpath'):
-            name = scmutil.canonpath(root, cwd, name, auditor)
+            name = pathutil.canonpath(root, cwd, name, auditor)
         elif kind in ('relglob', 'path'):
             name = util.normpath(name)
         elif kind in ('listfile', 'listfile0'):
--- a/mercurial/mdiff.py	Mon Jan 20 11:16:26 2014 -0200
+++ b/mercurial/mdiff.py	Tue Jan 21 14:44:01 2014 -0600
@@ -6,8 +6,8 @@
 # GNU General Public License version 2 or any later version.
 
 from i18n import _
-import bdiff, mpatch, util
-import re, struct, base85, zlib
+import bdiff, mpatch, util, base85
+import re, struct, zlib
 
 def splitnewlines(text):
     '''like str.splitlines, but only split on newlines.'''
--- a/mercurial/merge.py	Mon Jan 20 11:16:26 2014 -0200
+++ b/mercurial/merge.py	Tue Jan 21 14:44:01 2014 -0600
@@ -679,8 +679,16 @@
     wlock = repo.wlock()
     try:
         wc = repo[None]
+        pl = wc.parents()
+        p1 = pl[0]
+        pa = None
+        if ancestor:
+            pa = repo[ancestor]
+
         if node is None:
-            # tip of current branch
+            # Here is where we should consider bookmarks, divergent bookmarks,
+            # foreground changesets (successors), and tip of current branch;
+            # but currently we are only checking the branch tips.
             try:
                 node = repo.branchtip(wc.branch())
             except error.RepoLookupError:
@@ -688,12 +696,38 @@
                     node = repo.lookup("tip") # update to tip
                 else:
                     raise util.Abort(_("branch %s not found") % wc.branch())
+
+            if p1.obsolete() and not p1.children():
+                # allow updating to successors
+                successors = obsolete.successorssets(repo, p1.node())
+
+                # behavior of certain cases is as follows,
+                #
+                # divergent changesets: update to highest rev, similar to what
+                #     is currently done when there are more than one head
+                #     (i.e. 'tip')
+                #
+                # replaced changesets: same as divergent except we know there
+                # is no conflict
+                #
+                # pruned changeset: no update is done; though, we could
+                #     consider updating to the first non-obsolete parent,
+                #     similar to what is current done for 'hg prune'
+
+                if successors:
+                    # flatten the list here handles both divergent (len > 1)
+                    # and the usual case (len = 1)
+                    successors = [n for sub in successors for n in sub]
+
+                    # get the max revision for the given successors set,
+                    # i.e. the 'tip' of a set
+                    node = repo.revs("max(%ln)", successors)[0]
+                    pa = p1
+
         overwrite = force and not branchmerge
-        pl = wc.parents()
-        p1, p2 = pl[0], repo[node]
-        if ancestor:
-            pa = repo[ancestor]
-        else:
+
+        p2 = repo[node]
+        if pa is None:
             pa = p1.ancestor(p2)
 
         fp1, fp2, xp1, xp2 = p1.node(), p2.node(), str(p1), str(p2)
--- a/mercurial/obsolete.py	Mon Jan 20 11:16:26 2014 -0200
+++ b/mercurial/obsolete.py	Tue Jan 21 14:44:01 2014 -0600
@@ -84,6 +84,7 @@
 """
 import struct
 import util, base85, node
+import phases
 from i18n import _
 
 _pack = struct.pack
@@ -196,6 +197,14 @@
         self._data = data
         self._decodedmeta = None
 
+    def __hash__(self):
+        return hash(self._data)
+
+    def __eq__(self, other):
+        if type(other) != type(self):
+            return False
+        return self._data == other._data
+
     def precnode(self):
         """Precursor changeset node identifier"""
         return self._data[0]
@@ -268,7 +277,11 @@
         if not _enabled:
             raise util.Abort('obsolete feature is not enabled on this repo')
         known = set(self._all)
-        new = [m for m in markers if m not in known]
+        new = []
+        for m in markers:
+            if m not in known:
+                known.add(m)
+                new.append(m)
         if new:
             f = self.sopener('obsstore', 'ab')
             try:
@@ -428,14 +441,15 @@
 
     Some successors may be unknown locally.
 
-    This is a linear yield unsuited to detecting split changesets."""
+    This is a linear yield unsuited to detecting split changesets. It includes
+    initial nodes too."""
     remaining = set(nodes)
     seen = set(remaining)
     while remaining:
         current = remaining.pop()
         yield current
         for mark in obsstore.successors.get(current, ()):
-            # ignore marker flagged with with specified flag
+            # ignore marker flagged with specified flag
             if mark[2] & ignoreflags:
                 continue
             for suc in mark[1]:
@@ -443,6 +457,28 @@
                     seen.add(suc)
                     remaining.add(suc)
 
+def allprecursors(obsstore, nodes, ignoreflags=0):
+    """Yield node for every precursors of <nodes>.
+
+    Some precursors may be unknown locally.
+
+    This is a linear yield unsuited to detecting folded changesets. It includes
+    initial nodes too."""
+
+    remaining = set(nodes)
+    seen = set(remaining)
+    while remaining:
+        current = remaining.pop()
+        yield current
+        for mark in obsstore.precursors.get(current, ()):
+            # ignore marker flagged with specified flag
+            if mark[2] & ignoreflags:
+                continue
+            suc = mark[0]
+            if suc not in seen:
+                seen.add(suc)
+                remaining.add(suc)
+
 def foreground(repo, nodes):
     """return all nodes in the "foreground" of other node
 
@@ -473,29 +509,41 @@
 def successorssets(repo, initialnode, cache=None):
     """Return all set of successors of initial nodes
 
-    Successors set of changeset A are a group of revision that succeed A. It
-    succeed A as a consistent whole, each revision being only partial
-    replacement.  Successors set contains non-obsolete changeset only.
+    The successors set of a changeset A are a group of revisions that succeed
+    A. It succeeds A as a consistent whole, each revision being only a partial
+    replacement. The successors set contains non-obsolete changesets only.
 
-    In most cases a changeset A have zero (changeset pruned) or a single
-    successors set that contains a single successor (changeset A replaced by
-    A')
+    This function returns the full list of successor sets which is why it
+    returns a list of tuples and not just a single tuple. Each tuple is a valid
+    successors set. Not that (A,) may be a valid successors set for changeset A
+    (see below).
 
-    When changeset is split, it results successors set containing more than
-    a single element. Divergent rewriting will result in multiple successors
-    sets.
+    In most cases, a changeset A will have a single element (e.g. the changeset
+    A is replaced by A') in its successors set. Though, it is also common for a
+    changeset A to have no elements in its successor set (e.g. the changeset
+    has been pruned). Therefore, the returned list of successors sets will be
+    [(A',)] or [], respectively.
 
-    They are returned as a list of tuples containing all valid successors sets.
+    When a changeset A is split into A' and B', however, it will result in a
+    successors set containing more than a single element, i.e. [(A',B')].
+    Divergent changesets will result in multiple successors sets, i.e. [(A',),
+    (A'')].
 
-    Final successors unknown locally are considered plain prune (obsoleted
-    without successors).
+    If a changeset A is not obsolete, then it will conceptually have no
+    successors set. To distinguish this from a pruned changeset, the successor
+    set will only contain itself, i.e. [(A,)].
 
-    The optional `cache` parameter is a dictionary that may contains
-    precomputed successors sets. It is meant to reuse the computation of
-    previous call to `successorssets` when multiple calls are made at the same
-    time. The cache dictionary is updated in place. The caller is responsible
-    for its live spawn. Code that makes multiple calls to `successorssets`
-    *must* use this cache mechanism or suffer terrible performances."""
+    Finally, successors unknown locally are considered to be pruned (obsoleted
+    without any successors).
+
+    The optional `cache` parameter is a dictionary that may contain precomputed
+    successors sets. It is meant to reuse the computation of a previous call to
+    `successorssets` when multiple calls are made at the same time. The cache
+    dictionary is updated in place. The caller is responsible for its live
+    spawn. Code that makes multiple calls to `successorssets` *must* use this
+    cache mechanism or suffer terrible performances.
+
+    """
 
     succmarkers = repo.obsstore.successors
 
@@ -751,14 +799,26 @@
 @cachefor('bumped')
 def _computebumpedset(repo):
     """the set of revs trying to obsolete public revisions"""
-    # get all possible bumped changesets
-    tonode = repo.changelog.node
-    publicnodes = (tonode(r) for r in repo.revs('public()'))
-    successors = allsuccessors(repo.obsstore, publicnodes,
-                               ignoreflags=bumpedfix)
-    # revision public or already obsolete don't count as bumped
-    query = '%ld - obsolete() - public()'
-    return set(repo.revs(query, _knownrevs(repo, successors)))
+    bumped = set()
+    # utils function (avoid attribut lookup in the loop)
+    phase = repo._phasecache.phase # would be faster to grab the full list
+    public = phases.public
+    cl = repo.changelog
+    torev = cl.nodemap.get
+    obs = getrevs(repo, 'obsolete')
+    for rev in repo:
+        # We only evaluate mutable, non-obsolete revision
+        if (public < phase(repo, rev)) and (rev not in obs):
+            node = cl.node(rev)
+            # (future) A cache of precursors may worth if split is very common
+            for pnode in allprecursors(repo.obsstore, [node],
+                                       ignoreflags=bumpedfix):
+                prev = torev(pnode) # unfiltered! but so is phasecache
+                if (prev is not None) and (phase(repo, prev) <= public):
+                    # we have a public precursors
+                    bumped.add(rev)
+                    break # Next draft!
+    return bumped
 
 @cachefor('divergent')
 def _computedivergentset(repo):
--- a/mercurial/parsers.c	Mon Jan 20 11:16:26 2014 -0200
+++ b/mercurial/parsers.c	Tue Jan 21 14:44:01 2014 -0600
@@ -926,8 +926,13 @@
 static int nt_init(indexObject *self)
 {
 	if (self->nt == NULL) {
+		if (self->raw_length > INT_MAX) {
+			PyErr_SetString(PyExc_ValueError, "overflow in nt_init");
+			return -1;
+		}
 		self->ntcapacity = self->raw_length < 4
-			? 4 : self->raw_length / 2;
+			? 4 : (int)self->raw_length / 2;
+
 		self->nt = calloc(self->ntcapacity, sizeof(nodetree));
 		if (self->nt == NULL) {
 			PyErr_NoMemory();
--- a/mercurial/patch.py	Mon Jan 20 11:16:26 2014 -0200
+++ b/mercurial/patch.py	Tue Jan 21 14:44:01 2014 -0600
@@ -16,7 +16,6 @@
 from i18n import _
 from node import hex, short
 import base85, mdiff, scmutil, util, diffhelpers, copies, encoding, error
-import context
 
 gitre = re.compile('diff --git a/(.*) b/(.*)')
 
@@ -722,8 +721,9 @@
             if self.remove:
                 self.backend.unlink(self.fname)
             else:
-                self.lines[:] = h.new()
-                self.offset += len(h.new())
+                l = h.new(self.lines)
+                self.lines[:] = l
+                self.offset += len(l)
                 self.dirty = True
             return 0
 
@@ -1017,9 +1017,10 @@
         return old, oldstart, new, newstart
 
 class binhunk(object):
-    'A binary patch file. Only understands literals so far.'
+    'A binary patch file.'
     def __init__(self, lr, fname):
         self.text = None
+        self.delta = False
         self.hunk = ['GIT binary patch\n']
         self._fname = fname
         self._read(lr)
@@ -1027,7 +1028,9 @@
     def complete(self):
         return self.text is not None
 
-    def new(self):
+    def new(self, lines):
+        if self.delta:
+            return [applybindelta(self.text, ''.join(lines))]
         return [self.text]
 
     def _read(self, lr):
@@ -1036,14 +1039,19 @@
             hunk.append(l)
             return l.rstrip('\r\n')
 
+        size = 0
         while True:
             line = getline(lr, self.hunk)
             if not line:
                 raise PatchError(_('could not extract "%s" binary data')
                                  % self._fname)
             if line.startswith('literal '):
+                size = int(line[8:].rstrip())
                 break
-        size = int(line[8:].rstrip())
+            if line.startswith('delta '):
+                size = int(line[6:].rstrip())
+                self.delta = True
+                break
         dec = []
         line = getline(lr, self.hunk)
         while len(line) > 1:
@@ -1266,6 +1274,62 @@
         gp = gitpatches.pop()
         yield 'file', ('a/' + gp.path, 'b/' + gp.path, None, gp.copy())
 
+def applybindelta(binchunk, data):
+    """Apply a binary delta hunk
+    The algorithm used is the algorithm from git's patch-delta.c
+    """
+    def deltahead(binchunk):
+        i = 0
+        for c in binchunk:
+            i += 1
+            if not (ord(c) & 0x80):
+                return i
+        return i
+    out = ""
+    s = deltahead(binchunk)
+    binchunk = binchunk[s:]
+    s = deltahead(binchunk)
+    binchunk = binchunk[s:]
+    i = 0
+    while i < len(binchunk):
+        cmd = ord(binchunk[i])
+        i += 1
+        if (cmd & 0x80):
+            offset = 0
+            size = 0
+            if (cmd & 0x01):
+                offset = ord(binchunk[i])
+                i += 1
+            if (cmd & 0x02):
+                offset |= ord(binchunk[i]) << 8
+                i += 1
+            if (cmd & 0x04):
+                offset |= ord(binchunk[i]) << 16
+                i += 1
+            if (cmd & 0x08):
+                offset |= ord(binchunk[i]) << 24
+                i += 1
+            if (cmd & 0x10):
+                size = ord(binchunk[i])
+                i += 1
+            if (cmd & 0x20):
+                size |= ord(binchunk[i]) << 8
+                i += 1
+            if (cmd & 0x40):
+                size |= ord(binchunk[i]) << 16
+                i += 1
+            if size == 0:
+                size = 0x10000
+            offset_end = offset + size
+            out += data[offset:offset_end]
+        elif cmd != 0:
+            offset_end = i + cmd
+            out += binchunk[i:offset_end]
+            i += cmd
+        else:
+            raise PatchError(_('unexpected delta opcode 0'))
+    return out
+
 def applydiff(ui, fp, backend, store, strip=1, eolmode='strict'):
     """Reads a patch from fp and tries to apply it.
 
@@ -1441,21 +1505,6 @@
     backend = repobackend(ui, repo, ctx, store)
     return patchbackend(ui, backend, patchobj, strip, files, eolmode)
 
-def makememctx(repo, parents, text, user, date, branch, files, store,
-               editor=None):
-    def getfilectx(repo, memctx, path):
-        data, (islink, isexec), copied = store.getfile(path)
-        return context.memfilectx(path, data, islink=islink, isexec=isexec,
-                                  copied=copied)
-    extra = {}
-    if branch:
-        extra['branch'] = encoding.fromlocal(branch)
-    ctx =  context.memctx(repo, parents, text, files, getfilectx, user,
-                          date, extra)
-    if editor:
-        ctx._text = editor(repo, ctx, [])
-    return ctx
-
 def patch(ui, repo, patchname, strip=1, files=None, eolmode='strict',
           similarity=0):
     """Apply <patchname> to the working directory.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mercurial/pathutil.py	Tue Jan 21 14:44:01 2014 -0600
@@ -0,0 +1,144 @@
+import os, errno, stat
+
+import util
+from i18n import _
+
+class pathauditor(object):
+    '''ensure that a filesystem path contains no banned components.
+    the following properties of a path are checked:
+
+    - ends with a directory separator
+    - under top-level .hg
+    - starts at the root of a windows drive
+    - contains ".."
+    - traverses a symlink (e.g. a/symlink_here/b)
+    - inside a nested repository (a callback can be used to approve
+      some nested repositories, e.g., subrepositories)
+    '''
+
+    def __init__(self, root, callback=None):
+        self.audited = set()
+        self.auditeddir = set()
+        self.root = root
+        self.callback = callback
+        if os.path.lexists(root) and not util.checkcase(root):
+            self.normcase = util.normcase
+        else:
+            self.normcase = lambda x: x
+
+    def __call__(self, path):
+        '''Check the relative path.
+        path may contain a pattern (e.g. foodir/**.txt)'''
+
+        path = util.localpath(path)
+        normpath = self.normcase(path)
+        if normpath in self.audited:
+            return
+        # AIX ignores "/" at end of path, others raise EISDIR.
+        if util.endswithsep(path):
+            raise util.Abort(_("path ends in directory separator: %s") % path)
+        parts = util.splitpath(path)
+        if (os.path.splitdrive(path)[0]
+            or parts[0].lower() in ('.hg', '.hg.', '')
+            or os.pardir in parts):
+            raise util.Abort(_("path contains illegal component: %s") % path)
+        if '.hg' in path.lower():
+            lparts = [p.lower() for p in parts]
+            for p in '.hg', '.hg.':
+                if p in lparts[1:]:
+                    pos = lparts.index(p)
+                    base = os.path.join(*parts[:pos])
+                    raise util.Abort(_("path '%s' is inside nested repo %r")
+                                     % (path, base))
+
+        normparts = util.splitpath(normpath)
+        assert len(parts) == len(normparts)
+
+        parts.pop()
+        normparts.pop()
+        prefixes = []
+        while parts:
+            prefix = os.sep.join(parts)
+            normprefix = os.sep.join(normparts)
+            if normprefix in self.auditeddir:
+                break
+            curpath = os.path.join(self.root, prefix)
+            try:
+                st = os.lstat(curpath)
+            except OSError, err:
+                # EINVAL can be raised as invalid path syntax under win32.
+                # They must be ignored for patterns can be checked too.
+                if err.errno not in (errno.ENOENT, errno.ENOTDIR, errno.EINVAL):
+                    raise
+            else:
+                if stat.S_ISLNK(st.st_mode):
+                    raise util.Abort(
+                        _('path %r traverses symbolic link %r')
+                        % (path, prefix))
+                elif (stat.S_ISDIR(st.st_mode) and
+                      os.path.isdir(os.path.join(curpath, '.hg'))):
+                    if not self.callback or not self.callback(curpath):
+                        raise util.Abort(_("path '%s' is inside nested "
+                                           "repo %r")
+                                         % (path, prefix))
+            prefixes.append(normprefix)
+            parts.pop()
+            normparts.pop()
+
+        self.audited.add(normpath)
+        # only add prefixes to the cache after checking everything: we don't
+        # want to add "foo/bar/baz" before checking if there's a "foo/.hg"
+        self.auditeddir.update(prefixes)
+
+    def check(self, path):
+        try:
+            self(path)
+            return True
+        except (OSError, util.Abort):
+            return False
+
+def canonpath(root, cwd, myname, auditor=None):
+    '''return the canonical path of myname, given cwd and root'''
+    if util.endswithsep(root):
+        rootsep = root
+    else:
+        rootsep = root + os.sep
+    name = myname
+    if not os.path.isabs(name):
+        name = os.path.join(root, cwd, name)
+    name = os.path.normpath(name)
+    if auditor is None:
+        auditor = pathauditor(root)
+    if name != rootsep and name.startswith(rootsep):
+        name = name[len(rootsep):]
+        auditor(name)
+        return util.pconvert(name)
+    elif name == root:
+        return ''
+    else:
+        # Determine whether `name' is in the hierarchy at or beneath `root',
+        # by iterating name=dirname(name) until that causes no change (can't
+        # check name == '/', because that doesn't work on windows). The list
+        # `rel' holds the reversed list of components making up the relative
+        # file name we want.
+        rel = []
+        while True:
+            try:
+                s = util.samefile(name, root)
+            except OSError:
+                s = False
+            if s:
+                if not rel:
+                    # name was actually the same as root (maybe a symlink)
+                    return ''
+                rel.reverse()
+                name = os.path.join(*rel)
+                auditor(name)
+                return util.pconvert(name)
+            dirname, basename = util.split(name)
+            rel.append(basename)
+            if dirname == name:
+                break
+            name = dirname
+
+        raise util.Abort(_("%s not under root '%s'") % (myname, root))
--- a/mercurial/posix.py	Mon Jan 20 11:16:26 2014 -0200
+++ b/mercurial/posix.py	Tue Jan 21 14:44:01 2014 -0600
@@ -197,7 +197,6 @@
     return path.lower()
 
 if sys.platform == 'darwin':
-    import fcntl # only needed on darwin, missing on jython
 
     def normcase(path):
         '''
@@ -265,51 +264,6 @@
         # Decompose then lowercase (HFS+ technote specifies lower)
         return unicodedata.normalize('NFD', u).lower().encode('utf-8')
 
-    def realpath(path):
-        '''
-        Returns the true, canonical file system path equivalent to the given
-        path.
-
-        Equivalent means, in this case, resulting in the same, unique
-        file system link to the path. Every file system entry, whether a file,
-        directory, hard link or symbolic link or special, will have a single
-        path preferred by the system, but may allow multiple, differing path
-        lookups to point to it.
-
-        Most regular UNIX file systems only allow a file system entry to be
-        looked up by its distinct path. Obviously, this does not apply to case
-        insensitive file systems, whether case preserving or not. The most
-        complex issue to deal with is file systems transparently reencoding the
-        path, such as the non-standard Unicode normalisation required for HFS+
-        and HFSX.
-        '''
-        # Constants copied from /usr/include/sys/fcntl.h
-        F_GETPATH = 50
-        O_SYMLINK = 0x200000
-
-        try:
-            fd = os.open(path, O_SYMLINK)
-        except OSError, err:
-            if err.errno == errno.ENOENT:
-                return path
-            raise
-
-        try:
-            return fcntl.fcntl(fd, F_GETPATH, '\0' * 1024).rstrip('\0')
-        finally:
-            os.close(fd)
-elif sys.version_info < (2, 4, 2, 'final'):
-    # Workaround for http://bugs.python.org/issue1213894 (os.path.realpath
-    # didn't resolve symlinks that were the first component of the path.)
-    def realpath(path):
-        if os.path.isabs(path):
-            return os.path.realpath(path)
-        else:
-            return os.path.realpath('./' + path)
-else:
-    # Fallback to the likely inadequate Python builtin function.
-    realpath = os.path.realpath
-
 if sys.platform == 'cygwin':
     # workaround for cygwin, in which mount point part of path is
     # treated as case sensitive, even though underlying NTFS is case
--- a/mercurial/repair.py	Mon Jan 20 11:16:26 2014 -0200
+++ b/mercurial/repair.py	Tue Jan 21 14:44:01 2014 -0600
@@ -38,16 +38,8 @@
     """return the changesets which will be broken by the truncation"""
     s = set()
     def collectone(revlog):
-        linkgen = (revlog.linkrev(i) for i in revlog)
-        # find the truncation point of the revlog
-        for lrev in linkgen:
-            if lrev >= striprev:
-                break
-        # see if any revision after this point has a linkrev
-        # less than striprev (those will be broken by strip)
-        for lrev in linkgen:
-            if lrev < striprev:
-                s.add(lrev)
+        _, brokenset = revlog.getstrippoint(striprev)
+        s.update([revlog.linkrev(r) for r in brokenset])
 
     collectone(repo.manifest)
     for fname in files:
--- a/mercurial/repoview.py	Mon Jan 20 11:16:26 2014 -0200
+++ b/mercurial/repoview.py	Tue Jan 21 14:44:01 2014 -0600
@@ -94,20 +94,15 @@
     return frozenset(xrange(firstmutable, len(cl)))
 
 # function to compute filtered set
+#
+# When addding a new filter you MUST update the table at:
+#     mercurial.branchmap.subsettable
+# Otherwise your filter will have to recompute all its branches cache
+# from scratch (very slow).
 filtertable = {'visible': computehidden,
                'served': computeunserved,
                'immutable':  computemutable,
                'base':  computeimpactable}
-### Nearest subset relation
-# Nearest subset of filter X is a filter Y so that:
-# * Y is included in X,
-# * X - Y is as small as possible.
-# This create and ordering used for branchmap purpose.
-# the ordering may be partial
-subsettable = {None: 'visible',
-               'visible': 'served',
-               'served': 'immutable',
-               'immutable': 'base'}
 
 def filterrevs(repo, filtername):
     """returns set of filtered revision for this filter name"""
@@ -215,4 +210,3 @@
     @property
     def requirements(self):
         return self._unfilteredrepo.requirements
-
--- a/mercurial/revlog.py	Mon Jan 20 11:16:26 2014 -0200
+++ b/mercurial/revlog.py	Tue Jan 21 14:44:01 2014 -0600
@@ -202,6 +202,7 @@
         self._cache = None
         self._basecache = None
         self._chunkcache = (0, '')
+        self._chunkcachesize = 65536
         self.index = []
         self._pcache = {}
         self._nodecache = {nullid: nullrev}
@@ -215,6 +216,15 @@
                     v |= REVLOGGENERALDELTA
             else:
                 v = 0
+            if 'chunkcachesize' in opts:
+                self._chunkcachesize = opts['chunkcachesize']
+
+        if self._chunkcachesize <= 0:
+            raise RevlogError(_('revlog chunk cache size %r is not greater '
+                                'than 0') % self._chunkcachesize)
+        elif self._chunkcachesize & (self._chunkcachesize - 1):
+            raise RevlogError(_('revlog chunk cache size %r is not a power '
+                                'of 2') % self._chunkcachesize)
 
         i = ''
         self._initempty = True
@@ -401,7 +411,29 @@
         heads = [self.rev(n) for n in heads]
 
         # we want the ancestors, but inclusive
-        has = set(self.ancestors(common))
+        class lazyset(object):
+            def __init__(self, lazyvalues):
+                self.addedvalues = set()
+                self.lazyvalues = lazyvalues
+
+            def __contains__(self, value):
+                return value in self.addedvalues or value in self.lazyvalues
+
+            def __iter__(self):
+                added = self.addedvalues
+                for r in added:
+                    yield r
+                for r in self.lazyvalues:
+                    if not r in added:
+                        yield r
+
+            def add(self, value):
+                self.addedvalues.add(value)
+
+            def update(self, values):
+                self.addedvalues.update(values)
+
+        has = lazyset(self.ancestors(common))
         has.add(nullrev)
         has.update(common)
 
@@ -820,13 +852,19 @@
         else:
             df = self.opener(self.datafile)
 
-        readahead = max(65536, length)
-        df.seek(offset)
-        d = df.read(readahead)
+        # Cache data both forward and backward around the requested
+        # data, in a fixed size window. This helps speed up operations
+        # involving reading the revlog backwards.
+        cachesize = self._chunkcachesize
+        realoffset = offset & ~(cachesize - 1)
+        reallength = (((offset + length + cachesize) & ~(cachesize - 1))
+                      - realoffset)
+        df.seek(realoffset)
+        d = df.read(reallength)
         df.close()
-        self._addchunk(offset, d)
-        if readahead > length:
-            return util.buffer(d, 0, length)
+        self._addchunk(realoffset, d)
+        if offset != realoffset or reallength != length:
+            return util.buffer(d, offset - realoffset, length)
         return d
 
     def _getchunk(self, offset, length):
@@ -1168,6 +1206,15 @@
         self.nodemap[node] = curr
 
         entry = self._io.packentry(e, self.node, self.version, curr)
+        self._writeentry(transaction, ifh, dfh, entry, data, link, offset)
+
+        if type(text) == str: # only accept immutable objects
+            self._cache = (node, curr, text)
+        self._basecache = (curr, chainbase)
+        return node
+
+    def _writeentry(self, transaction, ifh, dfh, entry, data, link, offset):
+        curr = len(self) - 1
         if not self._inline:
             transaction.add(self.datafile, offset)
             transaction.add(self.indexfile, curr * len(entry))
@@ -1184,11 +1231,6 @@
             ifh.write(data[1])
             self.checkinlinesize(transaction, ifh)
 
-        if type(text) == str: # only accept immutable objects
-            self._cache = (node, curr, text)
-        self._basecache = (curr, chainbase)
-        return node
-
     def addgroup(self, bundle, linkmapper, transaction):
         """
         add a delta group
@@ -1263,6 +1305,46 @@
 
         return content
 
+    def getstrippoint(self, minlink):
+        """find the minimum rev that must be stripped to strip the linkrev
+
+        Returns a tuple containing the minimum rev and a set of all revs that
+        have linkrevs that will be broken by this strip.
+        """
+        brokenrevs = set()
+        strippoint = len(self)
+
+        heads = {}
+        futurelargelinkrevs = set()
+        for head in self.headrevs():
+            headlinkrev = self.linkrev(head)
+            heads[head] = headlinkrev
+            if headlinkrev >= minlink:
+                futurelargelinkrevs.add(headlinkrev)
+
+        # This algorithm involves walking down the rev graph, starting at the
+        # heads. Since the revs are topologically sorted according to linkrev,
+        # once all head linkrevs are below the minlink, we know there are
+        # no more revs that could have a linkrev greater than minlink.
+        # So we can stop walking.
+        while futurelargelinkrevs:
+            strippoint -= 1
+            linkrev = heads.pop(strippoint)
+
+            if linkrev < minlink:
+                brokenrevs.add(strippoint)
+            else:
+                futurelargelinkrevs.remove(linkrev)
+
+            for p in self.parentrevs(strippoint):
+                if p != nullrev:
+                    plinkrev = self.linkrev(p)
+                    heads[p] = plinkrev
+                    if plinkrev >= minlink:
+                        futurelargelinkrevs.add(plinkrev)
+
+        return strippoint, brokenrevs
+
     def strip(self, minlink, transaction):
         """truncate the revlog on the first revision with a linkrev >= minlink
 
@@ -1280,10 +1362,8 @@
         if len(self) == 0:
             return
 
-        for rev in self:
-            if self.index[rev][4] >= minlink:
-                break
-        else:
+        rev, _ = self.getstrippoint(minlink)
+        if rev == len(self):
             return
 
         # first truncate the files on disk
--- a/mercurial/revset.py	Mon Jan 20 11:16:26 2014 -0200
+++ b/mercurial/revset.py	Tue Jan 21 14:44:01 2014 -0600
@@ -12,6 +12,7 @@
 from i18n import _
 import encoding
 import obsolete as obsmod
+import pathutil
 import repoview
 
 def _revancestors(repo, revs, followfirst):
@@ -269,6 +270,10 @@
 def adds(repo, subset, x):
     """``adds(pattern)``
     Changesets that add a file matching pattern.
+
+    The pattern without explicit kind like ``glob:`` is expected to be
+    relative to the current directory and match against a file or a
+    directory.
     """
     # i18n: "adds" is a keyword
     pat = getstring(x, _("adds requires a pattern"))
@@ -525,16 +530,21 @@
     """``contains(pattern)``
     Revision contains a file matching pattern. See :hg:`help patterns`
     for information about file patterns.
+
+    The pattern without explicit kind like ``glob:`` is expected to be
+    relative to the current directory and match against a file exactly
+    for efficiency.
     """
     # i18n: "contains" is a keyword
     pat = getstring(x, _("contains requires a pattern"))
-    m = None
     s = []
     if not matchmod.patkind(pat):
+        pat = pathutil.canonpath(repo.root, repo.getcwd(), pat)
         for r in subset:
             if pat in repo[r]:
                 s.append(r)
     else:
+        m = None
         for r in subset:
             c = repo[r]
             if not m or matchmod.patkind(pat) == 'set':
@@ -711,20 +721,23 @@
     For performance reasons, ``filelog()`` does not show every changeset
     that affects the requested file(s). See :hg:`help log` for details. For
     a slower, more accurate result, use ``file()``.
+
+    The pattern without explicit kind like ``glob:`` is expected to be
+    relative to the current directory and match against a file exactly
+    for efficiency.
     """
 
     # i18n: "filelog" is a keyword
     pat = getstring(x, _("filelog requires a pattern"))
-    m = matchmod.match(repo.root, repo.getcwd(), [pat], default='relpath',
-                       ctx=repo[None])
     s = set()
 
     if not matchmod.patkind(pat):
-        for f in m.files():
-            fl = repo.file(f)
-            for fr in fl:
-                s.add(fl.linkrev(fr))
+        f = pathutil.canonpath(repo.root, repo.getcwd(), pat)
+        fl = repo.file(f)
+        for fr in fl:
+            s.add(fl.linkrev(fr))
     else:
+        m = matchmod.match(repo.root, repo.getcwd(), [pat], ctx=repo[None])
         for f in repo[None]:
             if m(f):
                 fl = repo.file(f)
@@ -867,6 +880,8 @@
 
     For a faster but less accurate result, consider using ``filelog()``
     instead.
+
+    This predicate uses ``glob:`` as the default kind of pattern.
     """
     # i18n: "file" is a keyword
     pat = getstring(x, _("file requires a pattern"))
@@ -1002,6 +1017,10 @@
 def modifies(repo, subset, x):
     """``modifies(pattern)``
     Changesets modifying files matched by pattern.
+
+    The pattern without explicit kind like ``glob:`` is expected to be
+    relative to the current directory and match against a file or a
+    directory.
     """
     # i18n: "modifies" is a keyword
     pat = getstring(x, _("modifies requires a pattern"))
@@ -1215,6 +1234,10 @@
 def removes(repo, subset, x):
     """``removes(pattern)``
     Changesets which remove files matching pattern.
+
+    The pattern without explicit kind like ``glob:`` is expected to be
+    relative to the current directory and match against a file or a
+    directory.
     """
     # i18n: "removes" is a keyword
     pat = getstring(x, _("removes requires a pattern"))
--- a/mercurial/scmutil.py	Mon Jan 20 11:16:26 2014 -0200
+++ b/mercurial/scmutil.py	Tue Jan 21 14:44:01 2014 -0600
@@ -8,8 +8,9 @@
 from i18n import _
 from mercurial.node import nullrev
 import util, error, osutil, revset, similar, encoding, phases, parsers
+import pathutil
 import match as matchmod
-import os, errno, re, stat, glob
+import os, errno, re, glob
 
 if os.name == 'nt':
     import scmwindows as scmplatform
@@ -97,9 +98,10 @@
         self._newfiles = set()
 
     def __call__(self, f):
+        if f in self._newfiles:
+            return
         fl = encoding.lower(f)
-        if (fl in self._loweredfiles and f not in self._dirstate and
-            f not in self._newfiles):
+        if fl in self._loweredfiles and f not in self._dirstate:
             msg = _('possible case-folding collision for %s') % f
             if self._abort:
                 raise util.Abort(msg)
@@ -107,100 +109,6 @@
         self._loweredfiles.add(fl)
         self._newfiles.add(f)
 
-class pathauditor(object):
-    '''ensure that a filesystem path contains no banned components.
-    the following properties of a path are checked:
-
-    - ends with a directory separator
-    - under top-level .hg
-    - starts at the root of a windows drive
-    - contains ".."
-    - traverses a symlink (e.g. a/symlink_here/b)
-    - inside a nested repository (a callback can be used to approve
-      some nested repositories, e.g., subrepositories)
-    '''
-
-    def __init__(self, root, callback=None):
-        self.audited = set()
-        self.auditeddir = set()
-        self.root = root
-        self.callback = callback
-        if os.path.lexists(root) and not util.checkcase(root):
-            self.normcase = util.normcase
-        else:
-            self.normcase = lambda x: x
-
-    def __call__(self, path):
-        '''Check the relative path.
-        path may contain a pattern (e.g. foodir/**.txt)'''
-
-        path = util.localpath(path)
-        normpath = self.normcase(path)
-        if normpath in self.audited:
-            return
-        # AIX ignores "/" at end of path, others raise EISDIR.
-        if util.endswithsep(path):
-            raise util.Abort(_("path ends in directory separator: %s") % path)
-        parts = util.splitpath(path)
-        if (os.path.splitdrive(path)[0]
-            or parts[0].lower() in ('.hg', '.hg.', '')
-            or os.pardir in parts):
-            raise util.Abort(_("path contains illegal component: %s") % path)
-        if '.hg' in path.lower():
-            lparts = [p.lower() for p in parts]
-            for p in '.hg', '.hg.':
-                if p in lparts[1:]:
-                    pos = lparts.index(p)
-                    base = os.path.join(*parts[:pos])
-                    raise util.Abort(_("path '%s' is inside nested repo %r")
-                                     % (path, base))
-
-        normparts = util.splitpath(normpath)
-        assert len(parts) == len(normparts)
-
-        parts.pop()
-        normparts.pop()
-        prefixes = []
-        while parts:
-            prefix = os.sep.join(parts)
-            normprefix = os.sep.join(normparts)
-            if normprefix in self.auditeddir:
-                break
-            curpath = os.path.join(self.root, prefix)
-            try:
-                st = os.lstat(curpath)
-            except OSError, err:
-                # EINVAL can be raised as invalid path syntax under win32.
-                # They must be ignored for patterns can be checked too.
-                if err.errno not in (errno.ENOENT, errno.ENOTDIR, errno.EINVAL):
-                    raise
-            else:
-                if stat.S_ISLNK(st.st_mode):
-                    raise util.Abort(
-                        _('path %r traverses symbolic link %r')
-                        % (path, prefix))
-                elif (stat.S_ISDIR(st.st_mode) and
-                      os.path.isdir(os.path.join(curpath, '.hg'))):
-                    if not self.callback or not self.callback(curpath):
-                        raise util.Abort(_("path '%s' is inside nested "
-                                           "repo %r")
-                                         % (path, prefix))
-            prefixes.append(normprefix)
-            parts.pop()
-            normparts.pop()
-
-        self.audited.add(normpath)
-        # only add prefixes to the cache after checking everything: we don't
-        # want to add "foo/bar/baz" before checking if there's a "foo/.hg"
-        self.auditeddir.update(prefixes)
-
-    def check(self, path):
-        try:
-            self(path)
-            return True
-        except (OSError, util.Abort):
-            return False
-
 class abstractvfs(object):
     """Abstract base class; cannot be instantiated"""
 
@@ -242,6 +150,9 @@
         finally:
             fp.close()
 
+    def chmod(self, path, mode):
+        return os.chmod(self.join(path), mode)
+
     def exists(self, path=None):
         return os.path.exists(self.join(path))
 
@@ -251,6 +162,9 @@
     def isdir(self, path=None):
         return os.path.isdir(self.join(path))
 
+    def isfile(self, path=None):
+        return os.path.isfile(self.join(path))
+
     def islink(self, path=None):
         return os.path.islink(self.join(path))
 
@@ -263,12 +177,18 @@
     def makedirs(self, path=None, mode=None):
         return util.makedirs(self.join(path), mode)
 
+    def makelock(self, info, path):
+        return util.makelock(info, self.join(path))
+
     def mkdir(self, path=None):
         return os.mkdir(self.join(path))
 
     def readdir(self, path=None, stat=None, skip=None):
         return osutil.listdir(self.join(path), stat, skip)
 
+    def readlock(self, path):
+        return util.readlock(self.join(path))
+
     def rename(self, src, dst):
         return util.rename(self.join(src), self.join(dst))
 
@@ -309,7 +229,7 @@
     def _setmustaudit(self, onoff):
         self._audit = onoff
         if onoff:
-            self.audit = pathauditor(self.base)
+            self.audit = pathutil.pathauditor(self.base)
         else:
             self.audit = util.always
 
@@ -444,52 +364,6 @@
         return self.vfs(path, mode, *args, **kw)
 
 
-def canonpath(root, cwd, myname, auditor=None):
-    '''return the canonical path of myname, given cwd and root'''
-    if util.endswithsep(root):
-        rootsep = root
-    else:
-        rootsep = root + os.sep
-    name = myname
-    if not os.path.isabs(name):
-        name = os.path.join(root, cwd, name)
-    name = os.path.normpath(name)
-    if auditor is None:
-        auditor = pathauditor(root)
-    if name != rootsep and name.startswith(rootsep):
-        name = name[len(rootsep):]
-        auditor(name)
-        return util.pconvert(name)
-    elif name == root:
-        return ''
-    else:
-        # Determine whether `name' is in the hierarchy at or beneath `root',
-        # by iterating name=dirname(name) until that causes no change (can't
-        # check name == '/', because that doesn't work on windows). The list
-        # `rel' holds the reversed list of components making up the relative
-        # file name we want.
-        rel = []
-        while True:
-            try:
-                s = util.samefile(name, root)
-            except OSError:
-                s = False
-            if s:
-                if not rel:
-                    # name was actually the same as root (maybe a symlink)
-                    return ''
-                rel.reverse()
-                name = os.path.join(*rel)
-                auditor(name)
-                return util.pconvert(name)
-            dirname, basename = util.split(name)
-            rel.append(basename)
-            if dirname == name:
-                break
-            name = dirname
-
-        raise util.Abort(_("%s not under root '%s'") % (myname, root))
-
 def walkrepos(path, followsym=False, seen_dirs=None, recurse=False):
     '''yield every hg repository under path, always recursively.
     The recurse flag will only control recursion into repo working dirs'''
@@ -767,7 +641,7 @@
     This is different from dirstate.status because it doesn't care about
     whether files are modified or clean.'''
     added, unknown, deleted, removed = [], [], [], []
-    audit_path = pathauditor(repo.root)
+    audit_path = pathutil.pathauditor(repo.root)
 
     ctx = repo[None]
     dirstate = repo.dirstate
@@ -851,14 +725,14 @@
               "Mercurial)") % "', '".join(missings))
     return requirements
 
-class filecacheentry(object):
-    def __init__(self, path, stat=True):
+class filecachesubentry(object):
+    def __init__(self, path, stat):
         self.path = path
         self.cachestat = None
         self._cacheable = None
 
         if stat:
-            self.cachestat = filecacheentry.stat(self.path)
+            self.cachestat = filecachesubentry.stat(self.path)
 
             if self.cachestat:
                 self._cacheable = self.cachestat.cacheable()
@@ -868,7 +742,7 @@
 
     def refresh(self):
         if self.cacheable():
-            self.cachestat = filecacheentry.stat(self.path)
+            self.cachestat = filecachesubentry.stat(self.path)
 
     def cacheable(self):
         if self._cacheable is not None:
@@ -882,7 +756,7 @@
         if not self.cacheable():
             return True
 
-        newstat = filecacheentry.stat(self.path)
+        newstat = filecachesubentry.stat(self.path)
 
         # we may not know if it's cacheable yet, check again now
         if newstat and self._cacheable is None:
@@ -906,24 +780,44 @@
             if e.errno != errno.ENOENT:
                 raise
 
+class filecacheentry(object):
+    def __init__(self, paths, stat=True):
+        self._entries = []
+        for path in paths:
+            self._entries.append(filecachesubentry(path, stat))
+
+    def changed(self):
+        '''true if any entry has changed'''
+        for entry in self._entries:
+            if entry.changed():
+                return True
+        return False
+
+    def refresh(self):
+        for entry in self._entries:
+            entry.refresh()
+
 class filecache(object):
-    '''A property like decorator that tracks a file under .hg/ for updates.
+    '''A property like decorator that tracks files under .hg/ for updates.
 
     Records stat info when called in _filecache.
 
-    On subsequent calls, compares old stat info with new info, and recreates
-    the object when needed, updating the new stat info in _filecache.
+    On subsequent calls, compares old stat info with new info, and recreates the
+    object when any of the files changes, updating the new stat info in
+    _filecache.
 
     Mercurial either atomic renames or appends for files under .hg,
     so to ensure the cache is reliable we need the filesystem to be able
     to tell us if a file has been replaced. If it can't, we fallback to
     recreating the object on every call (essentially the same behaviour as
-    propertycache).'''
-    def __init__(self, path):
-        self.path = path
+    propertycache).
+
+    '''
+    def __init__(self, *paths):
+        self.paths = paths
 
     def join(self, obj, fname):
-        """Used to compute the runtime path of the cached file.
+        """Used to compute the runtime path of a cached file.
 
         Users should subclass filecache and provide their own version of this
         function to call the appropriate join function on 'obj' (an instance
@@ -948,11 +842,11 @@
             if entry.changed():
                 entry.obj = self.func(obj)
         else:
-            path = self.join(obj, self.path)
+            paths = [self.join(obj, path) for path in self.paths]
 
             # We stat -before- creating the object so our cache doesn't lie if
             # a writer modified between the time we read and stat
-            entry = filecacheentry(path)
+            entry = filecacheentry(paths, True)
             entry.obj = self.func(obj)
 
             obj._filecache[self.name] = entry
@@ -964,7 +858,8 @@
         if self.name not in obj._filecache:
             # we add an entry for the missing value because X in __dict__
             # implies X in _filecache
-            ce = filecacheentry(self.join(obj, self.path), False)
+            paths = [self.join(obj, path) for path in self.paths]
+            ce = filecacheentry(paths, False)
             obj._filecache[self.name] = ce
         else:
             ce = obj._filecache[self.name]
--- a/mercurial/setdiscovery.py	Mon Jan 20 11:16:26 2014 -0200
+++ b/mercurial/setdiscovery.py	Tue Jan 21 14:44:01 2014 -0600
@@ -8,7 +8,8 @@
 
 from node import nullid
 from i18n import _
-import random, util, dagutil
+import random
+import util, dagutil
 
 def _updatesample(dag, nodes, sample, always, quicksamplesize=0):
     # if nodes is empty we scan the entire graph
--- a/mercurial/statichttprepo.py	Mon Jan 20 11:16:26 2014 -0200
+++ b/mercurial/statichttprepo.py	Tue Jan 21 14:44:01 2014 -0600
@@ -54,8 +54,10 @@
             data = data[:bytes]
         self.pos += len(data)
         return data
+    def readlines(self):
+        return self.read().splitlines(True)
     def __iter__(self):
-        return iter(self.read().splitlines(1))
+        return iter(self.readlines())
     def close(self):
         pass
 
--- a/mercurial/subrepo.py	Mon Jan 20 11:16:26 2014 -0200
+++ b/mercurial/subrepo.py	Tue Jan 21 14:44:01 2014 -0600
@@ -9,7 +9,9 @@
 import xml.dom.minidom
 import stat, subprocess, tarfile
 from i18n import _
-import config, scmutil, util, node, error, cmdutil, bookmarks, match as matchmod
+import config, util, node, error, cmdutil, bookmarks, match as matchmod
+import phases
+import pathutil
 hg = None
 propertycache = util.propertycache
 
@@ -344,12 +346,43 @@
     import hg as h
     hg = h
 
-    scmutil.pathauditor(ctx._repo.root)(path)
+    pathutil.pathauditor(ctx._repo.root)(path)
     state = ctx.substate[path]
     if state[2] not in types:
         raise util.Abort(_('unknown subrepo type %s') % state[2])
     return types[state[2]](ctx, path, state[:2])
 
+def newcommitphase(ui, ctx):
+    commitphase = phases.newcommitphase(ui)
+    substate = getattr(ctx, "substate", None)
+    if not substate:
+        return commitphase
+    check = ui.config('phases', 'checksubrepos', 'follow')
+    if check not in ('ignore', 'follow', 'abort'):
+        raise util.Abort(_('invalid phases.checksubrepos configuration: %s')
+                         % (check))
+    if check == 'ignore':
+        return commitphase
+    maxphase = phases.public
+    maxsub = None
+    for s in sorted(substate):
+        sub = ctx.sub(s)
+        subphase = sub.phase(substate[s][1])
+        if maxphase < subphase:
+            maxphase = subphase
+            maxsub = s
+    if commitphase < maxphase:
+        if check == 'abort':
+            raise util.Abort(_("can't commit in %s phase"
+                               " conflicting %s from subrepository %s") %
+                             (phases.phasenames[commitphase],
+                              phases.phasenames[maxphase], maxsub))
+        ui.warn(_("warning: changes are committed in"
+                  " %s phase from subrepository %s\n") %
+                (phases.phasenames[maxphase], maxsub))
+        return maxphase
+    return commitphase
+
 # subrepo classes need to implement the following abstract class:
 
 class abstractsubrepo(object):
@@ -384,6 +417,11 @@
         """
         raise NotImplementedError
 
+    def phase(self, state):
+        """returns phase of specified state in the subrepository.
+        """
+        return phases.public
+
     def remove(self):
         """remove the subrepo
 
@@ -651,6 +689,10 @@
         return node.hex(n)
 
     @annotatesubrepoerror
+    def phase(self, state):
+        return self._repo[state].phase()
+
+    @annotatesubrepoerror
     def remove(self):
         # we can't fully delete the repository as it may contain
         # local-only history
--- a/mercurial/templatekw.py	Mon Jan 20 11:16:26 2014 -0200
+++ b/mercurial/templatekw.py	Tue Jan 21 14:44:01 2014 -0600
@@ -117,7 +117,8 @@
         if rev in latesttags:
             continue
         ctx = repo[rev]
-        tags = [t for t in ctx.tags() if repo.tagtype(t) == 'global']
+        tags = [t for t in ctx.tags()
+                if (repo.tagtype(t) and repo.tagtype(t) != 'local')]
         if tags:
             latesttags[rev] = ctx.date()[0], 0, ':'.join(sorted(tags))
             continue
@@ -220,11 +221,12 @@
     return '%s: +%s/-%s' % (len(stats), adds, removes)
 
 def showextras(**args):
-    templ = args['templ']
-    for key, value in sorted(args['ctx'].extra().items()):
-        args = args.copy()
-        args.update(dict(key=key, value=value))
-        yield templ('extra', **args)
+    """:extras: List of dicts with key, value entries of the 'extras'
+    field of this changeset."""
+    extras = args['ctx'].extra()
+    c = [{'key': x[0], 'value': x[1]} for x in sorted(extras.items())]
+    f = _showlist('extra', c, plural='extras', **args)
+    return _hybrid(f, c, lambda x: '%s=%s' % (x['key'], x['value']))
 
 def showfileadds(**args):
     """:file_adds: List of strings. Files added by this changeset."""
@@ -392,6 +394,7 @@
     'parents': _showparents,
 }
 dockeywords.update(keywords)
+del dockeywords['branches']
 
 # tell hggettext to extract docstrings from these functions:
 i18nfunctions = dockeywords.values()
--- a/mercurial/templates/gitweb/graph.tmpl	Mon Jan 20 11:16:26 2014 -0200
+++ b/mercurial/templates/gitweb/graph.tmpl	Tue Jan 21 14:44:01 2014 -0600
@@ -108,4 +108,15 @@
 | {changenav%navgraph}
 </div>
 
+<script type="text/javascript">
+    ajaxScrollInit(
+            '{url|urlescape}graph/{rev}?revcount=%next%&style={style}',
+            {revcount}+60,
+            function (htmlText, previousVal) \{ return previousVal + 60; },
+            '#wrapper',
+            '<div class="%class%" style="text-align: center;">%text%</div>',
+            'graph'
+    );
+</script>
+
 {footer}
--- a/mercurial/templates/gitweb/shortlog.tmpl	Mon Jan 20 11:16:26 2014 -0200
+++ b/mercurial/templates/gitweb/shortlog.tmpl	Tue Jan 21 14:44:01 2014 -0600
@@ -32,7 +32,7 @@
 </div>
 
 <div class="title">&nbsp;</div>
-<table cellspacing="0">
+<table class="shortlogtable" cellspacing="0">
 {entries%shortlogentry}
 </table>
 
@@ -40,4 +40,19 @@
 {changenav%navshort}
 </div>
 
+<script type="text/javascript">
+    ajaxScrollInit(
+            '{url|urlescape}shortlog/%next%{sessionvars%urlparameter}',
+            '{nextentry%"{node}"}', <!-- NEXTHASH
+            function (htmlText, previousVal) \{
+                var m = htmlText.match(/'(\w+)', <!-- NEXTHASH/);
+                return m ? m[1] : null;
+            },
+            '.shortlogtable > tbody:nth-of-type(1)',
+            '<tr class="%class%">\
+            <td colspan="4" style="text-align: center;">%text%</td>\
+            </tr>'
+    );
+</script>
+
 {footer}
--- a/mercurial/templates/monoblue/graph.tmpl	Mon Jan 20 11:16:26 2014 -0200
+++ b/mercurial/templates/monoblue/graph.tmpl	Tue Jan 21 14:44:01 2014 -0600
@@ -104,4 +104,15 @@
         | {changenav%navgraph}
     </div>
 
+    <script type="text/javascript">
+    ajaxScrollInit(
+            '{url|urlescape}graph/{rev}?revcount=%next%&style={style}',
+            {revcount}+60,
+            function (htmlText, previousVal) \{ return previousVal + 60; },
+            '#wrapper',
+            '<div class="%class%" style="text-align: center;">%text%</div>',
+            'graph'
+    );
+    </script>
+
 {footer}
--- a/mercurial/templates/monoblue/shortlog.tmpl	Mon Jan 20 11:16:26 2014 -0200
+++ b/mercurial/templates/monoblue/shortlog.tmpl	Tue Jan 21 14:44:01 2014 -0600
@@ -33,7 +33,7 @@
 
     <h2 class="no-link no-border">shortlog</h2>
 
-    <table>
+    <table class="shortlogtable">
 {entries%shortlogentry}
     </table>
 
@@ -41,4 +41,19 @@
     {changenav%navshort}
     </div>
 
+    <script type="text/javascript">
+    ajaxScrollInit(
+            '{url|urlescape}shortlog/%next%{sessionvars%urlparameter}',
+            '{nextentry%"{node}"}', <!-- NEXTHASH
+            function (htmlText, previousVal) \{
+                var m = htmlText.match(/'(\w+)', <!-- NEXTHASH/);
+                return m ? m[1] : null;
+            },
+            '.shortlogtable > tbody:nth-of-type(1)',
+            '<tr class="%class%">\
+            <td colspan="4" style="text-align: center;">%text%</td>\
+            </tr>'
+    );
+    </script>
+
 {footer}
--- a/mercurial/templates/paper/graph.tmpl	Mon Jan 20 11:16:26 2014 -0200
+++ b/mercurial/templates/paper/graph.tmpl	Tue Jan 21 14:44:01 2014 -0600
@@ -124,7 +124,7 @@
 
 <script type="text/javascript">
     ajaxScrollInit(
-            '{url|urlescape}graph/{rev}?revcount=%next%',
+            '{url|urlescape}graph/{rev}?revcount=%next%&style={style}',
             {revcount}+60,
             function (htmlText, previousVal) \{ return previousVal + 60; },
             '#wrapper',
--- a/mercurial/templates/paper/shortlog.tmpl	Mon Jan 20 11:16:26 2014 -0200
+++ b/mercurial/templates/paper/shortlog.tmpl	Tue Jan 21 14:44:01 2014 -0600
@@ -73,7 +73,7 @@
 
 <script type="text/javascript">
     ajaxScrollInit(
-            '{url|urlescape}shortlog/%next%',
+            '{url|urlescape}shortlog/%next%{sessionvars%urlparameter}',
             '{nextentry%"{node}"}', <!-- NEXTHASH
             function (htmlText, previousVal) \{
                 var m = htmlText.match(/'(\w+)', <!-- NEXTHASH/);
--- a/mercurial/templates/spartan/header.tmpl	Mon Jan 20 11:16:26 2014 -0200
+++ b/mercurial/templates/spartan/header.tmpl	Tue Jan 21 14:44:01 2014 -0600
@@ -1,4 +1,4 @@
-<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
 <html>
 <head>
 <link rel="icon" href="{staticurl|urlescape}hgicon.png" type="image/png">
--- a/mercurial/templates/static/mercurial.js	Mon Jan 20 11:16:26 2014 -0200
+++ b/mercurial/templates/static/mercurial.js	Tue Jan 21 14:44:01 2014 -0600
@@ -394,7 +394,7 @@
                 },
                 function onsuccess(htmlText) {
                     if (mode == 'graph') {
-                        var addHeight = htmlText.match(/^<canvas id="graph".*height="(\d+)"><\/canvas>$/m)[1];
+                        var addHeight = htmlText.match(/^\s*<canvas id="graph".*height="(\d+)"><\/canvas>$/m)[1];
                         addHeight = parseInt(addHeight);
                         graph.canvas.height = addHeight;
 
--- a/mercurial/templates/static/style-coal.css	Mon Jan 20 11:16:26 2014 -0200
+++ b/mercurial/templates/static/style-coal.css	Tue Jan 21 14:44:01 2014 -0600
@@ -331,3 +331,27 @@
 .breadcrumb a {
     color: blue;
 }
+
+.scroll-loading {
+    -webkit-animation: change_color 1s linear 0s infinite alternate;
+    -moz-animation: change_color 1s linear 0s infinite alternate;
+    -o-animation: change_color 1s linear 0s infinite alternate;
+    animation: change_color 1s linear 0s infinite alternate;
+}
+
+@-webkit-keyframes change_color {
+  from { background-color: #A0CEFF; } to {  }
+}
+@-moz-keyframes change_color {
+  from { background-color: #A0CEFF; } to {  }
+}
+@-o-keyframes change_color {
+  from { background-color: #A0CEFF; } to {  }
+}
+@keyframes change_color {
+  from { background-color: #A0CEFF; } to {  }
+}
+
+.scroll-loading-error {
+    background-color: #FFCCCC !important;
+}
--- a/mercurial/templates/static/style-gitweb.css	Mon Jan 20 11:16:26 2014 -0200
+++ b/mercurial/templates/static/style-gitweb.css	Tue Jan 21 14:44:01 2014 -0600
@@ -167,3 +167,27 @@
 .block {
     border-top: 1px solid #d9d8d1;
 }
+
+.scroll-loading {
+  -webkit-animation: change_color 1s linear 0s infinite alternate;
+  -moz-animation: change_color 1s linear 0s infinite alternate;
+  -o-animation: change_color 1s linear 0s infinite alternate;
+  animation: change_color 1s linear 0s infinite alternate;
+}
+
+@-webkit-keyframes change_color {
+  from { background-color: #A0CEFF; } to {  }
+}
+@-moz-keyframes change_color {
+  from { background-color: #A0CEFF; } to {  }
+}
+@-o-keyframes change_color {
+  from { background-color: #A0CEFF; } to {  }
+}
+@keyframes change_color {
+  from { background-color: #A0CEFF; } to {  }
+}
+
+.scroll-loading-error {
+    background-color: #FFCCCC !important;
+}
--- a/mercurial/templates/static/style-monoblue.css	Mon Jan 20 11:16:26 2014 -0200
+++ b/mercurial/templates/static/style-monoblue.css	Tue Jan 21 14:44:01 2014 -0600
@@ -528,3 +528,27 @@
 .breadcrumb a:hover {
     text-decoration:underline;
 }
+
+.scroll-loading {
+  -webkit-animation: change_color 1s linear 0s infinite alternate;
+  -moz-animation: change_color 1s linear 0s infinite alternate;
+  -o-animation: change_color 1s linear 0s infinite alternate;
+  animation: change_color 1s linear 0s infinite alternate;
+}
+
+@-webkit-keyframes change_color {
+  from { background-color: #A0CEFF; } to {  }
+}
+@-moz-keyframes change_color {
+  from { background-color: #A0CEFF; } to {  }
+}
+@-o-keyframes change_color {
+  from { background-color: #A0CEFF; } to {  }
+}
+@keyframes change_color {
+  from { background-color: #A0CEFF; } to {  }
+}
+
+.scroll-loading-error {
+    background-color: #FFCCCC !important;
+}
--- a/mercurial/transaction.py	Mon Jan 20 11:16:26 2014 -0200
+++ b/mercurial/transaction.py	Tue Jan 21 14:44:01 2014 -0600
@@ -12,8 +12,8 @@
 # GNU General Public License version 2 or any later version.
 
 from i18n import _
-import os, errno
-import error, util
+import errno
+import error
 
 def active(func):
     def _active(self, *args, **kwds):
@@ -35,14 +35,11 @@
                 raise
         else:
             try:
-                fp = opener(f)
-                fn = fp.name
-                fp.close()
-                util.unlink(fn)
+                opener.unlink(f)
             except (IOError, OSError), inst:
                 if inst.errno != errno.ENOENT:
                     raise
-    util.unlink(journal)
+    opener.unlink(journal)
 
 class transaction(object):
     def __init__(self, report, opener, journal, after=None, createmode=None):
@@ -56,9 +53,9 @@
         self.journal = journal
         self._queue = []
 
-        self.file = util.posixfile(self.journal, "w")
+        self.file = opener.open(self.journal, "w")
         if createmode is not None:
-            os.chmod(self.journal, createmode & 0666)
+            opener.chmod(self.journal, createmode & 0666)
 
     def __del__(self):
         if self.journal:
@@ -136,8 +133,8 @@
         self.entries = []
         if self.after:
             self.after()
-        if os.path.isfile(self.journal):
-            util.unlink(self.journal)
+        if self.opener.isfile(self.journal):
+            self.opener.unlink(self.journal)
         self.journal = None
 
     @active
@@ -155,7 +152,7 @@
         try:
             if not self.entries:
                 if self.journal:
-                    util.unlink(self.journal)
+                    self.opener.unlink(self.journal)
                 return
 
             self.report(_("transaction abort!\n"))
@@ -173,7 +170,7 @@
 def rollback(opener, file, report):
     entries = []
 
-    fp = util.posixfile(file)
+    fp = opener.open(file)
     lines = fp.readlines()
     fp.close()
     for l in lines:
--- a/mercurial/treediscovery.py	Mon Jan 20 11:16:26 2014 -0200
+++ b/mercurial/treediscovery.py	Tue Jan 21 14:44:01 2014 -0600
@@ -19,7 +19,7 @@
     "heads" is either the supplied heads, or else the remote's heads.
     """
 
-    m = repo.changelog.nodemap
+    knownnode = repo.changelog.hasnode
     search = []
     fetch = set()
     seen = set()
@@ -41,7 +41,7 @@
 
     unknown = []
     for h in heads:
-        if h not in m:
+        if not knownnode(h):
             unknown.append(h)
         else:
             base.add(h)
@@ -71,23 +71,23 @@
             elif n in seenbranch:
                 repo.ui.debug("branch already found\n")
                 continue
-            elif n[1] and n[1] in m: # do we know the base?
+            elif n[1] and knownnode(n[1]): # do we know the base?
                 repo.ui.debug("found incomplete branch %s:%s\n"
                               % (short(n[0]), short(n[1])))
                 search.append(n[0:2]) # schedule branch range for scanning
                 seenbranch.add(n)
             else:
                 if n[1] not in seen and n[1] not in fetch:
-                    if n[2] in m and n[3] in m:
+                    if knownnode(n[2]) and knownnode(n[3]):
                         repo.ui.debug("found new changeset %s\n" %
                                       short(n[1]))
                         fetch.add(n[1]) # earliest unknown
                     for p in n[2:4]:
-                        if p in m:
+                        if knownnode(p):
                             base.add(p) # latest known
 
                 for p in n[2:4]:
-                    if p not in req and p not in m:
+                    if p not in req and not knownnode(p):
                         r.append(p)
                         req.add(p)
             seen.add(n[0])
@@ -114,7 +114,7 @@
             f = 1
             for i in l:
                 repo.ui.debug("narrowing %d:%d %s\n" % (f, len(l), short(i)))
-                if i in m:
+                if knownnode(i):
                     if f <= 2:
                         repo.ui.debug("found new branch changeset %s\n" %
                                           short(p))
@@ -130,7 +130,7 @@
 
     # sanity check our fetch list
     for f in fetch:
-        if f in m:
+        if knownnode(f):
             raise error.RepoError(_("already have changeset ")
                                   + short(f[:4]))
 
--- a/mercurial/ui.py	Mon Jan 20 11:16:26 2014 -0200
+++ b/mercurial/ui.py	Tue Jan 21 14:44:01 2014 -0600
@@ -640,6 +640,20 @@
         except EOFError:
             raise util.Abort(_('response expected'))
 
+    @staticmethod
+    def extractchoices(prompt):
+        """Extract prompt message and list of choices from specified prompt.
+
+        This returns tuple "(message, choices)", and "choices" is the
+        list of tuple "(response character, text without &)".
+        """
+        parts = prompt.split('$$')
+        msg = parts[0].rstrip(' ')
+        choices = [p.strip(' ') for p in parts[1:]]
+        return (msg,
+                [(s[s.index('&') + 1].lower(), s.replace('&', '', 1))
+                 for s in choices])
+
     def promptchoice(self, prompt, default=0):
         """Prompt user with a message, read response, and ensure it matches
         one of the provided choices. The prompt is formatted as follows:
@@ -651,10 +665,8 @@
         returned.
         """
 
-        parts = prompt.split('$$')
-        msg = parts[0].rstrip(' ')
-        choices = [p.strip(' ') for p in parts[1:]]
-        resps = [s[s.index('&') + 1].lower() for s in choices]
+        msg, choices = self.extractchoices(prompt)
+        resps = [r for r, t in choices]
         while True:
             r = self.prompt(msg, resps[default])
             if r.lower() in resps:
--- a/mercurial/url.py	Mon Jan 20 11:16:26 2014 -0200
+++ b/mercurial/url.py	Tue Jan 21 14:44:01 2014 -0600
@@ -32,10 +32,14 @@
                 user, passwd = auth.get('username'), auth.get('password')
                 self.ui.debug("using auth.%s.* for authentication\n" % group)
         if not user or not passwd:
+            u = util.url(authuri)
+            u.query = None
             if not self.ui.interactive():
-                raise util.Abort(_('http authorization required'))
+                raise util.Abort(_('http authorization required for %s') %
+                                 util.hidepassword(str(u)))
 
-            self.ui.write(_("http authorization required\n"))
+            self.ui.write(_("http authorization required for %s\n") %
+                          util.hidepassword(str(u)))
             self.ui.write(_("realm: %s\n") % realm)
             if user:
                 self.ui.write(_("user: %s\n") % user)
--- a/mercurial/util.py	Mon Jan 20 11:16:26 2014 -0200
+++ b/mercurial/util.py	Tue Jan 21 14:44:01 2014 -0600
@@ -14,9 +14,9 @@
 """
 
 from i18n import _
-import error, osutil, encoding, collections
+import error, osutil, encoding
 import errno, re, shutil, sys, tempfile, traceback
-import os, time, datetime, calendar, textwrap, signal
+import os, time, datetime, calendar, textwrap, signal, collections
 import imp, socket, urllib
 
 if os.name == 'nt':
@@ -52,7 +52,6 @@
 popen = platform.popen
 posixfile = platform.posixfile
 quotecommand = platform.quotecommand
-realpath = platform.realpath
 rename = platform.rename
 samedevice = platform.samedevice
 samefile = platform.samefile
@@ -1033,9 +1032,10 @@
     if t < 0:
         t = 0   # time.gmtime(lt) fails on Windows for lt < -43200
         tz = 0
-    if "%1" in format or "%2" in format:
+    if "%1" in format or "%2" in format or "%z" in format:
         sign = (tz > 0) and "-" or "+"
         minutes = abs(tz) // 60
+        format = format.replace("%z", "%1%2")
         format = format.replace("%1", "%c%02d" % (sign, minutes // 60))
         format = format.replace("%2", "%02d" % (minutes % 60))
     try:
@@ -1983,3 +1983,20 @@
         self._hooks.sort(key=lambda x: x[0])
         for source, hook in self._hooks:
             hook(*args)
+
+def debugstacktrace(msg='stacktrace', skip=0, f=sys.stderr):
+    '''Writes a message to f (stderr) with a nicely formatted stacktrace.
+    Skips the 'skip' last entries.
+    It can be used everywhere and do intentionally not require an ui object.
+    Not be used in production code but very convenient while developing.
+    '''
+    f.write('%s at:\n' % msg)
+    entries = [('%s:%s' % (fn, ln), func)
+        for fn, ln, func, _text in traceback.extract_stack()[:-skip - 1]]
+    if entries:
+        fnmax = max(len(entry[0]) for entry in entries)
+        for fnln, func in entries:
+            f.write(' %-*s in %s\n' % (fnmax, fnln, func))
+
+# convenient shortcut
+dst = debugstacktrace
--- a/mercurial/windows.py	Mon Jan 20 11:16:26 2014 -0200
+++ b/mercurial/windows.py	Tue Jan 21 14:44:01 2014 -0600
@@ -133,15 +133,6 @@
 def normcase(path):
     return encoding.upper(path)
 
-def realpath(path):
-    '''
-    Returns the true, canonical file system path equivalent to the given
-    path.
-    '''
-    # TODO: There may be a more clever way to do this that also handles other,
-    # less common file systems.
-    return os.path.normpath(normcase(os.path.realpath(path)))
-
 def samestat(s1, s2):
     return False
 
--- a/mercurial/worker.py	Mon Jan 20 11:16:26 2014 -0200
+++ b/mercurial/worker.py	Tue Jan 21 14:44:01 2014 -0600
@@ -6,7 +6,8 @@
 # GNU General Public License version 2 or any later version.
 
 from i18n import _
-import errno, os, signal, sys, threading, util
+import errno, os, signal, sys, threading
+import util
 
 def countcpus():
     '''try to count the number of CPUs on the system'''
--- a/tests/bzr-definitions	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/bzr-definitions	Tue Jan 21 14:44:01 2014 -0600
@@ -5,11 +5,10 @@
 TERM=dumb; export TERM
 echo '[extensions]' >> $HGRCPATH
 echo 'convert = ' >> $HGRCPATH
-echo 'hgext.graphlog = ' >> $HGRCPATH
 
 glog()
 {
-    hg glog --template '{rev}@{branch} "{desc|firstline}" files: {files}\n' "$@"
+    hg log -G --template '{rev}@{branch} "{desc|firstline}" files: {files}\n' "$@"
 }
 
 manifest()
Binary file tests/gpg/random_seed has changed
--- a/tests/hghave.py	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/hghave.py	Tue Jan 21 14:44:01 2014 -0600
@@ -233,6 +233,9 @@
     finally:
         os.rmdir(d)
 
+def has_root():
+    return getattr(os, 'geteuid', None) and os.geteuid() == 0
+
 def has_pyflakes():
     return matchoutput("sh -c \"echo 'import re' 2>&1 | pyflakes\"",
                        r"<stdin>:1: 're' imported but unused",
@@ -269,7 +272,12 @@
     return os.name != 'nt' # gross approximation
 
 def has_tic():
-    return matchoutput('test -x "`which tic`"', '')
+    try:
+        import curses
+        curses.COLOR_BLUE
+        return matchoutput('test -x "`which tic`"', '')
+    except ImportError:
+        return False
 
 def has_msys():
     return os.getenv('MSYSTEM')
@@ -312,6 +320,7 @@
     "p4": (has_p4, "Perforce server and client"),
     "pyflakes": (has_pyflakes, "Pyflakes python linter"),
     "pygments": (has_pygments, "Pygments source highlighting library"),
+    "root": (has_root, "root permissions"),
     "serve": (has_serve, "platform and python can manage 'hg serve -d'"),
     "ssl": (has_ssl, "python >= 2.6 ssl module and python OpenSSL"),
     "svn": (has_svn, "subversion client and admin tools"),
@@ -320,7 +329,7 @@
     "svn-bindings": (has_svn_bindings, "subversion python bindings"),
     "symlink": (has_symlink, "symbolic links"),
     "system-sh": (has_system_sh, "system() uses sh"),
-    "tic": (has_tic, "terminfo compiler"),
+    "tic": (has_tic, "terminfo compiler and curses module"),
     "tla": (has_tla, "GNU Arch tla client"),
     "unix-permissions": (has_unix_permissions, "unix-style permissions"),
     "windows": (has_windows, "Windows"),
--- a/tests/run-tests.py	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/run-tests.py	Tue Jan 21 14:44:01 2014 -0600
@@ -63,7 +63,7 @@
 # subprocess._cleanup can race with any Popen.wait or Popen.poll on py24
 # http://bugs.python.org/issue1731717 for details. We shouldn't be producing
 # zombies but it's pretty harmless even if we do.
-if sys.version_info[1] < 5:
+if sys.version_info < (2, 5):
     subprocess._cleanup = lambda: None
 
 closefds = os.name == 'posix'
@@ -103,6 +103,7 @@
 
 requiredtools = [os.path.basename(sys.executable), "diff", "grep", "unzip",
                  "gunzip", "bunzip2", "sed"]
+createdfiles = []
 
 defaults = {
     'jobs': ('HGTEST_JOBS', 1),
@@ -420,6 +421,11 @@
     if not options.keep_tmpdir:
         vlog("# Cleaning up HGTMP", HGTMP)
         shutil.rmtree(HGTMP, True)
+        for f in createdfiles:
+            try:
+                os.remove(f)
+            except OSError:
+                pass
 
 def usecorrectpython():
     # some tests run python interpreter. they must use same
@@ -439,6 +445,7 @@
         if findprogram(pyexename) != sys.executable:
             try:
                 os.symlink(sys.executable, mypython)
+                createdfiles.append(mypython)
             except OSError, err:
                 # child processes may race, which is harmless
                 if err.errno != errno.EEXIST:
@@ -498,18 +505,6 @@
 
     usecorrectpython()
 
-    vlog("# Installing dummy diffstat")
-    f = open(os.path.join(BINDIR, 'diffstat'), 'w')
-    f.write('#!' + sys.executable + '\n'
-            'import sys\n'
-            'files = 0\n'
-            'for line in sys.stdin:\n'
-            '    if line.startswith("diff "):\n'
-            '        files += 1\n'
-            'sys.stdout.write("files patched: %d\\n" % files)\n')
-    f.close()
-    os.chmod(os.path.join(BINDIR, 'diffstat'), 0700)
-
     if options.py3k_warnings and not options.anycoverage:
         vlog("# Updating hg command to enable Py3k Warnings switch")
         f = open(os.path.join(BINDIR, 'hg'), 'r')
@@ -611,7 +606,7 @@
     if el + '\n' == l:
         if os.altsep:
             # matching on "/" is not needed for this line
-            log("\nInfo, unnecessary glob: %s (glob)" % el)
+            return '-glob'
         return True
     i, n = 0, len(el)
     res = ''
@@ -639,9 +634,12 @@
             el = el[:-7].decode('string-escape') + '\n'
         if el == l or os.name == 'nt' and el[:-1] + '\r\n' == l:
             return True
-        if (el.endswith(" (re)\n") and rematch(el[:-6], l) or
-            el.endswith(" (glob)\n") and globmatch(el[:-8], l)):
-            return True
+        if el.endswith(" (re)\n"):
+            return rematch(el[:-6], l)
+        if el.endswith(" (glob)\n"):
+            return globmatch(el[:-8], l)
+        if os.altsep and l.replace('\\', '/') == el:
+            return '+glob'
     return False
 
 def tsttest(test, wd, options, replacements, env):
@@ -795,7 +793,19 @@
             if pos in expected and expected[pos]:
                 el = expected[pos].pop(0)
 
-            if linematch(el, lout):
+            r = linematch(el, lout)
+            if isinstance(r, str):
+                if r == '+glob':
+                    lout = el[:-1] + ' (glob)\n'
+                    r = False
+                elif r == '-glob':
+                    log('\ninfo, unnecessary glob in %s (after line %d):'
+                        ' %s (glob)\n' % (test, pos, el[-1]))
+                    r = True # pass on unnecessary glob
+                else:
+                    log('\ninfo, unknown linematch result: %r\n' % r)
+                    r = False
+            if r:
                 postout.append("  " + el)
             else:
                 if needescape(lout):
@@ -1082,6 +1092,9 @@
             done.put(runone(options, test, count))
         except KeyboardInterrupt:
             pass
+        except: # re-raises
+            done.put(('!', test, 'run-test raised an error, see traceback'))
+            raise
 
     try:
         while tests or running:
@@ -1098,7 +1111,7 @@
                 test = tests.pop(0)
                 if options.loop:
                     tests.append(test)
-                t = threading.Thread(target=job, args=(test, count))
+                t = threading.Thread(target=job, name=test, args=(test, count))
                 t.start()
                 running += 1
                 count += 1
@@ -1139,6 +1152,8 @@
         _checkhglib("Tested")
         print "# Ran %d tests, %d skipped, %d failed." % (
             tested, skipped + ignored, failed)
+        if results['!']:
+            print 'python hash seed:', os.environ['PYTHONHASHSEED']
         if options.time:
             outputtimes(options)
 
@@ -1190,7 +1205,6 @@
         # use a random python hash seed all the time
         # we do the randomness ourself to know what seed is used
         os.environ['PYTHONHASHSEED'] = str(random.getrandbits(32))
-        print 'python hash seed:', os.environ['PYTHONHASHSEED']
 
     global TESTDIR, HGTMP, INST, BINDIR, PYTHONDIR, COVERAGE_FILE
     TESTDIR = os.environ["TESTDIR"] = os.getcwd()
--- a/tests/test-alias.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-alias.t	Tue Jan 21 14:44:01 2014 -0600
@@ -1,8 +1,5 @@
   $ HGFOO=BAR; export HGFOO
   $ cat >> $HGRCPATH <<EOF
-  > [extensions]
-  > graphlog=
-  > 
   > [alias]
   > # should clobber ci but not commit (issue2993)
   > ci = version
@@ -34,7 +31,7 @@
   > count = !hg log -r "\$@" --template=. | wc -c | sed -e 's/ //g'
   > mcount = !hg log \$@ --template=. | wc -c | sed -e 's/ //g'
   > rt = root
-  > tglog = glog --template "{rev}:{node|short}: '{desc}' {branches}\n"
+  > tglog = log -G --template "{rev}:{node|short}: '{desc}' {branches}\n"
   > idalias = id
   > idaliaslong = id
   > idaliasshell = !echo test
--- a/tests/test-backout.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-backout.t	Tue Jan 21 14:44:01 2014 -0600
@@ -23,6 +23,12 @@
   changeset 2:2929462c3dff backs out changeset 1:a820f4f40a57
   $ cat a
   a
+  $ hg summary
+  parent: 2:2929462c3dff tip
+   Backed out changeset a820f4f40a57
+  branch: default
+  commit: (clean)
+  update: (current)
 
 file that was removed is recreated
 
@@ -42,6 +48,12 @@
   changeset 2:de31bdc76c0d backs out changeset 1:76862dcce372
   $ cat a
   content
+  $ hg summary
+  parent: 2:de31bdc76c0d tip
+   Backed out changeset 76862dcce372
+  branch: default
+  commit: (clean)
+  update: (current)
 
 backout of backout is as if nothing happened
 
@@ -50,6 +62,12 @@
   changeset 3:7f6d0f120113 backs out changeset 2:de31bdc76c0d
   $ test -f a
   [1]
+  $ hg summary
+  parent: 3:7f6d0f120113 tip
+   Backed out changeset de31bdc76c0d
+  branch: default
+  commit: (clean)
+  update: (current)
 
 across branch
 
@@ -64,6 +82,12 @@
   adding b
   $ hg co -C 0
   0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  $ hg summary
+  parent: 0:f7b1eb17ad24 
+   0
+  branch: default
+  commit: (clean)
+  update: 1 new changesets (update)
 
 should fail
 
@@ -74,12 +98,24 @@
   $ hg ci -Am2
   adding c
   created new head
+  $ hg summary
+  parent: 2:db815d6d32e6 tip
+   2
+  branch: default
+  commit: (clean)
+  update: 1 new changesets, 2 branch heads (merge)
 
 should fail
 
   $ hg backout 1
   abort: cannot backout change on a different branch
   [255]
+  $ hg summary
+  parent: 2:db815d6d32e6 tip
+   2
+  branch: default
+  commit: (clean)
+  update: 1 new changesets, 2 branch heads (merge)
 
 backout with merge
 
@@ -91,6 +127,12 @@
   $ echo line 2 >> a
   $ hg commit -d '0 0' -A -m a
   adding a
+  $ hg summary
+  parent: 0:59395513a13a tip
+   a
+  branch: default
+  commit: (clean)
+  update: (current)
 
 remove line 1
 
@@ -109,6 +151,12 @@
   0 files updated, 1 files merged, 0 files removed, 0 files unresolved
   (branch merge, don't forget to commit)
   $ hg commit -d '4 0' -m d
+  $ hg summary
+  parent: 4:c7df5e0b9c09 tip
+   d
+  branch: default
+  commit: (clean)
+  update: (current)
 
 check line 1 is back
 
@@ -131,17 +179,29 @@
   $ echo 1 > b
   $ hg commit -d '2 0' -A -m c
   adding b
+  $ hg summary
+  parent: 2:882396649954 tip
+   c
+  branch: default
+  commit: (clean)
+  update: (current)
 
 without --merge
   $ hg backout -d '3 0' 1 --tool=true
-  reverting a
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  changeset 22bca4c721e5 backed out, don't forget to commit.
   $ hg locate b
   b
   $ hg update -C tip
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ hg locate b
   b
+  $ hg summary
+  parent: 2:882396649954 tip
+   c
+  branch: default
+  commit: (clean)
+  update: (current)
 
 with --merge
   $ hg backout --merge -d '3 0' 1 --tool=true
@@ -180,6 +240,12 @@
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   (branch merge, don't forget to commit)
   $ hg commit -d '4 0' -A -m d
+  $ hg summary
+  parent: 4:b2f3bb92043e tip
+   d
+  branch: default
+  commit: (clean)
+  update: (current)
 
 backout of merge should fail
 
@@ -204,16 +270,34 @@
   $ hg backout -d '5 0' --parent 2 4 --tool=true
   removing d
   changeset 5:10e5328c8435 backs out changeset 4:b2f3bb92043e
+  $ hg summary
+  parent: 5:10e5328c8435 tip
+   Backed out changeset b2f3bb92043e
+  branch: default
+  commit: (clean)
+  update: (current)
 
   $ hg rollback
   repository tip rolled back to revision 4 (undo commit)
   working directory now based on revision 4
   $ hg update -C
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ hg summary
+  parent: 4:b2f3bb92043e tip
+   d
+  branch: default
+  commit: (clean)
+  update: (current)
 
   $ hg backout -d '6 0' --parent 3 4 --tool=true
   removing c
   changeset 5:033590168430 backs out changeset 4:b2f3bb92043e
+  $ hg summary
+  parent: 5:033590168430 tip
+   Backed out changeset b2f3bb92043e
+  branch: default
+  commit: (clean)
+  update: (current)
 
   $ cd ..
 
@@ -240,14 +324,20 @@
 
 without --merge
   $ hg backout -r 1 --tool=true
-  removing file1
-  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  changeset bf1602f437f3 backed out, don't forget to commit.
   $ hg branch
   branch2
   $ hg status -A
   R file1
   C default
   C file2
+  $ hg summary
+  parent: 2:45bbcd363bf0 tip
+   file2
+  branch: branch2
+  commit: 1 removed
+  update: (current)
 
 with --merge
   $ hg update -qC
@@ -258,6 +348,14 @@
   merging with changeset 3:d4e8f6db59fb
   0 files updated, 0 files merged, 1 files removed, 0 files unresolved
   (branch merge, don't forget to commit)
+  $ hg summary
+  parent: 2:45bbcd363bf0 
+   file2
+  parent: 3:d4e8f6db59fb tip
+   backout on branch1
+  branch: branch2
+  commit: 1 removed (merge)
+  update: (current)
   $ hg update -q -C 2
 
 on branch2 with branch1 not merged, so file1 should still exist:
@@ -268,6 +366,12 @@
   C default
   C file1
   C file2
+  $ hg summary
+  parent: 2:45bbcd363bf0 
+   file2
+  branch: branch2
+  commit: (clean)
+  update: 1 new changesets, 2 branch heads (merge)
 
 on branch2 with branch1 merged, so file1 should be gone:
 
@@ -280,6 +384,12 @@
   $ hg st -A
   C default
   C file2
+  $ hg summary
+  parent: 4:22149cdde76d tip
+   merge backout of branch1
+  branch: branch2
+  commit: (clean)
+  update: (current)
 
 on branch1, so no file1 and file2:
 
@@ -290,5 +400,11 @@
   $ hg st -A
   C default
   C file1
+  $ hg summary
+  parent: 1:bf1602f437f3 
+   file1
+  branch: branch1
+  commit: (clean)
+  update: (current)
 
   $ cd ..
--- a/tests/test-bisect.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-bisect.t	Tue Jan 21 14:44:01 2014 -0600
@@ -461,11 +461,14 @@
   > EOF
   $ chmod +x script.py
   $ hg bisect -r
-  $ hg bisect --good tip
-  $ hg bisect --bad 0
-  Testing changeset 15:e7fa0811edb0 (31 changesets remaining, ~4 tests)
-  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  $ hg up -qr tip
   $ hg bisect --command "python \"$TESTTMP/script.py\" and some parameters"
+  changeset 31:58c80a7c8a40: good
+  abort: cannot bisect (no known bad revisions)
+  [255]
+  $ hg up -qr 0
+  $ hg bisect --command "python \"$TESTTMP/script.py\" and some parameters"
+  changeset 0:b99c7b9c8e11: bad
   changeset 15:e7fa0811edb0: good
   changeset 7:03750880c6b5: good
   changeset 3:b53bea5e2fcb: bad
@@ -516,6 +519,39 @@
   $ hg parents
 
 
+test the same case, this time with updating
+
+  $ cat > script.sh <<'EOF'
+  > #!/bin/sh
+  > test -n "$HG_NODE" || (echo HG_NODE missing; exit 127)
+  > current="`hg log -r \"bisect(current)\" --template {node}`"
+  > test "$current" = "$HG_NODE" || (echo current is bad: $current; exit 127)
+  > rev="`hg log -r . --template {rev}`"
+  > test "$rev" -ge 6
+  > EOF
+  $ chmod +x script.sh
+  $ hg bisect -r
+  $ hg up -qr tip
+  $ hg bisect --command "sh \"$TESTTMP/script.sh\" and some params"
+  changeset 31:58c80a7c8a40: good
+  abort: cannot bisect (no known bad revisions)
+  [255]
+  $ hg up -qr 0
+  $ hg bisect --command "sh \"$TESTTMP/script.sh\" and some params"
+  changeset 0:b99c7b9c8e11: bad
+  changeset 15:e7fa0811edb0: good
+  changeset 7:03750880c6b5: good
+  changeset 3:b53bea5e2fcb: bad
+  changeset 5:7874a09ea728: bad
+  changeset 6:a3d5c6fdf0d3: good
+  The first good revision is:
+  changeset:   6:a3d5c6fdf0d3
+  user:        test
+  date:        Thu Jan 01 00:00:06 1970 +0000
+  summary:     msg 6
+  
+
+
 Check that bisect does not break on obsolete changesets
 =========================================================
 
--- a/tests/test-blackbox.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-blackbox.t	Tue Jan 21 14:44:01 2014 -0600
@@ -65,7 +65,7 @@
   $ hg rollback
   repository tip rolled back to revision 1 (undo pull)
 
-#if unix-permissions
+#if unix-permissions no-root
   $ chmod 000 .hg/blackbox.log
   $ hg --debug incoming
   warning: cannot write to blackbox.log: Permission denied
@@ -98,7 +98,7 @@
   (run 'hg update' to get a working copy)
 
 a failure reading from the log is fine
-#if unix-permissions
+#if unix-permissions no-root
   $ hg blackbox -l 3
   abort: Permission denied: $TESTTMP/blackboxtest2/.hg/blackbox.log
   [255]
--- a/tests/test-bookmarks-pushpull.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-bookmarks-pushpull.t	Tue Jan 21 14:44:01 2014 -0600
@@ -424,4 +424,22 @@
   remote: added 1 changesets with 1 changes to 1 files
   exporting bookmark add-foo
 
+pushing a new bookmark on a new head does not require -f if -B is specified
+
+  $ hg up -q X
+  $ hg book W
+  $ echo c5 > f2
+  $ hg ci -Am5
+  created new head
+  $ hg push -B W
+  pushing to http://localhost:$HGPORT/
+  searching for changes
+  remote: adding changesets
+  remote: adding manifests
+  remote: adding file changes
+  remote: added 1 changesets with 1 changes to 1 files (+1 heads)
+  exporting bookmark W
+  $ hg -R ../b id -r W
+  cc978a373a53 tip W
+
   $ cd ..
--- a/tests/test-bookmarks.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-bookmarks.t	Tue Jan 21 14:44:01 2014 -0600
@@ -549,7 +549,7 @@
 
 test stripping a non-checked-out but bookmarked revision
 
-  $ hg --config extensions.graphlog= log --graph
+  $ hg log --graph
   o  changeset:   4:9ba5f110a0b3
   |  branch:      test
   |  tag:         tip
@@ -587,7 +587,7 @@
   saved backup bundle to * (glob)
 should-end-on-two should end up pointing to revision 2, as that's the
 tipmost surviving ancestor of the stripped revision.
-  $ hg --config extensions.graphlog= log --graph
+  $ hg log --graph
   @  changeset:   3:9ba5f110a0b3
   |  branch:      test
   |  bookmark:    four
--- a/tests/test-bundle-vs-outgoing.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-bundle-vs-outgoing.t	Tue Jan 21 14:44:01 2014 -0600
@@ -75,12 +75,9 @@
   $ mkrev 8
   rev 8
 
-  $ echo "[extensions]" >> $HGRCPATH
-  $ echo "graphlog=" >> $HGRCPATH
-
 the story so far
 
-  $ hg glog --template "{rev}\n"
+  $ hg log -G --template "{rev}\n"
   @  8
   |
   | o  7
--- a/tests/test-check-code-hg.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-check-code-hg.t	Tue Jan 21 14:44:01 2014 -0600
@@ -25,6 +25,12 @@
   $ for f in "$TESTTMP"/*; do mv "$f" "$f.py"; done
 
 New errors are not allowed. Warnings are strongly discouraged.
+(The writing "no-che?k-code" is for not skipping this file when checking.)
 
   $ { hg manifest 2>/dev/null; ls "$TESTTMP"/*.py | sed 's-\\-/-g'; } |
   >   xargs "$check_code" --warnings --per-file=0 || false
+  Skipping hgext/zeroconf/Zeroconf.py it has no-che?k-code (glob)
+  Skipping i18n/polib.py it has no-che?k-code (glob)
+  Skipping mercurial/httpclient/__init__.py it has no-che?k-code (glob)
+  Skipping mercurial/httpclient/_readers.py it has no-che?k-code (glob)
+  Skipping mercurial/httpclient/socketutil.py it has no-che?k-code (glob)
--- a/tests/test-clone.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-clone.t	Tue Jan 21 14:44:01 2014 -0600
@@ -543,7 +543,7 @@
   $ rm -rf b # work around bug with http clone
 
 
-#if unix-permissions
+#if unix-permissions no-root
 
 Inaccessible source
 
@@ -596,7 +596,7 @@
   [255]
 
 
-#if unix-permissions
+#if unix-permissions no-root
 
 leave existing directory in place after clone failure
 
--- a/tests/test-command-template.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-command-template.t	Tue Jan 21 14:44:01 2014 -0600
@@ -447,7 +447,7 @@
 
 Error if style not readable:
 
-#if unix-permissions
+#if unix-permissions no-root
   $ touch q
   $ chmod 0 q
   $ hg log --style ./q
@@ -479,7 +479,7 @@
 Error if include fails:
 
   $ echo 'changeset = q' >> t
-#if unix-permissions
+#if unix-permissions no-root
   $ hg log --style ./t
   abort: template file ./q: Permission denied
   [255]
@@ -1445,7 +1445,7 @@
   $ hg ci -m h2e -d '4 0'
 
   $ hg merge -q
-  $ hg ci -m merge -d '5 0'
+  $ hg ci -m merge -d '5 -3600'
 
 No tag set:
 
@@ -1533,7 +1533,7 @@
   > EOF
 
   $ hg -R latesttag tip
-  test 10:dee8f28249af
+  test 10:9b4a630e5f5f
 
 Test recursive showlist template (issue1989):
 
@@ -1587,6 +1587,21 @@
   b
   a
 
+Test date format:
+
+  $ hg log -R latesttag --template 'date: {date(date, "%y %m %d %S %z")}\n'
+  date: 70 01 01 10 +0000
+  date: 70 01 01 09 +0000
+  date: 70 01 01 08 +0000
+  date: 70 01 01 07 +0000
+  date: 70 01 01 06 +0000
+  date: 70 01 01 05 +0100
+  date: 70 01 01 04 +0000
+  date: 70 01 01 03 +0000
+  date: 70 01 01 02 +0000
+  date: 70 01 01 01 +0000
+  date: 70 01 01 00 +0000
+
 Test string escaping:
 
   $ hg log -R latesttag -r 0 --template '>\n<>\\n<{if(rev, "[>\n<>\\n<]")}>\n<>\\n<\n'
--- a/tests/test-commit-multiple.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-commit-multiple.t	Tue Jan 21 14:44:01 2014 -0600
@@ -4,7 +4,6 @@
   $ cat <<EOF >> $HGRCPATH
   > [extensions]
   > transplant =
-  > graphlog =
   > EOF
   $ hg init repo
   $ cd repo
@@ -39,7 +38,7 @@
   $ echo fix2 > bugfix
   $ echo fix2 >> file1
   $ hg ci -Am"fix 2"
-  $ hg glog --template="$template"
+  $ hg log -G --template="$template"
   @  3  fix 2  [fixes]
   |
   o  2  fix 1  [fixes]
@@ -59,7 +58,7 @@
   [0-9a-f]{12} transplanted to [0-9a-f]{12} (re)
   applying [0-9a-f]{12} (re)
   [0-9a-f]{12} transplanted to [0-9a-f]{12} (re)
-  $ hg glog --template="$template"
+  $ hg log -G --template="$template"
   @  5  fix 2  [release]
   |
   o  4  fix 1  [release]
--- a/tests/test-commit-unresolved.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-commit-unresolved.t	Tue Jan 21 14:44:01 2014 -0600
@@ -1,6 +1,3 @@
-  $ echo "[extensions]" >> $HGRCPATH
-  $ echo "graphlog=" >> $HGRCPATH
-
   $ addcommit () {
   >     echo $1 > $1
   >     hg add $1
--- a/tests/test-completion.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-completion.t	Tue Jan 21 14:44:01 2014 -0600
@@ -305,7 +305,7 @@
 
   $ hg debugpathcomplete f
   fee
-  fie/
+  fie
   fo
   $ hg debugpathcomplete -f f
   fee
@@ -317,12 +317,6 @@
   $ hg debugpathcomplete -r F
   Fum
 
-If one directory and no files match, give an ambiguous answer
-
-  $ hg debugpathcomplete fi
-  fie/
-  fie/.
-
 Test debuglabelcomplete
 
   $ hg debuglabelcomplete
--- a/tests/test-convert-baz.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-convert-baz.t	Tue Jan 21 14:44:01 2014 -0600
@@ -4,7 +4,6 @@
 
   $ echo "[extensions]" >> $HGRCPATH
   $ echo "convert=" >> $HGRCPATH
-  $ echo 'graphlog =' >> $HGRCPATH
 
 create baz archive
   $ baz make-archive baz@mercurial--convert hg-test-convert-baz
@@ -129,7 +128,7 @@
 
   $ glog()
   > {
-  >     hg glog --template '{rev} "{desc|firstline}" files: {files}\n' "$@"
+  >     hg log -G --template '{rev} "{desc|firstline}" files: {files}\n' "$@"
   > }
 
 show graph log
--- a/tests/test-convert-cvs-branch.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-convert-cvs-branch.t	Tue Jan 21 14:44:01 2014 -0600
@@ -8,7 +8,6 @@
   > }
   $ echo "[extensions]" >> $HGRCPATH
   $ echo "convert = " >> $HGRCPATH
-  $ echo "graphlog = " >> $HGRCPATH
   $ echo "[convert]" >> $HGRCPATH
   $ echo "cvsps.cache=0" >> $HGRCPATH
 
@@ -79,7 +78,7 @@
 
 Check the result
 
-  $ hg -R src-hg glog --template '{rev} ({branches}) {desc} files: {files}\n'
+  $ hg -R src-hg log -G --template '{rev} ({branches}) {desc} files: {files}\n'
   o  5 () update tags files: .hgtags
   |
   | o  4 (BRANCH) mod a again files: a
--- a/tests/test-convert-cvs-detectmerge.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-convert-cvs-detectmerge.t	Tue Jan 21 14:44:01 2014 -0600
@@ -24,7 +24,6 @@
 
   $ echo "[extensions]" >> $HGRCPATH
   $ echo "convert = " >> $HGRCPATH
-  $ echo "graphlog = " >> $HGRCPATH
   $ echo "[convert]" >> $HGRCPATH
   $ echo "cvsps.cache=0" >> $HGRCPATH
   $ echo "cvsps.mergefrom=\[MERGE from (\S+)\]" >> $HGRCPATH
@@ -210,7 +209,7 @@
 
 graphical log
 
-  $ hg -R proj.hg glog --template="$template"
+  $ hg -R proj.hg log -G --template="$template"
   o  9: '' fix file1 [MERGE from v1-1]
   |
   | o  8: 'v1_1' fix file1
--- a/tests/test-convert-cvs-synthetic.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-convert-cvs-synthetic.t	Tue Jan 21 14:44:01 2014 -0600
@@ -1,9 +1,8 @@
 This feature requires use of builtin cvsps!
 
-  $ "$TESTDIR/hghave" cvs || exit 80
+  $ "$TESTDIR/hghave" cvs112 || exit 80
   $ echo "[extensions]" >> $HGRCPATH
   $ echo "convert = " >> $HGRCPATH
-  $ echo "graphlog = " >> $HGRCPATH
 
 create cvs repository with one project
 
@@ -153,9 +152,9 @@
   1 MERGE from HEAD: add file6
   0 MERGE from v1_2: add file5
 
-hg glog output (#1)
+hg log -G output (#1)
 
-  $ hg -R proj.hg glog --template "{rev} {desc}\n"
+  $ hg -R proj.hg log -G --template "{rev} {desc}\n"
   o  8 MERGE from v1_2: add file5
   |
   | o  7 MERGE from HEAD: add file6
@@ -200,9 +199,9 @@
   1 MERGE from HEAD: add file6
   0 MERGE from v1_2: add file5
 
-hg glog output (#2)
+hg log -G output (#2)
 
-  $ hg -R proj.hg2 glog --template "{rev} {desc}\n"
+  $ hg -R proj.hg2 log -G --template "{rev} {desc}\n"
   o  8 MERGE from v1_2: add file5
   |
   | o  7 MERGE from HEAD: add file6
--- a/tests/test-convert-cvs.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-convert-cvs.t	Tue Jan 21 14:44:01 2014 -0600
@@ -10,7 +10,6 @@
   > }
   $ echo "[extensions]" >> $HGRCPATH
   $ echo "convert = " >> $HGRCPATH
-  $ echo "graphlog = " >> $HGRCPATH
   $ cat > cvshooks.py <<EOF
   > def cvslog(ui,repo,hooktype,log):
   >     print "%s hook: %d entries"%(hooktype,len(log))
@@ -307,7 +306,7 @@
   2 funny
   1 fuzzy
   0 fuzzy
-  $ hg -R src-hg glog --template '{rev} ({branches}) {desc} date: {date|date} files: {files}\n'
+  $ hg -R src-hg log -G --template '{rev} ({branches}) {desc} date: {date|date} files: {files}\n'
   o  8 (branch) fuzzy date: * -1000 files: b/c (glob)
   |
   o  7 (branch) fuzzy date: * -1000 files: a (glob)
--- a/tests/test-convert-cvsnt-mergepoints.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-convert-cvsnt-mergepoints.t	Tue Jan 21 14:44:01 2014 -0600
@@ -22,7 +22,6 @@
   > }
   $ echo "[extensions]" >> $HGRCPATH
   $ echo "convert = " >> $HGRCPATH
-  $ echo "graphlog = " >> $HGRCPATH
 
 create cvs repository
 
--- a/tests/test-convert-darcs.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-convert-darcs.t	Tue Jan 21 14:44:01 2014 -0600
@@ -2,7 +2,6 @@
   $ "$TESTDIR/hghave" darcs || exit 80
   $ echo "[extensions]" >> $HGRCPATH
   $ echo "convert=" >> $HGRCPATH
-  $ echo 'graphlog =' >> $HGRCPATH
   $ DARCS_EMAIL='test@example.org'; export DARCS_EMAIL
 
 initialize darcs repo
--- a/tests/test-convert-datesort.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-convert-datesort.t	Tue Jan 21 14:44:01 2014 -0600
@@ -2,7 +2,6 @@
   $ cat >> $HGRCPATH <<EOF
   > [extensions]
   > convert=
-  > graphlog=
   > EOF
   $ hg init t
   $ cd t
@@ -83,7 +82,7 @@
 
 graph converted repo
 
-  $ hg -R t-datesort glog --template '{rev} "{desc}"\n'
+  $ hg -R t-datesort log -G --template '{rev} "{desc}"\n'
   o    12 "c1"
   |\
   | o  11 "b2x"
@@ -134,7 +133,7 @@
 
 graph converted repo
 
-  $ hg -R t-sourcesort glog --template '{rev} "{desc}"\n'
+  $ hg -R t-sourcesort log -G --template '{rev} "{desc}"\n'
   o    12 "c1"
   |\
   | o  11 "b2x"
@@ -185,7 +184,7 @@
 
 graph converted repo
 
-  $ hg -R t-closesort glog --template '{rev} "{desc}"\n'
+  $ hg -R t-closesort log -G --template '{rev} "{desc}"\n'
   o    12 "c1"
   |\
   | o  11 "c0"
--- a/tests/test-convert-filemap.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-convert-filemap.t	Tue Jan 21 14:44:01 2014 -0600
@@ -1,11 +1,10 @@
 
   $ HGMERGE=true; export HGMERGE
   $ echo '[extensions]' >> $HGRCPATH
-  $ echo 'graphlog =' >> $HGRCPATH
   $ echo 'convert =' >> $HGRCPATH
   $ glog()
   > {
-  >     hg glog --template '{rev} "{desc}" files: {files}\n' "$@"
+  >     hg log -G --template '{rev} "{desc}" files: {files}\n' "$@"
   > }
   $ hg init source
   $ cd source
@@ -473,7 +472,7 @@
 
   $ glog()
   > {
-  >     hg glog --template '{rev}:{node|short}@{branch} "{desc}" files: {files}\n' "$@"
+  >     hg log -G --template '{rev}:{node|short}@{branch} "{desc}" files: {files}\n' "$@"
   > }
 
 test anonymous branch pruning
--- a/tests/test-convert-git.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-convert-git.t	Tue Jan 21 14:44:01 2014 -0600
@@ -6,7 +6,6 @@
   $ echo "autocrlf = false" >> $HOME/.gitconfig
   $ echo "[extensions]" >> $HGRCPATH
   $ echo "convert=" >> $HGRCPATH
-  $ echo 'hgext.graphlog =' >> $HGRCPATH
   $ GIT_AUTHOR_NAME='test'; export GIT_AUTHOR_NAME
   $ GIT_AUTHOR_EMAIL='test@example.org'; export GIT_AUTHOR_EMAIL
   $ GIT_AUTHOR_DATE="2007-01-01 00:00:00 +0000"; export GIT_AUTHOR_DATE
@@ -114,7 +113,7 @@
   $ cd ..
   $ glog()
   > {
-  >     hg glog --template '{rev} "{desc|firstline}" files: {files}\n' "$@"
+  >     hg log -G --template '{rev} "{desc|firstline}" files: {files}\n' "$@"
   > }
   $ splitrepo()
   > {
--- a/tests/test-convert-hg-startrev.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-convert-hg-startrev.t	Tue Jan 21 14:44:01 2014 -0600
@@ -1,7 +1,6 @@
 
   $ cat >> $HGRCPATH <<EOF
   > [extensions]
-  > graphlog =
   > convert =
   > [convert]
   > hg.saverev = yes
@@ -9,7 +8,7 @@
 
   $ glog()
   > {
-  >     hg -R "$1" glog --template '{rev} "{desc}" files: {files}\n'
+  >     hg -R "$1" log -G --template '{rev} "{desc}" files: {files}\n'
   > }
 
   $ hg init source
--- a/tests/test-convert-mtn.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-convert-mtn.t	Tue Jan 21 14:44:01 2014 -0600
@@ -16,7 +16,6 @@
 
   $ echo "[extensions]" >> $HGRCPATH
   $ echo "convert=" >> $HGRCPATH
-  $ echo 'graphlog =' >> $HGRCPATH
 
 Windows version of monotone home
 
@@ -257,7 +256,7 @@
   0 largefile
   $ glog()
   > {
-  >     hg glog --template '{rev} "{desc|firstline}" files: {files}\n' "$@"
+  >     hg log -G --template '{rev} "{desc|firstline}" files: {files}\n' "$@"
   > }
   $ cd repo.mtn-hg
   $ hg up -C
--- a/tests/test-convert-splicemap.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-convert-splicemap.t	Tue Jan 21 14:44:01 2014 -0600
@@ -1,10 +1,9 @@
 
   $ echo "[extensions]" >> $HGRCPATH
   $ echo "convert=" >> $HGRCPATH
-  $ echo 'graphlog =' >> $HGRCPATH
   $ glog()
   > {
-  >     hg glog --template '{rev}:{node|short} "{desc|firstline}"\
+  >     hg log -G --template '{rev}:{node|short} "{desc|firstline}"\
   >  files: {files}\n' "$@"
   > }
   $ hg init repo1
--- a/tests/test-convert-svn-branches.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-convert-svn-branches.t	Tue Jan 21 14:44:01 2014 -0600
@@ -4,7 +4,6 @@
   $ cat >> $HGRCPATH <<EOF
   > [extensions]
   > convert =
-  > graphlog =
   > EOF
 
   $ svnadmin create svn-repo
@@ -58,7 +57,7 @@
   0 branch trunk@1 into old3
 
   $ cd A-hg
-  $ hg glog --template 'branch={branches} {rev} {desc|firstline} files: {files}\n'
+  $ hg log -G --template 'branch={branches} {rev} {desc|firstline} files: {files}\n'
   o  branch=newbranch 11 branch trunk@1 into old3 files:
   |
   | o  branch= 10 last change to a files: a
--- a/tests/test-convert-svn-encoding.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-convert-svn-encoding.t	Tue Jan 21 14:44:01 2014 -0600
@@ -4,7 +4,6 @@
   $ cat >> $HGRCPATH <<EOF
   > [extensions]
   > convert =
-  > graphlog =
   > EOF
 
   $ svnadmin create svn-repo
--- a/tests/test-convert-svn-move.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-convert-svn-move.t	Tue Jan 21 14:44:01 2014 -0600
@@ -4,7 +4,6 @@
   $ cat >> $HGRCPATH <<EOF
   > [extensions]
   > convert =
-  > graphlog =
   > EOF
 
   $ svnadmin create svn-repo
@@ -39,7 +38,7 @@
   0 rename d4old into d4new
 
   $ cd A-hg
-  $ hg glog --template '{rev} {desc|firstline} files: {files}\n'
+  $ hg log -G --template '{rev} {desc|firstline} files: {files}\n'
   o  13 rename d4old into d4new files: d4new/g d4old/g
   |
   o  12 add d4old files: d4old/g
--- a/tests/test-convert-svn-sink.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-convert-svn-sink.t	Tue Jan 21 14:44:01 2014 -0600
@@ -17,7 +17,6 @@
   $ cat >> $HGRCPATH <<EOF
   > [extensions]
   > convert =
-  > graphlog =
   > EOF
 
   $ hg init a
--- a/tests/test-convert-svn-source.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-convert-svn-source.t	Tue Jan 21 14:44:01 2014 -0600
@@ -4,7 +4,6 @@
   $ cat >> $HGRCPATH <<EOF
   > [extensions]
   > convert =
-  > graphlog =
   > [convert]
   > svn.trunk = mytrunk
   > EOF
@@ -127,7 +126,7 @@
   updating tags
 
   $ cd B-hg
-  $ hg glog --template '{rev} {desc|firstline} date: {date|date} files: {files}\n'
+  $ hg log -G --template '{rev} {desc|firstline} date: {date|date} files: {files}\n'
   o  7 update tags date: * +0000 files: .hgtags (glob)
   |
   o  6 work in progress date: * -1000 files: letter2.txt (glob)
@@ -165,7 +164,7 @@
   0 work in progress
   $ hg -R fmap branch -q
   default
-  $ hg glog -R fmap --template '{rev} {desc|firstline} files: {files}\n'
+  $ hg log -G -R fmap --template '{rev} {desc|firstline} files: {files}\n'
   o  1 work in progress files: letter2.txt
   |
   o  0 second letter files: letter2.txt
--- a/tests/test-convert-svn-startrev.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-convert-svn-startrev.t	Tue Jan 21 14:44:01 2014 -0600
@@ -4,7 +4,6 @@
   $ cat >> $HGRCPATH <<EOF
   > [extensions]
   > convert =
-  > graphlog =
   > EOF
   $ convert()
   > {
@@ -15,7 +14,7 @@
   >         --config convert.svn.branches="  " \
   >         --config convert.svn.tags= \
   >         --datesort svn-repo $repopath
-  >     hg -R $repopath glog \
+  >     hg -R $repopath log -G \
   >         --template '{rev} {desc|firstline} files: {files}\n'
   >     echo
   > }
--- a/tests/test-convert-svn-tags.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-convert-svn-tags.t	Tue Jan 21 14:44:01 2014 -0600
@@ -4,7 +4,6 @@
   $ cat >> $HGRCPATH <<EOF
   > [extensions]
   > convert =
-  > graphlog =
   > EOF
 
   $ svnadmin create svn-repo
@@ -25,7 +24,7 @@
   updating tags
 
   $ cd A-hg
-  $ hg glog --template '{rev} {desc|firstline} tags: {tags}\n'
+  $ hg log -G --template '{rev} {desc|firstline} tags: {tags}\n'
   o  6 update tags tags: tip
   |
   o  5 changea tags: trunk.goodtag
--- a/tests/test-convert-tagsbranch-topology.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-convert-tagsbranch-topology.t	Tue Jan 21 14:44:01 2014 -0600
@@ -6,7 +6,6 @@
   $ echo "autocrlf = false" >> $HOME/.gitconfig
   $ echo "[extensions]" >> $HGRCPATH
   $ echo "convert=" >> $HGRCPATH
-  $ echo 'hgext.graphlog =' >> $HGRCPATH
   $ echo '[convert]' >> $HGRCPATH
   $ echo 'hg.usebranchnames = True' >> $HGRCPATH
   $ echo 'hg.tagsbranch = tags-update' >> $HGRCPATH
@@ -26,7 +25,7 @@
   > }
   $ glog()
   > {
-  >     hg glog --template '{rev} "{desc|firstline}" files: {files}\n' "$@"
+  >     hg log -G --template '{rev} "{desc|firstline}" files: {files}\n' "$@"
   > }
   $ convertrepo()
   > {
--- a/tests/test-convert-tla.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-convert-tla.t	Tue Jan 21 14:44:01 2014 -0600
@@ -3,7 +3,6 @@
   $ tla my-id "mercurial <mercurial@selenic.com>"
   $ echo "[extensions]" >> $HGRCPATH
   $ echo "convert=" >> $HGRCPATH
-  $ echo 'graphlog =' >> $HGRCPATH
 
 create tla archive
 
@@ -109,7 +108,7 @@
   $ tla register-archive -d tla@mercurial--convert
   $ glog()
   > {
-  >     hg glog --template '{rev} "{desc|firstline}" files: {files}\n' "$@"
+  >     hg log -G --template '{rev} "{desc|firstline}" files: {files}\n' "$@"
   > }
 
 show graph log
--- a/tests/test-convert.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-convert.t	Tue Jan 21 14:44:01 2014 -0600
@@ -310,7 +310,7 @@
   abort: cannot create new bundle repository
   [255]
 
-#if unix-permissions
+#if unix-permissions no-root
 
 conversion to dir without permissions should fail
 
--- a/tests/test-debugbuilddag.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-debugbuilddag.t	Tue Jan 21 14:44:01 2014 -0600
@@ -1,5 +1,3 @@
-  $ echo "[extensions]" >> $HGRCPATH
-  $ echo "graphlog=" >> $HGRCPATH
 
 plain
 
@@ -60,7 +58,7 @@
   $ hg id
   000000000000
 glog
-  $ hg glog --template '{rev}: {desc} [{branches}] @ {date}\n'
+  $ hg log -G --template '{rev}: {desc} [{branches}] @ {date}\n'
   o  11: r11 [] @ 11.00
   |
   o  10: r10 [] @ 10.00
@@ -106,7 +104,7 @@
   $ hg id
   000000000000
 glog
-  $ hg glog --template '{rev}: {desc} [{branches}] @ {date}\n'
+  $ hg log -G --template '{rev}: {desc} [{branches}] @ {date}\n'
   o  11: r11 [] @ 11.00
   |
   o  10: r10 [] @ 10.00
@@ -132,7 +130,7 @@
   o  0: r0 [start] @ 0.00
   
 glog of
-  $ hg glog --template '{rev}: {desc} [{branches}]\n' of
+  $ hg log -G --template '{rev}: {desc} [{branches}]\n' of
   o  11: r11 []
   |
   o  10: r10 []
@@ -182,7 +180,7 @@
   $ hg id
   000000000000
 glog
-  $ hg glog --template '{rev}: {desc} [{branches}] @ {date}\n'
+  $ hg log -G --template '{rev}: {desc} [{branches}] @ {date}\n'
   o  11: r11 [] @ 11.00
   |
   o  10: r10 [] @ 10.00
@@ -208,7 +206,7 @@
   o  0: r0 [] @ 0.00
   
 glog mf
-  $ hg glog --template '{rev}: {desc} [{branches}]\n' mf
+  $ hg log -G --template '{rev}: {desc} [{branches}]\n' mf
   o  11: r11 []
   |
   o  10: r10 []
--- a/tests/test-debugcommands.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-debugcommands.t	Tue Jan 21 14:44:01 2014 -0600
@@ -23,3 +23,25 @@
   uncompressed data size (min/max/avg) : 43 / 43 / 43
   full revision size (min/max/avg)     : 44 / 44 / 44
   delta size (min/max/avg)             : 0 / 0 / 0
+
+
+Test internal debugstacktrace command
+
+  $ cat > debugstacktrace.py << EOF
+  > from mercurial.util import debugstacktrace, dst, sys
+  > def f():
+  >     dst('hello world')
+  > def g():
+  >     f()
+  >     debugstacktrace(skip=-5, f=sys.stdout)
+  > g()
+  > EOF
+  $ python debugstacktrace.py
+  hello world at:
+   debugstacktrace.py:7 in * (glob)
+   debugstacktrace.py:5 in g
+   debugstacktrace.py:3 in f
+  stacktrace at:
+   debugstacktrace.py:7 *in * (glob)
+   debugstacktrace.py:6 *in g (glob)
+   */util.py:* in debugstacktrace (glob)
--- a/tests/test-doctest.py	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-doctest.py	Tue Jan 21 14:44:01 2014 -0600
@@ -1,49 +1,29 @@
 # this is hack to make sure no escape characters are inserted into the output
-import os
+import os, sys
 if 'TERM' in os.environ:
     del os.environ['TERM']
 import doctest
 
-import mercurial.util
-doctest.testmod(mercurial.util)
-# Only run doctests for the current platform
-doctest.testmod(mercurial.util.platform)
-
-import mercurial.changelog
-doctest.testmod(mercurial.changelog)
-
-import mercurial.dagparser
-doctest.testmod(mercurial.dagparser, optionflags=doctest.NORMALIZE_WHITESPACE)
-
-import mercurial.match
-doctest.testmod(mercurial.match)
-
-import mercurial.store
-doctest.testmod(mercurial.store)
-
-import mercurial.ui
-doctest.testmod(mercurial.ui)
+def testmod(name, optionflags=0, testtarget=None):
+    __import__(name)
+    mod = sys.modules[name]
+    if testtarget is not None:
+        mod = getattr(mod, testtarget)
+    doctest.testmod(mod, optionflags=optionflags)
 
-import mercurial.url
-doctest.testmod(mercurial.url)
-
-import mercurial.dispatch
-doctest.testmod(mercurial.dispatch)
-
-import mercurial.encoding
-doctest.testmod(mercurial.encoding)
-
-import mercurial.hgweb.hgwebdir_mod
-doctest.testmod(mercurial.hgweb.hgwebdir_mod)
-
-import hgext.convert.cvsps
-doctest.testmod(hgext.convert.cvsps)
-
-import mercurial.revset
-doctest.testmod(mercurial.revset)
-
-import mercurial.minirst
-doctest.testmod(mercurial.minirst)
-
-import mercurial.templatefilters
-doctest.testmod(mercurial.templatefilters)
+testmod('mercurial.changelog')
+testmod('mercurial.dagparser', optionflags=doctest.NORMALIZE_WHITESPACE)
+testmod('mercurial.dispatch')
+testmod('mercurial.encoding')
+testmod('mercurial.hgweb.hgwebdir_mod')
+testmod('mercurial.match')
+testmod('mercurial.minirst')
+testmod('mercurial.revset')
+testmod('mercurial.store')
+testmod('mercurial.templatefilters')
+testmod('mercurial.ui')
+testmod('mercurial.url')
+testmod('mercurial.util')
+testmod('mercurial.util', testtarget='platform')
+testmod('hgext.convert.cvsps')
+testmod('hgext.convert.filemap')
--- a/tests/test-filecache.py	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-filecache.py	Tue Jan 21 14:44:01 2014 -0600
@@ -18,9 +18,10 @@
     def sjoin(self, p):
         return p
 
-    @filecache('x')
+    @filecache('x', 'y')
     def cached(self):
         print 'creating'
+        return 'string from function'
 
     def invalidate(self):
         for k in self._filecache:
@@ -30,17 +31,20 @@
                 pass
 
 def basic(repo):
-    # file doesn't exist, calls function
+    print "* neither file exists"
+    # calls function
     repo.cached
 
     repo.invalidate()
-    # file still doesn't exist, uses cache
+    print "* neither file still exists"
+    # uses cache
     repo.cached
 
     # create empty file
     f = open('x', 'w')
     f.close()
     repo.invalidate()
+    print "* empty file x created"
     # should recreate the object
     repo.cached
 
@@ -48,11 +52,13 @@
     f.write('a')
     f.close()
     repo.invalidate()
+    print "* file x changed size"
     # should recreate the object
     repo.cached
 
     repo.invalidate()
-    # stats file again, nothing changed, reuses object
+    print "* nothing changed with either file"
+    # stats file again, reuses object
     repo.cached
 
     # atomic replace file, size doesn't change
@@ -63,6 +69,42 @@
     f.close()
 
     repo.invalidate()
+    print "* file x changed inode"
+    repo.cached
+
+    # create empty file y
+    f = open('y', 'w')
+    f.close()
+    repo.invalidate()
+    print "* empty file y created"
+    # should recreate the object
+    repo.cached
+
+    f = open('y', 'w')
+    f.write('A')
+    f.close()
+    repo.invalidate()
+    print "* file y changed size"
+    # should recreate the object
+    repo.cached
+
+    f = scmutil.opener('.')('y', 'w', atomictemp=True)
+    f.write('B')
+    f.close()
+
+    repo.invalidate()
+    print "* file y changed inode"
+    repo.cached
+
+    f = scmutil.opener('.')('x', 'w', atomictemp=True)
+    f.write('c')
+    f.close()
+    f = scmutil.opener('.')('y', 'w', atomictemp=True)
+    f.write('C')
+    f.close()
+
+    repo.invalidate()
+    print "* both files changed inode"
     repo.cached
 
 def fakeuncacheable():
@@ -76,10 +118,11 @@
     origcacheable = extensions.wrapfunction(util.cachestat, 'cacheable',
                                             wrapcacheable)
 
-    try:
-        os.remove('x')
-    except OSError:
-        pass
+    for fn in ['x', 'y']:
+        try:
+            os.remove(fn)
+        except OSError:
+            pass
 
     basic(fakerepo())
 
@@ -103,13 +146,28 @@
 
 def setbeforeget(repo):
     os.remove('x')
-    repo.cached = 0
+    os.remove('y')
+    repo.cached = 'string set externally'
     repo.invalidate()
+    print "* neither file exists"
     print repo.cached
     repo.invalidate()
     f = open('x', 'w')
     f.write('a')
     f.close()
+    print "* file x created"
+    print repo.cached
+
+    repo.cached = 'string 2 set externally'
+    repo.invalidate()
+    print "* string set externally again"
+    print repo.cached
+
+    repo.invalidate()
+    f = open('y', 'w')
+    f.write('b')
+    f.close()
+    print "* file y created"
     print repo.cached
 
 print 'basic:'
--- a/tests/test-filecache.py.out	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-filecache.py.out	Tue Jan 21 14:44:01 2014 -0600
@@ -1,17 +1,45 @@
 basic:
 
+* neither file exists
 creating
+* neither file still exists
+* empty file x created
+creating
+* file x changed size
 creating
+* nothing changed with either file
+* file x changed inode
 creating
+* empty file y created
+creating
+* file y changed size
+creating
+* file y changed inode
+creating
+* both files changed inode
 creating
 
 fakeuncacheable:
 
+* neither file exists
 creating
+* neither file still exists
 creating
+* empty file x created
+creating
+* file x changed size
+creating
+* nothing changed with either file
 creating
+* file x changed inode
 creating
+* empty file y created
 creating
+* file y changed size
+creating
+* file y changed inode
+creating
+* both files changed inode
 creating
 repository tip rolled back to revision -1 (undo commit)
 working directory now based on revision -1
@@ -20,6 +48,13 @@
 
 setbeforeget:
 
-0
+* neither file exists
+string set externally
+* file x created
 creating
-None
+string from function
+* string set externally again
+string 2 set externally
+* file y created
+creating
+string from function
--- a/tests/test-fncache.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-fncache.t	Tue Jan 21 14:44:01 2014 -0600
@@ -70,7 +70,7 @@
   .hg/00changelog.i
   .hg/00manifest.i
   .hg/cache
-  .hg/cache/branchheads-served
+  .hg/cache/branch2-served
   .hg/data
   .hg/data/tst.d.hg
   .hg/data/tst.d.hg/foo.i
@@ -98,7 +98,7 @@
   .hg
   .hg/00changelog.i
   .hg/cache
-  .hg/cache/branchheads-served
+  .hg/cache/branch2-served
   .hg/dirstate
   .hg/last-message.txt
   .hg/requires
--- a/tests/test-getbundle.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-getbundle.t	Tue Jan 21 14:44:01 2014 -0600
@@ -2,17 +2,12 @@
 
 = Test the getbundle() protocol function =
 
-Enable graphlog extension:
-
-  $ echo "[extensions]" >> $HGRCPATH
-  $ echo "graphlog=" >> $HGRCPATH
-
 Create a test repository:
 
   $ hg init repo
   $ cd repo
   $ hg debugbuilddag -n -m '+2 :fork +5 :p1 *fork +6 :p2 /p1 :m1 +3' > /dev/null
-  $ hg glog --template '{node}\n'
+  $ hg log -G --template '{node}\n'
   o  10c14a2cc935e1d8c31f9e98587dcf27fb08a6da
   |
   o  4801a72e5d88cb515b0c7e40fae34180f3f837f2
--- a/tests/test-glog.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-glog.t	Tue Jan 21 14:44:01 2014 -0600
@@ -102,7 +102,6 @@
   > EOF
 
   $ echo "[extensions]" >> $HGRCPATH
-  $ echo "graphlog=" >> $HGRCPATH
   $ echo "printrevset=`pwd`/printrevset.py" >> $HGRCPATH
 
   $ hg init repo
@@ -110,7 +109,7 @@
 
 Empty repo:
 
-  $ hg glog
+  $ hg log -G
 
 
 Building DAG:
@@ -152,7 +151,7 @@
   $ commit 34 "head" 32
 
 
-  $ hg glog -q
+  $ hg log -G -q
   @  34:fea3ac5810e0
   |
   | o  33:68608f5145f9
@@ -224,7 +223,7 @@
   o  0:e6eb3150255d
   
 
-  $ hg glog
+  $ hg log -G
   @  changeset:   34:fea3ac5810e0
   |  tag:         tip
   |  parent:      32:d06dffa21a31
@@ -461,7 +460,7 @@
   
 
 File glog:
-  $ hg glog a
+  $ hg log -G a
   @  changeset:   34:fea3ac5810e0
   |  tag:         tip
   |  parent:      32:d06dffa21a31
@@ -699,7 +698,7 @@
 
 File glog per revset:
 
-  $ hg glog -r 'file("a")'
+  $ hg log -G -r 'file("a")'
   @  changeset:   34:fea3ac5810e0
   |  tag:         tip
   |  parent:      32:d06dffa21a31
@@ -1131,14 +1130,14 @@
 
 
 Empty revision range - display nothing:
-  $ hg glog -r 1..0
+  $ hg log -G -r 1..0
 
   $ cd ..
 
 #if no-outer-repo
 
 From outer space:
-  $ hg glog -l1 repo
+  $ hg log -G -l1 repo
   @  changeset:   34:fea3ac5810e0
   |  tag:         tip
   |  parent:      32:d06dffa21a31
@@ -1146,7 +1145,7 @@
   |  date:        Thu Jan 01 00:00:34 1970 +0000
   |  summary:     (34) head
   |
-  $ hg glog -l1 repo/a
+  $ hg log -G -l1 repo/a
   @  changeset:   34:fea3ac5810e0
   |  tag:         tip
   |  parent:      32:d06dffa21a31
@@ -1154,7 +1153,7 @@
   |  date:        Thu Jan 01 00:00:34 1970 +0000
   |  summary:     (34) head
   |
-  $ hg glog -l1 repo/missing
+  $ hg log -G -l1 repo/missing
 
 #endif
 
@@ -1169,7 +1168,7 @@
   $ hg commit -mtwo
   $ echo more >two
   $ hg commit -mmore
-  $ hg glog two
+  $ hg log -G two
   @  changeset:   2:12c28321755b
   |  tag:         tip
   |  user:        test
@@ -1183,14 +1182,14 @@
   |
 
 Issue1896: File log with explicit style
-  $ hg glog --style=default one
+  $ hg log -G --style=default one
   o  changeset:   0:3d578b4a1f53
      user:        test
      date:        Thu Jan 01 00:00:00 1970 +0000
      summary:     one
   
 Issue2395: glog --style header and footer
-  $ hg glog --style=xml one
+  $ hg log -G --style=xml one
   <?xml version="1.0"?>
   <log>
   o  <logentry revision="0" node="3d578b4a1f537d5fcf7301bfa9c0b97adfaa6fb1">
@@ -1276,7 +1275,7 @@
   $ cd repo
   $ touch b
   $ hg ci -Aqm0
-  $ hg glog -l2 a
+  $ hg log -G -l2 a
   o  changeset:   34:fea3ac5810e0
   |  parent:      32:d06dffa21a31
   |  user:        test
@@ -1291,7 +1290,7 @@
   | |
 
 File + limit + -ra:b, (b - a) < limit:
-  $ hg glog -l3000 -r32:tip a
+  $ hg log -G -l3000 -r32:tip a
   o  changeset:   34:fea3ac5810e0
   |  parent:      32:d06dffa21a31
   |  user:        test
@@ -1314,7 +1313,7 @@
 
 Point out a common and an uncommon unshown parent
 
-  $ hg glog -r 'rev(8) or rev(9)'
+  $ hg log -G -r 'rev(8) or rev(9)'
   o    changeset:   9:7010c0af0a35
   |\   parent:      7:b632bb1b1224
   | |  parent:      8:7a0b11f71937
@@ -1332,7 +1331,7 @@
 
 File + limit + -ra:b, b < tip:
 
-  $ hg glog -l1 -r32:34 a
+  $ hg log -G -l1 -r32:34 a
   o  changeset:   34:fea3ac5810e0
   |  parent:      32:d06dffa21a31
   |  user:        test
@@ -1342,7 +1341,7 @@
 
 file(File) + limit + -ra:b, b < tip:
 
-  $ hg glog -l1 -r32:34 -r 'file("a")'
+  $ hg log -G -l1 -r32:34 -r 'file("a")'
   o  changeset:   34:fea3ac5810e0
   |  parent:      32:d06dffa21a31
   |  user:        test
@@ -1352,7 +1351,7 @@
 
 limit(file(File) and a::b), b < tip:
 
-  $ hg glog -r 'limit(file("a") and 32::34, 1)'
+  $ hg log -G -r 'limit(file("a") and 32::34, 1)'
   o    changeset:   32:d06dffa21a31
   |\   parent:      27:886ed638191b
   | |  parent:      31:621d83e11f67
@@ -1363,11 +1362,11 @@
 
 File + limit + -ra:b, b < tip:
 
-  $ hg glog -r 'limit(file("a") and 34::32, 1)'
+  $ hg log -G -r 'limit(file("a") and 34::32, 1)'
 
 File + limit + -ra:b, b < tip, (b - a) < limit:
 
-  $ hg glog -l10 -r33:34 a
+  $ hg log -G -l10 -r33:34 a
   o  changeset:   34:fea3ac5810e0
   |  parent:      32:d06dffa21a31
   |  user:        test
@@ -1387,7 +1386,7 @@
   marked working directory as branch branch
   (branches are permanent and global, did you want a bookmark?)
   $ commit 36 "buggy merge: identical parents" 35 35
-  $ hg glog -l5
+  $ hg log -G -l5
   @  changeset:   36:08a19a744424
   |  branch:      branch
   |  tag:         tip
@@ -1561,7 +1560,7 @@
   $ hg ci -m "mv a b; add d"
   $ hg mv dir/b e
   $ hg ci -m "mv dir/b e"
-  $ hg glog --template '({rev}) {desc|firstline}\n'
+  $ hg log -G --template '({rev}) {desc|firstline}\n'
   @  (4) mv dir/b e
   |
   o  (3) mv a b; add d
@@ -2058,7 +2057,7 @@
   $ testlog --hidden
   []
   []
-  $ hg glog --template '{rev} {desc}\n'
+  $ hg log -G --template '{rev} {desc}\n'
   o  7 Added tag foo-bar for changeset fc281d8ff18d
   |
   o    6 merge 5 and 4
@@ -2078,7 +2077,7 @@
 
 A template without trailing newline should do something sane
 
-  $ hg glog -r ::2 --template '{rev} {desc}'
+  $ hg log -G -r ::2 --template '{rev} {desc}'
   o  2 mv b dir/b
   |
   o  1 copy a b
@@ -2088,7 +2087,7 @@
 
 Extra newlines must be preserved
 
-  $ hg glog -r ::2 --template '\n{rev} {desc}\n\n'
+  $ hg log -G -r ::2 --template '\n{rev} {desc}\n\n'
   o
   |  2 mv b dir/b
   |
@@ -2101,7 +2100,7 @@
 
 The almost-empty template should do something sane too ...
 
-  $ hg glog -r ::2 --template '\n'
+  $ hg log -G -r ::2 --template '\n'
   o
   |
   o
@@ -2111,12 +2110,12 @@
 
 issue3772
 
-  $ hg glog -r :null
+  $ hg log -G -r :null
   o  changeset:   -1:000000000000
      user:
      date:        Thu Jan 01 00:00:00 1970 +0000
   
-  $ hg glog -r null:null
+  $ hg log -G -r null:null
   o  changeset:   -1:000000000000
      user:
      date:        Thu Jan 01 00:00:00 1970 +0000
--- a/tests/test-gpg.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-gpg.t	Tue Jan 21 14:44:01 2014 -0600
@@ -31,4 +31,7 @@
   $ "$TESTDIR/md5sum.py" "$TESTDIR/gpg/trustdb.gpg"
   f6b9c78c65fa9536e7512bb2ceb338ae  */gpg/trustdb.gpg (glob)
 
+don't leak any state to next test run
+  $ rm -f "$TESTDIR/gpg/random_seed"
+
   $ cd ..
--- a/tests/test-graft.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-graft.t	Tue Jan 21 14:44:01 2014 -0600
@@ -25,7 +25,7 @@
   $ hg phase --public 3
   $ hg phase --force --secret 6
 
-  $ hg --config extensions.graphlog= log -G --template '{author}@{rev}.{phase}: {desc}\n'
+  $ hg log -G --template '{author}@{rev}.{phase}: {desc}\n'
   @    test@6.secret: 6
   |\
   | o  test@5.draft: 5
@@ -249,7 +249,7 @@
 
 View graph:
 
-  $ hg --config extensions.graphlog= log -G --template '{author}@{rev}.{phase}: {desc}\n'
+  $ hg log -G --template '{author}@{rev}.{phase}: {desc}\n'
   @  test@11.draft: 3
   |
   o  test@10.draft: 4
--- a/tests/test-hardlinks.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-hardlinks.t	Tue Jan 21 14:44:01 2014 -0600
@@ -196,7 +196,7 @@
   $ nlinksdir r4
   2 r4/.hg/00changelog.i
   2 r4/.hg/branch
-  2 r4/.hg/cache/branchheads-served
+  2 r4/.hg/cache/branch2-served
   2 r4/.hg/dirstate
   2 r4/.hg/hgrc
   2 r4/.hg/last-message.txt
@@ -226,7 +226,7 @@
   $ nlinksdir r4
   2 r4/.hg/00changelog.i
   1 r4/.hg/branch
-  2 r4/.hg/cache/branchheads-served
+  2 r4/.hg/cache/branch2-served
   1 r4/.hg/dirstate
   2 r4/.hg/hgrc
   2 r4/.hg/last-message.txt
--- a/tests/test-help.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-help.t	Tue Jan 21 14:44:01 2014 -0600
@@ -341,7 +341,7 @@
   Mercurial Distributed SCM (version *) (glob)
   (see http://mercurial.selenic.com for more information)
   
-  Copyright (C) 2005-2013 Matt Mackall and others
+  Copyright (C) 2005-2014 Matt Mackall and others
   This is free software; see the source for copying conditions. There is NO
   warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
 
@@ -723,7 +723,8 @@
   
       Any other string is treated as a bookmark, tag, or branch name. A bookmark
       is a movable pointer to a revision. A tag is a permanent name associated
-      with a revision. A branch name denotes the tipmost revision of that
+      with a revision. A branch name denotes the tipmost open branch head of
+      that branch - or if they are all closed, the tipmost closed head of the
       branch. Bookmark, tag, and branch names must not contain the ":"
       character.
   
@@ -1878,9 +1879,9 @@
   <p>
   Any other string is treated as a bookmark, tag, or branch name. A
   bookmark is a movable pointer to a revision. A tag is a permanent name
-  associated with a revision. A branch name denotes the tipmost revision
-  of that branch. Bookmark, tag, and branch names must not contain the &quot;:&quot;
-  character.
+  associated with a revision. A branch name denotes the tipmost open branch head
+  of that branch - or if they are all closed, the tipmost closed head of the
+  branch. Bookmark, tag, and branch names must not contain the &quot;:&quot; character.
   </p>
   <p>
   The reserved name &quot;tip&quot; always identifies the most recent revision.
--- a/tests/test-hgrc.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-hgrc.t	Tue Jan 21 14:44:01 2014 -0600
@@ -58,7 +58,7 @@
   Mercurial Distributed SCM (version *) (glob)
   (see http://mercurial.selenic.com for more information)
   
-  Copyright (C) 2005-2013 Matt Mackall and others
+  Copyright (C) 2005-2014 Matt Mackall and others
   This is free software; see the source for copying conditions. There is NO
   warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
   $ unset FAKEPATH
--- a/tests/test-hgweb-commands.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-hgweb-commands.t	Tue Jan 21 14:44:01 2014 -0600
@@ -1196,6 +1196,17 @@
   | <a href="/graph/2ef0ac749a14?style=gitweb">(0)</a> <a href="/graph/tip?style=gitweb">tip</a> 
   </div>
   
+  <script type="text/javascript">
+      ajaxScrollInit(
+              '/graph/3?revcount=%next%&style=gitweb',
+              60+60,
+              function (htmlText, previousVal) { return previousVal + 60; },
+              '#wrapper',
+              '<div class="%class%" style="text-align: center;">%text%</div>',
+              'graph'
+      );
+  </script>
+  
   <script type="text/javascript">process_dates()</script>
   <div class="page_footer">
   <div class="page_footer_text">test</div>
--- a/tests/test-hgweb-empty.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-hgweb-empty.t	Tue Jan 21 14:44:01 2014 -0600
@@ -361,7 +361,7 @@
   
   <script type="text/javascript">
       ajaxScrollInit(
-              '/graph/-1?revcount=%next%',
+              '/graph/-1?revcount=%next%&style=paper',
               60+60,
               function (htmlText, previousVal) { return previousVal + 60; },
               '#wrapper',
--- a/tests/test-hgweb-filelog.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-hgweb-filelog.t	Tue Jan 21 14:44:01 2014 -0600
@@ -604,7 +604,7 @@
   $ ("$TESTDIR/get-with-headers.py" localhost:$HGPORT 'log/tip/c?style=spartan')
   200 Script output follows
   
-  <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+  <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
   <html>
   <head>
   <link rel="icon" href="/static/hgicon.png" type="image/png">
--- a/tests/test-hgweb.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-hgweb.t	Tue Jan 21 14:44:01 2014 -0600
@@ -314,7 +314,7 @@
 
   $ "$TESTDIR/get-with-headers.py" --twice localhost:$HGPORT 'static/style-gitweb.css' - date etag server
   200 Script output follows
-  content-length: 4607
+  content-length: 5262
   content-type: text/css
   
   body { font-family: sans-serif; font-size: 12px; border:solid #d9d8d1; border-width:1px; margin:10px; }
@@ -486,6 +486,30 @@
   .block {
       border-top: 1px solid #d9d8d1;
   }
+  
+  .scroll-loading {
+    -webkit-animation: change_color 1s linear 0s infinite alternate;
+    -moz-animation: change_color 1s linear 0s infinite alternate;
+    -o-animation: change_color 1s linear 0s infinite alternate;
+    animation: change_color 1s linear 0s infinite alternate;
+  }
+  
+  @-webkit-keyframes change_color {
+    from { background-color: #A0CEFF; } to {  }
+  }
+  @-moz-keyframes change_color {
+    from { background-color: #A0CEFF; } to {  }
+  }
+  @-o-keyframes change_color {
+    from { background-color: #A0CEFF; } to {  }
+  }
+  @keyframes change_color {
+    from { background-color: #A0CEFF; } to {  }
+  }
+  
+  .scroll-loading-error {
+      background-color: #FFCCCC !important;
+  }
   304 Not Modified
   
 
--- a/tests/test-histedit-bookmark-motion.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-histedit-bookmark-motion.t	Tue Jan 21 14:44:01 2014 -0600
@@ -2,7 +2,6 @@
 
   $ cat >> $HGRCPATH <<EOF
   > [extensions]
-  > graphlog=
   > histedit=
   > EOF
 
--- a/tests/test-histedit-commute.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-histedit-commute.t	Tue Jan 21 14:44:01 2014 -0600
@@ -2,7 +2,6 @@
 
   $ cat >> $HGRCPATH <<EOF
   > [extensions]
-  > graphlog=
   > histedit=
   > EOF
 
--- a/tests/test-histedit-drop.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-histedit-drop.t	Tue Jan 21 14:44:01 2014 -0600
@@ -2,7 +2,6 @@
 
   $ cat >> $HGRCPATH <<EOF
   > [extensions]
-  > graphlog=
   > histedit=
   > EOF
 
--- a/tests/test-histedit-edit.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-histedit-edit.t	Tue Jan 21 14:44:01 2014 -0600
@@ -2,7 +2,6 @@
 
   $ cat >> $HGRCPATH <<EOF
   > [extensions]
-  > graphlog=
   > histedit=
   > EOF
 
--- a/tests/test-histedit-fold-non-commute.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-histedit-fold-non-commute.t	Tue Jan 21 14:44:01 2014 -0600
@@ -2,7 +2,6 @@
 
   $ cat >> $HGRCPATH <<EOF
   > [extensions]
-  > graphlog=
   > histedit=
   > EOF
 
--- a/tests/test-histedit-fold.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-histedit-fold.t	Tue Jan 21 14:44:01 2014 -0600
@@ -14,7 +14,6 @@
   > [alias]
   > logt = log --template '{rev}:{node|short} {desc|firstline}\n'
   > [extensions]
-  > graphlog=
   > histedit=
   > EOF
 
--- a/tests/test-histedit-no-change.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-histedit-no-change.t	Tue Jan 21 14:44:01 2014 -0600
@@ -5,7 +5,6 @@
 
   $ cat >> $HGRCPATH <<EOF
   > [extensions]
-  > graphlog=
   > histedit=
   > EOF
 
@@ -64,7 +63,7 @@
   > {
   >     comment="${1:-log}"
   >     echo % "${comment}"
-  >     hg glog --template '{rev} {node} \"{desc|firstline}\"\n'
+  >     hg log -G --template '{rev} {node} \"{desc|firstline}\"\n'
   > }
 
 
--- a/tests/test-histedit-non-commute-abort.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-histedit-non-commute-abort.t	Tue Jan 21 14:44:01 2014 -0600
@@ -2,7 +2,6 @@
 
   $ cat >> $HGRCPATH <<EOF
   > [extensions]
-  > graphlog=
   > histedit=
   > EOF
 
--- a/tests/test-histedit-non-commute.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-histedit-non-commute.t	Tue Jan 21 14:44:01 2014 -0600
@@ -2,7 +2,6 @@
 
   $ cat >> $HGRCPATH <<EOF
   > [extensions]
-  > graphlog=
   > histedit=
   > EOF
 
--- a/tests/test-histedit-outgoing.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-histedit-outgoing.t	Tue Jan 21 14:44:01 2014 -0600
@@ -1,6 +1,5 @@
   $ cat >> $HGRCPATH <<EOF
   > [extensions]
-  > graphlog=
   > histedit=
   > EOF
 
--- a/tests/test-http.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-http.t	Tue Jan 21 14:44:01 2014 -0600
@@ -156,12 +156,24 @@
   >    --config server.preferuncompressed=True
   $ cat pid >> $DAEMON_PIDS
 
+  $ cat << EOF > get_pass.py
+  > import getpass
+  > def newgetpass(arg):
+  >   return "pass"
+  > getpass.getpass = newgetpass
+  > EOF
+
   $ hg id http://localhost:$HGPORT2/
-  abort: http authorization required
+  abort: http authorization required for http://localhost:$HGPORT2/
   [255]
-  $ hg id http://user@localhost:$HGPORT2/
-  abort: http authorization required
+  $ hg id http://localhost:$HGPORT2/
+  abort: http authorization required for http://localhost:$HGPORT2/
   [255]
+  $ hg id --config ui.interactive=true --config extensions.getpass=get_pass.py http://user@localhost:$HGPORT2/
+  http authorization required for http://localhost:$HGPORT2/
+  realm: mercurial
+  user: user
+  password: 5fed3813f7f5
   $ hg id http://user:pass@localhost:$HGPORT2/
   5fed3813f7f5
   $ echo '[auth]' >> .hg/hgrc
@@ -183,7 +195,7 @@
   5 files updated, 0 files merged, 0 files removed, 0 files unresolved
 
   $ hg id http://user2@localhost:$HGPORT2/
-  abort: http authorization required
+  abort: http authorization required for http://localhost:$HGPORT2/
   [255]
   $ hg id http://user:pass2@localhost:$HGPORT2/
   abort: HTTP Error 403: no
--- a/tests/test-impexp-branch.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-impexp-branch.t	Tue Jan 21 14:44:01 2014 -0600
@@ -1,5 +1,5 @@
   $ echo '[extensions]' >> $HGRCPATH
-  $ echo 'mq =' >> $HGRCPATH
+  $ echo 'strip =' >> $HGRCPATH
 
   $ cat >findbranch.py <<EOF
   > import re, sys
--- a/tests/test-import-bypass.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-import-bypass.t	Tue Jan 21 14:44:01 2014 -0600
@@ -1,9 +1,8 @@
   $ echo "[extensions]" >> $HGRCPATH
   $ echo "purge=" >> $HGRCPATH
-  $ echo "graphlog=" >> $HGRCPATH
 
   $ shortlog() {
-  >     hg glog --template '{rev}:{node|short} {author} {date|hgdate} - {branch} - {desc|firstline}\n'
+  >     hg log -G --template '{rev}:{node|short} {author} {date|hgdate} - {branch} - {desc|firstline}\n'
   > }
 
 Test --bypass with other options
--- a/tests/test-import-git.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-import-git.t	Tue Jan 21 14:44:01 2014 -0600
@@ -320,6 +320,118 @@
   045c85ba38952325e126c70962cc0f9d9077bc67 644   mbinary1
   a874b471193996e7cb034bb301cac7bdaf3e3f46 644   mbinary2
 
+Binary file and delta hunk (we build the patch using this sed hack to
+avoid an unquoted ^, which check-code says breaks sh on solaris):
+
+  $ sed 's/ caret /^/g;s/ dollarparen /$(/g' > quote-hack.patch <<'EOF'
+  > diff --git a/delta b/delta
+  > new file mode 100644
+  > index 0000000000000000000000000000000000000000..8c9b7831b231c2600843e303e66b521353a200b3
+  > GIT binary patch
+  > literal 3749
+  > zcmV;W4qEYvP)<h;3K|Lk000e1NJLTq006iE002D*0ssI2kt{U(0000PbVXQnQ*UN;
+  > zcVTj606}DLVr3vnZDD6+Qe|Oed2z{QJOBU=M@d9MRCwC#oC!>o#}>x{(W-y~UN*tK
+  > z%A%sxiUy2Ys)0Vm#ueArYKoYqX;GuiqZpgirM6nCVoYk?YNAz3G~z;BZ~@~&OQEe4
+  > zmGvS5isFJI;Pd_7J+EKxyHZeu` caret t4r2>F;h-+VK3{_{WoGv8dSpFDYDrA%3UX03pt
+  > zOaVoi0*W#P6lDr1$`nwPDWE7*rhuYM0Y#YtiZTThWeO<D6i}2YpqR<%$s>bRRaI42
+  > zS3iFIxJ8Q=EnBv1Z7?pBw_bLjJb3V+tgP(Tty_2R-mR#p04x78n2n7MSOFyt4i1iv
+  > zjxH`PPEJmgD7U?IK&h;(EGQ@_DJc<@01=4fiNXHcKZ8LhZQ8T}E3U4tUS3}OrcgQW
+  > zWdX{K8#l7Ev&#$ysR)G#0*rC+<WGZ3?CtG4bm-ve>Dj$|_qJ`@D*stNP_AFUe&x!Q
+  > zJ9q9B7Z=ym)MyZ?Tg1ROunUYr81nV?B@!tYS~5_|%gfW#(_s<4UN1!Q?Dv8d>g#m6
+  > z%*@R2@bI2JdnzxQ!EDU`$eQY!tgI~Zn$prz;gaXNod5*5p(1Bz=P$qfvZ$y?dC@X~
+  > zlAD+NAKhB{=;6bMwzjqn>9mavvKOGd`s%A+fBiL>Q;xJWpa72C+}u{JTHUX>{~}Qj
+  > zUb%hyHgN~c?cBLjInvUALMD9g-aXt54ZL8AOCvXL-V6!~ijR*kEG$&Mv?!pE61OlI
+  > z8nzMSPE8F7bH|Py*RNl1VUCggq<V)>@_6gkEeiz7{rmTeuNTW6+KVS#0FG%IHf-3L
+  > zGiS21vn>WCCr+GLx caret !uNetzB6u3o(w6&1C2?_LW8ij$+$sZ*zZ`|US3H@8N~%&V%Z
+  > zAeA0HdhFS=$6|nzn3%YH`SN<>DQRO;Qc caret )dfdvA caret 5u`Xf;Zzu<ZQHgG?28V-#s<;T
+  > zzkh#LA)v7gpoE5ou3o*GoUUF%b#iht&kl9d0)><$FE1}ACr68;uCA`6DrGmz_U+rp
+  > zL>Rx;X_yhk$fP_yJrTCQ|NgsW0A<985g&c@k-NKly<>mgU8n||ZPPV<`SN8#%$+-T
+  > zfP$T!ou8jypFVwnzqhxyUvIxXd-wF~*U!ht=hCH1wzjqn9x#)IrhDa;S0JbK caret z_$W
+  > zd(8rX@;7|t*;GJ5h$SZ{v(}+UBEs$4w~?{@9%`_Z<P<kox5bMWuUWH(sF9hONgd$Q
+  > zunCgwT@1|CU9+;X caret 4z&|M~@yw23Ay50NFWn=FqF%yLZEUty;AT2??1oV@B)Nt))J7
+  > zh>{5j2@f7T=-an%L_`E)h;mZ4D_5>?7tjQtVPRo2XU-&;mX(!l-MSTJP4XWY82JAC
+  > z@57+y&!1=P{Mn{W8)-HzEsgAtd63}Cazc>O6vGb>51%@9DzbyI3?4j~$ijmT95_IS
+  > zS#r!LCDW%*4-O7CGnkr$xXR1RQ&UrA<CQt} caret 73NL%zk`)Jk!yxUAt-1r}ggLn-Zq}
+  > z*s){8pw68;i+kiG%CpBKYSJLLFyq&*U8}qDp+kpe&6<Vp(Z58%l#~>ZK?&s7y?b}i
+  > zuwcOgO%x-27A;y785zknl_{sU;E6v$8{pWmVS{KaJPpu`i;HP$#flY@u~Ua~K3%tN
+  > z-LhrNh{9SoHgDd%WXTc$$~Dq{?AWou3!H&?V8K{ caret {P9Ot5vecD?%1&-E-ntBFj87(
+  > zy5`QE%QRX7qcHC%1{Ua}M~}L6=`wQUNEQ=I;qc+ZMMXtK2T+0os;jEco;}OV9z1w3
+  > zARqv caret bm-85xnRCng3OT|MyVSmR3ND7 caret ?KaQGG! caret (aTbo1N;Nz;X3Q9FJbwK6`0?Yp
+  > zj*X2ac;Pw3!I2|JShDaF>-gJmzm1NLj){rk&o|$E caret WAsfrK=x&@B!`w7Hik81sPz4
+  > zuJTaiCppM>-+c!wPzcUw)5@?J4U-u|pJ~xbWUe-C+60k caret 7>9!)56DbjmA~`OJJ40v
+  > zu3hCA7eJXZWeN|1iJLu87$;+fS8+Kq6O`aT)*_x@sY#t7LxwoEcVw*)cWhhQW@l%!
+  > z{#Z=y+qcK@%z{p*D=8_Fcg278AnH3fI5;~yGu?9TscxXaaP*4$f<LIv! caret 5Lfr%vKg
+  > zpxmunH#%=+ICMvZA~wyNH%~eMl!-g caret R!cYJ#WmLq5N8viz#J%%LPtkO?V)tZ81cp>
+  > z{ALK?fNPePmd;289&M8Q3>YwgZX5GcGY&n>K1<x)!`;Qjg&}bb!Lrnl@xH#kS~VYE
+  > zpJmIJO`A3iy+Y3X`k>cY-@}Iw2Onq`=!ba3eATgs3yg3Wej=+P-Z8WF#w=RXvS@J3
+  > zEyhVTj-gO?kfDu1g9afo<RkPrYzG#_yF41IFxF%Ylg>9lx6<clPweR-b7Hn+r)e1l
+  > zO6c6FbNt@;;*w$z;N|H>h{czme)_4V6UC4hv**kX2@L caret Bgds dollarparen &P7M4dhfmWe)!=B
+  > zR3X=Y{P9N}p@-##@1ZNW1YbVaiP~D@8m&<dzEP&cO|87Ju#j*=;wH~Exr>i*Hpp&@
+  > z`9!Sj+O;byD~s8qZ>6QB8uv7Bpn&&?xe;;e<M4F8KEID&pT7QmqoSgq&06adp5T=U
+  > z6DH*4=AB7C1D9Amu?ia-wtxSAlmTEO96XHx)-+rKP;ip$pukuSJGW3P1aUmc2yo%)
+  > z&<t3F>d1X+1qzaag-%x+eKHx{?Afz3GBQSw9u0lw<mB+I#v11TKRpKWQS+lvVL7=u
+  > zHr6)1ynEF<i3kO6A8&ppPMo-F=PnWfXkSj@i*7J6C<F}wR?s(O0niC?t+6;+k}pPq
+  > zrok&TPU40rL0ZYDwenNrrmPZ`gjo@DEF`7 caret cKP||pUr;+r)hyn9O37=xA`3%Bj-ih
+  > z+1usk<%5G-y+R?tA`qY=)6&vNjL{P?QzHg%P%>`ZxP=QB%DHY6L26?36V_p caret {}n$q
+  > z3@9W=KmGI*Ng_Q#AzA%-z|Z caret |#oW(hkfgpuS$RKRhlrarX%efMMCs}GLChec5+y{6
+  > z1Qnxim_C-fmQuaAK_NUHUBV&;1c0V)wji<RcdZ*aAWTwyt>hVnlt caret asFCe0&a@tqp
+  > zEEy;$L}D$X6)wfQNl8gu6Z>oB3_RrP=gTyK2@@w#LbQfLNHj>Q&z(C5wUFhK+}0aV
+  > zSohlc=7K+spN<ctf}5KgKqNyJDNP9;LZd)nTE=9|6Xdr9%Hzk63-tL2c9FD*rsyYY
+  > z!}t+Yljq7-p$X;4_YL?6d;mdY3R##o1e%rlPxrsMh8|;sKTr~ caret QD#sw3&vS$FwlTk
+  > zp1#Gw!Qo-$LtvpXt#ApV0g) caret F=qFB`VB!W297x=$mr<$>rco3v$QKih_xN!k6;M=@
+  > zCr?gDNQj7tm@;JwD;Ty&NlBSCYZk(b3dZeN8D4h2{r20dSFc7;(>E&r`s=TVtzpB4
+  > zk+ caret N&zCAiRns(?p6iBlk9v&h{1ve(FNtc)td51M>)TkXhc6{>5C)`fS$&)A1*CP1%
+  > zld+peue4aYbg3C0!+4mu+}vE caret j_feX+ZijvffBI7Ofh#RZ*U3<3J5(+nfRCzexqQ5
+  > zgM&##Y4Dd{e%ZKjqrbm@|Ni}l4jo!AqtFynj3Xsd$o caret ?yV4$|UQ(j&UWCH>M=o_&N
+  > zmclXc3i|Q#<;#EoG>~V}4unTHbUK}u=y4;rA3S&vzC3 caret aJP!&D4RvvGfoyo(>C>la
+  > zijP<=v>X{3Ne&2BXo}DV8l0V-jdv`$am0ubG{Wuh%CTd|l9Q7m;G&|U@#Dvbhlj(d
+  > zg6W{3ATxYt#T?)3;SmIgOP4M|Dki~I_TX7SxP0x}wI~DQI7Lhm2BI7gph(aPIFAd;
+  > zQ&UsF`Q{rOz+z=87c5v%@5u~d6dWV5OlX`oH3cAH&UlvsZUEo(Q(P|lKs17rXvaiU
+  > zQcj}IEufi1+Bnh6&(EhF{7O3vLHp`jjlp0J<M1kh$+$2xGm~Zk7OY7(q=&Rdhq*RG
+  > zwrmcd5MnP}xByB_)P@{J>DR9x6;`cUwPM8z){yooNiXPOc9_{W-gtwxE5TUg0vJk6
+  > zO#JGruV&1cL6VGK2?+_YQr4`+EY8;Sm$9U$uuGRN=uj3k7?O9b+R~J7t_y*K64ZnI
+  > zM+{aE<b(v?vSmw;9zFP!aE266zHIhlmdI@ caret xa6o2jwdRk54a$>pcRbC29ZyG!Cfdp
+  > zutFf`Q`vljgo!(wHf=)F#m2_MIuj;L(2ja2YsQRX+rswV{d<H`Ar;(@%aNa9VPU8Z
+  > z;tq*`y}dm#NDJHKlV}uTIm!_vAq5E7!X-p{P=Z=Sh668>PuVS1*6e}OwOiMc;u3OQ
+  > z@Bs)w3=lzfKoufH$SFuPG@uZ4NOnM#+=8LnQ2Q4zUd+nM+OT26;lqbN{P07dhH{jH
+  > zManE8 caret dLms-Q2;1kB<*Q1a3f8kZr;xX=!Qro@`~@xN*Qj>gx;i;0Z24!~i2uLb`}v
+  > zA?R$|wvC+m caret Ups=*(4lDh*=UN8{5h(A?p#D caret 2N$8u4Z55!q?ZAh(iEEng9_Zi>IgO
+  > z#~**JC8hE4@n{hO&8btT5F*?nC_%LhA3i)PDhh-pB_&1wGrDIl caret *=8x3n&;akBf caret -
+  > zJd&86kq$%%907v caret tgWoQdwI`|oNK%VvU~S#C<o caret F?6c48?Cjj#-4P<>HFD%&|Ni~t
+  > zKJ(|#H`$<5W+6ZkBb213rXonKZLB+X> caret L}J@W6osP3piLD_5?R!`S}*{xLBzFiL4@
+  > zX+}l{`A%?f@T5tT%ztu60p;)be`fWC`tP@WpO=?cpf8Xuf1OSj6d3f@Ki(ovDYq%0
+  > z{4ZSe`kOay5@=lAT!}vFzxyemC{sXDrhuYM0Y#ZI1r%ipD9W11{w=@&xgJ}t2x;ep
+  > P00000NkvXXu0mjfZ5|Er
+  > 
+  > literal 0
+  > HcmV?d00001
+  > 
+  > EOF
+  $ hg import -d "1000000 0" -m delta quote-hack.patch
+  applying quote-hack.patch
+  $ rm quote-hack.patch
+
+  $ hg manifest --debug | grep delta
+  9600f98bb60ce732634d126aaa4ac1ec959c573e 644   delta
+
+  $ hg import -d "1000000 0" -m delta - <<'EOF'
+  > diff --git a/delta b/delta
+  > index 8c9b7831b231c2600843e303e66b521353a200b3..0021dd95bc0dba53c39ce81377126d43731d68df 100644
+  > GIT binary patch
+  > delta 49
+  > zcmZ1~yHs|=21Z8J$r~9bFdA-lVv=EEw4WT$qRf2QSa5SIOAHI6(&k4T8H|kLo4vWB
+  > FSO9ZT4bA`n
+  > 
+  > delta 49
+  > zcmV-10M7rV9i<(xumJ(}ld%Di0Xefm0vrMXpOaq%BLm9I%d>?9Tm%6Vv*HM70RcC&
+  > HOA1;9yU-AD
+  > 
+  > EOF
+  applying patch from stdin
+
+  $ hg manifest --debug | grep delta
+  56094bbea136dcf8dbd4088f6af469bde1a98b75 644   delta
+
 Filenames with spaces:
 
   $ sed 's,EOL$,,g' <<EOF | hg import -d "1000000 0" -m spaces -
@@ -334,7 +446,7 @@
   applying patch from stdin
 
   $ hg tip -q
-  12:47500ce1614e
+  14:4b79479c9a6d
 
   $ cat "foo bar"
   foo
@@ -357,7 +469,7 @@
   applying patch from stdin
 
   $ hg tip -q
-  13:6757efb07ea9
+  15:9cbe44af4ae9
 
   $ cat foo3
   foo
@@ -392,8 +504,8 @@
 Invalid base85 content
 
   $ hg rollback
-  repository tip rolled back to revision 14 (undo import)
-  working directory now based on revision 14
+  repository tip rolled back to revision 16 (undo import)
+  working directory now based on revision 16
   $ hg revert -aq
   $ hg import -d "1000000 0" -m invalid-binary - <<"EOF"
   > diff --git a/text2 b/binary2
--- a/tests/test-import-merge.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-import-merge.t	Tue Jan 21 14:44:01 2014 -0600
@@ -130,7 +130,7 @@
   $ hg ci -m3
   $ hg export 2 | head -7 > ../a.patch
   $ hg export tip > out
-  >>> apatch = open("../a.patch", "a")
+  >>> apatch = open("../a.patch", "ab")
   >>> apatch.write("".join(open("out").readlines()[7:]))
 
   $ cd ..
--- a/tests/test-inherit-mode.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-inherit-mode.t	Tue Jan 21 14:44:01 2014 -0600
@@ -66,7 +66,7 @@
   00700 ./.hg/
   00600 ./.hg/00changelog.i
   00770 ./.hg/cache/
-  00660 ./.hg/cache/branchheads-served
+  00660 ./.hg/cache/branch2-served
   00660 ./.hg/dirstate
   00660 ./.hg/last-message.txt
   00600 ./.hg/requires
@@ -111,7 +111,7 @@
   00770 ../push/.hg/
   00660 ../push/.hg/00changelog.i
   00770 ../push/.hg/cache/
-  00660 ../push/.hg/cache/branchheads-base
+  00660 ../push/.hg/cache/branch2-base
   00660 ../push/.hg/requires
   00770 ../push/.hg/store/
   00660 ../push/.hg/store/00changelog.i
--- a/tests/test-init.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-init.t	Tue Jan 21 14:44:01 2014 -0600
@@ -26,6 +26,31 @@
   $ hg ci --cwd local -A -m "init"
   adding foo
 
+test custom revlog chunk cache sizes
+
+  $ hg --config format.chunkcachesize=0 log -R local -pv
+  abort: revlog chunk cache size 0 is not greater than 0!
+  [255]
+  $ hg --config format.chunkcachesize=1023 log -R local -pv
+  abort: revlog chunk cache size 1023 is not a power of 2!
+  [255]
+  $ hg --config format.chunkcachesize=1024 log -R local -pv
+  changeset:   0:08b9e9f63b32
+  tag:         tip
+  user:        test
+  date:        Thu Jan 01 00:00:00 1970 +0000
+  files:       foo
+  description:
+  init
+  
+  
+  diff -r 000000000000 -r 08b9e9f63b32 foo
+  --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+  +++ b/foo	Thu Jan 01 00:00:00 1970 +0000
+  @@ -0,0 +1,1 @@
+  +this
+  
+
 creating repo with format.usestore=false
 
   $ hg --config format.usestore=false init old
--- a/tests/test-journal-exists.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-journal-exists.t	Tue Jan 21 14:44:01 2014 -0600
@@ -22,7 +22,7 @@
 
 Check that zero-size journals are correctly aborted:
 
-#if unix-permissions
+#if unix-permissions no-root
   $ hg bundle -qa repo.hg
   $ chmod -w foo/.hg/store/00changelog.i
 
--- a/tests/test-largefiles.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-largefiles.t	Tue Jan 21 14:44:01 2014 -0600
@@ -977,7 +977,7 @@
   M sub2/large6
   saved backup bundle to $TESTTMP/d/.hg/strip-backup/f574fb32bb45-backup.hg (glob)
   0 largefiles cached
-  nothing to rebase
+  nothing to rebase - working directory parent is also destination
   $ [ -f .hg/largefiles/e166e74c7303192238d60af5a9c4ce9bef0b7928 ]
   $ hg log --template '{rev}:{node|short}  {desc|firstline}\n'
   9:598410d3eb9a  modify normal file largefile in repo d
@@ -1374,9 +1374,10 @@
   (run 'hg heads' to see heads, 'hg merge' to merge)
   2 largefiles cached
   $ hg merge
-  merging sub/large4
   largefile sub/large4 has a merge conflict
-  keep (l)ocal or take (o)ther? l
+  ancestor was 971fb41e78fea4f8e0ba5244784239371cb00591
+  keep (l)ocal d846f26643bfa8ec210be40cc93cc6b7ff1128ea or
+  take (o)ther e166e74c7303192238d60af5a9c4ce9bef0b7928? l
   3 files updated, 1 files merged, 0 files removed, 0 files unresolved
   (branch merge, don't forget to commit)
   getting changed largefiles
@@ -2256,7 +2257,7 @@
   > largefiles=
   > EOF
   $ hg -R enabledlocally root
-  $TESTTMP/individualenabling/enabledlocally
+  $TESTTMP/individualenabling/enabledlocally (glob)
   $ hg -R notenabledlocally root
   abort: unknown repository format: requires features 'largefiles' (upgrade Mercurial)!
   [255]
--- a/tests/test-lfconvert.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-lfconvert.t	Tue Jan 21 14:44:01 2014 -0600
@@ -4,8 +4,7 @@
   > [extensions]
   > largefiles =
   > share =
-  > graphlog =
-  > mq =
+  > strip =
   > convert =
   > [largefiles]
   > minsize = 0.5
@@ -134,7 +133,7 @@
   $ hg cat -r . sub/maybelarge.dat > stuff/maybelarge.dat
   $ hg resolve -m stuff/maybelarge.dat
   $ hg commit -m"merge"
-  $ hg glog --template "{rev}:{node|short}  {desc|firstline}\n"
+  $ hg log -G --template "{rev}:{node|short}  {desc|firstline}\n"
   @    5:4884f215abda  merge
   |\
   | o  4:7285f817b77e  remove large, normal3
@@ -154,7 +153,7 @@
   $ hg lfconvert --size 0.2 bigfile-repo largefiles-repo
   initializing destination largefiles-repo
   $ cd largefiles-repo
-  $ hg glog --template "{rev}:{node|short}  {desc|firstline}\n"
+  $ hg log -G --template "{rev}:{node|short}  {desc|firstline}\n"
   o    5:8e05f5f2b77e  merge
   |\
   | o  4:a5a02de7a8e4  remove large, normal3
@@ -248,7 +247,7 @@
 # "hg remove" + "hg merge" + "hg commit".
 #  $ hg -R ../bigfile-repo debugdata -c 5
 #  $ hg debugdata -c 5
-  $ hg glog --template "{rev}:{node|short}  {desc|firstline}\n"
+  $ hg log -G --template "{rev}:{node|short}  {desc|firstline}\n"
   o  6:1635824e6f59  add anotherlarge (should be a largefile)
   |
   o    5:7215f8deeaaf  merge
@@ -292,7 +291,7 @@
   1 merge
   0 add anotherlarge (should be a largefile)
 
-  $ hg -R largefiles-repo-hg glog --template "{rev}:{node|short}  {desc|firstline}\n"
+  $ hg -R largefiles-repo-hg log -G --template "{rev}:{node|short}  {desc|firstline}\n"
   o  6:17126745edfd  add anotherlarge (should be a largefile)
   |
   o    5:9cc5aa7204f0  merge
--- a/tests/test-lock-badness.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-lock-badness.t	Tue Jan 21 14:44:01 2014 -0600
@@ -1,5 +1,4 @@
-  $ "$TESTDIR/hghave" unix-permissions || exit 80
-
+#if unix-permissions no-root
   $ hg init a
   $ echo a > a/a
   $ hg -R a ci -A -m a
@@ -21,4 +20,4 @@
   [255]
 
   $ chmod 700 a/.hg/store
-
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-module-imports.t	Tue Jan 21 14:44:01 2014 -0600
@@ -0,0 +1,39 @@
+This code uses the ast module, which was new in 2.6, so we'll skip
+this test on anything earlier.
+  $ python -c 'import sys ; assert sys.version_info >= (2, 6)' || exit 80
+
+  $ import_checker="$TESTDIR"/../contrib/import-checker.py
+Run the doctests from the import checker, and make sure
+it's working correctly.
+  $ TERM=dumb
+  $ export TERM
+  $ python -m doctest $import_checker
+
+  $ cd "$TESTDIR"/..
+  $ if hg identify -q > /dev/null 2>&1; then :
+  > else
+  >     echo "skipped: not a Mercurial working dir" >&2
+  >     exit 80
+  > fi
+
+There are a handful of cases here that require renaming a module so it
+doesn't overlap with a stdlib module name. There are also some cycles
+here that we should still endeavor to fix, and some cycles will be
+hidden by deduplication algorithm in the cycle detector, so fixing
+these may expose other cycles.
+
+  $ hg locate 'mercurial/**.py' | xargs python "$import_checker"
+  mercurial/dispatch.py mixed stdlib and relative imports:
+     commands, error, extensions, fancyopts, hg, hook, util
+  mercurial/fileset.py mixed stdlib and relative imports:
+     error, merge, parser, util
+  mercurial/revset.py mixed stdlib and relative imports:
+     discovery, error, hbisect, parser, phases, util
+  mercurial/templater.py mixed stdlib and relative imports:
+     config, error, parser, templatefilters, util
+  mercurial/ui.py mixed stdlib and relative imports:
+     config, error, formatter, scmutil, util
+  Import cycle: mercurial.cmdutil -> mercurial.subrepo -> mercurial.cmdutil
+  Import cycle: mercurial.repoview -> mercurial.revset -> mercurial.repoview
+  Import cycle: mercurial.fileset -> mercurial.merge -> mercurial.subrepo -> mercurial.match -> mercurial.fileset
+  Import cycle: mercurial.filemerge -> mercurial.match -> mercurial.fileset -> mercurial.merge -> mercurial.filemerge
--- a/tests/test-mq-merge.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-mq-merge.t	Tue Jan 21 14:44:01 2014 -0600
@@ -147,11 +147,13 @@
   -b
   +a
   +c
-  diff --git a/aa b/aa
-  new file mode 100644
-  --- /dev/null
+  diff --git a/a b/aa
+  copy from a
+  copy to aa
+  --- a/a
   +++ b/aa
-  @@ -0,0 +1,1 @@
+  @@ -1,1 +1,1 @@
+  -b
   +a
 
 Check patcha2 is still a regular patch:
--- a/tests/test-mq-qpush-exact.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-mq-qpush-exact.t	Tue Jan 21 14:44:01 2014 -0600
@@ -1,6 +1,5 @@
   $ echo "[extensions]" >> $HGRCPATH
   $ echo "mq=" >> $HGRCPATH
-  $ echo "graphlog=" >> $HGRCPATH
 
 make a test repository that looks like this:
 
--- a/tests/test-mq-safety.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-mq-safety.t	Tue Jan 21 14:44:01 2014 -0600
@@ -1,6 +1,5 @@
   $ echo '[extensions]' >> $HGRCPATH
   $ echo 'hgext.mq =' >> $HGRCPATH
-  $ echo 'hgext.graphlog =' >> $HGRCPATH
 
   $ hg init repo
   $ cd repo
--- a/tests/test-mv-cp-st-diff.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-mv-cp-st-diff.t	Tue Jan 21 14:44:01 2014 -0600
@@ -1567,3 +1567,41 @@
   @@ -0,0 +1,1 @@
   +a
   $ cd ..
+
+
+test for case where we didn't look sufficiently far back to find rename ancestor
+
+  $ hg init diffstop
+  $ cd diffstop
+  $ echo > f
+  $ hg ci -qAmf
+  $ hg mv f g
+  $ hg ci -m'f->g'
+  $ hg up -qr0
+  $ touch x
+  $ hg ci -qAmx
+  $ echo f > f
+  $ hg ci -qmf=f
+  $ hg merge -q
+  $ hg ci -mmerge
+  $ hg log -G --template '{rev}  {desc}'
+  @    4  merge
+  |\
+  | o  3  f=f
+  | |
+  | o  2  x
+  | |
+  o |  1  f->g
+  |/
+  o  0  f
+  
+  $ hg diff --git -r 2
+  diff --git a/f b/g
+  rename from f
+  rename to g
+  --- a/f
+  +++ b/g
+  @@ -1,1 +1,1 @@
+  -
+  +f
+  $ cd ..
--- a/tests/test-newbranch.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-newbranch.t	Tue Jan 21 14:44:01 2014 -0600
@@ -1,13 +1,13 @@
-  $ branchcache=.hg/cache/branchheads
+  $ branchcache=.hg/cache/branch2
 
   $ listbranchcaches() {
-  >    for f in .hg/cache/branchheads*;
+  >    for f in .hg/cache/branch2*;
   >       do echo === $f ===;
   >       cat $f;
   >     done;
   > }
   $ purgebranchcaches() {
-  >     rm .hg/cache/branchheads*
+  >     rm .hg/cache/branch2*
   > }
 
   $ hg init t
@@ -158,13 +158,13 @@
   4:adf1a74a7f7b
 
   $ listbranchcaches
-  === .hg/cache/branchheads ===
+  === .hg/cache/branch2 ===
   corrupted
-  === .hg/cache/branchheads-served ===
+  === .hg/cache/branch2-served ===
   adf1a74a7f7b4cd193d12992f5d0d6a004ed21d6 4
-  c21617b13b220988e7a2e26290fbe4325ffa7139 bar
-  1c28f494dae69a2f8fc815059d257eccf3fcfe75 default
-  adf1a74a7f7b4cd193d12992f5d0d6a004ed21d6 foo
+  c21617b13b220988e7a2e26290fbe4325ffa7139 o bar
+  1c28f494dae69a2f8fc815059d257eccf3fcfe75 o default
+  adf1a74a7f7b4cd193d12992f5d0d6a004ed21d6 o foo
 
 Push should update the branch cache:
 
@@ -175,20 +175,20 @@
   $ hg push -qr 0 ../target
 
   $ (cd ../target/; listbranchcaches)
-  === .hg/cache/branchheads-base ===
+  === .hg/cache/branch2-base ===
   db01e8ea3388fd3c7c94e1436ea2bd6a53d581c5 0
-  db01e8ea3388fd3c7c94e1436ea2bd6a53d581c5 default
+  db01e8ea3388fd3c7c94e1436ea2bd6a53d581c5 o default
 
 Pushing everything:
 
   $ hg push -qf ../target
 
   $ (cd ../target/; listbranchcaches)
-  === .hg/cache/branchheads-base ===
+  === .hg/cache/branch2-base ===
   adf1a74a7f7b4cd193d12992f5d0d6a004ed21d6 4
-  c21617b13b220988e7a2e26290fbe4325ffa7139 bar
-  1c28f494dae69a2f8fc815059d257eccf3fcfe75 default
-  adf1a74a7f7b4cd193d12992f5d0d6a004ed21d6 foo
+  c21617b13b220988e7a2e26290fbe4325ffa7139 o bar
+  1c28f494dae69a2f8fc815059d257eccf3fcfe75 o default
+  adf1a74a7f7b4cd193d12992f5d0d6a004ed21d6 o foo
 
 Update with no arguments: tipmost revision of the current branch:
 
--- a/tests/test-obsolete-checkheads.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-obsolete-checkheads.t	Tue Jan 21 14:44:01 2014 -0600
@@ -10,9 +10,8 @@
   > [ui]
   > logtemplate='{node|short} ({phase}) {desc|firstline}\n'
   > [extensions]
-  > graphlog=
+  > obs=${TESTTMP}/obs.py
   > EOF
-  $ echo "obs=${TESTTMP}/obs.py" >> $HGRCPATH
   $ mkcommit() {
   >    echo "$1" > "$1"
   >    hg add "$1"
@@ -52,7 +51,7 @@
   $ mkcommit new
   created new head
   $ hg debugobsolete --flags 1 `getid old` `getid new`
-  $ hg glog --hidden
+  $ hg log -G --hidden
   @  71e3228bffe1 (draft) add new
   |
   | x  c70b08862e08 (draft) add old
@@ -84,7 +83,7 @@
   pulling from $TESTTMP/remote (glob)
   searching for changes
   no changes found
-  $ hg glog --hidden
+  $ hg log -G --hidden
   @  71e3228bffe1 (draft) add new
   |
   | o  c70b08862e08 (public) add old
@@ -112,7 +111,7 @@
 #   $ cp -r ../backup1 ../remote
 #   $ hg -R ../remote phase --public c70b08862e08
 #   $ hg phase --draft --force c70b08862e08
-#   $ hg glog --hidden
+#   $ hg log -G --hidden
 #   @  71e3228bffe1 (draft) add new
 #   |
 #   | x  c70b08862e08 (draft) add old
@@ -141,7 +140,7 @@
   $ hg up -q '.^'
   $ mkcommit other
   created new head
-  $ hg glog --hidden
+  $ hg log -G --hidden
   @  d7d41ccbd4de (draft) add other
   |
   | o  71e3228bffe1 (draft) add new
@@ -193,7 +192,7 @@
   $ mkcommit desc2
   created new head
   $ hg debugobsolete `getid old` `getid new`
-  $ hg glog --hidden
+  $ hg log -G --hidden
   @  5fe37041cc2b (draft) add desc2
   |
   | o  a3ef1d111c5f (draft) add desc1
@@ -204,7 +203,7 @@
   |/
   o  b4952fcf48cf (public) add base
   
-  $ hg glog --hidden -R ../remote
+  $ hg log -G --hidden -R ../remote
   o  71e3228bffe1 (draft) add new
   |
   | o  c70b08862e08 (draft) add old
@@ -248,12 +247,12 @@
   $ hg  id --debug -r tip
   71e3228bffe1886550777233d6c97bb5a6b2a650 tip
   $ hg debugobsolete c70b08862e0838ea6d7c59c85da2f1ed6c8d67da 71e3228bffe1886550777233d6c97bb5a6b2a650
-  $ hg glog --hidden
+  $ hg log -G --hidden
   @  71e3228bffe1 (draft) add new
   |
   o  b4952fcf48cf (public) add base
   
-  $ hg glog --hidden -R ../remote
+  $ hg log -G --hidden -R ../remote
   o  c70b08862e08 (draft) add old
   |
   @  b4952fcf48cf (public) add base
@@ -261,9 +260,6 @@
 
 Push should not complain about new heads.
 
-It should not complain about "unsynced remote changes!" either but that's not
-handled yet.
-
   $ hg push --traceback
   pushing to $TESTTMP/remote (glob)
   searching for changes
--- a/tests/test-obsolete.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-obsolete.t	Tue Jan 21 14:44:01 2014 -0600
@@ -1,6 +1,4 @@
   $ cat >> $HGRCPATH << EOF
-  > [extensions]
-  > graphlog=
   > [phases]
   > # public changeset are not obsolete
   > publish=false
@@ -120,7 +118,7 @@
 
 Check that graphlog detect that a changeset is obsolete:
 
-  $ hg glog
+  $ hg log -G
   @  changeset:   5:5601fb93a350
   |  tag:         tip
   |  parent:      1:7c3bad9141dc
@@ -217,7 +215,7 @@
 Check that public changeset are not accounted as obsolete:
 
   $ hg --hidden phase --public 2
-  $ hg --config 'extensions.graphlog=' glog
+  $ hg log -G
   @  changeset:   5:5601fb93a350
   |  tag:         tip
   |  parent:      1:7c3bad9141dc
@@ -514,7 +512,7 @@
 ---------------------------------------
 
 
-  $ hg glog
+  $ hg log -G
   o  changeset:   3:6f9641995072
   |  tag:         tip
   |  parent:      1:7c3bad9141dc
@@ -548,7 +546,7 @@
   date:        Thu Jan 01 00:00:00 1970 +0000
   summary:     add original_d
   
-  $ hg glog -r '::unstable()'
+  $ hg log -G -r '::unstable()'
   @  changeset:   5:cda648ca50f5
   |  tag:         tip
   |  user:        test
@@ -653,7 +651,7 @@
 
 Do not warn about new head when the new head is a successors of a remote one
 
-  $ hg glog
+  $ hg log -G
   @  changeset:   5:cda648ca50f5
   |  tag:         tip
   |  user:        test
--- a/tests/test-parseindex2.py	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-parseindex2.py	Tue Jan 21 14:44:01 2014 -0600
@@ -1,11 +1,9 @@
+"""This unit test tests parsers.parse_index2()."""
+
 from mercurial import parsers
 from mercurial.node import nullid, nullrev
 import struct
 
-# This unit test compares the return value of the original Python
-# implementation of parseindex and the new C implementation for
-# an index file with and without inlined data
-
 # original python implementation
 def gettype(q):
     return int(q & 0xFFFF)
@@ -106,6 +104,9 @@
     else:
         print "Expected to get TypeError."
 
+   # Check parsers.parse_index2() on an index file against the original
+   # Python implementation of parseindex, both with and without inlined data.
+
     py_res_1 = py_parseindex(data_inlined, True)
     c_res_1 = parse_index2(data_inlined, True)
 
--- a/tests/test-patchbomb.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-patchbomb.t	Tue Jan 21 14:44:01 2014 -0600
@@ -2127,7 +2127,7 @@
   $ hg ci -md -d '4 0'
   $ echo d >> d
   $ hg ci -mdd -d '5 0'
-  $ hg --config extensions.graphlog= glog --template "{rev}:{node|short} {desc|firstline}\n"
+  $ hg log -G --template "{rev}:{node|short} {desc|firstline}\n"
   @  10:3b6f1ec9dde9 dd
   |
   o  9:2f9fa9b998c5 d
--- a/tests/test-permissions.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-permissions.t	Tue Jan 21 14:44:01 2014 -0600
@@ -1,4 +1,4 @@
-  $ "$TESTDIR/hghave" unix-permissions || exit 80
+#ifdef unix-permissions no-root
 
   $ hg init t
   $ cd t
@@ -70,3 +70,5 @@
   $ chmod +rx dir
 
   $ cd ..
+
+#endif
--- a/tests/test-phases-exchange.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-phases-exchange.t	Tue Jan 21 14:44:01 2014 -0600
@@ -1,9 +1,5 @@
   $ "$TESTDIR/hghave" killdaemons || exit 80
 
-  $ cat >> $HGRCPATH <<EOF
-  > [extensions]
-  > graphlog=
-  > EOF
   $ hgph() { hg log -G --template "{rev} {phase} {desc} - {node|short}\n" $*; }
 
   $ mkcommit() {
@@ -399,7 +395,7 @@
 
 initial setup
 
-  $ hg glog # of alpha
+  $ hg log -G # of alpha
   o  changeset:   6:145e75495359
   |  tag:         tip
   |  user:        test
@@ -1062,7 +1058,7 @@
   |
   o  0 public a-A - 054250a37db4
   
-#if unix-permissions
+#if unix-permissions no-root
 
 Pushing From an unlockable repo
 --------------------------------
--- a/tests/test-phases.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-phases.t	Tue Jan 21 14:44:01 2014 -0600
@@ -175,28 +175,28 @@
 
 check that branch cache with "served" filter are properly computed and stored
 
-  $ ls ../push-dest/.hg/cache/branchheads*
-  ../push-dest/.hg/cache/branchheads-served
-  $ cat ../push-dest/.hg/cache/branchheads-served
+  $ ls ../push-dest/.hg/cache/branch2*
+  ../push-dest/.hg/cache/branch2-served
+  $ cat ../push-dest/.hg/cache/branch2-served
   6d6770faffce199f1fddd1cf87f6f026138cf061 6 465891ffab3c47a3c23792f7dc84156e19a90722
-  b3325c91a4d916bcc4cdc83ea3fe4ece46a42f6e default
-  6d6770faffce199f1fddd1cf87f6f026138cf061 default
+  b3325c91a4d916bcc4cdc83ea3fe4ece46a42f6e o default
+  6d6770faffce199f1fddd1cf87f6f026138cf061 o default
   $ hg heads -R ../push-dest --template '{rev}:{node} {phase}\n'  #update visible cache too
   6:6d6770faffce199f1fddd1cf87f6f026138cf061 draft
   5:2713879da13d6eea1ff22b442a5a87cb31a7ce6a secret
   3:b3325c91a4d916bcc4cdc83ea3fe4ece46a42f6e draft
-  $ ls ../push-dest/.hg/cache/branchheads*
-  ../push-dest/.hg/cache/branchheads-served
-  ../push-dest/.hg/cache/branchheads-visible
-  $ cat ../push-dest/.hg/cache/branchheads-served
+  $ ls ../push-dest/.hg/cache/branch2*
+  ../push-dest/.hg/cache/branch2-served
+  ../push-dest/.hg/cache/branch2-visible
+  $ cat ../push-dest/.hg/cache/branch2-served
   6d6770faffce199f1fddd1cf87f6f026138cf061 6 465891ffab3c47a3c23792f7dc84156e19a90722
-  b3325c91a4d916bcc4cdc83ea3fe4ece46a42f6e default
-  6d6770faffce199f1fddd1cf87f6f026138cf061 default
-  $ cat ../push-dest/.hg/cache/branchheads-visible
+  b3325c91a4d916bcc4cdc83ea3fe4ece46a42f6e o default
+  6d6770faffce199f1fddd1cf87f6f026138cf061 o default
+  $ cat ../push-dest/.hg/cache/branch2-visible
   6d6770faffce199f1fddd1cf87f6f026138cf061 6
-  b3325c91a4d916bcc4cdc83ea3fe4ece46a42f6e default
-  2713879da13d6eea1ff22b442a5a87cb31a7ce6a default
-  6d6770faffce199f1fddd1cf87f6f026138cf061 default
+  b3325c91a4d916bcc4cdc83ea3fe4ece46a42f6e o default
+  2713879da13d6eea1ff22b442a5a87cb31a7ce6a o default
+  6d6770faffce199f1fddd1cf87f6f026138cf061 o default
 
 
 Restore condition prior extra insertion.
@@ -378,10 +378,6 @@
 
 initial picture
 
-  $ cat >> $HGRCPATH << EOF
-  > [extensions]
-  > hgext.graphlog=
-  > EOF
   $ hg log -G --template "{rev} {phase} {desc}\n"
   @    7 secret merge B' and E
   |\
--- a/tests/test-pull-permission.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-pull-permission.t	Tue Jan 21 14:44:01 2014 -0600
@@ -1,4 +1,4 @@
-  $ "$TESTDIR/hghave" unix-permissions || exit 80
+#if unix-permissions no-root
 
   $ hg init a
   $ cd a
@@ -30,3 +30,5 @@
   1 files, 1 changesets, 1 total revisions
 
   $ cd ..
+
+#endif
--- a/tests/test-push-warn.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-push-warn.t	Tue Jan 21 14:44:01 2014 -0600
@@ -1,6 +1,3 @@
-  $ echo "[extensions]" >> $HGRCPATH
-  $ echo "graphlog=" >> $HGRCPATH
-
   $ hg init a
   $ cd a
   $ echo foo > t1
@@ -38,8 +35,8 @@
   query 2; still undecided: 1, sample size is: 1
   2 total queries
   listing keys for "bookmarks"
-  new remote heads on branch 'default'
-  new remote head 1e108cc5548c
+  new remote heads on branch 'default':
+   1e108cc5548c
   abort: push creates new remote head 1e108cc5548c!
   (pull and merge or see "hg help push" for details about pushing new heads)
   [255]
@@ -129,9 +126,9 @@
   $ hg push -v -r 3 -r 4 ../c
   pushing to ../c
   searching for changes
-  new remote heads on branch 'default'
-  new remote head a5dda829a167
-  new remote head ee8fbc7a0295
+  new remote heads on branch 'default':
+   a5dda829a167
+   ee8fbc7a0295
   abort: push creates new remote head a5dda829a167!
   (merge or see "hg help push" for details about pushing new heads)
   [255]
@@ -367,7 +364,7 @@
   $ hg push --branch f --new-branch ../f
   pushing to ../f
   searching for changes
-  abort: push creates multiple headed new branch 'f'
+  abort: push creates new branch 'f' with multiple heads
   (merge or see "hg help push" for details about pushing new heads)
   [255]
   $ hg push --branch f --new-branch --force ../f
@@ -532,7 +529,7 @@
 
 glog of local:
 
-  $ hg glog --template "{rev}: {branches} {desc}\n"
+  $ hg log -G --template "{rev}: {branches} {desc}\n"
   @  2: A a2
   |
   | o  1: B b
@@ -541,7 +538,7 @@
   
 glog of remote:
 
-  $ hg glog -R inner --template "{rev}: {branches} {desc}\n"
+  $ hg log -G -R inner --template "{rev}: {branches} {desc}\n"
   @  2: B b1
   |
   o  1: B b
@@ -615,7 +612,7 @@
 
 glog of local:
 
-  $ hg glog --template "{rev}: {branches} {desc}\n"
+  $ hg log -G --template "{rev}: {branches} {desc}\n"
   @  3: A a2
   |
   o  2: A a1
@@ -626,7 +623,7 @@
   
 glog of remote:
 
-  $ hg glog -R inner --template "{rev}: {branches} {desc}\n"
+  $ hg log -G -R inner --template "{rev}: {branches} {desc}\n"
   @  3: B b1
   |
   | o  2: A a1
@@ -700,7 +697,7 @@
 
 glog of local:
 
-  $ hg glog --template "{rev}: {branches} {desc}\n"
+  $ hg log -G --template "{rev}: {branches} {desc}\n"
   @  5: A b3
   |
   | o  4: B a3
@@ -715,7 +712,7 @@
   
 glog of remote:
 
-  $ hg glog -R inner --template "{rev}: {branches} {desc}\n"
+  $ hg log -G -R inner --template "{rev}: {branches} {desc}\n"
   @  3: B b1
   |
   o  2: B b0
--- a/tests/test-rebase-abort.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-rebase-abort.t	Tue Jan 21 14:44:01 2014 -0600
@@ -1,6 +1,5 @@
   $ cat >> $HGRCPATH <<EOF
   > [extensions]
-  > graphlog=
   > rebase=
   > 
   > [phases]
--- a/tests/test-rebase-bookmarks.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-rebase-bookmarks.t	Tue Jan 21 14:44:01 2014 -0600
@@ -1,6 +1,5 @@
   $ cat >> $HGRCPATH <<EOF
   > [extensions]
-  > graphlog=
   > rebase=
   > 
   > [phases]
--- a/tests/test-rebase-cache.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-rebase-cache.t	Tue Jan 21 14:44:01 2014 -0600
@@ -1,6 +1,5 @@
   $ cat >> $HGRCPATH <<EOF
   > [extensions]
-  > graphlog=
   > rebase=
   > mq=
   > 
--- a/tests/test-rebase-check-restore.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-rebase-check-restore.t	Tue Jan 21 14:44:01 2014 -0600
@@ -1,6 +1,5 @@
   $ cat >> $HGRCPATH <<EOF
   > [extensions]
-  > graphlog=
   > rebase=
   > 
   > [phases]
--- a/tests/test-rebase-collapse.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-rebase-collapse.t	Tue Jan 21 14:44:01 2014 -0600
@@ -1,6 +1,5 @@
   $ cat >> $HGRCPATH <<EOF
   > [extensions]
-  > graphlog=
   > rebase=
   > mq=
   > 
@@ -275,18 +274,18 @@
   7:c65502d4178782309ce0574c5ae6ee9485a9bafa default
   6:c772a8b2dc17629cec88a19d09c926c4814b12c7 default
 
-  $ cat $TESTTMP/b2/.hg/cache/branchheads-served
+  $ cat $TESTTMP/b2/.hg/cache/branch2-served
   c65502d4178782309ce0574c5ae6ee9485a9bafa 7
-  c772a8b2dc17629cec88a19d09c926c4814b12c7 default
-  c65502d4178782309ce0574c5ae6ee9485a9bafa default
+  c772a8b2dc17629cec88a19d09c926c4814b12c7 o default
+  c65502d4178782309ce0574c5ae6ee9485a9bafa o default
 
   $ hg strip 4
   saved backup bundle to $TESTTMP/b2/.hg/strip-backup/8a5212ebc852-backup.hg (glob)
 
-  $ cat $TESTTMP/b2/.hg/cache/branchheads-served
+  $ cat $TESTTMP/b2/.hg/cache/branch2-served
   c65502d4178782309ce0574c5ae6ee9485a9bafa 4
-  2870ad076e541e714f3c2bc32826b5c6a6e5b040 default
-  c65502d4178782309ce0574c5ae6ee9485a9bafa default
+  2870ad076e541e714f3c2bc32826b5c6a6e5b040 o default
+  c65502d4178782309ce0574c5ae6ee9485a9bafa o default
 
   $ hg heads --template="{rev}:{node} {branch}\n"
   4:c65502d4178782309ce0574c5ae6ee9485a9bafa default
--- a/tests/test-rebase-conflicts.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-rebase-conflicts.t	Tue Jan 21 14:44:01 2014 -0600
@@ -1,6 +1,5 @@
   $ cat >> $HGRCPATH <<EOF
   > [extensions]
-  > graphlog=
   > rebase=
   > 
   > [phases]
--- a/tests/test-rebase-detach.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-rebase-detach.t	Tue Jan 21 14:44:01 2014 -0600
@@ -1,6 +1,5 @@
   $ cat >> $HGRCPATH <<EOF
   > [extensions]
-  > graphlog=
   > rebase=
   > 
   > [phases]
--- a/tests/test-rebase-interruptions.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-rebase-interruptions.t	Tue Jan 21 14:44:01 2014 -0600
@@ -1,6 +1,5 @@
   $ cat >> $HGRCPATH <<EOF
   > [extensions]
-  > graphlog=
   > rebase=
   > 
   > [phases]
--- a/tests/test-rebase-issue-noparam-single-rev.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-rebase-issue-noparam-single-rev.t	Tue Jan 21 14:44:01 2014 -0600
@@ -1,6 +1,5 @@
   $ cat >> $HGRCPATH <<EOF
   > [extensions]
-  > graphlog=
   > rebase=
   > 
   > [phases]
--- a/tests/test-rebase-mq-skip.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-rebase-mq-skip.t	Tue Jan 21 14:44:01 2014 -0600
@@ -3,7 +3,6 @@
 
   $ cat >> $HGRCPATH <<EOF
   > [extensions]
-  > graphlog=
   > rebase=
   > mq=
   > 
--- a/tests/test-rebase-mq.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-rebase-mq.t	Tue Jan 21 14:44:01 2014 -0600
@@ -1,6 +1,5 @@
   $ cat >> $HGRCPATH <<EOF
   > [extensions]
-  > graphlog=
   > rebase=
   > mq=
   > 
--- a/tests/test-rebase-named-branches.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-rebase-named-branches.t	Tue Jan 21 14:44:01 2014 -0600
@@ -1,6 +1,5 @@
   $ cat >> $HGRCPATH <<EOF
   > [extensions]
-  > graphlog=
   > rebase=
   > 
   > [phases]
@@ -241,3 +240,97 @@
   @  0: 'A'
   
   $ cd ..
+
+Rebase to other head on branch
+
+Set up a case:
+
+  $ hg init case1
+  $ cd case1
+  $ touch f
+  $ hg ci -qAm0
+  $ hg branch -q b
+  $ echo >> f
+  $ hg ci -qAm 'b1'
+  $ hg up -qr -2
+  $ hg branch -qf b
+  $ hg ci -qm 'b2'
+  $ hg up -qr -3
+  $ hg branch -q c
+  $ hg ci -m 'c1'
+
+  $ hg tglog
+  @  3: 'c1' c
+  |
+  | o  2: 'b2' b
+  |/
+  | o  1: 'b1' b
+  |/
+  o  0: '0'
+  
+  $ hg clone -q . ../case2
+
+rebase 'b2' to another lower branch head
+
+  $ hg up -qr 2
+  $ hg rebase
+  nothing to rebase - working directory parent is also destination
+  [1]
+  $ hg tglog
+  o  3: 'c1' c
+  |
+  | @  2: 'b2' b
+  |/
+  | o  1: 'b1' b
+  |/
+  o  0: '0'
+  
+
+rebase 'b1' on top of the tip of the branch ('b2') - ignoring the tip branch ('c1')
+
+  $ cd ../case2
+  $ hg up -qr 1
+  $ hg rebase
+  saved backup bundle to $TESTTMP/case2/.hg/strip-backup/40039acb7ca5-backup.hg (glob)
+  $ hg tglog
+  @  3: 'b1' b
+  |
+  | o  2: 'c1' c
+  | |
+  o |  1: 'b2' b
+  |/
+  o  0: '0'
+  
+
+rebase 'c1' to the branch head 'c2' that is closed
+
+  $ hg branch -qf c
+  $ hg ci -qm 'c2 closed' --close
+  $ hg up -qr 2
+  $ hg tglog
+  o  4: 'c2 closed' c
+  |
+  o  3: 'b1' b
+  |
+  | @  2: 'c1' c
+  | |
+  o |  1: 'b2' b
+  |/
+  o  0: '0'
+  
+  $ hg rebase
+  nothing to rebase - working directory parent is also destination
+  [1]
+  $ hg tglog
+  o  4: 'c2 closed' c
+  |
+  o  3: 'b1' b
+  |
+  | @  2: 'c1' c
+  | |
+  o |  1: 'b2' b
+  |/
+  o  0: '0'
+  
+
+  $ cd ..
--- a/tests/test-rebase-newancestor.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-rebase-newancestor.t	Tue Jan 21 14:44:01 2014 -0600
@@ -1,6 +1,5 @@
   $ cat >> $HGRCPATH <<EOF
   > [extensions]
-  > graphlog=
   > rebase=
   > 
   > [alias]
--- a/tests/test-rebase-parameters.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-rebase-parameters.t	Tue Jan 21 14:44:01 2014 -0600
@@ -1,6 +1,5 @@
   $ cat >> $HGRCPATH <<EOF
   > [extensions]
-  > graphlog=
   > rebase=
   > 
   > [phases]
@@ -80,16 +79,39 @@
   abort: cannot specify both a revision and a base
   [255]
 
+  $ hg rebase --rev '1 & !1'
+  abort: empty "rev" revision set - nothing to rebase
+  [255]
+
+  $ hg rebase --source '1 & !1'
+  abort: empty "source" revision set - nothing to rebase
+  [255]
+
+  $ hg rebase --base '1 & !1'
+  abort: empty "base" revision set - can't compute rebase set
+  [255]
+
   $ hg rebase
-  nothing to rebase
+  nothing to rebase - working directory parent is also destination
+  [1]
+
+  $ hg rebase -b.
+  nothing to rebase - e7ec4e813ba6 is both "base" and destination
   [1]
 
   $ hg up -q 7
 
   $ hg rebase --traceback
-  nothing to rebase
+  nothing to rebase - working directory parent is already an ancestor of destination e7ec4e813ba6
   [1]
 
+  $ hg rebase -b.
+  nothing to rebase - "base" 02de42196ebe is already an ancestor of destination e7ec4e813ba6
+  [1]
+
+  $ hg rebase --dest '1 & !1'
+  abort: empty revision set
+  [255]
 
 These work:
 
@@ -127,7 +149,6 @@
 
   $ cd ..
 
-
 Rebase with base == '.' => same as no arguments (from 3 onto 8):
 
   $ hg clone -q -u 3 a a2
--- a/tests/test-rebase-pull.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-rebase-pull.t	Tue Jan 21 14:44:01 2014 -0600
@@ -1,6 +1,5 @@
   $ cat >> $HGRCPATH <<EOF
   > [extensions]
-  > graphlog=
   > rebase=
   > 
   > [alias]
@@ -85,7 +84,7 @@
   adding manifests
   adding file changes
   added 1 changesets with 1 changes to 1 files
-  nothing to rebase
+  nothing to rebase - working directory parent is already an ancestor of destination 77ae9631bcca
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   updating bookmark norebase
 
--- a/tests/test-rebase-rename.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-rebase-rename.t	Tue Jan 21 14:44:01 2014 -0600
@@ -1,6 +1,5 @@
   $ cat >> $HGRCPATH <<EOF
   > [extensions]
-  > graphlog=
   > rebase=
   > 
   > [alias]
--- a/tests/test-rebase-scenario-global.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-rebase-scenario-global.t	Tue Jan 21 14:44:01 2014 -0600
@@ -1,6 +1,5 @@
   $ cat >> $HGRCPATH <<EOF
   > [extensions]
-  > graphlog=
   > rebase=
   > 
   > [phases]
@@ -236,7 +235,7 @@
 G onto G - rebase onto same changeset:
 
   $ hg rebase -b 6 -d 6
-  nothing to rebase
+  nothing to rebase - eea13746799a is both "base" and destination
   [1]
 
 G onto F - rebase onto an ancestor:
@@ -248,7 +247,7 @@
 F onto G - rebase onto a descendant:
 
   $ hg rebase -b 5 -d 6
-  nothing to rebase
+  nothing to rebase - "base" 24b6387c8c8c is already an ancestor of destination eea13746799a
   [1]
 
 C onto A - rebase onto an ancestor:
--- a/tests/test-record.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-record.t	Tue Jan 21 14:44:01 2014 -0600
@@ -673,15 +673,15 @@
   diff --git a/subdir/f1 b/subdir/f1
   1 hunks, 1 lines changed
   examine changes to 'subdir/f1'? [Ynesfdaq?] 
-  y - record this change
-  n - skip this change
+  y - yes, record this change
+  n - no, skip this change
   e - edit this change manually
   s - skip remaining changes to this file
   f - record remaining changes to this file
   d - done, skip remaining changes and files
   a - record all changes to all remaining files
   q - quit, recording no changes
-  ? - display help
+  ? - ? (display help)
   examine changes to 'subdir/f1'? [Ynesfdaq?] 
   abort: user quit
   [255]
@@ -1277,5 +1277,25 @@
    c
   +d
   
+Test --user when ui.username not set
+  $ unset HGUSER
+  $ echo e >> subdir/f1
+  $ hg record  --config ui.username= -d '8 0' --user xyz -m "user flag" <<EOF
+  > y
+  > y
+  > EOF
+  diff --git a/subdir/f1 b/subdir/f1
+  1 hunks, 1 lines changed
+  examine changes to 'subdir/f1'? [Ynesfdaq?] 
+  @@ -4,3 +4,4 @@
+   b
+   c
+   d
+  +e
+  record this change to 'subdir/f1'? [Ynesfdaq?] 
+  $ hg log --template '{author}\n' -l 1
+  xyz
+  $ HGUSER="test"
+  $ export HGUSER
 
   $ cd ..
--- a/tests/test-repair-strip.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-repair-strip.t	Tue Jan 21 14:44:01 2014 -0600
@@ -1,4 +1,4 @@
-  $ "$TESTDIR/hghave" unix-permissions || exit 80
+#if unix-permissions no-root
 
   $ echo "[extensions]" >> $HGRCPATH
   $ echo "mq=">> $HGRCPATH
@@ -130,3 +130,5 @@
   2 files, 2 changesets, 2 total revisions
 
   $ cd ..
+
+#endif
--- a/tests/test-revset-outgoing.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-revset-outgoing.t	Tue Jan 21 14:44:01 2014 -0600
@@ -1,7 +1,4 @@
   $ cat >> $HGRCPATH <<EOF
-  > [extensions]
-  > graphlog=
-  > 
   > [alias]
   > tlog = log --template "{rev}:{node|short}: '{desc}' {branches}\n"
   > tglog = tlog -G
--- a/tests/test-revset.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-revset.t	Tue Jan 21 14:44:01 2014 -0600
@@ -273,6 +273,11 @@
   1
   3
   5
+  $ log 'contains("../repo/a")'
+  0
+  1
+  3
+  5
   $ log 'desc(B)'
   5
   $ log 'descendants(2 or 3)'
@@ -287,6 +292,12 @@
   $ log 'file("b*")'
   1
   4
+  $ log 'filelog("b")'
+  1
+  4
+  $ log 'filelog("../repo/b")'
+  1
+  4
   $ log 'follow()'
   0
   1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-run-tests.py	Tue Jan 21 14:44:01 2014 -0600
@@ -0,0 +1,87 @@
+"""test line matching with some failing examples and some which warn
+
+run-test.t only checks positive matches and can not see warnings
+(both by design)
+"""
+
+import os, re
+# this is hack to make sure no escape characters are inserted into the output
+if 'TERM' in os.environ:
+    del os.environ['TERM']
+import doctest
+run_tests = __import__('run-tests')
+
+def lm(expected, output):
+    r"""check if output matches expected
+
+    does it generally work?
+        >>> lm('H*e (glob)\n', 'Here\n')
+        True
+
+    fail on bad test data
+        >>> try: lm('a\n','a')
+        ... except AssertionError, ex: print ex
+        missing newline
+        >>> try: lm('single backslash\n', 'single \backslash\n')
+        ... except AssertionError, ex: print ex
+        single backslash or unknown char
+    """
+    assert expected.endswith('\n') and output.endswith('\n'), 'missing newline'
+    assert not re.search(r'[^ \w\\/\r\n()*?]', expected + output), \
+           'single backslash or unknown char'
+    match = run_tests.linematch(expected, output)
+    if isinstance(match, str):
+        return 'special: ' + match
+    else:
+        return bool(match) # do not return match object
+
+def wintests():
+    r"""test matching like running on windows
+
+    enable windows matching on any os
+        >>> _osaltsep = os.altsep
+        >>> os.altsep = True
+
+    valid match on windows
+        >>> lm('g/a*/d (glob)\n', 'g\\abc/d\n')
+        True
+
+    direct matching, glob unnecessary
+        >>> lm('g/b (glob)\n', 'g/b\n')
+        'special: -glob'
+
+    missing glob
+        >>> lm('/g/c/d/fg\n', '\\g\\c\\d/fg\n')
+        'special: +glob'
+
+    restore os.altsep
+        >>> os.altsep = _osaltsep
+    """
+    pass
+
+def otherostests():
+    r"""test matching like running on non-windows os
+
+    disable windows matching on any os
+        >>> _osaltsep = os.altsep
+        >>> os.altsep = False
+
+    backslash does not match slash
+        >>> lm('h/a* (glob)\n', 'h\\ab\n')
+        False
+
+    direct matching glob can not be recognized
+        >>> lm('h/b (glob)\n', 'h/b\n')
+        True
+
+    missing glob can not not be recognized
+        >>> lm('/h/c/df/g/\n', '\\h/c\\df/g\\\n')
+        False
+
+    restore os.altsep
+        >>> os.altsep = _osaltsep
+    """
+    pass
+
+if __name__ == '__main__':
+    doctest.testmod()
--- a/tests/test-serve.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-serve.t	Tue Jan 21 14:44:01 2014 -0600
@@ -45,12 +45,14 @@
 
 With -v and -p daytime (should fail because low port)
 
+#if no-root
   $ KILLQUIETLY=Y
   $ hgserve -p daytime
   abort: cannot start server at 'localhost:13': Permission denied
   abort: child process failed to start
   % errors
   $ KILLQUIETLY=N
+#endif
 
 With --prefix foo
 
--- a/tests/test-strip-cross.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-strip-cross.t	Tue Jan 21 14:44:01 2014 -0600
@@ -1,7 +1,7 @@
 test stripping of filelogs where the linkrev doesn't always increase
 
   $ echo '[extensions]' >> $HGRCPATH
-  $ echo 'hgext.mq =' >> $HGRCPATH
+  $ echo 'strip =' >> $HGRCPATH
   $ hg init orig
   $ cd orig
   $ commit()
--- a/tests/test-strip.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-strip.t	Tue Jan 21 14:44:01 2014 -0600
@@ -1,6 +1,5 @@
   $ echo "[extensions]" >> $HGRCPATH
   $ echo "strip=" >> $HGRCPATH
-  $ echo "graphlog=" >> $HGRCPATH
 
   $ restore() {
   >     hg unbundle -q .hg/strip-backup/*
@@ -226,7 +225,7 @@
 
   $ hg up
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
-  $ hg glog
+  $ hg log -G
   @  changeset:   4:264128213d29
   |  tag:         tip
   |  parent:      1:ef3a871183d7
@@ -259,7 +258,7 @@
 
   $ hg strip "roots(2)" 3
   saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
-  $ hg glog
+  $ hg log -G
   @  changeset:   2:264128213d29
   |  tag:         tip
   |  user:        test
@@ -277,7 +276,7 @@
      summary:     a
   
   $ restore
-  $ hg glog
+  $ hg log -G
   o  changeset:   4:443431ffac4f
   |  tag:         tip
   |  user:        test
@@ -311,7 +310,7 @@
   $ hg strip 2 4
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   saved backup bundle to $TESTTMP/test/.hg/strip-backup/*-backup.hg (glob)
-  $ hg glog
+  $ hg log -G
   o  changeset:   2:65bd5f99a4a3
   |  tag:         tip
   |  user:        test
--- a/tests/test-subrepo.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-subrepo.t	Tue Jan 21 14:44:01 2014 -0600
@@ -468,12 +468,8 @@
 KeyError
 
   $ hg backout ".^"
-  reverting .hgsubstate
-  reverting subrepo s
-  reverting s/a (glob)
-  reverting subrepo ss
-  reverting subrepo t
   0 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  changeset c373c8102e68 backed out, don't forget to commit.
 
   $ hg up -C # discard changes
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
@@ -1232,4 +1228,69 @@
   searching for changes
   no changes found
   [1]
+  $ cd ..
 
+Test phase choice for newly created commit with "phases.subrepochecks"
+configuration
+
+  $ cd t
+  $ hg update -q -r 12
+
+  $ cat >> s/ss/.hg/hgrc <<EOF
+  > [phases]
+  > new-commit = secret
+  > EOF
+  $ cat >> s/.hg/hgrc <<EOF
+  > [phases]
+  > new-commit = draft
+  > EOF
+  $ echo phasecheck1 >> s/ss/a
+  $ hg -R s commit -S --config phases.checksubrepos=abort -m phasecheck1
+  committing subrepository ss
+  transaction abort!
+  rollback completed
+  abort: can't commit in draft phase conflicting secret from subrepository ss
+  [255]
+  $ echo phasecheck2 >> s/ss/a
+  $ hg -R s commit -S --config phases.checksubrepos=ignore -m phasecheck2
+  committing subrepository ss
+  $ hg -R s/ss phase tip
+  3: secret
+  $ hg -R s phase tip
+  6: draft
+  $ echo phasecheck3 >> s/ss/a
+  $ hg -R s commit -S -m phasecheck3
+  committing subrepository ss
+  warning: changes are committed in secret phase from subrepository ss
+  $ hg -R s/ss phase tip
+  4: secret
+  $ hg -R s phase tip
+  7: secret
+
+  $ cat >> t/.hg/hgrc <<EOF
+  > [phases]
+  > new-commit = draft
+  > EOF
+  $ cat >> .hg/hgrc <<EOF
+  > [phases]
+  > new-commit = public
+  > EOF
+  $ echo phasecheck4 >>   s/ss/a
+  $ echo phasecheck4 >>   t/t
+  $ hg commit -S -m phasecheck4
+  committing subrepository s
+  committing subrepository s/ss
+  warning: changes are committed in secret phase from subrepository ss
+  committing subrepository t
+  warning: changes are committed in secret phase from subrepository s
+  created new head
+  $ hg -R s/ss phase tip
+  5: secret
+  $ hg -R s phase tip
+  8: secret
+  $ hg -R t phase tip
+  6: draft
+  $ hg phase tip
+  15: secret
+
+  $ cd ..
--- a/tests/test-transplant.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-transplant.t	Tue Jan 21 14:44:01 2014 -0600
@@ -430,6 +430,81 @@
   adding manifests
   adding file changes
   added 4 changesets with 4 changes to 4 files
+
+test "--merge" causing pull from source repository on local host
+
+  $ hg --config extensions.mq= -q strip 2
+  $ hg transplant -s ../t --merge tip
+  searching for changes
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 2 changesets with 2 changes to 2 files
+  applying a53251cdf717
+  4:a53251cdf717 merged at 4831f4dc831a
+
+test interactive transplant
+
+  $ hg --config extensions.strip= -q strip 0
+  $ hg -R ../t log -G --template "{rev}:{node|short}"
+  @  4:a53251cdf717
+  |
+  o  3:722f4667af76
+  |
+  o  2:37a1297eb21b
+  |
+  | o  1:d11e3596cc1a
+  |/
+  o  0:17ab29e464c6
+  
+  $ hg transplant -q --config ui.interactive=true -s ../t <<EOF
+  > p
+  > y
+  > n
+  > n
+  > m
+  > c
+  > EOF
+  0:17ab29e464c6
+  apply changeset? [ynmpcq?]: --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+  +++ b/r1	Thu Jan 01 00:00:00 1970 +0000
+  @@ -0,0 +1,1 @@
+  +r1
+  apply changeset? [ynmpcq?]: 1:d11e3596cc1a
+  apply changeset? [ynmpcq?]: 2:37a1297eb21b
+  apply changeset? [ynmpcq?]: 3:722f4667af76
+  apply changeset? [ynmpcq?]: 4:a53251cdf717
+  apply changeset? [ynmpcq?]:  (no-eol)
+  $ hg log -G --template "{node|short}"
+  @    88be5dde5260
+  |\
+  | o  722f4667af76
+  | |
+  | o  37a1297eb21b
+  |/
+  o  17ab29e464c6
+  
+  $ hg transplant -q --config ui.interactive=true -s ../t <<EOF
+  > x
+  > ?
+  > y
+  > q
+  > EOF
+  1:d11e3596cc1a
+  apply changeset? [ynmpcq?]: unrecognized response
+  apply changeset? [ynmpcq?]: y: yes, transplant this changeset
+  n: no, skip this changeset
+  m: merge at this changeset
+  p: show patch
+  c: commit selected changesets
+  q: quit and cancel transplant
+  ?: ? (show this help)
+  apply changeset? [ynmpcq?]: 4:a53251cdf717
+  apply changeset? [ynmpcq?]:  (no-eol)
+  $ hg heads --template "{node|short}\n"
+  88be5dde5260
+
   $ cd ..
 
 
--- a/tests/test-treediscovery-legacy.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-treediscovery-legacy.t	Tue Jan 21 14:44:01 2014 -0600
@@ -5,8 +5,6 @@
   $ cat >> $HGRCPATH <<EOF
   > [ui]
   > logtemplate="{rev} {node|short}: {desc} {branches}\n"
-  > [extensions]
-  > graphlog=
   > EOF
   $ cp $HGRCPATH $HGRCPATH-withcap
 
@@ -66,7 +64,7 @@
   $ hg init main
   $ cd main
   $ hg debugbuilddag -mo '+2:tbase @name1 +3:thead1 <tbase @name2 +4:thead2 @both /thead1 +2:tmaintip'
-  $ hg glog
+  $ hg log -G
   o  11 a19bfa7e7328: r11 both
   |
   o  10 8b6bad1512e1: r10 both
--- a/tests/test-treediscovery.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-treediscovery.t	Tue Jan 21 14:44:01 2014 -0600
@@ -7,8 +7,6 @@
   $ cat >> $HGRCPATH <<EOF
   > [ui]
   > logtemplate="{rev} {node|short}: {desc} {branches}\n"
-  > [extensions]
-  > graphlog=
   > EOF
 
 Setup HTTP server control:
@@ -53,7 +51,7 @@
   $ hg init main
   $ cd main
   $ hg debugbuilddag -mo '+2:tbase @name1 +3:thead1 <tbase @name2 +4:thead2 @both /thead1 +2:tmaintip'
-  $ hg glog
+  $ hg log -G
   o  11 a19bfa7e7328: r11 both
   |
   o  10 8b6bad1512e1: r10 both
--- a/tests/test-update-branches.t	Mon Jan 20 11:16:26 2014 -0200
+++ b/tests/test-update-branches.t	Tue Jan 21 14:44:01 2014 -0600
@@ -34,8 +34,7 @@
 
 Initial repo state:
 
-  $ hg --config 'extensions.graphlog=' \
-  >    glog --template '{rev}:{node|short} {parents} {branches}\n'
+  $ hg log -G --template '{rev}:{node|short} {parents} {branches}\n'
   @  5:ff252e8273df  b1
   |
   o  4:d047485b3896 0:60829823a42a  b1
@@ -230,6 +229,17 @@
   $ hg bookmarks
    * bm                        5:ff252e8273df
 
+Test that 4 is detected as the no-argument destination from 3 and also moves
+the bookmark with it
+  $ hg up --quiet 0          # we should be able to update to 3 directly
+  $ hg up --quiet --hidden 3 # but not implemented yet.
+  $ hg book -f bm
+  $ hg up
+  1 files updated, 0 files merged, 0 files removed, 0 files unresolved
+  updating bookmark bm
+  $ hg book
+   * bm                        4:d047485b3896
+
 Test that 5 is detected as a valid destination from 1
   $ hg up --quiet 0          # we should be able to update to 3 directly
   $ hg up --quiet --hidden 3 # but not implemented yet.
@@ -243,3 +253,14 @@
   abort: uncommitted changes
   (commit or update --clean to discard changes)
   [255]
+
+Test that we don't crash when updating from a pruned changeset (i.e. has no
+successors). Behavior should probably be that we update to the first
+non-obsolete parent but that will be decided later.
+  $ hg id --debug -r 2
+  bd10386d478cd5a9faf2e604114c8e6da62d3889
+  $ hg up --quiet 0
+  $ hg up --quiet 2
+  $ hg debugobsolete bd10386d478cd5a9faf2e604114c8e6da62d3889
+  $ hg up
+  0 files updated, 0 files merged, 0 files removed, 0 files unresolved