changeset 15843:64582443a20a

merge with i18n
author Wagner Bruna <wbruna@softwareexpress.com.br>
date Tue, 10 Jan 2012 15:48:16 -0200
parents 94a4748db392 (diff) a1bf5e1c4416 (current diff)
children e7dde08254b7
files
diffstat 66 files changed, 1556 insertions(+), 1002 deletions(-) [+]
line wrap: on
line diff
--- a/.hgsigs	Mon Jan 09 02:32:01 2012 +0700
+++ b/.hgsigs	Tue Jan 10 15:48:16 2012 -0200
@@ -46,3 +46,4 @@
 384082750f2c51dc917d85a7145748330fa6ef4d 0 iD8DBQBOmd+OywK+sNU5EO8RAgDgAJ9V/X+G7VLwhTpHrZNiOHabzSyzYQCdE2kKfIevJUYB9QLAWCWP6DPwrwI=
 41453d55b481ddfcc1dacb445179649e24ca861d 0 iD8DBQBOsFhpywK+sNU5EO8RAqM6AKCyfxUae3/zLuiLdQz+JR78690eMACfQ6JTBQib4AbE+rUDdkeFYg9K/+4=
 195dbd1cef0c2f9f8bcf4ea303238105f716bda3 0 iD8DBQBO1/fWywK+sNU5EO8RAmoPAKCR5lpv1D6JLURHD8KVLSV4GRVEBgCgnd0Sy78ligNfqAMafmACRDvj7vo=
+6344043924497cd06d781d9014c66802285072e4 0 iD8DBQBPALgmywK+sNU5EO8RAlfhAJ9nYOdWnhfVDHYtDTJAyJtXBAQS9wCgnefoSQt7QABkbGxM+Q85UYEBuD0=
--- a/.hgtags	Mon Jan 09 02:32:01 2012 +0700
+++ b/.hgtags	Tue Jan 10 15:48:16 2012 -0200
@@ -58,3 +58,4 @@
 384082750f2c51dc917d85a7145748330fa6ef4d 2.0-rc
 41453d55b481ddfcc1dacb445179649e24ca861d 2.0
 195dbd1cef0c2f9f8bcf4ea303238105f716bda3 2.0.1
+6344043924497cd06d781d9014c66802285072e4 2.0.2
--- a/contrib/mercurial.el	Mon Jan 09 02:32:01 2012 +0700
+++ b/contrib/mercurial.el	Tue Jan 10 15:48:16 2012 -0200
@@ -15,8 +15,7 @@
 
 ;; You should have received a copy of the GNU General Public License
 ;; along with mercurial.el, GNU Emacs, or XEmacs; see the file COPYING
-;; (`C-h C-l').  If not, write to the Free Software Foundation, Inc.,
-;; 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+;; (`C-h C-l').  If not, see <http://www.gnu.org/licenses/>.
 
 ;;; Commentary:
 
--- a/contrib/mq.el	Mon Jan 09 02:32:01 2012 +0700
+++ b/contrib/mq.el	Tue Jan 10 15:48:16 2012 -0200
@@ -15,8 +15,7 @@
 
 ;; You should have received a copy of the GNU General Public License
 ;; along with mq.el, GNU Emacs, or XEmacs; see the file COPYING (`C-h
-;; C-l').  If not, write to the Free Software Foundation, Inc., 59
-;; Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+;; C-l').  If not, see <http://www.gnu.org/licenses/>.
 
 (eval-when-compile (require 'cl))
 (require 'mercurial)
Binary file contrib/wix/COPYING.rtf has changed
--- a/contrib/wix/guids.wxi	Mon Jan 09 02:32:01 2012 +0700
+++ b/contrib/wix/guids.wxi	Tue Jan 10 15:48:16 2012 -0200
@@ -24,7 +24,7 @@
   <?define i18nFolder.guid = {EADFA693-A0B5-4f31-87C9-3997CFAC1B42} ?>
 
   <!-- templates.wxs -->
-  <?define templates.root.guid = {111509CB-4C96-4035-80BC-F66A99CD5ACB} ?>
+  <?define templates.root.guid = {8DF97574-33E9-412F-8414-65B48BB18783} ?>
   <?define templates.atom.guid = {AB5D2908-BC95-44BE-9D79-069EF43D93E2} ?>
   <?define templates.coal.guid = {B63CCAAB-4EAF-43b4-901E-4BD13F5B78FC} ?>
   <?define templates.gitweb.guid = {6A33D168-F84E-45AA-912C-23CAC2D66BCA} ?>
--- a/contrib/wix/templates.wxs	Mon Jan 09 02:32:01 2012 +0700
+++ b/contrib/wix/templates.wxs	Tue Jan 10 15:48:16 2012 -0200
@@ -31,6 +31,7 @@
           <File Name="map-cmdline.changelog" KeyPath="yes" />
           <File Name="map-cmdline.compact" />
           <File Name="map-cmdline.default" />
+          <File Name="map-cmdline.bisect" />
           <File Name="map-cmdline.xml" />
           <File Name="template-vars.txt" />
         </Component>
--- a/hgext/color.py	Mon Jan 09 02:32:01 2012 +0700
+++ b/hgext/color.py	Tue Jan 10 15:48:16 2012 -0200
@@ -2,19 +2,8 @@
 #
 # Copyright (C) 2007 Kevin Christen <kevin.christen@gmail.com>
 #
-# This program is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License as published by the
-# Free Software Foundation; either version 2 of the License, or (at your
-# option) any later version.
-#
-# This program is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
-# Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+# This software may be used and distributed according to the terms of the
+# GNU General Public License version 2 or any later version.
 
 '''colorize output from some commands
 
--- a/hgext/convert/common.py	Mon Jan 09 02:32:01 2012 +0700
+++ b/hgext/convert/common.py	Tue Jan 10 15:48:16 2012 -0200
@@ -339,7 +339,7 @@
 
         # Since ARG_MAX is for command line _and_ environment, lower our limit
         # (and make happy Windows shells while doing this).
-        return argmax / 2 - 1
+        return argmax // 2 - 1
 
     def limit_arglist(self, arglist, cmd, closestdin, *args, **kwargs):
         cmdlen = len(self._cmdline(cmd, closestdin, *args, **kwargs))
--- a/hgext/convert/cvsps.py	Mon Jan 09 02:32:01 2012 +0700
+++ b/hgext/convert/cvsps.py	Tue Jan 10 15:48:16 2012 -0200
@@ -556,27 +556,25 @@
 
     # Sort files in each changeset
 
+    def entitycompare(l, r):
+        'Mimic cvsps sorting order'
+        l = l.file.split('/')
+        r = r.file.split('/')
+        nl = len(l)
+        nr = len(r)
+        n = min(nl, nr)
+        for i in range(n):
+            if i + 1 == nl and nl < nr:
+                return -1
+            elif i + 1 == nr and nl > nr:
+                return +1
+            elif l[i] < r[i]:
+                return -1
+            elif l[i] > r[i]:
+                return +1
+        return 0
+
     for c in changesets:
-        def pathcompare(l, r):
-            'Mimic cvsps sorting order'
-            l = l.split('/')
-            r = r.split('/')
-            nl = len(l)
-            nr = len(r)
-            n = min(nl, nr)
-            for i in range(n):
-                if i + 1 == nl and nl < nr:
-                    return -1
-                elif i + 1 == nr and nl > nr:
-                    return +1
-                elif l[i] < r[i]:
-                    return -1
-                elif l[i] > r[i]:
-                    return +1
-            return 0
-        def entitycompare(l, r):
-            return pathcompare(l.file, r.file)
-
         c.entries.sort(entitycompare)
 
     # Sort changesets by date
--- a/hgext/convert/subversion.py	Mon Jan 09 02:32:01 2012 +0700
+++ b/hgext/convert/subversion.py	Tue Jan 10 15:48:16 2012 -0200
@@ -106,11 +106,11 @@
                        discover_changed_paths,
                        strict_node_history,
                        receiver)
-    except SubversionException, (inst, num):
-        pickle.dump(num, fp, protocol)
     except IOError:
         # Caller may interrupt the iteration
         pickle.dump(None, fp, protocol)
+    except Exception, inst:
+        pickle.dump(str(inst), fp, protocol)
     else:
         pickle.dump(None, fp, protocol)
     fp.close()
@@ -145,7 +145,7 @@
             except:
                 if entry is None:
                     break
-                raise SubversionException("child raised exception", entry)
+                raise util.Abort(_("log stream exception '%s'") % entry)
             yield entry
 
     def close(self):
--- a/hgext/convert/transport.py	Mon Jan 09 02:32:01 2012 +0700
+++ b/hgext/convert/transport.py	Tue Jan 10 15:48:16 2012 -0200
@@ -15,8 +15,7 @@
 # GNU General Public License for more details.
 
 # You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
 
 from mercurial import util
 from svn.core import SubversionException, Pool
--- a/hgext/fetch.py	Mon Jan 09 02:32:01 2012 +0700
+++ b/hgext/fetch.py	Tue Jan 10 15:48:16 2012 -0200
@@ -83,7 +83,7 @@
         # Is this a simple fast-forward along the current branch?
         newheads = repo.branchheads(branch)
         newchildren = repo.changelog.nodesbetween([parent], newheads)[2]
-        if len(newheads) == 1:
+        if len(newheads) == 1 and len(newchildren):
             if newchildren[0] != parent:
                 return hg.clean(repo, newchildren[0])
             else:
@@ -102,6 +102,9 @@
                       (len(newheads) - 1))
             return 1
 
+        if not newheads:
+            return 0
+
         # Otherwise, let's merge.
         err = False
         if newheads:
--- a/hgext/hgcia.py	Mon Jan 09 02:32:01 2012 +0700
+++ b/hgext/hgcia.py	Tue Jan 10 15:48:16 2012 -0200
@@ -113,7 +113,7 @@
                 # diffstat is stupid
                 self.name = 'cia'
             def write(self, data):
-                self.lines.append(data)
+                self.lines += data.splitlines(True)
             def close(self):
                 pass
 
--- a/hgext/largefiles/lfcommands.py	Mon Jan 09 02:32:01 2012 +0700
+++ b/hgext/largefiles/lfcommands.py	Tue Jan 10 15:48:16 2012 -0200
@@ -117,22 +117,10 @@
 
 def _addchangeset(ui, rsrc, rdst, ctx, revmap):
  # Convert src parents to dst parents
-    parents = []
-    for p in ctx.parents():
-        parents.append(revmap[p.node()])
-    while len(parents) < 2:
-        parents.append(node.nullid)
+    parents = _convertparents(ctx, revmap)
 
     # Generate list of changed files
-    files = set(ctx.files())
-    if node.nullid not in parents:
-        mc = ctx.manifest()
-        mp1 = ctx.parents()[0].manifest()
-        mp2 = ctx.parents()[1].manifest()
-        files |= (set(mp1) | set(mp2)) - set(mc)
-        for f in mc:
-            if mc[f] != mp1.get(f, None) or mc[f] != mp2.get(f, None):
-                files.add(f)
+    files = _getchangedfiles(ctx, parents)
 
     def getfilectx(repo, memctx, f):
         if lfutil.standin(f) in files:
@@ -160,23 +148,7 @@
             return context.memfilectx(f, data, 'l' in fctx.flags(),
                                       'x' in fctx.flags(), renamed)
         else:
-            try:
-                fctx = ctx.filectx(f)
-            except error.LookupError:
-                raise IOError()
-            renamed = fctx.renamed()
-            if renamed:
-                renamed = renamed[0]
-            data = fctx.data()
-            if f == '.hgtags':
-                newdata = []
-                for line in data.splitlines():
-                    id, name = line.split(' ', 1)
-                    newdata.append('%s %s\n' % (node.hex(revmap[node.bin(id)]),
-                        name))
-                data = ''.join(newdata)
-            return context.memfilectx(f, data, 'l' in fctx.flags(),
-                                      'x' in fctx.flags(), renamed)
+            return _getnormalcontext(repo.ui, ctx, f, revmap)
 
     dstfiles = []
     for file in files:
@@ -185,31 +157,15 @@
         else:
             dstfiles.append(file)
     # Commit
-    mctx = context.memctx(rdst, parents, ctx.description(), dstfiles,
-                          getfilectx, ctx.user(), ctx.date(), ctx.extra())
-    ret = rdst.commitctx(mctx)
-    rdst.dirstate.setparents(ret)
-    revmap[ctx.node()] = rdst.changelog.tip()
+    _commitcontext(rdst, parents, ctx, dstfiles, getfilectx, revmap)
 
 def _lfconvert_addchangeset(rsrc, rdst, ctx, revmap, lfiles, normalfiles,
         matcher, size, lfiletohash):
     # Convert src parents to dst parents
-    parents = []
-    for p in ctx.parents():
-        parents.append(revmap[p.node()])
-    while len(parents) < 2:
-        parents.append(node.nullid)
+    parents = _convertparents(ctx, revmap)
 
     # Generate list of changed files
-    files = set(ctx.files())
-    if node.nullid not in parents:
-        mc = ctx.manifest()
-        mp1 = ctx.parents()[0].manifest()
-        mp2 = ctx.parents()[1].manifest()
-        files |= (set(mp1) | set(mp2)) - set(mc)
-        for f in mc:
-            if mc[f] != mp1.get(f, None) or mc[f] != mp2.get(f, None):
-                files.add(f)
+    files = _getchangedfiles(ctx, parents)
 
     dstfiles = []
     for f in files:
@@ -237,7 +193,9 @@
             dstfiles.append(lfutil.standin(f))
             # largefile in manifest if it has not been removed/renamed
             if f in ctx.manifest():
-                if 'l' in ctx.filectx(f).flags():
+                fctx = ctx.filectx(f)
+                if 'l' in fctx.flags():
+                    renamed = fctx.renamed()
                     if renamed and renamed[0] in lfiles:
                         raise util.Abort(_('largefile %s becomes symlink') % f)
 
@@ -281,32 +239,80 @@
             return context.memfilectx(f, lfiletohash[srcfname] + '\n', 'l' in
                 fctx.flags(), 'x' in fctx.flags(), renamed)
         else:
-            try:
-                fctx = ctx.filectx(f)
-            except error.LookupError:
-                raise IOError()
-            renamed = fctx.renamed()
-            if renamed:
-                renamed = renamed[0]
-
-            data = fctx.data()
-            if f == '.hgtags':
-                newdata = []
-                for line in data.splitlines():
-                    id, name = line.split(' ', 1)
-                    newdata.append('%s %s\n' % (node.hex(revmap[node.bin(id)]),
-                        name))
-                data = ''.join(newdata)
-            return context.memfilectx(f, data, 'l' in fctx.flags(),
-                                      'x' in fctx.flags(), renamed)
+            return _getnormalcontext(repo.ui, ctx, f, revmap)
 
     # Commit
+    _commitcontext(rdst, parents, ctx, dstfiles, getfilectx, revmap)
+
+def _commitcontext(rdst, parents, ctx, dstfiles, getfilectx, revmap):
     mctx = context.memctx(rdst, parents, ctx.description(), dstfiles,
                           getfilectx, ctx.user(), ctx.date(), ctx.extra())
     ret = rdst.commitctx(mctx)
     rdst.dirstate.setparents(ret)
     revmap[ctx.node()] = rdst.changelog.tip()
 
+# Generate list of changed files
+def _getchangedfiles(ctx, parents):
+    files = set(ctx.files())
+    if node.nullid not in parents:
+        mc = ctx.manifest()
+        mp1 = ctx.parents()[0].manifest()
+        mp2 = ctx.parents()[1].manifest()
+        files |= (set(mp1) | set(mp2)) - set(mc)
+        for f in mc:
+            if mc[f] != mp1.get(f, None) or mc[f] != mp2.get(f, None):
+                files.add(f)
+    return files
+
+# Convert src parents to dst parents
+def _convertparents(ctx, revmap):
+    parents = []
+    for p in ctx.parents():
+        parents.append(revmap[p.node()])
+    while len(parents) < 2:
+        parents.append(node.nullid)
+    return parents
+
+# Get memfilectx for a normal file
+def _getnormalcontext(ui, ctx, f, revmap):
+    try:
+        fctx = ctx.filectx(f)
+    except error.LookupError:
+        raise IOError()
+    renamed = fctx.renamed()
+    if renamed:
+        renamed = renamed[0]
+
+    data = fctx.data()
+    if f == '.hgtags':
+        data = _converttags (ui, revmap, data)
+    return context.memfilectx(f, data, 'l' in fctx.flags(),
+                              'x' in fctx.flags(), renamed)
+
+# Remap tag data using a revision map
+def _converttags(ui, revmap, data):
+    newdata = []
+    for line in data.splitlines():
+        try:
+            id, name = line.split(' ', 1)
+        except ValueError:
+            ui.warn(_('skipping incorrectly formatted tag %s\n'
+                % line))
+            continue
+        try:
+            newid = node.bin(id)
+        except TypeError:
+            ui.warn(_('skipping incorrectly formatted id %s\n'
+                % id))
+            continue
+        try:
+            newdata.append('%s %s\n' % (node.hex(revmap[newid]),
+                name))
+        except KeyError:
+            ui.warn(_('no mapping for id %s\n' % id))
+            continue
+    return ''.join(newdata)
+
 def _islfile(file, ctx, matcher, size):
     '''Return true if file should be considered a largefile, i.e.
     matcher matches it or it is larger than size.'''
@@ -455,7 +461,13 @@
             ret = -1
     state = repo.dirstate[lfutil.standin(lfile)]
     if state == 'n':
-        lfdirstate.normal(lfile)
+        # When rebasing, we need to synchronize the standin and the largefile,
+        # because otherwise the largefile will get reverted.  But for commit's
+        # sake, we have to mark the file as unclean.
+        if getattr(repo, "_isrebasing", False):
+           lfdirstate.normallookup(lfile)
+        else:
+            lfdirstate.normal(lfile)
     elif state == 'r':
         lfdirstate.remove(lfile)
     elif state == 'a':
--- a/hgext/largefiles/lfutil.py	Mon Jan 09 02:32:01 2012 +0700
+++ b/hgext/largefiles/lfutil.py	Tue Jan 10 15:48:16 2012 -0200
@@ -139,6 +139,8 @@
         return super(largefiles_dirstate, self).drop(unixpath(f))
     def forget(self, f):
         return super(largefiles_dirstate, self).forget(unixpath(f))
+    def normallookup(self, f):
+        return super(largefiles_dirstate, self).normallookup(unixpath(f))
 
 def openlfdirstate(ui, repo):
     '''
@@ -152,11 +154,7 @@
 
     # If the largefiles dirstate does not exist, populate and create
     # it. This ensures that we create it on the first meaningful
-    # largefiles operation in a new clone. It also gives us an easy
-    # way to forcibly rebuild largefiles state:
-    #   rm .hg/largefiles/dirstate && hg status
-    # Or even, if things are really messed up:
-    #   rm -rf .hg/largefiles && hg status
+    # largefiles operation in a new clone.
     if not os.path.exists(os.path.join(admin, 'dirstate')):
         util.makedirs(admin)
         matcher = getstandinmatcher(repo)
@@ -170,27 +168,19 @@
             except OSError, err:
                 if err.errno != errno.ENOENT:
                     raise
-
-        lfdirstate.write()
-
     return lfdirstate
 
 def lfdirstate_status(lfdirstate, repo, rev):
-    wlock = repo.wlock()
-    try:
-        match = match_.always(repo.root, repo.getcwd())
-        s = lfdirstate.status(match, [], False, False, False)
-        unsure, modified, added, removed, missing, unknown, ignored, clean = s
-        for lfile in unsure:
-            if repo[rev][standin(lfile)].data().strip() != \
-                    hashfile(repo.wjoin(lfile)):
-                modified.append(lfile)
-            else:
-                clean.append(lfile)
-                lfdirstate.normal(lfile)
-        lfdirstate.write()
-    finally:
-        wlock.release()
+    match = match_.always(repo.root, repo.getcwd())
+    s = lfdirstate.status(match, [], False, False, False)
+    unsure, modified, added, removed, missing, unknown, ignored, clean = s
+    for lfile in unsure:
+        if repo[rev][standin(lfile)].data().strip() != \
+                hashfile(repo.wjoin(lfile)):
+            modified.append(lfile)
+        else:
+            clean.append(lfile)
+            lfdirstate.normal(lfile)
     return (modified, added, removed, missing, unknown, ignored, clean)
 
 def listlfiles(repo, rev=None, matcher=None):
@@ -232,6 +222,16 @@
         return
     copytostoreabsolute(repo, repo.wjoin(file), hash)
 
+def copyalltostore(repo, node):
+    '''Copy all largefiles in a given revision to the store'''
+
+    ctx = repo[node]
+    for filename in ctx.files():
+        if isstandin(filename) and filename in ctx.manifest():
+            realfile = splitstandin(filename)
+            copytostore(repo, ctx.node(), realfile)
+
+
 def copytostoreabsolute(repo, file, hash):
     util.makedirs(os.path.dirname(storepath(repo, hash)))
     if inusercache(repo.ui, hash):
--- a/hgext/largefiles/overrides.py	Mon Jan 09 02:32:01 2012 +0700
+++ b/hgext/largefiles/overrides.py	Tue Jan 10 15:48:16 2012 -0200
@@ -20,6 +20,8 @@
 import lfutil
 import lfcommands
 
+# -- Utility functions: commonly/repeatedly needed functionality ---------------
+
 def installnormalfilesmatchfn(manifest):
     '''overrides scmutil.match so that the matcher it returns will ignore all
     largefiles'''
@@ -51,13 +53,7 @@
     restore matchfn to reverse'''
     scmutil.match = getattr(scmutil.match, 'oldmatch', scmutil.match)
 
-# -- Wrappers: modify existing commands --------------------------------
-
-# Add works by going through the files that the user wanted to add and
-# checking if they should be added as largefiles. Then it makes a new
-# matcher which matches only the normal files and runs the original
-# version of add.
-def override_add(orig, ui, repo, *pats, **opts):
+def add_largefiles(ui, repo, *pats, **opts):
     large = opts.pop('large', None)
     lfsize = lfutil.getminsize(
         ui, lfutil.islfilesrepo(repo), opts.pop('lfsize', None))
@@ -117,20 +113,10 @@
                     if f in m.files()]
     finally:
         wlock.release()
-
-    installnormalfilesmatchfn(repo[None].manifest())
-    result = orig(ui, repo, *pats, **opts)
-    restorematchfn()
-
-    return (result == 1 or bad) and 1 or 0
+    return bad
 
-def override_remove(orig, ui, repo, *pats, **opts):
-    manifest = repo[None].manifest()
-    installnormalfilesmatchfn(manifest)
-    orig(ui, repo, *pats, **opts)
-    restorematchfn()
-
-    after, force = opts.get('after'), opts.get('force')
+def remove_largefiles(ui, repo, *pats, **opts):
+    after = opts.get('after')
     if not pats and not after:
         raise util.Abort(_('no files specified'))
     m = scmutil.match(repo[None], pats, opts)
@@ -139,18 +125,17 @@
         s = repo.status(match=m, clean=True)
     finally:
         repo.lfstatus = False
+    manifest = repo[None].manifest()
     modified, added, deleted, clean = [[f for f in list
                                         if lfutil.standin(f) in manifest]
                                        for list in [s[0], s[1], s[3], s[6]]]
 
     def warn(files, reason):
         for f in files:
-            ui.warn(_('not removing %s: %s (use -f to force removal)\n')
+            ui.warn(_('not removing %s: %s (use forget to undo)\n')
                     % (m.rel(f), reason))
 
-    if force:
-        remove, forget = modified + deleted + clean, added
-    elif after:
+    if after:
         remove, forget = deleted, []
         warn(modified + added + clean, _('file still exists'))
     else:
@@ -169,21 +154,48 @@
         lfdirstate = lfutil.openlfdirstate(ui, repo)
         for f in remove:
             if not after:
-                os.unlink(repo.wjoin(f))
+                # If this is being called by addremove, notify the user that we
+                # are removing the file.
+                if getattr(repo, "_isaddremove", False):
+                    ui.status(_('removing %s\n' % f))
+                if os.path.exists(repo.wjoin(f)):
+                    os.unlink(repo.wjoin(f))
                 currentdir = os.path.split(f)[0]
                 while currentdir and not os.listdir(repo.wjoin(currentdir)):
                     os.rmdir(repo.wjoin(currentdir))
                     currentdir = os.path.split(currentdir)[0]
             lfdirstate.remove(f)
         lfdirstate.write()
-
         forget = [lfutil.standin(f) for f in forget]
         remove = [lfutil.standin(f) for f in remove]
         lfutil.repo_forget(repo, forget)
-        lfutil.repo_remove(repo, remove, unlink=True)
+        # If this is being called by addremove, let the original addremove
+        # function handle this.
+        if not getattr(repo, "_isaddremove", False):
+            lfutil.repo_remove(repo, remove, unlink=True)
     finally:
         wlock.release()
 
+# -- Wrappers: modify existing commands --------------------------------
+
+# Add works by going through the files that the user wanted to add and
+# checking if they should be added as largefiles. Then it makes a new
+# matcher which matches only the normal files and runs the original
+# version of add.
+def override_add(orig, ui, repo, *pats, **opts):
+    bad = add_largefiles(ui, repo, *pats, **opts)
+    installnormalfilesmatchfn(repo[None].manifest())
+    result = orig(ui, repo, *pats, **opts)
+    restorematchfn()
+
+    return (result == 1 or bad) and 1 or 0
+
+def override_remove(orig, ui, repo, *pats, **opts):
+    installnormalfilesmatchfn(repo[None].manifest())
+    orig(ui, repo, *pats, **opts)
+    restorematchfn()
+    remove_largefiles(ui, repo, *pats, **opts)
+
 def override_status(orig, ui, repo, *pats, **opts):
     try:
         repo.lfstatus = True
@@ -591,7 +603,6 @@
 
 def hg_update(orig, repo, node):
     result = orig(repo, node)
-    # XXX check if it worked first
     lfcommands.updatelfiles(repo.ui, repo)
     return result
 
@@ -840,7 +851,11 @@
             ui.status('\n')
 
 def override_summary(orig, ui, repo, *pats, **opts):
-    orig(ui, repo, *pats, **opts)
+    try:
+        repo.lfstatus = True
+        orig(ui, repo, *pats, **opts)
+    finally:
+        repo.lfstatus = False
 
     if opts.pop('large', None):
         toupload = getoutgoinglfiles(ui, repo, None, **opts)
@@ -850,26 +865,29 @@
             ui.status(_('largefiles: %d to upload\n') % len(toupload))
 
 def override_addremove(orig, ui, repo, *pats, **opts):
-    # Check if the parent or child has largefiles; if so, disallow
-    # addremove. If there is a symlink in the manifest then getting
-    # the manifest throws an exception: catch it and let addremove
-    # deal with it.
-    try:
-        manifesttip = set(repo['tip'].manifest())
-    except util.Abort:
-        manifesttip = set()
-    try:
-        manifestworking = set(repo[None].manifest())
-    except util.Abort:
-        manifestworking = set()
+    # Get the list of missing largefiles so we can remove them
+    lfdirstate = lfutil.openlfdirstate(ui, repo)
+    s = lfdirstate.status(match_.always(repo.root, repo.getcwd()), [], False,
+        False, False)
+    (unsure, modified, added, removed, missing, unknown, ignored, clean) = s
 
-    # Manifests are only iterable so turn them into sets then union
-    for file in manifesttip.union(manifestworking):
-        if file.startswith(lfutil.shortname):
-            raise util.Abort(
-                _('addremove cannot be run on a repo with largefiles'))
-
-    return orig(ui, repo, *pats, **opts)
+    # Call into the normal remove code, but the removing of the standin, we want
+    # to have handled by original addremove.  Monkey patching here makes sure
+    # we don't remove the standin in the largefiles code, preventing a very
+    # confused state later.
+    repo._isaddremove = True
+    remove_largefiles(ui, repo, *missing, **opts)
+    repo._isaddremove = False
+    # Call into the normal add code, and any files that *should* be added as
+    # largefiles will be
+    add_largefiles(ui, repo, *pats, **opts)
+    # Now that we've handled largefiles, hand off to the original addremove
+    # function to take care of the rest.  Make sure it doesn't do anything with
+    # largefiles by installing a matcher that will ignore them.
+    installnormalfilesmatchfn(repo[None].manifest())
+    result = orig(ui, repo, *pats, **opts)
+    restorematchfn()
+    return result
 
 # Calling purge with --all will cause the largefiles to be deleted.
 # Override repo.status to prevent this from happening.
@@ -892,15 +910,19 @@
     result = orig(ui, repo, **opts)
     merge.update(repo, node=None, branchmerge=False, force=True,
         partial=lfutil.isstandin)
-    lfdirstate = lfutil.openlfdirstate(ui, repo)
-    lfiles = lfutil.listlfiles(repo)
-    oldlfiles = lfutil.listlfiles(repo, repo[None].parents()[0].rev())
-    for file in lfiles:
-        if file in oldlfiles:
-            lfdirstate.normallookup(file)
-        else:
-            lfdirstate.add(file)
-    lfdirstate.write()
+    wlock = repo.wlock()
+    try:
+        lfdirstate = lfutil.openlfdirstate(ui, repo)
+        lfiles = lfutil.listlfiles(repo)
+        oldlfiles = lfutil.listlfiles(repo, repo[None].parents()[0].rev())
+        for file in lfiles:
+            if file in oldlfiles:
+                lfdirstate.normallookup(file)
+            else:
+                lfdirstate.add(file)
+        lfdirstate.write()
+    finally:
+        wlock.release()
     return result
 
 def override_transplant(orig, ui, repo, *revs, **opts):
--- a/hgext/largefiles/proto.py	Mon Jan 09 02:32:01 2012 +0700
+++ b/hgext/largefiles/proto.py	Tue Jan 10 15:48:16 2012 -0200
@@ -27,12 +27,12 @@
             proto.getfile(tmpfp)
             tmpfp.seek(0)
             if sha != lfutil.hexsha1(tmpfp):
-                return wireproto.pushres(1)
+                raise IOError(0, _('largefile contents do not match hash'))
             tmpfp.close()
             lfutil.copytostoreabsolute(repo, tmpname, sha)
         except IOError, e:
-            repo.ui.warn(_('largefiles: failed to put %s (%s) into store: %s') %
-                         (sha, tmpname, e.strerror))
+            repo.ui.warn(_('largefiles: failed to put %s into store: %s') %
+                         (sha, e.strerror))
             return wireproto.pushres(1)
     finally:
         tmpfp.close()
@@ -81,10 +81,16 @@
             # input file-like into a bundle before sending it, so we can't use
             # it ...
             if issubclass(self.__class__, httprepo.httprepository):
+                res = None
                 try:
-                    return int(self._call('putlfile', data=fd, sha=sha,
-                        headers={'content-type':'application/mercurial-0.1'}))
+                    res = self._call('putlfile', data=fd, sha=sha,
+                        headers={'content-type':'application/mercurial-0.1'})
+                    d, output = res.split('\n', 1)
+                    for l in output.splitlines(True):
+                        self.ui.warn(_('remote: '), l, '\n')
+                    return int(d)
                 except (ValueError, urllib2.HTTPError):
+                    self.ui.warn(_('unexpected putlfile response: %s') % res)
                     return 1
             # ... but we can't use sshrepository._call because the data=
             # argument won't get sent, and _callpush does exactly what we want
--- a/hgext/largefiles/reposetup.py	Mon Jan 09 02:32:01 2012 +0700
+++ b/hgext/largefiles/reposetup.py	Tue Jan 10 15:48:16 2012 -0200
@@ -11,7 +11,8 @@
 import types
 import os
 
-from mercurial import context, error, manifest, match as match_, node, util
+from mercurial import context, error, manifest, match as match_, util
+from mercurial import node as node_
 from mercurial.i18n import _
 
 import lfcommands
@@ -26,8 +27,6 @@
 
     for name in ('status', 'commitctx', 'commit', 'push'):
         method = getattr(repo, name)
-        #if not (isinstance(method, types.MethodType) and
-        #        method.im_func is repo.__class__.commitctx.im_func):
         if (isinstance(method, types.FunctionType) and
             method.func_name == 'wrap'):
             ui.warn(_('largefiles: repo method %r appears to have already been'
@@ -148,9 +147,6 @@
                 result = super(lfiles_repo, self).status(node1, node2, m,
                     True, clean, unknown, listsubrepos)
                 if working:
-                    # hold the wlock while we read largefiles and
-                    # update the lfdirstate
-                    wlock = repo.wlock()
                     try:
                         # Any non-largefiles that were explicitly listed must be
                         # taken out or lfdirstate.status will report an error.
@@ -187,7 +183,6 @@
                                 else:
                                     clean.append(lfile)
                                     lfdirstate.normal(lfile)
-                            lfdirstate.write()
                         else:
                             tocheck = unsure + modified + added + clean
                             modified, added, clean = [], [], []
@@ -202,10 +197,9 @@
                                         clean.append(lfile)
                                 else:
                                     added.append(lfile)
+                    finally:
                         # Replace the original ignore function
                         lfdirstate._ignore = orig_ignore
-                    finally:
-                        wlock.release()
 
                     for standin in ctx1.manifest():
                         if not lfutil.isstandin(standin):
@@ -262,12 +256,7 @@
         # cache.
         def commitctx(self, *args, **kwargs):
             node = super(lfiles_repo, self).commitctx(*args, **kwargs)
-            ctx = self[node]
-            for filename in ctx.files():
-                if lfutil.isstandin(filename) and filename in ctx.manifest():
-                    realfile = lfutil.splitstandin(filename)
-                    lfutil.copytostore(self, ctx.node(), realfile)
-
+            lfutil.copyalltostore(self, node)
             return node
 
         # Before commit, largefile standins have not had their
@@ -279,14 +268,18 @@
 
             wlock = repo.wlock()
             try:
+                # Case 0: Rebase
+                # We have to take the time to pull down the new largefiles now.
+                # Otherwise if we are rebasing, any largefiles that were
+                # modified in the destination changesets get overwritten, either
+                # by the rebase or in the first commit after the rebase.
+                # updatelfiles will update the dirstate to mark any pulled
+                # largefiles as modified
                 if getattr(repo, "_isrebasing", False):
-                    # We have to take the time to pull down the new
-                    # largefiles now. Otherwise if we are rebasing,
-                    # any largefiles that were modified in the
-                    # destination changesets get overwritten, either
-                    # by the rebase or in the first commit after the
-                    # rebase.
                     lfcommands.updatelfiles(repo.ui, repo)
+                    result = orig(text=text, user=user, date=date, match=match,
+                                    force=force, editor=editor, extra=extra)
+                    return result
                 # Case 1: user calls commit with no specific files or
                 # include/exclude patterns: refresh and commit all files that
                 # are "dirty".
@@ -321,10 +314,13 @@
                             if not os.path.exists(
                                     repo.wjoin(lfutil.standin(lfile))):
                                 lfdirstate.drop(lfile)
+
+                    result = orig(text=text, user=user, date=date, match=match,
+                                    force=force, editor=editor, extra=extra)
+                    # This needs to be after commit; otherwise precommit hooks
+                    # get the wrong status
                     lfdirstate.write()
-
-                    return orig(text=text, user=user, date=date, match=match,
-                                    force=force, editor=editor, extra=extra)
+                    return result
 
                 for f in match.files():
                     if lfutil.isstandin(f):
@@ -356,7 +352,6 @@
                         lfdirstate.normal(lfile)
                     else:
                         lfdirstate.drop(lfile)
-                lfdirstate.write()
 
                 # Cook up a new matcher that only matches regular files or
                 # standins corresponding to the big files requested by the
@@ -397,8 +392,12 @@
                         return f in standins
 
                 match.matchfn = matchfn
-                return orig(text=text, user=user, date=date, match=match,
+                result = orig(text=text, user=user, date=date, match=match,
                                 force=force, editor=editor, extra=extra)
+                # This needs to be after commit; otherwise precommit hooks
+                # get the wrong status
+                lfdirstate.write()
+                return result
             finally:
                 wlock.release()
 
@@ -409,7 +408,7 @@
                 o = repo.changelog.nodesbetween(o, revs)[0]
                 for n in o:
                     parents = [p for p in repo.changelog.parents(n)
-                               if p != node.nullid]
+                               if p != node_.nullid]
                     ctx = repo[n]
                     files = set(ctx.files())
                     if len(parents) == 2:
--- a/hgext/mq.py	Mon Jan 09 02:32:01 2012 +0700
+++ b/hgext/mq.py	Tue Jan 10 15:48:16 2012 -0200
@@ -1854,8 +1854,9 @@
 def delete(ui, repo, *patches, **opts):
     """remove patches from queue
 
-    The patches must not be applied, and at least one patch is required. With
-    -k/--keep, the patch files are preserved in the patch directory.
+    The patches must not be applied, and at least one patch is required. Exact
+    patch identifiers must be given. With -k/--keep, the patch files are
+    preserved in the patch directory.
 
     To stop managing a patch and move it into permanent history,
     use the :hg:`qfinish` command."""
--- a/hgext/progress.py	Mon Jan 09 02:32:01 2012 +0700
+++ b/hgext/progress.py	Tue Jan 10 15:48:16 2012 -0200
@@ -2,19 +2,8 @@
 #
 # Copyright (C) 2010 Augie Fackler <durin42@gmail.com>
 #
-# This program is free software; you can redistribute it and/or modify it
-# under the terms of the GNU General Public License as published by the
-# Free Software Foundation; either version 2 of the License, or (at your
-# option) any later version.
-#
-# This program is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General
-# Public License for more details.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write to the Free Software Foundation, Inc.,
-# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+# This software may be used and distributed according to the terms of the
+# GNU General Public License version 2 or any later version.
 
 """show progress bars for some actions
 
--- a/hgext/purge.py	Mon Jan 09 02:32:01 2012 +0700
+++ b/hgext/purge.py	Tue Jan 10 15:48:16 2012 -0200
@@ -20,8 +20,7 @@
 # GNU General Public License for more details.
 #
 # You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
 
 '''command to delete untracked files from the working directory'''
 
--- a/hgext/rebase.py	Mon Jan 09 02:32:01 2012 +0700
+++ b/hgext/rebase.py	Tue Jan 10 15:48:16 2012 -0200
@@ -15,7 +15,7 @@
 '''
 
 from mercurial import hg, util, repair, merge, cmdutil, commands, bookmarks
-from mercurial import extensions, patch
+from mercurial import extensions, patch, scmutil
 from mercurial.commands import templateopts
 from mercurial.node import nullrev
 from mercurial.lock import release
@@ -187,10 +187,12 @@
             if revf:
                 rebaseset = repo.revs('%lr', revf)
             elif srcf:
-                rebaseset = repo.revs('(%r)::', srcf)
+                src = scmutil.revrange(repo, [srcf])
+                rebaseset = repo.revs('(%ld)::', src)
             else:
-                base = basef or '.'
-                rebaseset = repo.revs('(children(ancestor(%r, %d)) & ::%r)::',
+                base = scmutil.revrange(repo, [basef or '.'])
+                rebaseset = repo.revs(
+                    '(children(ancestor(%ld, %d)) and ::(%ld))::',
                     base, dest, base)
 
             if rebaseset:
@@ -269,7 +271,7 @@
                                         'resolve, then hg rebase --continue)'))
                     finally:
                         ui.setconfig('ui', 'forcemerge', '')
-                cmdutil.duplicatecopies(repo, rev, target, p2)
+                cmdutil.duplicatecopies(repo, rev, target)
                 if not collapsef:
                     newrev = concludenode(repo, rev, p1, p2, extrafn=extrafn,
                                           editor=editor)
--- a/hgext/zeroconf/Zeroconf.py	Mon Jan 09 02:32:01 2012 +0700
+++ b/hgext/zeroconf/Zeroconf.py	Tue Jan 10 15:48:16 2012 -0200
@@ -17,8 +17,8 @@
     Lesser General Public License for more details.
 
     You should have received a copy of the GNU Lesser General Public
-    License along with this library; if not, write to the Free Software
-    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+    License along with this library; if not, see
+    <http://www.gnu.org/licenses/>.
 
 """
 
--- a/i18n/ja.po	Mon Jan 09 02:32:01 2012 +0700
+++ b/i18n/ja.po	Tue Jan 10 15:48:16 2012 -0200
@@ -108,7 +108,7 @@
 msgstr ""
 "Project-Id-Version: Mercurial\n"
 "Report-Msgid-Bugs-To: <mercurial-devel@selenic.com>\n"
-"POT-Creation-Date: 2011-12-29 12:28+0900\n"
+"POT-Creation-Date: 2011-12-31 13:47+0900\n"
 "PO-Revision-Date: 2009-11-16 21:24+0100\n"
 "Last-Translator: Japanese translation team <mercurial-ja@googlegroups.com>\n"
 "Language-Team: Japanese\n"
@@ -381,16 +381,17 @@
 #, python-format
 msgid "acl: user \"%s\" not allowed on branch \"%s\" (changeset \"%s\")"
 msgstr ""
-
-#, fuzzy, python-format
+"acl: ユーザ \"%s\" はブランチ \"%s\" が許可されていません(リビジョン \"%s\")"
+
+#, python-format
 msgid "acl: user \"%s\" denied on \"%s\" (changeset \"%s\")"
 msgstr ""
-"acl: ユーザ \"%s\" はブランチ \"%s\" で拒否されました(リビジョン \"%s\")"
-
-#, fuzzy, python-format
+"acl: ユーザ \"%s\" はファイル \"%s\" で拒否されました(リビジョン \"%s\")"
+
+#, python-format
 msgid "acl: user \"%s\" not allowed on \"%s\" (changeset \"%s\")"
 msgstr ""
-"acl: ユーザ \"%s\" はブランチ \"%s\" で拒否されました(リビジョン \"%s\")"
+"acl: ユーザ \"%s\" はファイル \"%s\" が許可されていません(リビジョン \"%s\")"
 
 msgid "hooks for integrating with the Bugzilla bug tracker"
 msgstr ""
@@ -3345,9 +3346,8 @@
 "    指定されたファイルに未コミット変更がある場合、 実行は中断されます。\n"
 "    "
 
-#, fuzzy
 msgid "track large binary files"
-msgstr "これはバイナリファイルです\n"
+msgstr "大容量バイナリファイルの管理"
 
 msgid ""
 "Large binary files tend to be not very compressible, not very\n"
@@ -3443,12 +3443,19 @@
 
 msgid ""
 "Files that match one of these patterns will be added as largefiles\n"
-"regardless of their size.\n"
-msgstr ""
-
-#, fuzzy
+"regardless of their size."
+msgstr ""
+
+msgid ""
+"The ``largefiles.minsize`` and ``largefiles.patterns`` config options\n"
+"will be ignored for any repositories not already containing a\n"
+"largefile. To add the first largefile to a repository, you must\n"
+"explicitly do so with the --large flag passed to the :hg:`add`\n"
+"command.\n"
+msgstr ""
+
 msgid "convert a normal repository to a largefiles repository"
-msgstr "別 SCM のリポジトリから Mercurial リポジトリへの変換"
+msgstr "既存リポジトリから largefiles を利用するリポジトリへの変換"
 
 msgid ""
 "    Convert repository SOURCE to a new repository DEST, identical to\n"
@@ -3472,21 +3479,20 @@
 "    this, the DEST repository can be used without largefiles at all."
 msgstr ""
 
-#, fuzzy
 msgid "getting largefiles"
-msgstr "ファイルの取得中"
-
-#, fuzzy, python-format
+msgstr "大容量ファイルの取得中"
+
+#, python-format
 msgid "getting %s:%s\n"
-msgstr "%s を取得しています\n"
+msgstr "ファイル %s の取得中:%s\n"
 
 #, python-format
 msgid "%s: data corruption (expected %s, got %s)\n"
 msgstr ""
 
-#, fuzzy, python-format
+#, python-format
 msgid "searching %d changesets for largefiles\n"
-msgstr "類似ファイルを探索中"
+msgstr "大容量ファイルのために %d 個のリビジョンを検索中\n"
 
 #, python-format
 msgid "verified contents of %d revisions of %d largefiles\n"
@@ -3496,25 +3502,24 @@
 msgid "verified existence of %d revisions of %d largefiles\n"
 msgstr ""
 
-#, fuzzy, python-format
+#, python-format
 msgid "unsupported URL scheme %r"
-msgstr "URL 要素 \"%s\" は未サポートです"
-
-#, fuzzy, python-format
+msgstr "%r は未サポートな URL 形式です"
+
+#, python-format
 msgid "%s does not appear to be a largefile store"
-msgstr "'%s' は Mercurial リポジトリ形式とは思われません"
-
-#, fuzzy, python-format
+msgstr "%s は largefiles 対応とは思われません"
+
+#, python-format
 msgid "%s is not a local Mercurial repo"
 msgstr "%s はローカルの Mercurial リポジトリではありません"
 
-#, fuzzy, python-format
+#, python-format
 msgid "initializing destination %s\n"
 msgstr "変換先リポジトリ %s の初期化中\n"
 
-#, fuzzy
 msgid "converting revisions"
-msgstr "リビジョンの表示"
+msgstr "リビジョンの変換中"
 
 #, python-format
 msgid "renamed/copied largefile %s becomes symlink"
@@ -3531,9 +3536,8 @@
 msgid "largefile %s missing from store (needs to be uploaded)"
 msgstr ""
 
-#, fuzzy
 msgid "getting changed largefiles\n"
-msgstr "ファイルの取得中"
+msgstr "更新された大容量ファイルの取得中\n"
 
 #, python-format
 msgid "%d largefiles updated, %d removed\n"
@@ -3545,9 +3549,8 @@
 msgid "convert from a largefiles repo to a normal repo"
 msgstr ""
 
-#, fuzzy
 msgid "hg lfconvert SOURCE DEST [FILE ...]"
-msgstr "hg convert [OPTION]... SOURCE [DEST [REVMAP]]"
+msgstr "hg lfconvert SOURCE DEST [FILE ...]"
 
 #, python-format
 msgid "largefiles: size must be number (not %s)\n"
@@ -3556,13 +3559,13 @@
 msgid "minimum size for largefiles must be specified"
 msgstr ""
 
-#, fuzzy, python-format
+#, python-format
 msgid "unknown operating system: %s\n"
-msgstr "未知のパッチです: %s\n"
-
-#, fuzzy, python-format
+msgstr "未知の OS です: %s\n"
+
+#, python-format
 msgid "Found %s in store\n"
-msgstr "%s が %r にありました\n"
+msgstr "%s が見つかりました\n"
 
 #, python-format
 msgid "Found %s in system cache\n"
@@ -3589,33 +3592,29 @@
 "  but got %s)\n"
 msgstr ""
 
-#, fuzzy, python-format
+#, python-format
 msgid "%s already a largefile\n"
-msgstr "%s は登録済です!\n"
-
-#, fuzzy, python-format
+msgstr "%s は大容量ファイルとして登録済です\n"
+
+#, python-format
 msgid "adding %s as a largefile\n"
-msgstr "パッチ %s を追加中\n"
+msgstr "%s を大容量ファイルとして追加登録中\n"
 
 msgid "no files specified"
 msgstr "ファイル名指定がありません"
 
-#, fuzzy, python-format
+#, python-format
 msgid "not removing %s: %s (use -f to force removal)\n"
-msgstr ""
-"%s は削除されません: ファイルは改変されています(削除の強行は -f を指定)\n"
-
-#, fuzzy
+msgstr "%s は削除されません: %s (削除の強行は -f を指定)\n"
+
 msgid "file still exists"
-msgstr "ファイル %s は既に存在します\n"
-
-#, fuzzy
+msgstr "ファイルは維持されます"
+
 msgid "file is modified"
-msgstr "変更ファイル数     %d"
-
-#, fuzzy
+msgstr "ファイルは改変されています"
+
 msgid "file has been marked for add"
-msgstr "%s: コピー失敗 - 削除予定のファイルです\n"
+msgstr "追加登録予定のファイルです"
 
 #, python-format
 msgid "removing %s\n"
@@ -3650,12 +3649,12 @@
 msgid "merging %s\n"
 msgstr "%s をマージ中\n"
 
-#, fuzzy, python-format
+#, python-format
 msgid ""
 "largefile %s has a merge conflict\n"
 "keep (l)ocal or take (o)ther?"
 msgstr ""
-" %s のマージに適切なツールが見つかりません\n"
+"大容量ファイル %s のマージで衝突が検出されました。\n"
 "どちらの内容を採用しますか? 作業領域:(l)ocal マージ対象:(o)ther"
 
 msgid "&Local"
@@ -3664,9 +3663,8 @@
 msgid "&Other"
 msgstr "&Other"
 
-#, fuzzy
 msgid "destination largefile already exists"
-msgstr "複製先 '%s' は既に存在します"
+msgstr "大容量ファイルの複製先は既に存在します"
 
 msgid "no files to copy"
 msgstr "コピーするファイルがありません"
@@ -3682,16 +3680,15 @@
 msgid "not removing %s: file is already untracked\n"
 msgstr "%s は削除されません: 既に構成管理対象ではありません\n"
 
-#, fuzzy
 msgid "largefiles: No remote repo\n"
-msgstr "ローカルリポジトリ以外は検証できません"
+msgstr ""
 
 msgid "largefiles to upload:\n"
-msgstr ""
+msgstr "転送予定大容量ファイル:\n"
 
 #, python-format
 msgid "largefiles: %d to upload\n"
-msgstr ""
+msgstr "largefiles: 転送予定ファイル数 %d\n"
 
 msgid "addremove cannot be run on a repo with largefiles"
 msgstr ""
@@ -3704,13 +3701,11 @@
 msgid "requested largefile %s not present in cache"
 msgstr ""
 
-#, fuzzy
 msgid "putlfile failed:"
-msgstr "フィルターに失敗"
-
-#, fuzzy
+msgstr "大容量ファイルの転送に失敗:"
+
 msgid "putlfile failed (unexpected response):"
-msgstr "履歴反映に失敗(未知のレスポンス):"
+msgstr "大容量ファイルの転送に失敗 (未知の応答):"
 
 msgid "unexpected response:"
 msgstr "未知の応答:"
@@ -3723,9 +3718,9 @@
 msgid "remotestore: put %s to remote store %s"
 msgstr ""
 
-#, fuzzy, python-format
+#, python-format
 msgid "remotestore: could not open file %s: %s"
-msgstr "変換ファイル %r を開くことができません: %s"
+msgstr "remotestore: ファイル %s を開くことができません: %s"
 
 #, python-format
 msgid "remotestore: largefile %s is invalid"
@@ -3735,13 +3730,13 @@
 msgid "remotestore: largefile %s is missing"
 msgstr ""
 
-#, fuzzy, python-format
+#, python-format
 msgid "changeset %s: %s: contents differ\n"
-msgstr "リビジョン %d:%s: %s\n"
-
-#, fuzzy, python-format
+msgstr "リビジョン %s: %s: 内容が異なります\n"
+
+#, python-format
 msgid "changeset %s: %s missing\n"
-msgstr "リビジョン %d:%s: %s\n"
+msgstr "リビジョン %s: ファイル %s が不在です\n"
 
 #, python-format
 msgid ""
@@ -3769,9 +3764,8 @@
 msgid "verify largefile contents not just existence"
 msgstr ""
 
-#, fuzzy
 msgid "display outgoing largefiles"
-msgstr "当該スタイルで表示をカスタマイズ"
+msgstr "転送対象大容量ファイルを表示"
 
 msgid "manage a stack of patches"
 msgstr "パッチ併用の管理"
@@ -5315,9 +5309,8 @@
 msgid "operate on patch repository"
 msgstr "パッチ管理リポジトリへの操作"
 
-#, fuzzy
 msgid "hooks for sending email push notifications"
-msgstr "commit/push 契機でのメール通知用フック集"
+msgstr "push 通知電子メール送信用のフック集"
 
 msgid ""
 "This extension let you run hooks sending email notifications when\n"
@@ -6147,9 +6140,8 @@
 "ancestor of base and dest)"
 msgstr "指定リビジョンの先祖から移動 (移動先との共通祖先まで遡ります)"
 
-#, fuzzy
 msgid "rebase these revisions"
-msgstr "指定リビジョンの解析"
+msgstr "指定リビジョンの移動"
 
 msgid "rebase onto the specified changeset"
 msgstr "複製先リビジョン"
@@ -6305,16 +6297,14 @@
 msgid "tool option will be ignored\n"
 msgstr ""
 
-#, fuzzy
 msgid "cannot specify both a source and a base"
 msgstr "--soruce と --base は併用できません"
 
 msgid "cannot specify both a revision and a base"
-msgstr "--soruce と --base は併用できません"
-
-#, fuzzy
+msgstr "--rev と --base は併用できません"
+
 msgid "cannot specify both a revision and a source"
-msgstr "--soruce と --base は併用できません"
+msgstr "--rev と --soruce は併用できません"
 
 msgid "detach requires a revision to be specified"
 msgstr "--detach にはリビジョン指定が必要です"
@@ -6325,9 +6315,8 @@
 msgid "can't remove original changesets with unrebased descendants"
 msgstr ""
 
-#, fuzzy
 msgid "use --keep to keep original changesets"
-msgstr "元リビジョンを維持"
+msgstr "元リビジョンを維持する場合は --keep を使用してください"
 
 msgid "nothing to rebase\n"
 msgstr "リベースの必要はありません\n"
@@ -6380,9 +6369,8 @@
 msgid "cannot rebase onto an applied mq patch"
 msgstr "MQ パッチ上へのリベースはできません"
 
-#, fuzzy
 msgid "no matching revisions"
-msgstr "合致するガードはありません"
+msgstr "合致するリビジョンはありません"
 
 msgid "can't rebase multiple roots"
 msgstr ""
@@ -6718,18 +6706,16 @@
 "    "
 msgstr ""
 
-#, fuzzy
 msgid "convert a shared repository to a normal one"
-msgstr "別 SCM のリポジトリから Mercurial リポジトリへの変換"
+msgstr "共有状態のリポジトリから通常リポジトリへの変換"
 
 msgid ""
 "    Copy the store data to the repo and remove the sharedpath data.\n"
 "    "
 msgstr ""
 
-#, fuzzy
 msgid "this is not a shared repo"
-msgstr "%s は %s の親リビジョンではありません"
+msgstr "共有状態のリポジトリではありません"
 
 msgid "do not create a working copy"
 msgstr "作業領域の更新を抑止します"
@@ -11275,21 +11261,13 @@
 "    - unbundle"
 
 msgid ""
-"    It's possible to lose data with rollback: commit, update back to\n"
-"    an older changeset, and then rollback. The update removes the\n"
-"    changes you committed from the working directory, and rollback\n"
-"    removes them from history. To avoid data loss, you must pass\n"
-"    --force in this case."
-msgstr ""
-"    例えば commit、旧リビジョンへの update、 rollback の順で実行すると、\n"
-"    データが喪失します。 commit 内容が、 update により作業領域から、\n"
-"    rollback により履歴から破棄されるためです。\n"
-"    このケースにおけるデータ喪失を避けるには --force を指定してください。\n"
-"    (訳注: --force 指定が『無い』場合、 このケースのようなデータ喪失は、\n"
-"    実行中断により防止されます。 原文では、 --force 指定は\n"
-"    \"avoid data loss\" (データ喪失の回避) のためと記載されていますが、\n"
-"    実際には『データ喪失に構わず rollback を強行する』場合にのみ\n"
-"    --force を指定してください)"
+"    To avoid permanent data loss, rollback will refuse to rollback a\n"
+"    commit transaction if it isn't checked out. Use --force to\n"
+"    override this protection."
+msgstr ""
+"    データが永遠に失われるのを回避するため、 コミットの巻き戻し操作は、\n"
+"    作業領域の親リビジョン以外に対しては、 失敗するようになっています。\n"
+"    この回避挙動は --force 指定により抑止されます。"
 
 msgid ""
 "    This command is not intended for use on public repositories. Once\n"
@@ -20286,85 +20264,10 @@
 msgstr "連携先でのリビジョンの検索"
 
 msgid "push failed (unexpected response):"
-msgstr "履歴反映に失敗(未知のレスポンス):"
+msgstr "履歴反映に失敗 (未知の応答):"
 
 msgid "look up remote changes"
 msgstr "連携先での変更の検索"
 
 msgid "push failed:"
 msgstr "履歴反映に失敗:"
-
-#~ msgid "acl: access denied for changeset %s"
-#~ msgstr "acl: チェンジセット %s のアクセスは拒否されました"
-
-#~ msgid "%s Please enter a valid value"
-#~ msgstr "%s 適切な値を入力してください"
-
-#~ msgid "Please enter a valid value.\n"
-#~ msgstr "適切な値を入力してください。\n"
-
-#~ msgid "source is descendant of destination"
-#~ msgstr "移動元は移動先の子孫です"
-
-#~ msgid "cannot backout a merge changeset without --parent"
-#~ msgstr "マージリビジョンの打消しには --parent 指定が必要です"
-
-#~ msgid "    .. note::"
-#~ msgstr "    .. note::"
-
-#~ msgid "    See :hg:`help urls` for valid source format details."
-#~ msgstr ""
-#~ "    リポジトリ位置指定の詳細は、 :hg:`help urls` を参照してください。"
-
-#~ msgid ""
-#~ "    It is possible to specify an ``ssh://`` URL as the destination, but "
-#~ "no\n"
-#~ "    ``.hg/hgrc`` and working directory will be created on the remote "
-#~ "side.\n"
-#~ "    Please see :hg:`help urls` for important details about ``ssh://`` "
-#~ "URLs."
-#~ msgstr ""
-#~ "    複製先として ``ssh://`` URL 形式を指定することも可能ですが、\n"
-#~ "    遠隔ホスト上では、 ``.hg/hgrc`` の作成も、\n"
-#~ "    作業領域の更新も行われません。\n"
-#~ "    ``ssh://`` URL 形式の詳細は、 :hg:`help urls` を参照してください。"
-
-#~ msgid ""
-#~ "    A set of changesets (tags, or branch names) to pull may be specified\n"
-#~ "    by listing each changeset (tag, or branch name) with -r/--rev.\n"
-#~ "    If -r/--rev is used, the cloned repository will contain only a "
-#~ "subset\n"
-#~ "    of the changesets of the source repository. Only the set of "
-#~ "changesets\n"
-#~ "    defined by all -r/--rev options (including all their ancestors)\n"
-#~ "    will be pulled into the destination repository.\n"
-#~ "    No subsequent changesets (including subsequent tags) will be present\n"
-#~ "    in the destination."
-#~ msgstr ""
-#~ "    複製先に取り込む一連のリビジョンは、 -r/--rev によりリビジョン\n"
-#~ "    (タグ名やブランチ名も可) を列挙することで指定します。\n"
-#~ "    -r/--rev でのリビジョン指定複製を行なう場合、 複製先リポジトリには、\n"
-#~ "    複製元リポジトリの持つリビジョンの、 一部のみが取り込まれます。\n"
-#~ "    取り込み対象は、 -r/--rev での指定リビジョン (およびその祖先) です。\n"
-#~ "    指定リビジョン以後のリビジョンは、 複製先に取り込まれません\n"
-#~ "    (後続のタグ付けリビジョンも除外されます)。"
-
-#~ msgid ""
-#~ "    Using -r/--rev (or 'clone src#rev dest') implies --pull, even for\n"
-#~ "    local source repositories."
-#~ msgstr ""
-#~ "    -r/--rev 指定付き (ないしは :hg:`clone 複製元#リビジョン` 形式)\n"
-#~ "    複製の場合、 同一ファイルシステム上での複製であっても、\n"
-#~ "    暗黙的に --pull 指定を伴います。"
-
-#~ msgid "options:\n"
-#~ msgstr "オプション:\n"
-
-#~ msgid "applied %s\n"
-#~ msgstr "%s に対して適用\n"
-
-#~ msgid "limit requires two arguments"
-#~ msgstr "limit 指定には2つの引数が必要です"
-
-#~ msgid "last requires two arguments"
-#~ msgstr "last 指定には2つの引数が必要です"
--- a/i18n/pt_BR.po	Mon Jan 09 02:32:01 2012 +0700
+++ b/i18n/pt_BR.po	Tue Jan 10 15:48:16 2012 -0200
@@ -4206,10 +4206,23 @@
 
 msgid ""
 "Files that match one of these patterns will be added as largefiles\n"
-"regardless of their size.\n"
+"regardless of their size."
 msgstr ""
 "Arquivos que corresponderem a um desses padrões serão adicionados\n"
-"como largefiles sem que seus tamanhos sejam considerados.\n"
+"como largefiles sem que seus tamanhos sejam considerados."
+
+msgid ""
+"The ``largefiles.minsize`` and ``largefiles.patterns`` config options\n"
+"will be ignored for any repositories not already containing a\n"
+"largefile. To add the first largefile to a repository, you must\n"
+"explicitly do so with the --large flag passed to the :hg:`add`\n"
+"command.\n"
+msgstr ""
+"As opções de configuração ``largefiles.minsize`` e ``largefiles.patterns``\n"
+"serão ignoradas em qualquer repositório que ainda não contenha um\n"
+"largefile. Para adicionar o primeiro largefile de um repositório,\n"
+"você deve fazê-lo explicitamente passando a opção --large para o\n"
+"comando :hg:`add`.\n"
 
 msgid "convert a normal repository to a largefiles repository"
 msgstr "converte um repositório normal em um repositório largefiles"
@@ -4402,6 +4415,28 @@
 msgid "uncommitted local changes"
 msgstr "alterações locais pendentes"
 
+msgid "&Largefile"
+msgstr "&Largefile"
+
+msgid "&Normal file"
+msgstr "Arquivo &Normal"
+
+#, python-format
+msgid ""
+"%s has been turned into a largefile\n"
+"use (l)argefile or keep as (n)ormal file?"
+msgstr ""
+"%s foi transformado em um largefile\n"
+"usar (l)argefile ou manter como arquivo (n)ormal?"
+
+#, python-format
+msgid ""
+"%s has been turned into a normal file\n"
+"keep as (l)argefile or use (n)ormal file?"
+msgstr ""
+"%s foi transformado em um arquivo normal\n"
+"manter como (l)argefile ou usar um arquivo (n)ormal?"
+
 #, python-format
 msgid "merging %s and %s to %s\n"
 msgstr "mesclando %s e %s para %s\n"
@@ -10651,12 +10686,12 @@
 
 msgid ""
 "    If a graft merge results in conflicts, the graft process is\n"
-"    aborted so that the current merge can be manually resolved. Once\n"
-"    all conflicts are addressed, the graft process can be continued\n"
-"    with the -c/--continue option."
+"    interrupted so that the current merge can be manually resolved.\n"
+"    Once all conflicts are addressed, the graft process can be\n"
+"    continued with the -c/--continue option."
 msgstr ""
 "    Se a mesclagem de enxerto resultar em conflitos, o processo de\n"
-"    enxerto será abortado para que a mesclagem atual possa ser\n"
+"    enxerto será interrompido para que a mesclagem atual possa ser\n"
 "    resolvida manualmente. Uma vez que todos os conflitos estejam\n"
 "    resolvidos, o processo de enxerto pode ser retomado usando a\n"
 "    opção -c/--continue."
@@ -12502,17 +12537,14 @@
 "    - unbundle"
 
 msgid ""
-"    It's possible to lose data with rollback: commit, update back to\n"
-"    an older changeset, and then rollback. The update removes the\n"
-"    changes you committed from the working directory, and rollback\n"
-"    removes them from history. To avoid data loss, you must pass\n"
-"    --force in this case."
-msgstr ""
-"    É possível perder dados com o comando rollback: se for feito um\n"
-"    commit, update para uma revisão antiga, e em seguida rollback.\n"
-"    O update remove as mudanças recém gravadas na última consolidação,\n"
-"    e o rollback as remove do histórico. Para evitar perda de dados,\n"
-"    você deve passar --force neste caso."
+"    To avoid permanent data loss, rollback will refuse to rollback a\n"
+"    commit transaction if it isn't checked out. Use --force to\n"
+"    override this protection."
+msgstr ""
+"    Para evitar perda permanente de dados, o comando rollback se recusará\n"
+"    a desfazer a transação de um commit se a revisão correspondente não\n"
+"    for a revisão atual do diretório de trabalho. Para desabilitar essa\n"
+"    proteção e remover a revisão de qualquer maneira, use a opção --force."
 
 msgid ""
 "    This command is not intended for use on public repositories. Once\n"
--- a/mercurial/byterange.py	Mon Jan 09 02:32:01 2012 +0700
+++ b/mercurial/byterange.py	Tue Jan 10 15:48:16 2012 -0200
@@ -9,10 +9,8 @@
 #   Lesser General Public License for more details.
 #
 #   You should have received a copy of the GNU Lesser General Public
-#   License along with this library; if not, write to the
-#      Free Software Foundation, Inc.,
-#      59 Temple Place, Suite 330,
-#      Boston, MA  02111-1307  USA
+#   License along with this library; if not, see
+#   <http://www.gnu.org/licenses/>.
 
 # This file is part of urlgrabber, a high-level cross-protocol url-grabber
 # Copyright 2002-2004 Michael D. Stenner, Ryan Tomayko
--- a/mercurial/cmdutil.py	Mon Jan 09 02:32:01 2012 +0700
+++ b/mercurial/cmdutil.py	Tue Jan 10 15:48:16 2012 -0200
@@ -1198,18 +1198,10 @@
         bad.extend(f for f in rejected if f in match.files())
     return bad
 
-def duplicatecopies(repo, rev, p1, p2):
+def duplicatecopies(repo, rev, p1):
     "Reproduce copies found in the source revision in the dirstate for grafts"
-    # Here we simulate the copies and renames in the source changeset
-    cop, diver = copies.copies(repo, repo[rev], repo[p1], repo[p2], True)
-    m1 = repo[rev].manifest()
-    m2 = repo[p1].manifest()
-    for k, v in cop.iteritems():
-        if k in m1:
-            if v in m1 or v in m2:
-                repo.dirstate.copy(v, k)
-                if v in m2 and v not in m1 and k in m2:
-                    repo.dirstate.remove(v)
+    for dst, src in copies.pathcopies(repo[p1], repo[rev]).iteritems():
+        repo.dirstate.copy(src, dst)
 
 def commit(ui, repo, commitfunc, pats, opts):
     '''commit the specified files or all outstanding changes'''
--- a/mercurial/commands.py	Mon Jan 09 02:32:01 2012 +0700
+++ b/mercurial/commands.py	Tue Jan 10 15:48:16 2012 -0200
@@ -2627,7 +2627,7 @@
             repo.dirstate.setparents(current.node(), nullid)
             repo.dirstate.write()
             # fix up dirstate for copies and renames
-            cmdutil.duplicatecopies(repo, ctx.rev(), current.node(), nullid)
+            cmdutil.duplicatecopies(repo, ctx.rev(), current.node())
             # report any conflicts
             if stats and stats[3] > 0:
                 # write out state for --continue
@@ -2694,7 +2694,7 @@
 
     Returns 0 if a match is found, 1 otherwise.
     """
-    reflags = 0
+    reflags = re.M
     if opts.get('ignore_case'):
         reflags |= re.I
     try:
@@ -3444,7 +3444,7 @@
     revision.
 
     With -s/--similarity, hg will attempt to discover renames and
-    copies in the patch in the same way as 'addremove'.
+    copies in the patch in the same way as :hg:`addremove`.
 
     To read a patch from standard input, use "-" as the patch name. If
     a URL is specified, the patch will be downloaded from it.
@@ -5206,18 +5206,7 @@
     changestates = zip(states, 'MAR!?IC', stat)
 
     if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
-        ctxn = repo[nullid]
-        ctx1 = repo[node1]
-        ctx2 = repo[node2]
-        added = stat[1]
-        if node2 is None:
-            added = stat[0] + stat[1] # merged?
-
-        for k, v in copies.copies(repo, ctx1, ctx2, ctxn)[0].iteritems():
-            if k in added:
-                copy[k] = v
-            elif v in added:
-                copy[v] = k
+        copy = copies.pathcopies(repo[node1], repo[node2])
 
     for state, char, files in changestates:
         if state in show:
--- a/mercurial/context.py	Mon Jan 09 02:32:01 2012 +0700
+++ b/mercurial/context.py	Tue Jan 10 15:48:16 2012 -0200
@@ -7,7 +7,7 @@
 
 from node import nullid, nullrev, short, hex
 from i18n import _
-import ancestor, mdiff, error, util, scmutil, subrepo, patch, encoding
+import ancestor, mdiff, error, util, scmutil, subrepo, patch, encoding, phases
 import match as matchmod
 import os, errno, stat
 
@@ -119,13 +119,15 @@
         return self._repo.nodebookmarks(self._node)
     def phase(self):
         if self._rev == -1:
-            return 0
+            return phases.public
         if self._rev >= len(self._repo._phaserev):
             # outdated cache
             del self._repo._phaserev
         return self._repo._phaserev[self._rev]
+    def phasestr(self):
+        return phases.phasenames[self.phase()]
     def mutable(self):
-        return self._repo._phaserev[self._rev] > 0
+        return self._repo._phaserev[self._rev] > phases.public
     def hidden(self):
         return self._rev in self._repo.changelog.hiddenrevs
 
@@ -812,7 +814,7 @@
         return b
 
     def phase(self):
-        phase = 1 # default phase to draft
+        phase = phases.draft # default phase to draft
         for p in self.parents():
             phase = max(phase, p.phase())
         return phase
--- a/mercurial/copies.py	Mon Jan 09 02:32:01 2012 +0700
+++ b/mercurial/copies.py	Tue Jan 10 15:48:16 2012 -0200
@@ -84,7 +84,91 @@
         return None
     return limit
 
-def copies(repo, c1, c2, ca, checkdirs=False):
+def _chain(src, dst, a, b):
+    '''chain two sets of copies a->b'''
+    t = a.copy()
+    for k, v in b.iteritems():
+        if v in t:
+            # found a chain
+            if t[v] != k:
+                # file wasn't renamed back to itself
+                t[k] = t[v]
+            if v not in dst:
+                # chain was a rename, not a copy
+                del t[v]
+        if v in src:
+            # file is a copy of an existing file
+            t[k] = v
+    return t
+
+def _tracefile(fctx, actx):
+    '''return file context that is the ancestor of fctx present in actx'''
+    stop = actx.rev()
+    am = actx.manifest()
+
+    for f in fctx.ancestors():
+        if am.get(f.path(), None) == f.filenode():
+            return f
+        if f.rev() < stop:
+            return None
+
+def _dirstatecopies(d):
+    ds = d._repo.dirstate
+    c = ds.copies().copy()
+    for k in c.keys():
+        if ds[k] not in 'anm':
+            del c[k]
+    return c
+
+def _forwardcopies(a, b):
+    '''find {dst@b: src@a} copy mapping where a is an ancestor of b'''
+
+    # check for working copy
+    w = None
+    if b.rev() is None:
+        w = b
+        b = w.p1()
+        if a == b:
+            # short-circuit to avoid issues with merge states
+            return _dirstatecopies(w)
+
+    # 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'
+    cm = {}
+    for f in b:
+        if f not in a:
+            ofctx = _tracefile(b[f], a)
+            if ofctx:
+                cm[f] = ofctx.path()
+
+    # combine copies from dirstate if necessary
+    if w is not None:
+        cm = _chain(a, w, cm, _dirstatecopies(w))
+
+    return cm
+
+def _backwardcopies(a, b):
+    # because the forward mapping is 1:n, we can lose renames here
+    # in particular, we find renames better than copies
+    f = _forwardcopies(b, a)
+    r = {}
+    for k, v in f.iteritems():
+        r[v] = k
+    return r
+
+def pathcopies(x, y):
+    '''find {dst@y: src@x} copy mapping for directed compare'''
+    if x == y or not x or not y:
+        return {}
+    a = y.ancestor(x)
+    if a == x:
+        return _forwardcopies(x, y)
+    if a == y:
+        return _backwardcopies(x, y)
+    return _chain(x, y, _backwardcopies(x, a), _forwardcopies(a, y))
+
+def mergecopies(repo, c1, c2, ca, checkdirs=True):
     """
     Find moves and copies between context c1 and c2
     """
--- a/mercurial/dirstate.py	Mon Jan 09 02:32:01 2012 +0700
+++ b/mercurial/dirstate.py	Tue Jan 10 15:48:16 2012 -0200
@@ -4,6 +4,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 errno
 
 from node import nullid
 from i18n import _
@@ -49,7 +50,7 @@
         self._rootdir = os.path.join(root, '')
         self._dirty = False
         self._dirtypl = False
-        self._lastnormaltime = None
+        self._lastnormaltime = 0
         self._ui = ui
 
     @propertycache
@@ -80,7 +81,9 @@
     def _branch(self):
         try:
             return self._opener.read("branch").strip() or "default"
-        except IOError:
+        except IOError, inst:
+            if inst.errno != errno.ENOENT:
+                raise
             return "default"
 
     @propertycache
@@ -251,7 +254,7 @@
                 "_ignore"):
             if a in self.__dict__:
                 delattr(self, a)
-        self._lastnormaltime = None
+        self._lastnormaltime = 0
         self._dirty = False
 
     def copy(self, source, dest):
@@ -415,7 +418,7 @@
             delattr(self, "_dirs")
         self._copymap = {}
         self._pl = [nullid, nullid]
-        self._lastnormaltime = None
+        self._lastnormaltime = 0
         self._dirty = True
 
     def rebuild(self, parent, files):
@@ -463,7 +466,7 @@
             write(f)
         st.write(cs.getvalue())
         st.close()
-        self._lastnormaltime = None
+        self._lastnormaltime = 0
         self._dirty = self._dirtypl = False
 
     def _dirignore(self, f):
--- a/mercurial/dispatch.py	Mon Jan 09 02:32:01 2012 +0700
+++ b/mercurial/dispatch.py	Tue Jan 10 15:48:16 2012 -0200
@@ -583,7 +583,7 @@
         raise util.Abort(_("option --cwd may not be abbreviated!"))
     if options["repository"]:
         raise util.Abort(_(
-            "Option -R has to be separated from other options (e.g. not -qR) "
+            "option -R has to be separated from other options (e.g. not -qR) "
             "and --repository may only be abbreviated as --repo!"))
 
     if options["encoding"]:
--- a/mercurial/encoding.py	Mon Jan 09 02:32:01 2012 +0700
+++ b/mercurial/encoding.py	Tue Jan 10 15:48:16 2012 -0200
@@ -105,7 +105,7 @@
                 return localstr(u.encode('UTF-8'), r)
 
         except LookupError, k:
-            raise error.Abort("%s, please check your locale settings" % k)
+            raise error.Abort(k, hint="please check your locale settings")
         except UnicodeDecodeError:
             pass
     u = s.decode("utf-8", "replace") # last ditch
@@ -132,7 +132,7 @@
         sub = s[max(0, inst.start - 10):inst.start + 10]
         raise error.Abort("decoding near '%s': %s!" % (sub, inst))
     except LookupError, k:
-        raise error.Abort("%s, please check your locale settings" % k)
+        raise error.Abort(k, hint="please check your locale settings")
 
 # How to treat ambiguous-width characters. Set to 'wide' to treat as wide.
 wide = (os.environ.get("HGENCODINGAMBIGUOUS", "narrow") == "wide"
--- a/mercurial/httpconnection.py	Mon Jan 09 02:32:01 2012 +0700
+++ b/mercurial/httpconnection.py	Tue Jan 10 15:48:16 2012 -0200
@@ -38,7 +38,7 @@
         self.write = self._data.write
         self.length = os.fstat(self._data.fileno()).st_size
         self._pos = 0
-        self._total = self.length / 1024 * 2
+        self._total = self.length // 1024 * 2
 
     def read(self, *args, **kwargs):
         try:
@@ -51,7 +51,7 @@
         # requires authentication. Since we can't know until we try
         # once whether authentication will be required, just lie to
         # the user and maybe the push succeeds suddenly at 50%.
-        self.ui.progress(_('sending'), self._pos / 1024,
+        self.ui.progress(_('sending'), self._pos // 1024,
                          unit=_('kb'), total=self._total)
         return ret
 
--- a/mercurial/keepalive.py	Mon Jan 09 02:32:01 2012 +0700
+++ b/mercurial/keepalive.py	Tue Jan 10 15:48:16 2012 -0200
@@ -9,10 +9,8 @@
 #   Lesser General Public License for more details.
 #
 #   You should have received a copy of the GNU Lesser General Public
-#   License along with this library; if not, write to the
-#      Free Software Foundation, Inc.,
-#      59 Temple Place, Suite 330,
-#      Boston, MA  02111-1307  USA
+#   License along with this library; if not, see
+#   <http://www.gnu.org/licenses/>.
 
 # This file is part of urlgrabber, a high-level cross-protocol url-grabber
 # Copyright 2002-2004 Michael D. Stenner, Ryan Tomayko
--- a/mercurial/localrepo.py	Mon Jan 09 02:32:01 2012 +0700
+++ b/mercurial/localrepo.py	Tue Jan 10 15:48:16 2012 -0200
@@ -181,7 +181,7 @@
 
     @propertycache
     def _phaserev(self):
-        cache = [0] * len(self)
+        cache = [phases.public] * len(self)
         for phase in phases.trackedphases:
             roots = map(self.changelog.rev, self._phaseroots[phase])
             if roots:
@@ -1253,7 +1253,8 @@
                       parent2=xp2, pending=p)
             self.changelog.finalize(trp)
             # set the new commit is proper phase
-            targetphase = self.ui.configint('phases', 'new-commit', 1)
+            targetphase = self.ui.configint('phases', 'new-commit',
+                                            phases.draft)
             if targetphase:
                 # retract boundary do not alter parent changeset.
                 # if a parent have higher the resulting phase will
@@ -1554,7 +1555,7 @@
             else:
                 # Remote is old or publishing all common changesets
                 # should be seen as public
-                phases.advanceboundary(self, 0, common + added)
+                phases.advanceboundary(self, phases.public, common + added)
         finally:
             lock.release()
 
@@ -1615,14 +1616,14 @@
                 # even when we don't push, exchanging phase data is useful
                 remotephases = remote.listkeys('phases')
                 if not remotephases: # old server or public only repo
-                    phases.advanceboundary(self, 0, fut)
+                    phases.advanceboundary(self, phases.public, fut)
                     # don't push any phase data as there is nothing to push
                 else:
                     ana = phases.analyzeremotephases(self, fut, remotephases)
                     rheads, rroots = ana
                     ### Apply remote phase on local
                     if remotephases.get('publishing', False):
-                        phases.advanceboundary(self, 0, fut)
+                        phases.advanceboundary(self, phases.public, fut)
                     else: # publish = False
                         for phase, rpheads in enumerate(rheads):
                             phases.advanceboundary(self, phase, rpheads)
@@ -1631,21 +1632,60 @@
                     # XXX If push failed we should use strict common and not
                     # future to avoir pushing phase data on unknown changeset.
                     # This is to done later.
-                    futctx = [self[n] for n in fut if n != nullid]
-                    for phase in phases.trackedphases[::-1]:
-                        prevphase = phase -1
-                        # get all candidate for head in previous phase
-                        inprev = [ctx for ctx in futctx
-                                      if ctx.phase() == prevphase]
-                        for newremotehead in  self.set('heads(%ld & (%ln::))',
-                                              inprev, rroots[phase]):
-                            r = remote.pushkey('phases',
-                                               newremotehead.hex(),
-                                               str(phase), str(prevphase))
-                            if not r:
-                                self.ui.warn(_('updating phase of %s'
-                                               'to %s failed!\n')
-                                                % (newremotehead, prevphase))
+
+                    # element we want to push
+                    topush = []
+
+                    # store details of known remote phase of several revision
+                    # /!\ set of index I holds rev where: I <= rev.phase()
+                    # /!\ public phase (index 0) is ignored
+                    remdetails = [set() for i in xrange(len(phases.allphases))]
+                    _revs = set()
+                    for relremphase in phases.trackedphases[::-1]:
+                        # we iterate backward because the list alway grows
+                        # when filled in this direction.
+                        _revs.update(self.revs('%ln::%ln',
+                                               rroots[relremphase], fut))
+                        remdetails[relremphase].update(_revs)
+
+                    for phase in phases.allphases[:-1]:
+                        # We don't need the last phase as we will never want to
+                        # move anything to it while moving phase backward.
+
+                        # Get the list of all revs on remote which are in a
+                        # phase higher than currently processed phase.
+                        relremrev = remdetails[phase + 1]
+
+                        if not relremrev:
+                            # no candidate to remote push anymore
+                            # break before any expensive revset
+                            break
+
+                        #dynamical inject appropriate phase symbol
+                        phasename = phases.phasenames[phase]
+                        odrevset = 'heads(%%ld and %s())' % phasename
+                        outdated =  self.set(odrevset, relremrev)
+                        for od in outdated:
+                            candstart = len(remdetails) - 1
+                            candstop = phase + 1
+                            candidateold = xrange(candstart, candstop, -1)
+                            for oldphase in candidateold:
+                                if od.rev() in remdetails[oldphase]:
+                                    break
+                            else: # last one: no need to search
+                                oldphase = phase + 1
+                            topush.append((oldphase, phase, od))
+
+                    # push every needed data
+                    for oldphase, newphase, newremotehead in topush:
+                        r = remote.pushkey('phases',
+                                           newremotehead.hex(),
+                                           str(oldphase), str(newphase))
+                        if not r:
+                            self.ui.warn(_('updating phase of %s '
+                                           'to %s from %s failed!\n')
+                                            % (newremotehead, newphase,
+                                               oldphase))
             finally:
                 locallock.release()
         finally:
@@ -2057,9 +2097,9 @@
             if publishing and srctype == 'push':
                 # Old server can not push the boundary themself.
                 # This clause ensure pushed changeset are alway marked as public
-                phases.advanceboundary(self, 0, added)
+                phases.advanceboundary(self, phases.public, added)
             elif srctype != 'strip': # strip should not touch boundary at all
-                phases.retractboundary(self, 1, added)
+                phases.retractboundary(self, phases.draft, added)
 
             # make changelog see real files again
             cl.finalize(trp)
--- a/mercurial/merge.py	Mon Jan 09 02:32:01 2012 +0700
+++ b/mercurial/merge.py	Tue Jan 10 15:48:16 2012 -0200
@@ -183,7 +183,7 @@
         pa = p1.p1()
     elif pa and repo.ui.configbool("merge", "followcopies", True):
         dirs = repo.ui.configbool("merge", "followdirs", True)
-        copy, diverge = copies.copies(repo, p1, p2, pa, dirs)
+        copy, diverge = copies.mergecopies(repo, p1, p2, pa, dirs)
         for of, fl in diverge.iteritems():
             act("divergent renames", "dr", of, fl)
 
--- a/mercurial/patch.py	Mon Jan 09 02:32:01 2012 +0700
+++ b/mercurial/patch.py	Tue Jan 10 15:48:16 2012 -0200
@@ -1600,7 +1600,7 @@
 
     copy = {}
     if opts.git or opts.upgrade:
-        copy = copies.copies(repo, ctx1, ctx2, repo[nullid])[0]
+        copy = copies.pathcopies(ctx1, ctx2)
 
     difffn = lambda opts, losedata: trydiff(repo, revs, ctx1, ctx2,
                  modified, added, removed, copy, getfilectx, opts, losedata, prefix)
--- a/mercurial/phases.py	Mon Jan 09 02:32:01 2012 +0700
+++ b/mercurial/phases.py	Tue Jan 10 15:48:16 2012 -0200
@@ -102,8 +102,9 @@
 from node import nullid, bin, hex, short
 from i18n import _
 
-allphases = range(3)
+allphases = public, draft, secret = range(3)
 trackedphases = allphases[1:]
+phasenames = ['public', 'draft', 'secret']
 
 def readroots(repo):
     """Read phase roots from disk"""
@@ -242,7 +243,7 @@
 def visibleheads(repo):
     """return the set of visible head of this repo"""
     # XXX we want a cache on this
-    sroots = repo._phaseroots[2]
+    sroots = repo._phaseroots[secret]
     if sroots:
         # XXX very slow revset. storing heads or secret "boundary" would help.
         revset = repo.set('heads(not (%ln::))', sroots)
--- a/mercurial/posix.py	Mon Jan 09 02:32:01 2012 +0700
+++ b/mercurial/posix.py	Tue Jan 10 15:48:16 2012 -0200
@@ -438,6 +438,8 @@
     def cacheable(self):
         return bool(self.stat.st_ino)
 
+    __hash__ = object.__hash__
+
     def __eq__(self, other):
         try:
             return self.stat == other.stat
--- a/mercurial/revset.py	Mon Jan 09 02:32:01 2012 +0700
+++ b/mercurial/revset.py	Tue Jan 10 15:48:16 2012 -0200
@@ -6,7 +6,7 @@
 # GNU General Public License version 2 or any later version.
 
 import re
-import parser, util, error, discovery, hbisect
+import parser, util, error, discovery, hbisect, phases
 import node as nodemod
 import bookmarks as bookmarksmod
 import match as matchmod
@@ -395,6 +395,12 @@
     s = set(repo.changelog.descendants(*args)) | set(args)
     return [r for r in subset if r in s]
 
+def draft(repo, subset, x):
+    """``draft()``
+    Changeset in draft phase."""
+    getargs(x, 0, 0, _("draft takes no arguments"))
+    return [r for r in subset if repo._phaserev[r] == phases.draft]
+
 def filelog(repo, subset, x):
     """``filelog(pattern)``
     Changesets connected to the specified filelog.
@@ -725,6 +731,12 @@
     except error.RepoLookupError:
         return []
 
+def public(repo, subset, x):
+    """``public()``
+    Changeset in public phase."""
+    getargs(x, 0, 0, _("public takes no arguments"))
+    return [r for r in subset if repo._phaserev[r] == phases.public]
+
 def removes(repo, subset, x):
     """``removes(pattern)``
     Changesets which remove files matching pattern.
@@ -763,6 +775,12 @@
     cs = set(children(repo, subset, x))
     return [r for r in s if r not in cs]
 
+def secret(repo, subset, x):
+    """``secret()``
+    Changeset in secret phase."""
+    getargs(x, 0, 0, _("secret takes no arguments"))
+    return [r for r in subset if repo._phaserev[r] == phases.secret]
+
 def sort(repo, subset, x):
     """``sort(set[, [-]key...])``
     Sort set by keys. The default sort order is ascending, specify a key
@@ -861,6 +879,7 @@
     "date": date,
     "desc": desc,
     "descendants": descendants,
+    "draft": draft,
     "file": hasfile,
     "filelog": filelog,
     "first": first,
@@ -881,11 +900,13 @@
     "p2": p2,
     "parents": parents,
     "present": present,
+    "public": public,
     "removes": removes,
     "rev": rev,
     "reverse": reverse,
     "roots": roots,
     "sort": sort,
+    "secret": secret,
     "tag": tag,
     "tagged": tagged,
     "user": user,
@@ -1108,7 +1129,7 @@
             return '(0-0)' # a minimal way to represent an empty set
         if l == 1:
             return argtype(t, s[0])
-        m = l / 2
+        m = l // 2
         return '(%s or %s)' % (listexp(s[:m], t), listexp(s[m:], t))
 
     ret = ''
--- a/mercurial/scmutil.py	Mon Jan 09 02:32:01 2012 +0700
+++ b/mercurial/scmutil.py	Tue Jan 10 15:48:16 2012 -0200
@@ -313,8 +313,8 @@
             try:
                 name_st = os.stat(name)
             except OSError:
-                break
-            if util.samestat(name_st, root_st):
+                name_st = None
+            if name_st and util.samestat(name_st, root_st):
                 if not rel:
                     # name was actually the same as root (maybe a symlink)
                     return ''
--- a/mercurial/simplemerge.py	Mon Jan 09 02:32:01 2012 +0700
+++ b/mercurial/simplemerge.py	Tue Jan 10 15:48:16 2012 -0200
@@ -11,8 +11,7 @@
 # GNU General Public License for more details.
 #
 # You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
 
 # mbp: "you know that thing where cvs gives you conflict markers?"
 # s: "i hate that."
--- a/mercurial/sslutil.py	Mon Jan 09 02:32:01 2012 +0700
+++ b/mercurial/sslutil.py	Tue Jan 10 15:48:16 2012 -0200
@@ -13,8 +13,16 @@
 try:
     # avoid using deprecated/broken FakeSocket in python 2.6
     import ssl
-    ssl_wrap_socket = ssl.wrap_socket
     CERT_REQUIRED = ssl.CERT_REQUIRED
+    def ssl_wrap_socket(sock, keyfile, certfile,
+                cert_reqs=ssl.CERT_NONE, ca_certs=None):
+        sslsocket = ssl.wrap_socket(sock, keyfile, certfile,
+                cert_reqs=cert_reqs, ca_certs=ca_certs)
+        # check if wrap_socket failed silently because socket had been closed
+        # - see http://bugs.python.org/issue13721
+        if not sslsocket.cipher():
+            raise util.Abort(_('ssl connection failed'))
+        return sslsocket
 except ImportError:
     CERT_REQUIRED = 2
 
@@ -95,36 +103,39 @@
         host = self.host
         cacerts = self.ui.config('web', 'cacerts')
         hostfingerprint = self.ui.config('hostfingerprints', host)
-        if cacerts and not hostfingerprint:
+        if not getattr(sock, 'getpeercert', False): # python 2.5 ?
+            if hostfingerprint:
+                raise util.Abort(_("host fingerprint for %s can't be "
+                                   "verified (Python too old)") % host)
+            self.ui.warn(_("warning: certificate for %s can't be verified "
+                           "(Python too old)\n") % host)
+            return
+        if not sock.cipher(): # work around http://bugs.python.org/issue13721
+            raise util.Abort(_('%s ssl connection error') % host)
+        peercert = sock.getpeercert(True)
+        if not peercert:
+            raise util.Abort(_('%s certificate error: '
+                               'no certificate received') % host)
+        peerfingerprint = util.sha1(peercert).hexdigest()
+        nicefingerprint = ":".join([peerfingerprint[x:x + 2]
+            for x in xrange(0, len(peerfingerprint), 2)])
+        if hostfingerprint:
+            if peerfingerprint.lower() != \
+                    hostfingerprint.replace(':', '').lower():
+                raise util.Abort(_('invalid certificate for %s with '
+                                   'fingerprint %s') % (host, nicefingerprint))
+            self.ui.debug('%s certificate matched fingerprint %s\n' %
+                          (host, nicefingerprint))
+        elif cacerts:
             msg = _verifycert(sock.getpeercert(), host)
             if msg:
-                raise util.Abort(_('%s certificate error: %s '
-                                   '(use --insecure to connect '
-                                   'insecurely)') % (host, msg))
+                raise util.Abort(_('%s certificate error: %s') % (host, msg),
+                                 hint=_('configure hostfingerprint %s or use '
+                                        '--insecure to connect insecurely') %
+                                      nicefingerprint)
             self.ui.debug('%s certificate successfully verified\n' % host)
         else:
-            if getattr(sock, 'getpeercert', False):
-                peercert = sock.getpeercert(True)
-                peerfingerprint = util.sha1(peercert).hexdigest()
-                nicefingerprint = ":".join([peerfingerprint[x:x + 2]
-                    for x in xrange(0, len(peerfingerprint), 2)])
-                if hostfingerprint:
-                    if peerfingerprint.lower() != \
-                            hostfingerprint.replace(':', '').lower():
-                        raise util.Abort(_('invalid certificate for %s '
-                                           'with fingerprint %s') %
-                                         (host, nicefingerprint))
-                    self.ui.debug('%s certificate matched fingerprint %s\n' %
-                                  (host, nicefingerprint))
-                else:
-                    self.ui.warn(_('warning: %s certificate '
-                                   'with fingerprint %s not verified '
-                                   '(check hostfingerprints or web.cacerts '
-                                   'config setting)\n') %
-                                 (host, nicefingerprint))
-            else: # python 2.5 ?
-                if hostfingerprint:
-                    raise util.Abort(_("host fingerprint for %s can't be "
-                                       "verified (Python too old)") % host)
-                self.ui.warn(_("warning: certificate for %s can't be "
-                               "verified (Python too old)\n") % host)
+            self.ui.warn(_('warning: %s certificate with fingerprint %s not '
+                           'verified (check hostfingerprints or web.cacerts '
+                           'config setting)\n') %
+                         (host, nicefingerprint))
--- a/mercurial/templatekw.py	Mon Jan 09 02:32:01 2012 +0700
+++ b/mercurial/templatekw.py	Tue Jan 10 15:48:16 2012 -0200
@@ -276,7 +276,11 @@
     return ctx.hex()
 
 def showphase(repo, ctx, templ, **args):
-    """:rev: Integer. The changeset phase."""
+    """:rev: String. The changeset phase name."""
+    return ctx.phasestr()
+
+def showphaseidx(repo, ctx, templ, **args):
+    """:rev: Integer. The changeset phase index."""
     return ctx.phase()
 
 def showrev(repo, ctx, templ, **args):
@@ -317,6 +321,7 @@
     'manifest': showmanifest,
     'node': shownode,
     'phase': showphase,
+    'phaseidx': showphaseidx,
     'rev': showrev,
     'tags': showtags,
 }
--- a/tests/dummyssh	Mon Jan 09 02:32:01 2012 +0700
+++ b/tests/dummyssh	Tue Jan 10 15:48:16 2012 -0200
@@ -16,5 +16,9 @@
     log.write(" %d:%s" % (i+1, arg))
 log.write("\n")
 log.close()
-r = os.system(sys.argv[2])
+hgcmd = sys.argv[2]
+if os.name == 'nt':
+    # hack to make simple unix single quote quoting work on windows
+    hgcmd = hgcmd.replace("'", '"')
+r = os.system(hgcmd)
 sys.exit(bool(r))
--- a/tests/test-command-template.t	Mon Jan 09 02:32:01 2012 +0700
+++ b/tests/test-command-template.t	Tue Jan 10 15:48:16 2012 -0200
@@ -1117,7 +1117,7 @@
   $ hg log --template '{date|age}\n' > /dev/null || exit 1
 
   $ hg log -l1 --template '{date|age}\n' 
-  8 years from now
+  7 years from now
   $ hg log --template '{date|date}\n'
   Wed Jan 01 10:01:00 2020 +0000
   Mon Jan 12 13:46:40 1970 +0000
--- a/tests/test-encoding.t	Mon Jan 09 02:32:01 2012 +0700
+++ b/tests/test-encoding.t	Tue Jan 10 15:48:16 2012 -0200
@@ -235,7 +235,8 @@
 hg log (dolphin)
 
   $ HGENCODING=dolphin hg log
-  abort: unknown encoding: dolphin, please check your locale settings
+  abort: unknown encoding: dolphin
+  (please check your locale settings)
   [255]
   $ HGENCODING=ascii hg branch `cat latin-1-tag`
   abort: decoding near '\xe9': 'ascii' codec can't decode byte 0xe9 in position 0: ordinal not in range(128)! (esc)
--- a/tests/test-globalopts.t	Mon Jan 09 02:32:01 2012 +0700
+++ b/tests/test-globalopts.t	Tue Jan 10 15:48:16 2012 -0200
@@ -136,16 +136,16 @@
   abort: option --cwd may not be abbreviated!
   [255]
   $ hg --rep a tip
-  abort: Option -R has to be separated from other options (e.g. not -qR) and --repository may only be abbreviated as --repo!
+  abort: option -R has to be separated from other options (e.g. not -qR) and --repository may only be abbreviated as --repo!
   [255]
   $ hg --repositor a tip
-  abort: Option -R has to be separated from other options (e.g. not -qR) and --repository may only be abbreviated as --repo!
+  abort: option -R has to be separated from other options (e.g. not -qR) and --repository may only be abbreviated as --repo!
   [255]
   $ hg -qR a tip
-  abort: Option -R has to be separated from other options (e.g. not -qR) and --repository may only be abbreviated as --repo!
+  abort: option -R has to be separated from other options (e.g. not -qR) and --repository may only be abbreviated as --repo!
   [255]
   $ hg -qRa tip
-  abort: Option -R has to be separated from other options (e.g. not -qR) and --repository may only be abbreviated as --repo!
+  abort: option -R has to be separated from other options (e.g. not -qR) and --repository may only be abbreviated as --repo!
   [255]
 
 Testing --cwd:
--- a/tests/test-graft.t	Mon Jan 09 02:32:01 2012 +0700
+++ b/tests/test-graft.t	Tue Jan 10 15:48:16 2012 -0200
@@ -106,14 +106,6 @@
    b: local copied/moved to a -> m
   preserving b for resolve of b
   updating: b 1/1 files (100.00%)
-    searching for copies back to rev 1
-    unmatched files in local:
-     a
-    unmatched files in other:
-     b
-    all copies found (* = to merge, ! = divergent):
-     b -> a *
-    checking for directory renames
   b
    b: searching for copy revision for a
    b: copy a:b789fdd96dc2f3bd229c1dd8eedf0fc60e2b68e3
@@ -127,12 +119,6 @@
    e: remote is newer -> g
   updating: e 1/1 files (100.00%)
   getting e
-    searching for copies back to rev 1
-    unmatched files in local:
-     c
-    all copies found (* = to merge, ! = divergent):
-     c -> b *
-    checking for directory renames
   e
   grafting revision 4
     searching for copies back to rev 1
@@ -152,12 +138,6 @@
   my e@77eb504366ab+ other e@9c233e8e184d ancestor e@68795b066622
   warning: conflicts during merge.
   merging e incomplete! (edit conflicts, then use 'hg resolve --mark')
-    searching for copies back to rev 1
-    unmatched files in local:
-     c
-    all copies found (* = to merge, ! = divergent):
-     c -> b *
-    checking for directory renames
   abort: unresolved conflicts, can't continue
   (use hg resolve and hg graft --continue)
   [255]
--- a/tests/test-grep.t	Mon Jan 09 02:32:01 2012 +0700
+++ b/tests/test-grep.t	Tue Jan 10 15:48:16 2012 -0200
@@ -59,8 +59,9 @@
 
 follow
 
-  $ hg grep --traceback -f 'import$' port2
+  $ hg grep --traceback -f 'import\n\Z' port2
   port:0:import
+  
   $ echo deport >> port2
   $ hg commit -m 5 -u eggs -d '6 0'
   $ hg grep -f --all -nu port port2
--- a/tests/test-https.t	Mon Jan 09 02:32:01 2012 +0700
+++ b/tests/test-https.t	Tue Jan 10 15:48:16 2012 -0200
@@ -180,7 +180,8 @@
 cacert mismatch
 
   $ hg -R copy-pull pull --config web.cacerts=pub.pem https://127.0.0.1:$HGPORT/
-  abort: 127.0.0.1 certificate error: certificate is for localhost (use --insecure to connect insecurely)
+  abort: 127.0.0.1 certificate error: certificate is for localhost
+  (configure hostfingerprint 91:4f:1a:ff:87:24:9c:09:b6:85:9b:88:b1:90:6d:30:75:64:91:ca or use --insecure to connect insecurely)
   [255]
   $ hg -R copy-pull pull --config web.cacerts=pub.pem https://127.0.0.1:$HGPORT/ --insecure
   warning: 127.0.0.1 certificate with fingerprint 91:4f:1a:ff:87:24:9c:09:b6:85:9b:88:b1:90:6d:30:75:64:91:ca not verified (check hostfingerprints or web.cacerts config setting)
--- a/tests/test-largefiles-small-disk.t	Mon Jan 09 02:32:01 2012 +0700
+++ b/tests/test-largefiles-small-disk.t	Tue Jan 10 15:48:16 2012 -0200
@@ -65,4 +65,3 @@
 The largefile is not created in .hg/largefiles:
 
   $ ls bob/.hg/largefiles
-  dirstate
--- a/tests/test-largefiles.t	Mon Jan 09 02:32:01 2012 +0700
+++ b/tests/test-largefiles.t	Tue Jan 10 15:48:16 2012 -0200
@@ -1,5 +1,6 @@
   $ "$TESTDIR/hghave" symlink unix-permissions serve || exit 80
-
+  $ USERCACHE=`pwd`/cache; export USERCACHE
+  $ mkdir -p ${USERCACHE}
   $ cat >> $HGRCPATH <<EOF
   > [extensions]
   > largefiles=
@@ -11,10 +12,14 @@
   > [largefiles]
   > minsize=2
   > patterns=glob:**.dat
+  > usercache=${USERCACHE}
+  > [hooks]
+  > precommit=echo "Invoking status precommit hook"; hg status
   > EOF
 
 Create the repo with a couple of revisions of both large and normal
-files, testing that status correctly shows largefiles.
+files, testing that status correctly shows largefiles and that summary output
+is correct.
 
   $ hg init a
   $ cd a
@@ -26,16 +31,28 @@
   $ hg add normal1 sub/normal2
   $ hg add --large large1 sub/large2
   $ hg commit -m "add files"
+  Invoking status precommit hook
+  A large1
+  A normal1
+  A sub/large2
+  A sub/normal2
   $ echo normal11 > normal1
   $ echo normal22 > sub/normal2
   $ echo large11 > large1
   $ echo large22 > sub/large2
-  $ hg st
+  $ hg commit -m "edit files"
+  Invoking status precommit hook
   M large1
   M normal1
   M sub/large2
   M sub/normal2
-  $ hg commit -m "edit files"
+  $ hg sum --large
+  parent: 1:ce8896473775 tip
+   edit files
+  branch: default
+  commit: (clean)
+  update: (current)
+  largefiles: No remote repo
 
 Commit preserved largefile contents.
 
@@ -52,17 +69,32 @@
  
   $ hg remove normal1 large1
   $ hg commit -m "remove files"
+  Invoking status precommit hook
+  R large1
+  R normal1
   $ ls
   sub
+  $ echo "testlargefile" > large1-test
+  $ hg add --large large1-test
+  $ hg st
+  A large1-test
+  $ hg rm large1-test
+  not removing large1-test: file has been marked for add (use forget to undo)
+  $ hg st
+  A large1-test
+  $ hg forget large1-test
+  $ hg st
+  ? large1-test
+  $ rm large1-test
 
 Copy both largefiles and normal files (testing that status output is correct).
 
   $ hg cp sub/normal2 normal1
   $ hg cp sub/large2 large1
-  $ hg st
+  $ hg commit -m "copy files"
+  Invoking status precommit hook
   A large1
   A normal1
-  $ hg commit -m "copy files"
   $ cat normal1
   normal22
   $ cat large1
@@ -75,6 +107,15 @@
   $ hg mv sub/normal2 sub/normal4
   $ hg mv sub/large2 sub/large4
   $ hg commit -m "move files"
+  Invoking status precommit hook
+  A large3
+  A normal3
+  A sub/large4
+  A sub/normal4
+  R large1
+  R normal1
+  R sub/large2
+  R sub/normal2
   $ cat normal3
   normal22
   $ cat large3
@@ -144,6 +185,11 @@
   $ echo normal4 > sub/normal4
   $ echo large4 > sub/large4
   $ hg commit normal3 large3 sub/normal4 sub/large4 -m "edit files again"
+  Invoking status precommit hook
+  M large3
+  M normal3
+  M sub/large4
+  M sub/normal4
   $ cat normal3
   normal3
   $ cat large3
@@ -162,6 +208,11 @@
   $ echo large44 > sub/large4
   $ cd sub
   $ hg commit -m "edit files yet again"
+  Invoking status precommit hook
+  M large3
+  M normal3
+  M sub/large4
+  M sub/normal4
   $ cat ../normal3
   normal33
   $ cat ../large3
@@ -226,7 +277,8 @@
 Test forget on largefiles.
 
   $ hg forget large3 large5 test.dat reallylarge ratherlarge medium
-  $ hg st
+  $ hg commit -m "add/edit more largefiles"
+  Invoking status precommit hook
   A sub2/large6
   A sub2/large7
   R large3
@@ -236,7 +288,6 @@
   ? ratherlarge
   ? reallylarge
   ? test.dat
-  $ hg commit -m "add/edit more largefiles"
   $ hg st
   ? large3
   ? large5
@@ -257,6 +308,20 @@
   $ cat sub2/large7
   large7
 
+Test addremove: verify that files that should be added as largfiles are added as
+such and that already-existing largfiles are not added as normal files by
+accident.
+
+  $ rm normal3
+  $ rm sub/large4
+  $ echo "testing addremove with patterns" > testaddremove.dat
+  $ echo "normaladdremove" > normaladdremove
+  $ hg addremove
+  removing sub/large4
+  adding testaddremove.dat as a largefile
+  removing normal3
+  adding normaladdremove
+
 Clone a largefiles repo.
 
   $ hg clone . ../b
@@ -334,10 +399,16 @@
   $ echo large4-modified > sub/large4
   $ echo normal3-modified > normal3
   $ hg commit -m "modify normal file and largefile in repo b"
+  Invoking status precommit hook
+  M normal3
+  M sub/large4
   $ cd ../d
   $ echo large6-modified > sub2/large6
   $ echo normal4-modified > sub/normal4
   $ hg commit -m "modify normal file largefile in repo d"
+  Invoking status precommit hook
+  M sub/normal4
+  M sub2/large6
   $ cd ..
   $ hg clone d e
   updating to branch default
@@ -354,7 +425,10 @@
   added 1 changesets with 2 changes to 2 files (+1 heads)
   getting changed largefiles
   1 largefiles updated, 0 removed
-  saved backup bundle to $TESTTMP/d/.hg/strip-backup/f574fb32bb45-backup.hg (glob)
+  Invoking status precommit hook
+  M sub/normal4
+  M sub2/large6
+  saved backup bundle to $TESTTMP/d/.hg/strip-backup/f574fb32bb45-backup.hg
   nothing to rebase
   $ hg log --template '{rev}:{node|short}  {desc|firstline}\n'
   9:598410d3eb9a  modify normal file largefile in repo d
@@ -389,59 +463,21 @@
   $ hg rebase
   getting changed largefiles
   1 largefiles updated, 0 removed
-  saved backup bundle to $TESTTMP/e/.hg/strip-backup/f574fb32bb45-backup.hg (glob)
-  $ hg log
-  changeset:   9:598410d3eb9a
-  tag:         tip
-  user:        test
-  date:        Thu Jan 01 00:00:00 1970 +0000
-  summary:     modify normal file largefile in repo d
-  
-  changeset:   8:a381d2c8c80e
-  user:        test
-  date:        Thu Jan 01 00:00:00 1970 +0000
-  summary:     modify normal file and largefile in repo b
-  
-  changeset:   7:daea875e9014
-  user:        test
-  date:        Thu Jan 01 00:00:00 1970 +0000
-  summary:     add/edit more largefiles
-  
-  changeset:   6:4355d653f84f
-  user:        test
-  date:        Thu Jan 01 00:00:00 1970 +0000
-  summary:     edit files yet again
-  
-  changeset:   5:9d5af5072dbd
-  user:        test
-  date:        Thu Jan 01 00:00:00 1970 +0000
-  summary:     edit files again
-  
-  changeset:   4:74c02385b94c
-  user:        test
-  date:        Thu Jan 01 00:00:00 1970 +0000
-  summary:     move files
-  
-  changeset:   3:9e8fbc4bce62
-  user:        test
-  date:        Thu Jan 01 00:00:00 1970 +0000
-  summary:     copy files
-  
-  changeset:   2:51a0ae4d5864
-  user:        test
-  date:        Thu Jan 01 00:00:00 1970 +0000
-  summary:     remove files
-  
-  changeset:   1:ce8896473775
-  user:        test
-  date:        Thu Jan 01 00:00:00 1970 +0000
-  summary:     edit files
-  
-  changeset:   0:30d30fe6a5be
-  user:        test
-  date:        Thu Jan 01 00:00:00 1970 +0000
-  summary:     add files
-  
+  Invoking status precommit hook
+  M sub/normal4
+  M sub2/large6
+  saved backup bundle to $TESTTMP/e/.hg/strip-backup/f574fb32bb45-backup.hg
+  $ hg log --template '{rev}:{node|short}  {desc|firstline}\n'
+  9:598410d3eb9a  modify normal file largefile in repo d
+  8:a381d2c8c80e  modify normal file and largefile in repo b
+  7:daea875e9014  add/edit more largefiles
+  6:4355d653f84f  edit files yet again
+  5:9d5af5072dbd  edit files again
+  4:74c02385b94c  move files
+  3:9e8fbc4bce62  copy files
+  2:51a0ae4d5864  remove files
+  1:ce8896473775  edit files
+  0:30d30fe6a5be  add files
   $ cat normal3
   normal3-modified
   $ cat sub/normal4
@@ -457,63 +493,24 @@
 
   $ echo large4-modified-again > sub/large4 
   $ hg commit -m "Modify large4 again"
+  Invoking status precommit hook
+  M sub/large4
   $ hg rollback
   repository tip rolled back to revision 9 (undo commit)
   working directory now based on revision 9
   $ hg st
   M sub/large4
-  $ hg log
-  changeset:   9:598410d3eb9a
-  tag:         tip
-  user:        test
-  date:        Thu Jan 01 00:00:00 1970 +0000
-  summary:     modify normal file largefile in repo d
-  
-  changeset:   8:a381d2c8c80e
-  user:        test
-  date:        Thu Jan 01 00:00:00 1970 +0000
-  summary:     modify normal file and largefile in repo b
-  
-  changeset:   7:daea875e9014
-  user:        test
-  date:        Thu Jan 01 00:00:00 1970 +0000
-  summary:     add/edit more largefiles
-  
-  changeset:   6:4355d653f84f
-  user:        test
-  date:        Thu Jan 01 00:00:00 1970 +0000
-  summary:     edit files yet again
-  
-  changeset:   5:9d5af5072dbd
-  user:        test
-  date:        Thu Jan 01 00:00:00 1970 +0000
-  summary:     edit files again
-  
-  changeset:   4:74c02385b94c
-  user:        test
-  date:        Thu Jan 01 00:00:00 1970 +0000
-  summary:     move files
-  
-  changeset:   3:9e8fbc4bce62
-  user:        test
-  date:        Thu Jan 01 00:00:00 1970 +0000
-  summary:     copy files
-  
-  changeset:   2:51a0ae4d5864
-  user:        test
-  date:        Thu Jan 01 00:00:00 1970 +0000
-  summary:     remove files
-  
-  changeset:   1:ce8896473775
-  user:        test
-  date:        Thu Jan 01 00:00:00 1970 +0000
-  summary:     edit files
-  
-  changeset:   0:30d30fe6a5be
-  user:        test
-  date:        Thu Jan 01 00:00:00 1970 +0000
-  summary:     add files
-  
+  $ hg log --template '{rev}:{node|short}  {desc|firstline}\n'
+  9:598410d3eb9a  modify normal file largefile in repo d
+  8:a381d2c8c80e  modify normal file and largefile in repo b
+  7:daea875e9014  add/edit more largefiles
+  6:4355d653f84f  edit files yet again
+  5:9d5af5072dbd  edit files again
+  4:74c02385b94c  move files
+  3:9e8fbc4bce62  copy files
+  2:51a0ae4d5864  remove files
+  1:ce8896473775  edit files
+  0:30d30fe6a5be  add files
   $ cat sub/large4
   large4-modified-again
 
@@ -621,6 +618,8 @@
   $ cd f
   $ echo "large4-merge-test" > sub/large4
   $ hg commit -m "Modify large4 to test merge"
+  Invoking status precommit hook
+  M sub/large4
   $ hg pull ../e
   pulling from ../e
   searching for changes
@@ -638,6 +637,10 @@
   getting changed largefiles
   1 largefiles updated, 0 removed
   $ hg commit -m "Merge repos e and f"
+  Invoking status precommit hook
+  M normal3
+  M sub/normal4
+  M sub2/large6
   $ cat normal3
   normal3-modified
   $ cat sub/normal4
@@ -654,9 +657,13 @@
   $ echo large > large
   $ hg add --large large
   $ hg commit -m 'add largefile'
+  Invoking status precommit hook
+  A large
   $ hg update -q ".^"
   $ echo change >> normal3
   $ hg commit -m 'some change'
+  Invoking status precommit hook
+  M normal3
   created new head
   $ hg merge
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
@@ -721,10 +728,10 @@
 Test that renaming a largefile results in correct output for status
 
   $ hg rename sub/large4 large4-renamed
-  $ hg st
+  $ hg commit -m "test rename output"
+  Invoking status precommit hook
   A large4-renamed
   R sub/large4
-  $ hg commit -m "test rename output"
   $ cat large4-renamed
   large4-modified
   $ cd sub2
@@ -740,7 +747,9 @@
   $ hg init
   $ echo c1 > f1
   $ hg add f1
-  $ hg com -m "m1"
+  $ hg commit -m "m1"
+  Invoking status precommit hook
+  A f1
   $ cd ..
   $ hg serve -R r1 -d -p $HGPORT --pid-file hg.pid
   $ cat hg.pid >> $DAEMON_PIDS
@@ -771,7 +780,9 @@
   $ hg init
   $ echo c1 > f1
   $ hg add --large f1
-  $ hg com -m "m1"
+  $ hg commit -m "m1"
+  Invoking status precommit hook
+  A f1
   $ cd ..
   $ hg serve -R r4 -d -p $HGPORT2 --pid-file hg.pid
   $ cat hg.pid >> $DAEMON_PIDS
@@ -801,7 +812,9 @@
   $ hg init
   $ echo c1 > f1
   $ hg add f1
-  $ hg com -m "m1"
+  $ hg commit -m "m1"
+  Invoking status precommit hook
+  A f1
   $ cat >> .hg/hgrc <<!
   > [web]
   > push_ssl = false
@@ -814,7 +827,9 @@
   $ cd r7
   $ echo c2 > f2
   $ hg add --large f2
-  $ hg com -m "m2"
+  $ hg commit -m "m2"
+  Invoking status precommit hook
+  A f2
   $ hg --config extensions.largefiles=! -R ../r6 serve -d -p $HGPORT --pid-file ../hg.pid
   $ cat ../hg.pid >> $DAEMON_PIDS
   $ hg push http://localhost:$HGPORT
@@ -824,6 +839,21 @@
   [255]
   $ cd ..
 
+putlfile errors are shown (issue3123)
+Corrupt the cached largefile in r7
+  $ echo corruption > $USERCACHE/4cdac4d8b084d0b599525cf732437fb337d422a8
+  $ hg init empty
+  $ hg serve -R empty -d -p $HGPORT1 --pid-file hg.pid \
+  >   --config 'web.allow_push=*' --config web.push_ssl=False
+  $ cat hg.pid >> $DAEMON_PIDS
+  $ hg push -R r7 http://localhost:$HGPORT1
+  pushing to http://localhost:$HGPORT1/
+  searching for changes
+  remote: largefiles: failed to put 4cdac4d8b084d0b599525cf732437fb337d422a8 into store: largefile contents do not match hash
+  abort: remotestore: could not put $TESTTMP/r7/.hg/largefiles/4cdac4d8b084d0b599525cf732437fb337d422a8 to remote store http://localhost:$HGPORT1/
+  [255]
+  $ rm -rf empty
+
 Clone a local repository owned by another user
 We have to simulate that here by setting $HOME and removing write permissions
   $ ORIGHOME="$HOME"
@@ -835,6 +865,8 @@
   $ dd if=/dev/urandom bs=1k count=11k > a-large-file 2> /dev/null
   $ hg add --large a-large-file
   $ hg commit -m "Add a large file"
+  Invoking status precommit hook
+  A a-large-file
   $ cd ..
   $ chmod -R a-w pubrepo
   $ cd ..
@@ -861,9 +893,13 @@
   $ dd if=/dev/zero bs=1k count=10k of=largefile 2>/dev/null
   $ hg add --large largefile
   $ hg commit -m "commit a large file"
+  Invoking status precommit hook
+  A largefile
   $ ln -s largefile largelink
   $ hg add largelink
   $ hg commit -m "commit a large symlink"
+  Invoking status precommit hook
+  A largelink
   $ rm -f largelink
   $ hg up >/dev/null
   $ test -f largelink
--- a/tests/test-lfconvert.t	Mon Jan 09 02:32:01 2012 +0700
+++ b/tests/test-lfconvert.t	Tue Jan 10 15:48:16 2012 -0200
@@ -3,6 +3,7 @@
   > largefiles =
   > share =
   > graphlog =
+  > mq =
   > [largefiles]
   > minsize = 0.5
   > patterns = **.other
@@ -18,21 +19,47 @@
   > EOF
   $ mkdir sub
   $ dd if=/dev/zero bs=1k count=256 > large 2> /dev/null
+  $ dd if=/dev/zero bs=1k count=256 > large2 2> /dev/null
   $ echo normal > normal1
   $ echo alsonormal > sub/normal2
   $ dd if=/dev/zero bs=1k count=10 > sub/maybelarge.dat 2> /dev/null
   $ hg addremove
   adding large
+  adding large2
   adding normal1
   adding sub/maybelarge.dat
   adding sub/normal2
   $ hg commit -m"add large, normal1" large normal1
   $ hg commit -m"add sub/*" sub
+Test tag parsing
+  $ cat >> .hgtags <<EOF
+  > IncorrectlyFormattedTag!
+  > invalidhash sometag
+  > 0123456789abcdef anothertag
+  > EOF
+  $ hg add .hgtags
+  $ hg commit -m"add large2" large2 .hgtags
+  $ hg rename large2 large3
+Test link+rename largefile codepath
+  $ ln -sf large large3
+  $ hg commit -m"make large2 a symlink" large2 large3
   $ [ -d .hg/largefiles ] && echo fail || echo pass
   pass
   $ cd ..
   $ hg lfconvert --size 0.2 bigfile-repo largefiles-repo
   initializing destination largefiles-repo
+  skipping incorrectly formatted tag IncorrectlyFormattedTag!
+  skipping incorrectly formatted id invalidhash
+  no mapping for id 0123456789abcdef
+  abort: renamed/copied largefile large3 becomes symlink
+  [255]
+  $ cd bigfile-repo
+  $ hg strip --no-backup 2
+  0 files updated, 0 files merged, 2 files removed, 0 files unresolved
+  $ cd ..
+  $ rm -rf largefiles-repo
+  $ hg lfconvert --size 0.2 bigfile-repo largefiles-repo
+  initializing destination largefiles-repo
 
 "lfconvert" converts content correctly
   $ cd largefiles-repo
--- a/tests/test-mq-merge.t	Mon Jan 09 02:32:01 2012 +0700
+++ b/tests/test-mq-merge.t	Tue Jan 10 15:48:16 2012 -0200
@@ -149,13 +149,11 @@
   -b
   +a
   +c
-  diff --git a/a b/aa
-  copy from a
-  copy to aa
-  --- a/a
+  diff --git a/aa b/aa
+  new file mode 100644
+  --- /dev/null
   +++ b/aa
-  @@ -1,1 +1,1 @@
-  -b
+  @@ -0,0 +1,1 @@
   +a
 
 Check patcha2 is still a regular patch:
--- a/tests/test-mv-cp-st-diff.t	Mon Jan 09 02:32:01 2012 +0700
+++ b/tests/test-mv-cp-st-diff.t	Tue Jan 10 15:48:16 2012 -0200
@@ -560,6 +560,7 @@
   
   - parent to root: --rev . --rev 0
   M a
+    b
   R b
   
   diff --git a/a b/a
@@ -611,6 +612,7 @@
   
   - parent to branch: --rev . --rev 2
   M a
+    b
   A x/y
   R b
   
@@ -906,6 +908,7 @@
   
   - parent to root: --rev . --rev 0
   M a
+    b
   R b
   R c
   
@@ -975,6 +978,7 @@
   
   - parent to branch: --rev . --rev 2
   M a
+    b
   A x/y
   R b
   R c
--- a/tests/test-notify-changegroup.t	Mon Jan 09 02:32:01 2012 +0700
+++ b/tests/test-notify-changegroup.t	Tue Jan 10 15:48:16 2012 -0200
@@ -184,19 +184,19 @@
   Message-Id: <*> (glob)
   To: baz, foo@bar
   
-  changeset 84e487dddc58 in $TESTTMP/a
+  changeset 84e487dddc58 in $TESTTMP/a (glob)
   details: $TESTTMP/a?cmd=changeset;node=84e487dddc58
   summary: newfile
   
-  changeset b29c7a2b6b0c in $TESTTMP/a
+  changeset b29c7a2b6b0c in $TESTTMP/a (glob)
   details: $TESTTMP/a?cmd=changeset;node=b29c7a2b6b0c
   summary: x
   
-  changeset 0957c7d64886 in $TESTTMP/a
+  changeset 0957c7d64886 in $TESTTMP/a (glob)
   details: $TESTTMP/a?cmd=changeset;node=0957c7d64886
   summary: y
   
-  changeset 485b4e6b0249 in $TESTTMP/a
+  changeset 485b4e6b0249 in $TESTTMP/a (glob)
   details: $TESTTMP/a?cmd=changeset;node=485b4e6b0249
   summary: merged
   
--- a/tests/test-notify.t	Mon Jan 09 02:32:01 2012 +0700
+++ b/tests/test-notify.t	Tue Jan 10 15:48:16 2012 -0200
@@ -412,7 +412,7 @@
   > test = False
   > mbox = mbox
   > EOF
-  $ python -c 'print "no" * 500' >> a/a
+  $ python -c 'file("a/a", "ab").write("no" * 500 + "\n")'
   $ hg --cwd a commit -A -m "long line"
   $ hg --traceback --cwd b pull ../a
   pulling from ../a
--- a/tests/test-phases-exchange.t	Mon Jan 09 02:32:01 2012 +0700
+++ b/tests/test-phases-exchange.t	Tue Jan 10 15:48:16 2012 -0200
@@ -2,7 +2,7 @@
   > [extensions]
   > graphlog=
   > EOF
-  $ alias hgph='hg log --template "{rev} {phase} {desc} - {node|short}\n"'
+  $ alias hgph='hg log -G --template "{rev} {phase} {desc} - {node|short}\n"'
 
   $ mkcommit() {
   >    echo "$1" > "$1"
@@ -19,10 +19,14 @@
   $ mkcommit a-C
   $ mkcommit a-D
   $ hgph
-  3 1 a-D - b555f63b6063
-  2 1 a-C - 54acac6f23ab
-  1 1 a-B - 548a3d25dbf0
-  0 1 a-A - 054250a37db4
+  @  3 draft a-D - b555f63b6063
+  |
+  o  2 draft a-C - 54acac6f23ab
+  |
+  o  1 draft a-B - 548a3d25dbf0
+  |
+  o  0 draft a-A - 054250a37db4
+  
 
   $ hg init ../beta
   $ hg push -r 1 ../beta
@@ -33,21 +37,30 @@
   adding file changes
   added 2 changesets with 2 changes to 2 files
   $ hgph
-  3 1 a-D - b555f63b6063
-  2 1 a-C - 54acac6f23ab
-  1 0 a-B - 548a3d25dbf0
-  0 0 a-A - 054250a37db4
+  @  3 draft a-D - b555f63b6063
+  |
+  o  2 draft a-C - 54acac6f23ab
+  |
+  o  1 public a-B - 548a3d25dbf0
+  |
+  o  0 public a-A - 054250a37db4
+  
 
   $ cd ../beta
   $ hgph
-  1 0 a-B - 548a3d25dbf0
-  0 0 a-A - 054250a37db4
+  o  1 public a-B - 548a3d25dbf0
+  |
+  o  0 public a-A - 054250a37db4
+  
   $ hg up -q
   $ mkcommit b-A
   $ hgph
-  2 1 b-A - f54f1bb90ff3
-  1 0 a-B - 548a3d25dbf0
-  0 0 a-A - 054250a37db4
+  @  2 draft b-A - f54f1bb90ff3
+  |
+  o  1 public a-B - 548a3d25dbf0
+  |
+  o  0 public a-A - 054250a37db4
+  
   $ hg pull ../alpha
   pulling from ../alpha
   searching for changes
@@ -57,30 +70,43 @@
   added 2 changesets with 2 changes to 2 files (+1 heads)
   (run 'hg heads' to see heads, 'hg merge' to merge)
   $ hgph
-  4 0 a-D - b555f63b6063
-  3 0 a-C - 54acac6f23ab
-  2 1 b-A - f54f1bb90ff3
-  1 0 a-B - 548a3d25dbf0
-  0 0 a-A - 054250a37db4
+  o  4 public a-D - b555f63b6063
+  |
+  o  3 public a-C - 54acac6f23ab
+  |
+  | @  2 draft b-A - f54f1bb90ff3
+  |/
+  o  1 public a-B - 548a3d25dbf0
+  |
+  o  0 public a-A - 054250a37db4
+  
 
 pull did not updated ../alpha state.
 push from alpha to beta should update phase even if nothing is transfered
 
   $ cd ../alpha
   $ hgph # not updated by remote pull
-  3 1 a-D - b555f63b6063
-  2 1 a-C - 54acac6f23ab
-  1 0 a-B - 548a3d25dbf0
-  0 0 a-A - 054250a37db4
+  @  3 draft a-D - b555f63b6063
+  |
+  o  2 draft a-C - 54acac6f23ab
+  |
+  o  1 public a-B - 548a3d25dbf0
+  |
+  o  0 public a-A - 054250a37db4
+  
   $ hg push ../beta
   pushing to ../beta
   searching for changes
   no changes found
   $ hgph
-  3 0 a-D - b555f63b6063
-  2 0 a-C - 54acac6f23ab
-  1 0 a-B - 548a3d25dbf0
-  0 0 a-A - 054250a37db4
+  @  3 public a-D - b555f63b6063
+  |
+  o  2 public a-C - 54acac6f23ab
+  |
+  o  1 public a-B - 548a3d25dbf0
+  |
+  o  0 public a-A - 054250a37db4
+  
 
 update must update phase of common changeset too
 
@@ -95,21 +121,31 @@
 
   $ cd ../beta
   $ hgph # not updated by remote pull
-  4 0 a-D - b555f63b6063
-  3 0 a-C - 54acac6f23ab
-  2 1 b-A - f54f1bb90ff3
-  1 0 a-B - 548a3d25dbf0
-  0 0 a-A - 054250a37db4
+  o  4 public a-D - b555f63b6063
+  |
+  o  3 public a-C - 54acac6f23ab
+  |
+  | @  2 draft b-A - f54f1bb90ff3
+  |/
+  o  1 public a-B - 548a3d25dbf0
+  |
+  o  0 public a-A - 054250a37db4
+  
   $ hg pull ../alpha
   pulling from ../alpha
   searching for changes
   no changes found
   $ hgph
-  4 0 a-D - b555f63b6063
-  3 0 a-C - 54acac6f23ab
-  2 0 b-A - f54f1bb90ff3
-  1 0 a-B - 548a3d25dbf0
-  0 0 a-A - 054250a37db4
+  o  4 public a-D - b555f63b6063
+  |
+  o  3 public a-C - 54acac6f23ab
+  |
+  | @  2 public b-A - f54f1bb90ff3
+  |/
+  o  1 public a-B - 548a3d25dbf0
+  |
+  o  0 public a-A - 054250a37db4
+  
 
 Publish configuration option
 ----------------------------
@@ -135,11 +171,16 @@
   added 5 changesets with 5 changes to 5 files (+1 heads)
   (run 'hg heads' to see heads, 'hg merge' to merge)
   $ hgph
-  4 1 a-D - b555f63b6063
-  3 1 a-C - 54acac6f23ab
-  2 1 b-A - f54f1bb90ff3
-  1 1 a-B - 548a3d25dbf0
-  0 1 a-A - 054250a37db4
+  o  4 draft a-D - b555f63b6063
+  |
+  o  3 draft a-C - 54acac6f23ab
+  |
+  | o  2 draft b-A - f54f1bb90ff3
+  |/
+  o  1 draft a-B - 548a3d25dbf0
+  |
+  o  0 draft a-A - 054250a37db4
+  
   $ cd ..
 
 Pulling from publish=False to publish=False does not move boundary.
@@ -158,9 +199,12 @@
   added 3 changesets with 3 changes to 3 files
   (run 'hg update' to get a working copy)
   $ hgph
-  2 1 a-C - 54acac6f23ab
-  1 1 a-B - 548a3d25dbf0
-  0 1 a-A - 054250a37db4
+  o  2 draft a-C - 54acac6f23ab
+  |
+  o  1 draft a-B - 548a3d25dbf0
+  |
+  o  0 draft a-A - 054250a37db4
+  
 
 Even for common
 
@@ -173,10 +217,14 @@
   added 1 changesets with 1 changes to 1 files (+1 heads)
   (run 'hg heads' to see heads, 'hg merge' to merge)
   $ hgph
-  3 1 b-A - f54f1bb90ff3
-  2 1 a-C - 54acac6f23ab
-  1 1 a-B - 548a3d25dbf0
-  0 1 a-A - 054250a37db4
+  o  3 draft b-A - f54f1bb90ff3
+  |
+  | o  2 draft a-C - 54acac6f23ab
+  |/
+  o  1 draft a-B - 548a3d25dbf0
+  |
+  o  0 draft a-A - 054250a37db4
+  
 
 
 Pulling from Publish=True to Publish=False move boundary in common set.
@@ -191,11 +239,16 @@
   added 1 changesets with 1 changes to 1 files
   (run 'hg update' to get a working copy)
   $ hgph
-  4 0 a-D - b555f63b6063
-  3 0 b-A - f54f1bb90ff3
-  2 0 a-C - 54acac6f23ab
-  1 0 a-B - 548a3d25dbf0
-  0 0 a-A - 054250a37db4
+  o  4 public a-D - b555f63b6063
+  |
+  | o  3 public b-A - f54f1bb90ff3
+  | |
+  o |  2 public a-C - 54acac6f23ab
+  |/
+  o  1 public a-B - 548a3d25dbf0
+  |
+  o  0 public a-A - 054250a37db4
+  
 
 pulling from Publish=False to publish=False with some public
 
@@ -203,13 +256,20 @@
   $ mkcommit n-A
   $ mkcommit n-B
   $ hgph
-  6 1 n-B - 145e75495359
-  5 1 n-A - d6bcb4f74035
-  4 0 a-D - b555f63b6063
-  3 0 b-A - f54f1bb90ff3
-  2 0 a-C - 54acac6f23ab
-  1 0 a-B - 548a3d25dbf0
-  0 0 a-A - 054250a37db4
+  @  6 draft n-B - 145e75495359
+  |
+  o  5 draft n-A - d6bcb4f74035
+  |
+  | o  4 public a-D - b555f63b6063
+  | |
+  o |  3 public b-A - f54f1bb90ff3
+  | |
+  | o  2 public a-C - 54acac6f23ab
+  |/
+  o  1 public a-B - 548a3d25dbf0
+  |
+  o  0 public a-A - 054250a37db4
+  
   $ cd ../mu
   $ hg pull ../nu
   pulling from ../nu
@@ -220,24 +280,36 @@
   added 2 changesets with 2 changes to 2 files
   (run 'hg update' to get a working copy)
   $ hgph
-  6 1 n-B - 145e75495359
-  5 1 n-A - d6bcb4f74035
-  4 0 a-D - b555f63b6063
-  3 0 a-C - 54acac6f23ab
-  2 0 b-A - f54f1bb90ff3
-  1 0 a-B - 548a3d25dbf0
-  0 0 a-A - 054250a37db4
+  o  6 draft n-B - 145e75495359
+  |
+  o  5 draft n-A - d6bcb4f74035
+  |
+  | o  4 public a-D - b555f63b6063
+  | |
+  | o  3 public a-C - 54acac6f23ab
+  | |
+  o |  2 public b-A - f54f1bb90ff3
+  |/
+  o  1 public a-B - 548a3d25dbf0
+  |
+  o  0 public a-A - 054250a37db4
+  
   $ cd ..
 
 pulling into publish=True
 
   $ cd alpha
   $ hgph
-  4 0 b-A - f54f1bb90ff3
-  3 0 a-D - b555f63b6063
-  2 0 a-C - 54acac6f23ab
-  1 0 a-B - 548a3d25dbf0
-  0 0 a-A - 054250a37db4
+  o  4 public b-A - f54f1bb90ff3
+  |
+  | @  3 public a-D - b555f63b6063
+  | |
+  | o  2 public a-C - 54acac6f23ab
+  |/
+  o  1 public a-B - 548a3d25dbf0
+  |
+  o  0 public a-A - 054250a37db4
+  
   $ hg pull ../mu
   pulling from ../mu
   searching for changes
@@ -247,13 +319,20 @@
   added 2 changesets with 2 changes to 2 files
   (run 'hg update' to get a working copy)
   $ hgph
-  6 1 n-B - 145e75495359
-  5 1 n-A - d6bcb4f74035
-  4 0 b-A - f54f1bb90ff3
-  3 0 a-D - b555f63b6063
-  2 0 a-C - 54acac6f23ab
-  1 0 a-B - 548a3d25dbf0
-  0 0 a-A - 054250a37db4
+  o  6 draft n-B - 145e75495359
+  |
+  o  5 draft n-A - d6bcb4f74035
+  |
+  o  4 public b-A - f54f1bb90ff3
+  |
+  | @  3 public a-D - b555f63b6063
+  | |
+  | o  2 public a-C - 54acac6f23ab
+  |/
+  o  1 public a-B - 548a3d25dbf0
+  |
+  o  0 public a-A - 054250a37db4
+  
   $ cd ..
 
 pulling back into original repo
@@ -264,13 +343,20 @@
   searching for changes
   no changes found
   $ hgph
-  6 0 n-B - 145e75495359
-  5 0 n-A - d6bcb4f74035
-  4 0 a-D - b555f63b6063
-  3 0 b-A - f54f1bb90ff3
-  2 0 a-C - 54acac6f23ab
-  1 0 a-B - 548a3d25dbf0
-  0 0 a-A - 054250a37db4
+  @  6 public n-B - 145e75495359
+  |
+  o  5 public n-A - d6bcb4f74035
+  |
+  | o  4 public a-D - b555f63b6063
+  | |
+  o |  3 public b-A - f54f1bb90ff3
+  | |
+  | o  2 public a-C - 54acac6f23ab
+  |/
+  o  1 public a-B - 548a3d25dbf0
+  |
+  o  0 public a-A - 054250a37db4
+  
 
 Push
 ````
@@ -289,13 +375,20 @@
   $ cd ..
   $ cd alpha
   $ hgph
-  6 0 n-B - 145e75495359
-  5 0 n-A - d6bcb4f74035
-  4 0 b-A - f54f1bb90ff3
-  3 0 a-D - b555f63b6063
-  2 0 a-C - 54acac6f23ab
-  1 0 a-B - 548a3d25dbf0
-  0 0 a-A - 054250a37db4
+  o  6 public n-B - 145e75495359
+  |
+  o  5 public n-A - d6bcb4f74035
+  |
+  o  4 public b-A - f54f1bb90ff3
+  |
+  | @  3 public a-D - b555f63b6063
+  | |
+  | o  2 public a-C - 54acac6f23ab
+  |/
+  o  1 public a-B - 548a3d25dbf0
+  |
+  o  0 public a-A - 054250a37db4
+  
 
 (end insertion)
 
@@ -347,17 +440,28 @@
   $ mkcommit a-H
   created new head
   $ hgph
-  10 1 a-H - 967b449fbc94
-  9 1 a-G - 3e27b6f1eee1
-  8 1 a-F - b740e3e5c05d
-  7 1 a-E - e9f537e46dea
-  6 0 n-B - 145e75495359
-  5 0 n-A - d6bcb4f74035
-  4 0 b-A - f54f1bb90ff3
-  3 0 a-D - b555f63b6063
-  2 0 a-C - 54acac6f23ab
-  1 0 a-B - 548a3d25dbf0
-  0 0 a-A - 054250a37db4
+  @  10 draft a-H - 967b449fbc94
+  |
+  | o  9 draft a-G - 3e27b6f1eee1
+  | |
+  | o  8 draft a-F - b740e3e5c05d
+  | |
+  | o  7 draft a-E - e9f537e46dea
+  | |
+  +---o  6 public n-B - 145e75495359
+  | |
+  o |  5 public n-A - d6bcb4f74035
+  | |
+  o |  4 public b-A - f54f1bb90ff3
+  | |
+  | o  3 public a-D - b555f63b6063
+  | |
+  | o  2 public a-C - 54acac6f23ab
+  |/
+  o  1 public a-B - 548a3d25dbf0
+  |
+  o  0 public a-A - 054250a37db4
+  
 
 Pushing to Publish=False (unknown changeset)
 
@@ -369,29 +473,49 @@
   adding file changes
   added 2 changesets with 2 changes to 2 files
   $ hgph
-  10 1 a-H - 967b449fbc94
-  9 1 a-G - 3e27b6f1eee1
-  8 1 a-F - b740e3e5c05d
-  7 1 a-E - e9f537e46dea
-  6 0 n-B - 145e75495359
-  5 0 n-A - d6bcb4f74035
-  4 0 b-A - f54f1bb90ff3
-  3 0 a-D - b555f63b6063
-  2 0 a-C - 54acac6f23ab
-  1 0 a-B - 548a3d25dbf0
-  0 0 a-A - 054250a37db4
+  @  10 draft a-H - 967b449fbc94
+  |
+  | o  9 draft a-G - 3e27b6f1eee1
+  | |
+  | o  8 draft a-F - b740e3e5c05d
+  | |
+  | o  7 draft a-E - e9f537e46dea
+  | |
+  +---o  6 public n-B - 145e75495359
+  | |
+  o |  5 public n-A - d6bcb4f74035
+  | |
+  o |  4 public b-A - f54f1bb90ff3
+  | |
+  | o  3 public a-D - b555f63b6063
+  | |
+  | o  2 public a-C - 54acac6f23ab
+  |/
+  o  1 public a-B - 548a3d25dbf0
+  |
+  o  0 public a-A - 054250a37db4
+  
 
   $ cd ../mu
   $ hgph # d6bcb4f74035 and 145e75495359 changed because common is too smart
-  8 1 a-F - b740e3e5c05d
-  7 1 a-E - e9f537e46dea
-  6 0 n-B - 145e75495359
-  5 0 n-A - d6bcb4f74035
-  4 0 a-D - b555f63b6063
-  3 0 a-C - 54acac6f23ab
-  2 0 b-A - f54f1bb90ff3
-  1 0 a-B - 548a3d25dbf0
-  0 0 a-A - 054250a37db4
+  o  8 draft a-F - b740e3e5c05d
+  |
+  o  7 draft a-E - e9f537e46dea
+  |
+  | o  6 public n-B - 145e75495359
+  | |
+  | o  5 public n-A - d6bcb4f74035
+  | |
+  o |  4 public a-D - b555f63b6063
+  | |
+  o |  3 public a-C - 54acac6f23ab
+  | |
+  | o  2 public b-A - f54f1bb90ff3
+  |/
+  o  1 public a-B - 548a3d25dbf0
+  |
+  o  0 public a-A - 054250a37db4
+  
 
 Pushing to Publish=True (unknown changeset)
 
@@ -403,15 +527,24 @@
   adding file changes
   added 2 changesets with 2 changes to 2 files
   $ hgph # again d6bcb4f74035 and 145e75495359 changed because common is too smart
-  8 0 a-F - b740e3e5c05d
-  7 0 a-E - e9f537e46dea
-  6 0 n-B - 145e75495359
-  5 0 n-A - d6bcb4f74035
-  4 0 a-D - b555f63b6063
-  3 0 a-C - 54acac6f23ab
-  2 0 b-A - f54f1bb90ff3
-  1 0 a-B - 548a3d25dbf0
-  0 0 a-A - 054250a37db4
+  o  8 public a-F - b740e3e5c05d
+  |
+  o  7 public a-E - e9f537e46dea
+  |
+  | o  6 public n-B - 145e75495359
+  | |
+  | o  5 public n-A - d6bcb4f74035
+  | |
+  o |  4 public a-D - b555f63b6063
+  | |
+  o |  3 public a-C - 54acac6f23ab
+  | |
+  | o  2 public b-A - f54f1bb90ff3
+  |/
+  o  1 public a-B - 548a3d25dbf0
+  |
+  o  0 public a-A - 054250a37db4
+  
 
 Pushing to Publish=True (common changeset)
 
@@ -421,26 +554,44 @@
   searching for changes
   no changes found
   $ hgph
-  6 0 a-F - b740e3e5c05d
-  5 0 a-E - e9f537e46dea
-  4 0 a-D - b555f63b6063
-  3 0 a-C - 54acac6f23ab
-  2 0 b-A - f54f1bb90ff3
-  1 0 a-B - 548a3d25dbf0
-  0 0 a-A - 054250a37db4
+  o  6 public a-F - b740e3e5c05d
+  |
+  o  5 public a-E - e9f537e46dea
+  |
+  o  4 public a-D - b555f63b6063
+  |
+  o  3 public a-C - 54acac6f23ab
+  |
+  | @  2 public b-A - f54f1bb90ff3
+  |/
+  o  1 public a-B - 548a3d25dbf0
+  |
+  o  0 public a-A - 054250a37db4
+  
   $ cd ../alpha
   $ hgph # e9f537e46dea and b740e3e5c05d should have been sync to 0
-  10 1 a-H - 967b449fbc94
-  9 1 a-G - 3e27b6f1eee1
-  8 0 a-F - b740e3e5c05d
-  7 0 a-E - e9f537e46dea
-  6 0 n-B - 145e75495359
-  5 0 n-A - d6bcb4f74035
-  4 0 b-A - f54f1bb90ff3
-  3 0 a-D - b555f63b6063
-  2 0 a-C - 54acac6f23ab
-  1 0 a-B - 548a3d25dbf0
-  0 0 a-A - 054250a37db4
+  @  10 draft a-H - 967b449fbc94
+  |
+  | o  9 draft a-G - 3e27b6f1eee1
+  | |
+  | o  8 public a-F - b740e3e5c05d
+  | |
+  | o  7 public a-E - e9f537e46dea
+  | |
+  +---o  6 public n-B - 145e75495359
+  | |
+  o |  5 public n-A - d6bcb4f74035
+  | |
+  o |  4 public b-A - f54f1bb90ff3
+  | |
+  | o  3 public a-D - b555f63b6063
+  | |
+  | o  2 public a-C - 54acac6f23ab
+  |/
+  o  1 public a-B - 548a3d25dbf0
+  |
+  o  0 public a-A - 054250a37db4
+  
 
 Pushing to Publish=False (common changeset that change phase + unknown one)
 
@@ -452,30 +603,51 @@
   adding file changes
   added 1 changesets with 1 changes to 1 files (+1 heads)
   $ hgph
-  10 1 a-H - 967b449fbc94
-  9 1 a-G - 3e27b6f1eee1
-  8 0 a-F - b740e3e5c05d
-  7 0 a-E - e9f537e46dea
-  6 0 n-B - 145e75495359
-  5 0 n-A - d6bcb4f74035
-  4 0 b-A - f54f1bb90ff3
-  3 0 a-D - b555f63b6063
-  2 0 a-C - 54acac6f23ab
-  1 0 a-B - 548a3d25dbf0
-  0 0 a-A - 054250a37db4
+  @  10 draft a-H - 967b449fbc94
+  |
+  | o  9 draft a-G - 3e27b6f1eee1
+  | |
+  | o  8 public a-F - b740e3e5c05d
+  | |
+  | o  7 public a-E - e9f537e46dea
+  | |
+  +---o  6 public n-B - 145e75495359
+  | |
+  o |  5 public n-A - d6bcb4f74035
+  | |
+  o |  4 public b-A - f54f1bb90ff3
+  | |
+  | o  3 public a-D - b555f63b6063
+  | |
+  | o  2 public a-C - 54acac6f23ab
+  |/
+  o  1 public a-B - 548a3d25dbf0
+  |
+  o  0 public a-A - 054250a37db4
+  
   $ cd ../mu
   $ hgph # d6bcb4f74035 should have changed phase
   >      # again d6bcb4f74035 and 145e75495359 changed because common was too smart
-  9 1 a-H - 967b449fbc94
-  8 0 a-F - b740e3e5c05d
-  7 0 a-E - e9f537e46dea
-  6 0 n-B - 145e75495359
-  5 0 n-A - d6bcb4f74035
-  4 0 a-D - b555f63b6063
-  3 0 a-C - 54acac6f23ab
-  2 0 b-A - f54f1bb90ff3
-  1 0 a-B - 548a3d25dbf0
-  0 0 a-A - 054250a37db4
+  o  9 draft a-H - 967b449fbc94
+  |
+  | o  8 public a-F - b740e3e5c05d
+  | |
+  | o  7 public a-E - e9f537e46dea
+  | |
+  +---o  6 public n-B - 145e75495359
+  | |
+  o |  5 public n-A - d6bcb4f74035
+  | |
+  | o  4 public a-D - b555f63b6063
+  | |
+  | o  3 public a-C - 54acac6f23ab
+  | |
+  o |  2 public b-A - f54f1bb90ff3
+  |/
+  o  1 public a-B - 548a3d25dbf0
+  |
+  o  0 public a-A - 054250a37db4
+  
 
 
 Pushing to Publish=True (common changeset from publish=False)
@@ -486,28 +658,49 @@
   searching for changes
   no changes found
   $ hgph
-  9 0 a-H - 967b449fbc94
-  8 0 a-F - b740e3e5c05d
-  7 0 a-E - e9f537e46dea
-  6 0 n-B - 145e75495359
-  5 0 n-A - d6bcb4f74035
-  4 0 a-D - b555f63b6063
-  3 0 a-C - 54acac6f23ab
-  2 0 b-A - f54f1bb90ff3
-  1 0 a-B - 548a3d25dbf0
-  0 0 a-A - 054250a37db4
+  o  9 public a-H - 967b449fbc94
+  |
+  | o  8 public a-F - b740e3e5c05d
+  | |
+  | o  7 public a-E - e9f537e46dea
+  | |
+  +---o  6 public n-B - 145e75495359
+  | |
+  o |  5 public n-A - d6bcb4f74035
+  | |
+  | o  4 public a-D - b555f63b6063
+  | |
+  | o  3 public a-C - 54acac6f23ab
+  | |
+  o |  2 public b-A - f54f1bb90ff3
+  |/
+  o  1 public a-B - 548a3d25dbf0
+  |
+  o  0 public a-A - 054250a37db4
+  
   $ hgph -R ../alpha # a-H should have been synced to 0
-  10 0 a-H - 967b449fbc94
-  9 1 a-G - 3e27b6f1eee1
-  8 0 a-F - b740e3e5c05d
-  7 0 a-E - e9f537e46dea
-  6 0 n-B - 145e75495359
-  5 0 n-A - d6bcb4f74035
-  4 0 b-A - f54f1bb90ff3
-  3 0 a-D - b555f63b6063
-  2 0 a-C - 54acac6f23ab
-  1 0 a-B - 548a3d25dbf0
-  0 0 a-A - 054250a37db4
+  @  10 public a-H - 967b449fbc94
+  |
+  | o  9 draft a-G - 3e27b6f1eee1
+  | |
+  | o  8 public a-F - b740e3e5c05d
+  | |
+  | o  7 public a-E - e9f537e46dea
+  | |
+  +---o  6 public n-B - 145e75495359
+  | |
+  o |  5 public n-A - d6bcb4f74035
+  | |
+  o |  4 public b-A - f54f1bb90ff3
+  | |
+  | o  3 public a-D - b555f63b6063
+  | |
+  | o  2 public a-C - 54acac6f23ab
+  |/
+  o  1 public a-B - 548a3d25dbf0
+  |
+  o  0 public a-A - 054250a37db4
+  
 
 
 Discovery locally secret changeset on a remote repository:
@@ -517,18 +710,30 @@
   $ cd ../alpha
   $ mkcommit A-secret --config phases.new-commit=2
   $ hgph
-  11 2 A-secret - 435b5d83910c
-  10 0 a-H - 967b449fbc94
-  9 1 a-G - 3e27b6f1eee1
-  8 0 a-F - b740e3e5c05d
-  7 0 a-E - e9f537e46dea
-  6 0 n-B - 145e75495359
-  5 0 n-A - d6bcb4f74035
-  4 0 b-A - f54f1bb90ff3
-  3 0 a-D - b555f63b6063
-  2 0 a-C - 54acac6f23ab
-  1 0 a-B - 548a3d25dbf0
-  0 0 a-A - 054250a37db4
+  @  11 secret A-secret - 435b5d83910c
+  |
+  o  10 public a-H - 967b449fbc94
+  |
+  | o  9 draft a-G - 3e27b6f1eee1
+  | |
+  | o  8 public a-F - b740e3e5c05d
+  | |
+  | o  7 public a-E - e9f537e46dea
+  | |
+  +---o  6 public n-B - 145e75495359
+  | |
+  o |  5 public n-A - d6bcb4f74035
+  | |
+  o |  4 public b-A - f54f1bb90ff3
+  | |
+  | o  3 public a-D - b555f63b6063
+  | |
+  | o  2 public a-C - 54acac6f23ab
+  |/
+  o  1 public a-B - 548a3d25dbf0
+  |
+  o  0 public a-A - 054250a37db4
+  
   $ hg bundle --base 'parents(.)' -r . ../secret-bundle.hg
   1 changesets found
   $ hg -R ../mu unbundle ../secret-bundle.hg
@@ -538,34 +743,57 @@
   added 1 changesets with 1 changes to 1 files
   (run 'hg update' to get a working copy)
   $ hgph -R ../mu
-  10 1 A-secret - 435b5d83910c
-  9 0 a-H - 967b449fbc94
-  8 0 a-F - b740e3e5c05d
-  7 0 a-E - e9f537e46dea
-  6 0 n-B - 145e75495359
-  5 0 n-A - d6bcb4f74035
-  4 0 a-D - b555f63b6063
-  3 0 a-C - 54acac6f23ab
-  2 0 b-A - f54f1bb90ff3
-  1 0 a-B - 548a3d25dbf0
-  0 0 a-A - 054250a37db4
+  o  10 draft A-secret - 435b5d83910c
+  |
+  o  9 public a-H - 967b449fbc94
+  |
+  | o  8 public a-F - b740e3e5c05d
+  | |
+  | o  7 public a-E - e9f537e46dea
+  | |
+  +---o  6 public n-B - 145e75495359
+  | |
+  o |  5 public n-A - d6bcb4f74035
+  | |
+  | o  4 public a-D - b555f63b6063
+  | |
+  | o  3 public a-C - 54acac6f23ab
+  | |
+  o |  2 public b-A - f54f1bb90ff3
+  |/
+  o  1 public a-B - 548a3d25dbf0
+  |
+  o  0 public a-A - 054250a37db4
+  
   $ hg pull ../mu
   pulling from ../mu
   searching for changes
   no changes found
   $ hgph
-  11 1 A-secret - 435b5d83910c
-  10 0 a-H - 967b449fbc94
-  9 1 a-G - 3e27b6f1eee1
-  8 0 a-F - b740e3e5c05d
-  7 0 a-E - e9f537e46dea
-  6 0 n-B - 145e75495359
-  5 0 n-A - d6bcb4f74035
-  4 0 b-A - f54f1bb90ff3
-  3 0 a-D - b555f63b6063
-  2 0 a-C - 54acac6f23ab
-  1 0 a-B - 548a3d25dbf0
-  0 0 a-A - 054250a37db4
+  @  11 draft A-secret - 435b5d83910c
+  |
+  o  10 public a-H - 967b449fbc94
+  |
+  | o  9 draft a-G - 3e27b6f1eee1
+  | |
+  | o  8 public a-F - b740e3e5c05d
+  | |
+  | o  7 public a-E - e9f537e46dea
+  | |
+  +---o  6 public n-B - 145e75495359
+  | |
+  o |  5 public n-A - d6bcb4f74035
+  | |
+  o |  4 public b-A - f54f1bb90ff3
+  | |
+  | o  3 public a-D - b555f63b6063
+  | |
+  | o  2 public a-C - 54acac6f23ab
+  |/
+  o  1 public a-B - 548a3d25dbf0
+  |
+  o  0 public a-A - 054250a37db4
+  
   $ cd ..
 Test Clone behavior
 
@@ -577,17 +805,28 @@
 
   $ hg clone -U mu Tau
   $ hgph -R Tau
-  10 1 A-secret - 435b5d83910c
-  9 0 a-H - 967b449fbc94
-  8 0 a-F - b740e3e5c05d
-  7 0 a-E - e9f537e46dea
-  6 0 n-B - 145e75495359
-  5 0 n-A - d6bcb4f74035
-  4 0 a-D - b555f63b6063
-  3 0 a-C - 54acac6f23ab
-  2 0 b-A - f54f1bb90ff3
-  1 0 a-B - 548a3d25dbf0
-  0 0 a-A - 054250a37db4
+  o  10 draft A-secret - 435b5d83910c
+  |
+  o  9 public a-H - 967b449fbc94
+  |
+  | o  8 public a-F - b740e3e5c05d
+  | |
+  | o  7 public a-E - e9f537e46dea
+  | |
+  +---o  6 public n-B - 145e75495359
+  | |
+  o |  5 public n-A - d6bcb4f74035
+  | |
+  | o  4 public a-D - b555f63b6063
+  | |
+  | o  3 public a-C - 54acac6f23ab
+  | |
+  o |  2 public b-A - f54f1bb90ff3
+  |/
+  o  1 public a-B - 548a3d25dbf0
+  |
+  o  0 public a-A - 054250a37db4
+  
 
 2. cloning publishing repository
 
@@ -595,15 +834,27 @@
 
   $ hg clone -U alpha Upsilon
   $ hgph -R Upsilon
-  11 0 A-secret - 435b5d83910c
-  10 0 a-H - 967b449fbc94
-  9 0 a-G - 3e27b6f1eee1
-  8 0 a-F - b740e3e5c05d
-  7 0 a-E - e9f537e46dea
-  6 0 n-B - 145e75495359
-  5 0 n-A - d6bcb4f74035
-  4 0 b-A - f54f1bb90ff3
-  3 0 a-D - b555f63b6063
-  2 0 a-C - 54acac6f23ab
-  1 0 a-B - 548a3d25dbf0
-  0 0 a-A - 054250a37db4
+  o  11 public A-secret - 435b5d83910c
+  |
+  o  10 public a-H - 967b449fbc94
+  |
+  | o  9 public a-G - 3e27b6f1eee1
+  | |
+  | o  8 public a-F - b740e3e5c05d
+  | |
+  | o  7 public a-E - e9f537e46dea
+  | |
+  +---o  6 public n-B - 145e75495359
+  | |
+  o |  5 public n-A - d6bcb4f74035
+  | |
+  o |  4 public b-A - f54f1bb90ff3
+  | |
+  | o  3 public a-D - b555f63b6063
+  | |
+  | o  2 public a-C - 54acac6f23ab
+  |/
+  o  1 public a-B - 548a3d25dbf0
+  |
+  o  0 public a-A - 054250a37db4
+  
--- a/tests/test-phases.t	Mon Jan 09 02:32:01 2012 +0700
+++ b/tests/test-phases.t	Tue Jan 10 15:48:16 2012 -0200
@@ -1,4 +1,4 @@
-  $ alias hglog='hg log --template "{rev} {phase} {desc}\n"'
+  $ alias hglog='hg log --template "{rev} {phaseidx} {desc}\n"'
   $ mkcommit() {
   >    echo "$1" > "$1"
   >    hg add "$1"
@@ -91,6 +91,10 @@
 Test secret changeset are not pushed
 
   $ hg init ../push-dest
+  $ cat > ../push-dest/.hg/hgrc << EOF
+  > [phases]
+  > publish=False
+  > EOF
   $ hg push ../push-dest -f # force because we push multiple heads
   pushing to ../push-dest
   searching for changes
@@ -100,18 +104,18 @@
   added 5 changesets with 5 changes to 5 files (+1 heads)
   $ hglog
   7 2 merge B' and E
-  6 0 B'
+  6 1 B'
   5 2 H
   4 2 E
-  3 0 D
-  2 0 C
+  3 1 D
+  2 1 C
   1 0 B
   0 0 A
   $ cd ../push-dest
   $ hglog
-  4 0 B'
-  3 0 D
-  2 0 C
+  4 1 B'
+  3 1 D
+  2 1 C
   1 0 B
   0 0 A
   $ cd ..
@@ -134,3 +138,19 @@
   2 0 C
   1 0 B
   0 0 A
+  $ cd ..
+
+Test revset
+
+  $ cd initialrepo
+  $ hglog -r 'public()'
+  0 0 A
+  1 0 B
+  $ hglog -r 'draft()'
+  2 1 C
+  3 1 D
+  6 1 B'
+  $ hglog -r 'secret()'
+  4 2 E
+  5 2 H
+  7 2 merge B' and E
--- a/tests/test-push-http.t	Mon Jan 09 02:32:01 2012 +0700
+++ b/tests/test-push-http.t	Tue Jan 10 15:48:16 2012 -0200
@@ -29,7 +29,7 @@
   searching for changes
   remote: ssl required
   remote: ssl required
-  updating phase of ba677d0156c1to 0 failed!
+  updating phase of ba677d0156c1 to 0 from 1 failed!
   % serve errors
 
 expect authorization error
--- a/tests/test-rebase-named-branches.t	Mon Jan 09 02:32:01 2012 +0700
+++ b/tests/test-rebase-named-branches.t	Tue Jan 10 15:48:16 2012 -0200
@@ -22,25 +22,156 @@
   3 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ cd ..
 
-
-Rebasing descendant onto ancestor across different named branches
-
   $ hg clone -q -u . a a1
 
   $ cd a1
 
-  $ hg branch dev
-  marked working directory as branch dev
+  $ hg update 3
+  3 files updated, 0 files merged, 2 files removed, 0 files unresolved
+  $ hg branch dev-one
+  marked working directory as branch dev-one
+  (branches are permanent and global, did you want a bookmark?)
+  $ hg ci -m 'dev-one named branch'
+
+  $ hg update 7
+  2 files updated, 0 files merged, 3 files removed, 0 files unresolved
+  $ hg branch dev-two
+  marked working directory as branch dev-two
   (branches are permanent and global, did you want a bookmark?)
 
   $ echo x > x
 
   $ hg add x
 
-  $ hg ci -m 'extra named branch'
+  $ hg ci -m 'dev-two named branch'
+
+  $ hg tglog
+  @  9: 'dev-two named branch' dev-two
+  |
+  | o  8: 'dev-one named branch' dev-one
+  | |
+  o |  7: 'H'
+  | |
+  +---o  6: 'G'
+  | | |
+  o | |  5: 'F'
+  | | |
+  +---o  4: 'E'
+  | |
+  | o  3: 'D'
+  | |
+  | o  2: 'C'
+  | |
+  | o  1: 'B'
+  |/
+  o  0: 'A'
+  
+
+Branch name containing a dash (issue3181)
+
+  $ hg rebase -b dev-two -d dev-one --keepbranches
+  saved backup bundle to $TESTTMP/a1/.hg/strip-backup/*-backup.hg (glob)
+
+  $ hg tglog
+  @  9: 'dev-two named branch' dev-two
+  |
+  o  8: 'H'
+  |
+  | o  7: 'G'
+  |/|
+  o |  6: 'F'
+  | |
+  o |  5: 'dev-one named branch' dev-one
+  | |
+  | o  4: 'E'
+  | |
+  o |  3: 'D'
+  | |
+  o |  2: 'C'
+  | |
+  o |  1: 'B'
+  |/
+  o  0: 'A'
+  
+  $ hg rebase -s dev-one -d 0 --keepbranches
+  saved backup bundle to $TESTTMP/a1/.hg/strip-backup/*-backup.hg (glob)
 
   $ hg tglog
-  @  8: 'extra named branch' dev
+  @  8: 'dev-two named branch' dev-two
+  |
+  o  7: 'H'
+  |
+  | o  6: 'G'
+  |/|
+  o |  5: 'F'
+  | |
+  | o  4: 'E'
+  |/
+  | o  3: 'D'
+  | |
+  | o  2: 'C'
+  | |
+  | o  1: 'B'
+  |/
+  o  0: 'A'
+  
+  $ hg update 3
+  3 files updated, 0 files merged, 3 files removed, 0 files unresolved
+  $ hg branch dev-one
+  marked working directory as branch dev-one
+  (branches are permanent and global, did you want a bookmark?)
+  $ hg ci -m 'dev-one named branch'
+
+  $ hg tglog
+  @  9: 'dev-one named branch' dev-one
+  |
+  | o  8: 'dev-two named branch' dev-two
+  | |
+  | o  7: 'H'
+  | |
+  | | o  6: 'G'
+  | |/|
+  | o |  5: 'F'
+  | | |
+  | | o  4: 'E'
+  | |/
+  o |  3: 'D'
+  | |
+  o |  2: 'C'
+  | |
+  o |  1: 'B'
+  |/
+  o  0: 'A'
+  
+  $ hg rebase -b 'max(branch("dev-two"))' -d dev-one --keepbranches
+  saved backup bundle to $TESTTMP/a1/.hg/strip-backup/*-backup.hg (glob)
+
+  $ hg tglog
+  @  9: 'dev-two named branch' dev-two
+  |
+  o  8: 'H'
+  |
+  | o  7: 'G'
+  |/|
+  o |  6: 'F'
+  | |
+  o |  5: 'dev-one named branch' dev-one
+  | |
+  | o  4: 'E'
+  | |
+  o |  3: 'D'
+  | |
+  o |  2: 'C'
+  | |
+  o |  1: 'B'
+  |/
+  o  0: 'A'
+  
+  $ hg rebase -s 'max(branch("dev-one"))' -d 0 --keepbranches
+  saved backup bundle to $TESTTMP/a1/.hg/strip-backup/*-backup.hg (glob)
+
+  $ hg tglog
+  @  8: 'dev-two named branch' dev-two
   |
   o  7: 'H'
   |
@@ -59,6 +190,7 @@
   o  0: 'A'
   
 
+Rebasing descendant onto ancestor across different named branches
 
   $ hg rebase -s 1 -d 8 --keepbranches
   saved backup bundle to $TESTTMP/a1/.hg/strip-backup/*-backup.hg (glob)
@@ -70,7 +202,7 @@
   |
   o  6: 'B'
   |
-  o  5: 'extra named branch' dev
+  o  5: 'dev-two named branch' dev-two
   |
   o  4: 'H'
   |
@@ -96,7 +228,7 @@
   |
   o  6: 'B'
   |
-  o  5: 'extra named branch'
+  o  5: 'dev-two named branch'
   |
   o  4: 'H'
   |
--- a/tests/test-simplemerge.py	Mon Jan 09 02:32:01 2012 +0700
+++ b/tests/test-simplemerge.py	Tue Jan 10 15:48:16 2012 -0200
@@ -11,8 +11,7 @@
 # GNU General Public License for more details.
 #
 # You should have received a copy of the GNU General Public License
-# along with this program; if not, write to the Free Software
-# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+# along with this program; if not, see <http://www.gnu.org/licenses/>.
 
 import unittest
 from unittest import TestCase
--- a/tests/test-symlinks.t	Mon Jan 09 02:32:01 2012 +0700
+++ b/tests/test-symlinks.t	Tue Jan 10 15:48:16 2012 -0200
@@ -168,11 +168,12 @@
   ? foo
   $ hg status ../link
   ? foo
+  $ hg add foo
+  $ hg cp foo "$TESTTMP/link/bar"
+  foo has not been committed yet, so no copy data will be stored for bar.
   $ cd ..
 
 
-
-
   $ hg init b
   $ cd b
   $ ln -s nothing dangling