merge with i18n stable
authorMatt Mackall <mpm@selenic.com>
Fri, 31 Aug 2012 20:40:13 -0500
branchstable
changeset 17409 1fc45b9a1300
parent 17408 51d60983a32e (current diff)
parent 17405 b0aad9fb87f9 (diff)
child 17410 7c865f30e2b8
merge with i18n
--- a/contrib/wix/dist.wxs	Mon Aug 27 23:33:38 2012 +0900
+++ b/contrib/wix/dist.wxs	Fri Aug 31 20:40:13 2012 -0500
@@ -15,7 +15,7 @@
         <File Name="mercurial.osutil.pyd" />
         <File Name="mercurial.parsers.pyd" />
         <File Name="pyexpat.pyd" />
-        <File Name="python26.dll" />
+        <File Name="python27.dll" />
         <File Name="bz2.pyd" />
         <File Name="select.pyd" />
         <File Name="unicodedata.pyd" />
--- a/hgext/convert/common.py	Mon Aug 27 23:33:38 2012 +0900
+++ b/hgext/convert/common.py	Fri Aug 31 20:40:13 2012 -0500
@@ -276,9 +276,9 @@
                 pass
         cmdline = [util.shellquote(arg) for arg in cmdline]
         if not self.ui.debugflag:
-            cmdline += ['2>', util.nulldev]
+            cmdline += ['2>', os.devnull]
         if closestdin:
-            cmdline += ['<', util.nulldev]
+            cmdline += ['<', os.devnull]
         cmdline = ' '.join(cmdline)
         return cmdline
 
--- a/hgext/convert/gnuarch.py	Mon Aug 27 23:33:38 2012 +0900
+++ b/hgext/convert/gnuarch.py	Fri Aug 31 20:40:13 2012 -0500
@@ -184,7 +184,7 @@
         cmdline = [self.execmd, cmd]
         cmdline += args
         cmdline = [util.shellquote(arg) for arg in cmdline]
-        cmdline += ['>', util.nulldev, '2>', util.nulldev]
+        cmdline += ['>', os.devnull, '2>', os.devnull]
         cmdline = util.quotecommand(' '.join(cmdline))
         self.ui.debug(cmdline, '\n')
         return os.system(cmdline)
--- a/mercurial/cmdutil.py	Mon Aug 27 23:33:38 2012 +0900
+++ b/mercurial/cmdutil.py	Fri Aug 31 20:40:13 2012 -0500
@@ -515,7 +515,7 @@
         sys.stdout.flush()
         sys.stderr.flush()
 
-        nullfd = os.open(util.nulldev, os.O_RDWR)
+        nullfd = os.open(os.devnull, os.O_RDWR)
         logfilefd = nullfd
         if logfile:
             logfilefd = os.open(logfile, os.O_RDWR | os.O_CREAT | os.O_APPEND)
--- a/mercurial/commands.py	Mon Aug 27 23:33:38 2012 +0900
+++ b/mercurial/commands.py	Fri Aug 31 20:40:13 2012 -0500
@@ -1847,14 +1847,17 @@
         localrevs = opts.get('local_head')
         doit(localrevs, remoterevs)
 
-@command('debugfileset', [], ('REVSPEC'))
-def debugfileset(ui, repo, expr):
+@command('debugfileset',
+    [('r', 'rev', '', _('apply the filespec on this revision'), _('REV'))],
+    _('[-r REV] FILESPEC'))
+def debugfileset(ui, repo, expr, **opts):
     '''parse and apply a fileset specification'''
+    ctx = scmutil.revsingle(repo, opts.get('rev'), None)
     if ui.verbose:
         tree = fileset.parse(expr)[0]
         ui.note(tree, "\n")
 
-    for f in fileset.getfileset(repo[None], expr):
+    for f in fileset.getfileset(ctx, expr):
         ui.write("%s\n" % f)
 
 @command('debugfsinfo', [], _('[PATH]'))
@@ -1995,6 +1998,10 @@
         ui.write(_(" (check that your locale is properly set)\n"))
         problems += 1
 
+    # Python lib
+    ui.status(_("checking Python lib (%s)...\n")
+              % os.path.dirname(os.__file__))
+
     # compiled modules
     ui.status(_("checking installed modules (%s)...\n")
               % os.path.dirname(__file__))
@@ -4266,7 +4273,7 @@
                              hint=_("run 'hg heads .' to see heads"))
 
         parent = repo.dirstate.p1()
-        if len(nbhs) == 1:
+        if len(nbhs) <= 1:
             if len(bheads) > 1:
                 raise util.Abort(_("heads are bookmarked - "
                                    "please merge with an explicit rev"),
--- a/mercurial/fileset.py	Mon Aug 27 23:33:38 2012 +0900
+++ b/mercurial/fileset.py	Fri Aug 31 20:40:13 2012 -0500
@@ -107,6 +107,11 @@
     s = set(getset(mctx, x))
     return [r for r in mctx.subset if r not in s]
 
+def minusset(mctx, x, y):
+    xl = getset(mctx, x)
+    yl = set(getset(mctx, y))
+    return [f for f in xl if f not in yl]
+
 def listset(mctx, a, b):
     raise error.ParseError(_("can't use a list in this context"))
 
@@ -251,8 +256,11 @@
     """``grep(regex)``
     File contains the given regular expression.
     """
-    pat = getstring(x, _("grep requires a pattern"))
-    r = re.compile(pat)
+    try:
+        # i18n: "grep" is a keyword
+        r = re.compile(getstring(x, _("grep requires a pattern")))
+    except re.error, e:
+        raise error.ParseError(_('invalid match pattern: %s') % e)
     return [f for f in mctx.existing() if r.search(mctx.ctx[f].data())]
 
 _units = dict(k=2**10, K=2**10, kB=2**10, KB=2**10,
@@ -406,6 +414,7 @@
     'symbol': stringset,
     'and': andset,
     'or': orset,
+    'minus': minusset,
     'list': listset,
     'group': getset,
     'not': notset,
@@ -424,7 +433,14 @@
     def filter(self, files):
         return [f for f in files if f in self.subset]
     def existing(self):
-        return (f for f in self.subset if f in self.ctx)
+        if self._status is not None:
+            removed = set(self._status[3])
+            unknown = set(self._status[4] + self._status[5])
+        else:
+            removed = set()
+            unknown = set()
+        return (f for f in self.subset
+                if (f in self.ctx and f not in removed) or f in unknown)
     def narrow(self, files):
         return matchctx(self.ctx, self.filter(files), self._status)
 
@@ -438,14 +454,26 @@
                 return True
     return False
 
+# filesets using matchctx.existing()
+_existingcallers = [
+    'binary',
+    'exec',
+    'grep',
+    'size',
+    'symlink',
+]
+
 def getfileset(ctx, expr):
     tree, pos = parse(expr)
     if (pos != len(expr)):
         raise error.ParseError(_("invalid token"), pos)
 
     # do we need status info?
-    if _intree(['modified', 'added', 'removed', 'deleted',
-                'unknown', 'ignored', 'clean'], tree):
+    if (_intree(['modified', 'added', 'removed', 'deleted',
+                 'unknown', 'ignored', 'clean'], tree) or
+        # Using matchctx.existing() on a workingctx requires us to check
+        # for deleted files.
+        (ctx.rev() is None and _intree(_existingcallers, tree))):
         unknown = _intree(['unknown'], tree)
         ignored = _intree(['ignored'], tree)
 
@@ -457,7 +485,7 @@
             subset.extend(c)
     else:
         status = None
-        subset = ctx.walk(ctx.match([]))
+        subset = list(ctx.walk(ctx.match([])))
 
     return getset(matchctx(ctx, subset, status), tree)
 
--- a/mercurial/localrepo.py	Mon Aug 27 23:33:38 2012 +0900
+++ b/mercurial/localrepo.py	Fri Aug 31 20:40:13 2012 -0500
@@ -1009,7 +1009,7 @@
             util.rename(self.join('undo.dirstate'), self.join('dirstate'))
             try:
                 branch = self.opener.read('undo.branch')
-                self.dirstate.setbranch(branch)
+                self.dirstate.setbranch(encoding.tolocal(branch))
             except IOError:
                 ui.warn(_('named branch could not be reset: '
                           'current branch is still \'%s\'\n')
@@ -1312,6 +1312,7 @@
                 matched = set(changes[0] + changes[1] + changes[2])
 
                 for f in match.files():
+                    f = self.dirstate.normalize(f)
                     if f == '.' or f in matched or f in wctx.substate:
                         continue
                     if f in changes[3]: # missing
--- a/mercurial/obsolete.py	Mon Aug 27 23:33:38 2012 +0900
+++ b/mercurial/obsolete.py	Fri Aug 31 20:40:13 2012 -0500
@@ -52,7 +52,7 @@
   cannot contain '\0'.
 """
 import struct
-from mercurial import util, base85
+import util, base85
 from i18n import _
 
 # the obsolete feature is not mature enought to be enabled by default.
--- a/mercurial/parsers.c	Mon Aug 27 23:33:38 2012 +0900
+++ b/mercurial/parsers.c	Fri Aug 31 20:40:13 2012 -0500
@@ -1084,8 +1084,10 @@
 		return NULL;
 	}
 
-	if (nodelen > 40)
-		nodelen = 40;
+	if (nodelen > 40) {
+		PyErr_SetString(PyExc_ValueError, "key too long");
+		return NULL;
+	}
 
 	for (i = 0; i < nodelen; i++)
 		hexdigit(node, i);
--- a/mercurial/posix.py	Mon Aug 27 23:33:38 2012 +0900
+++ b/mercurial/posix.py	Fri Aug 31 20:40:13 2012 -0500
@@ -10,7 +10,6 @@
 import os, sys, errno, stat, getpass, pwd, grp, tempfile, unicodedata
 
 posixfile = open
-nulldev = '/dev/null'
 normpath = os.path.normpath
 samestat = os.path.samestat
 oslink = os.link
--- a/mercurial/store.py	Mon Aug 27 23:33:38 2012 +0900
+++ b/mercurial/store.py	Fri Aug 31 20:40:13 2012 -0500
@@ -7,7 +7,7 @@
 
 from i18n import _
 import osutil, scmutil, util
-import os, stat
+import os, stat, errno
 
 _sha = util.sha1
 
@@ -398,12 +398,14 @@
     def datafiles(self):
         rewrite = False
         existing = []
-        for f in self.fncache:
+        for f in sorted(self.fncache):
             ef = self.encode(f)
             try:
                 yield f, ef, self.getsize(ef)
                 existing.append(f)
-            except OSError:
+            except OSError, err:
+                if err.errno != errno.ENOENT:
+                    raise
                 # nonexistent entry
                 rewrite = True
         if rewrite:
--- a/mercurial/util.py	Mon Aug 27 23:33:38 2012 +0900
+++ b/mercurial/util.py	Fri Aug 31 20:40:13 2012 -0500
@@ -45,7 +45,6 @@
 nlinks = platform.nlinks
 normpath = platform.normpath
 normcase = platform.normcase
-nulldev = platform.nulldev
 openhardlinks = platform.openhardlinks
 oslink = platform.oslink
 parsepatchoutput = platform.parsepatchoutput
--- a/mercurial/verify.py	Mon Aug 27 23:33:38 2012 +0900
+++ b/mercurial/verify.py	Fri Aug 31 20:40:13 2012 -0500
@@ -120,6 +120,7 @@
     havemf = len(mf) > 0
 
     ui.status(_("checking changesets\n"))
+    hasmanifest = False
     seen = {}
     checklog(cl, "changelog", 0)
     total = len(repo)
@@ -130,16 +131,22 @@
 
         try:
             changes = cl.read(n)
-            mflinkrevs.setdefault(changes[0], []).append(i)
+            if changes[0] != nullid:
+                mflinkrevs.setdefault(changes[0], []).append(i)
+                hasmanifest = True
             for f in changes[3]:
                 filelinkrevs.setdefault(f, []).append(i)
         except Exception, inst:
+            hasmanifest = True
             exc(i, _("unpacking changeset %s") % short(n), inst)
     ui.progress(_('checking'), None)
 
     ui.status(_("checking manifests\n"))
     seen = {}
-    checklog(mf, "manifest", 0)
+    if hasmanifest:
+        # Do not check manifest if there are only changelog entries with
+        # null manifests.
+        checklog(mf, "manifest", 0)
     total = len(mf)
     for i in mf:
         ui.progress(_('checking'), i, total=total, unit=_('manifests'))
--- a/mercurial/windows.py	Mon Aug 27 23:33:38 2012 +0900
+++ b/mercurial/windows.py	Fri Aug 31 20:40:13 2012 -0500
@@ -24,7 +24,6 @@
 testpid = win32.testpid
 unlink = win32.unlink
 
-nulldev = 'NUL:'
 umask = 0022
 
 # wrap osutil.posixfile to provide friendlier exceptions
@@ -174,7 +173,7 @@
     # Work around "popen spawned process may not write to stdout
     # under windows"
     # http://bugs.python.org/issue1366
-    command += " 2> %s" % nulldev
+    command += " 2> %s" % os.devnull
     return os.popen(quotecommand(command), mode)
 
 def explainexit(code):
--- a/tests/test-bookmarks-merge.t	Mon Aug 27 23:33:38 2012 +0900
+++ b/tests/test-bookmarks-merge.t	Fri Aug 31 20:40:13 2012 -0500
@@ -91,3 +91,38 @@
      b                         1:d2ae7f538514
      c                         3:b8f96cf4688b
    * e                         7:ca784329f0ba
+
+# test warning when all heads are inactive bookmarks
+
+  $ hg up -C 6
+  1 files updated, 0 files merged, 1 files removed, 0 files unresolved
+  $ echo g > g
+  $ hg commit -Am 'g'
+  adding g
+  $ hg bookmark -i g
+  $ hg bookmarks
+     b                         1:d2ae7f538514
+     c                         3:b8f96cf4688b
+     e                         7:ca784329f0ba
+     g                         8:04dd21731d95
+  $ hg heads
+  changeset:   8:04dd21731d95
+  bookmark:    g
+  tag:         tip
+  parent:      6:be381d1126a0
+  user:        test
+  date:        Thu Jan 01 00:00:00 1970 +0000
+  summary:     g
+  
+  changeset:   7:ca784329f0ba
+  bookmark:    e
+  parent:      5:26bee9c5bcf3
+  parent:      4:a0546fcfe0fb
+  user:        test
+  date:        Thu Jan 01 00:00:00 1970 +0000
+  summary:     merge
+  
+  $ hg merge
+  abort: heads are bookmarked - please merge with an explicit rev
+  (run 'hg heads' to see all heads)
+  [255]
--- a/tests/test-cat.t	Mon Aug 27 23:33:38 2012 +0900
+++ b/tests/test-cat.t	Fri Aug 31 20:40:13 2012 -0500
@@ -21,3 +21,14 @@
   [1]
   $ hg cat -r 1 b
   1
+
+Test fileset
+
+  $ echo 3 > c
+  $ hg ci -Am addmore c
+  $ hg cat 'set:not(b) or a'
+  3
+  $ hg cat 'set:c or b'
+  1
+  3
+
--- a/tests/test-debugcomplete.t	Mon Aug 27 23:33:38 2012 +0900
+++ b/tests/test-debugcomplete.t	Fri Aug 31 20:40:13 2012 -0500
@@ -229,7 +229,7 @@
   debugdata: changelog, manifest
   debugdate: extended
   debugdiscovery: old, nonheads, ssh, remotecmd, insecure
-  debugfileset: 
+  debugfileset: rev
   debugfsinfo: 
   debuggetbundle: head, common, type
   debugignore: 
--- a/tests/test-encoding.t	Mon Aug 27 23:33:38 2012 +0900
+++ b/tests/test-encoding.t	Fri Aug 31 20:40:13 2012 -0500
@@ -44,6 +44,10 @@
   marked working directory as branch \xe9 (esc)
   (branches are permanent and global, did you want a bookmark?)
   $ HGENCODING=latin-1 hg ci -m 'latin1 branch'
+  $ hg -q rollback
+  $ HGENCODING=latin-1 hg branch
+  \xe9 (esc)
+  $ HGENCODING=latin-1 hg ci -m 'latin1 branch'
   $ rm .hg/branch
 
 hg log (ascii)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tests/test-fileset.t	Fri Aug 31 20:40:13 2012 -0500
@@ -0,0 +1,228 @@
+  $ fileset() {
+  >   hg debugfileset "$@"
+  > }
+
+  $ hg init repo
+  $ cd repo
+  $ echo a > a1
+  $ echo a > a2
+  $ echo b > b1
+  $ echo b > b2
+  $ hg ci -Am addfiles
+  adding a1
+  adding a2
+  adding b1
+  adding b2
+
+Test operators and basic patterns
+
+  $ fileset a1
+  a1
+  $ fileset 'a*'
+  a1
+  a2
+  $ fileset '"re:a\d"'
+  a1
+  a2
+  $ fileset 'a1 or a2'
+  a1
+  a2
+  $ fileset 'a1 | a2'
+  a1
+  a2
+  $ fileset 'a* and "*1"'
+  a1
+  $ fileset 'a* & "*1"'
+  a1
+  $ fileset 'not (r"a*")'
+  b1
+  b2
+  $ fileset '! ("a*")'
+  b1
+  b2
+  $ fileset 'a* - a1'
+  a2
+
+Test files status
+
+  $ rm a1
+  $ hg rm a2
+  $ echo b >> b2
+  $ hg cp b1 c1
+  $ echo c > c2
+  $ echo c > c3
+  $ cat > .hgignore <<EOF
+  > \.hgignore
+  > 2$
+  > EOF
+  $ fileset 'modified()'
+  b2
+  $ fileset 'added()'
+  c1
+  $ fileset 'removed()'
+  a2
+  $ fileset 'deleted()'
+  a1
+  $ fileset 'unknown()'
+  c3
+  $ fileset 'ignored()'
+  .hgignore
+  c2
+  $ fileset 'hgignore()'
+  a2
+  b2
+  $ fileset 'clean()'
+  b1
+  $ fileset 'copied()'
+  c1
+
+Test files properties
+
+  >>> file('bin', 'wb').write('\0a')
+  $ fileset 'binary()'
+  $ fileset 'binary() and unknown()'
+  bin
+  $ echo '^bin$' >> .hgignore
+  $ fileset 'binary() and ignored()'
+  bin
+  $ hg add bin
+  $ fileset 'binary()'
+  bin
+
+  $ fileset 'grep("b{1}")'
+  b2
+  c1
+  b1
+  $ fileset 'grep("missingparens(")'
+  hg: parse error: invalid match pattern: unbalanced parenthesis
+  [255]
+
+#if execbit
+  $ chmod +x b2
+  $ fileset 'exec()'
+  b2
+#endif
+
+#if symlink
+  $ ln -s b2 b2link
+  $ fileset 'symlink() and unknown()'
+  b2link
+  $ hg add b2link
+#endif
+
+  >>> file('1k', 'wb').write(' '*1024)
+  >>> file('2k', 'wb').write(' '*2048)
+  $ hg add 1k 2k
+  $ fileset 'size("bar")'
+  hg: parse error: couldn't parse size: bar
+  [255]
+  $ fileset 'size(1k)'
+  1k
+  $ fileset '(1k or 2k) and size("< 2k")'
+  1k
+  $ fileset '(1k or 2k) and size("<=2k")'
+  1k
+  2k
+  $ fileset '(1k or 2k) and size("> 1k")'
+  2k
+  $ fileset '(1k or 2k) and size(">=1K")'
+  1k
+  2k
+  $ fileset '(1k or 2k) and size(".5KB - 1.5kB")'
+  1k
+
+Test merge states
+
+  $ hg ci -m manychanges
+  $ hg up -C 0
+  * files updated, 0 files merged, * files removed, 0 files unresolved (glob)
+  $ echo c >> b2
+  $ hg ci -m diverging b2
+  created new head
+  $ fileset 'resolved()'
+  $ fileset 'unresolved()'
+  $ hg merge
+  merging b2
+  warning: conflicts during merge.
+  merging b2 incomplete! (edit conflicts, then use 'hg resolve --mark')
+  * files updated, 0 files merged, * files removed, 1 files unresolved (glob)
+  use 'hg resolve' to retry unresolved file merges or 'hg update -C .' to abandon
+  [1]
+  $ fileset 'resolved()'
+  $ fileset 'unresolved()'
+  b2
+  $ echo e > b2
+  $ hg resolve -m b2
+  $ fileset 'resolved()'
+  b2
+  $ fileset 'unresolved()'
+  $ hg ci -m merge
+
+Test subrepo predicate
+
+  $ hg init sub
+  $ echo a > sub/suba
+  $ hg -R sub add sub/suba
+  $ hg -R sub ci -m sub
+  $ echo 'sub = sub' > .hgsub
+  $ fileset 'subrepo()'
+  $ hg add .hgsub
+  $ fileset 'subrepo()'
+  sub
+  $ fileset 'subrepo("sub")'
+  sub
+  $ fileset 'subrepo("glob:*")'
+  sub
+  $ hg ci -m subrepo
+
+Test with a revision
+
+  $ hg log -G --template '{rev} {desc}\n'
+  @  4 subrepo
+  |
+  o    3 merge
+  |\
+  | o  2 diverging
+  | |
+  o |  1 manychanges
+  |/
+  o  0 addfiles
+  
+  $ echo unknown > unknown
+  $ fileset -r1 'modified()'
+  b2
+  $ fileset -r1 'added() and c1'
+  c1
+  $ fileset -r1 'removed()'
+  a2
+  $ fileset -r1 'deleted()'
+  $ fileset -r1 'unknown()'
+  $ fileset -r1 'ignored()'
+  $ fileset -r1 'hgignore()'
+  b2
+  bin
+  $ fileset -r1 'binary()'
+  bin
+  $ fileset -r1 'size(1k)'
+  1k
+  $ fileset -r3 'resolved()'
+  $ fileset -r3 'unresolved()'
+
+#if execbit
+  $ fileset -r1 'exec()'
+  b2
+#endif
+
+#if symlink
+  $ fileset -r1 'symlink()'
+  b2link
+#endif
+
+  $ fileset -r4 'subrepo("re:su.*")'
+  sub
+  $ fileset -r4 'subrepo("sub")'
+  sub
+  $ fileset -r4 'b2 or c1'
+  b2
+  c1
+
--- a/tests/test-install.t	Mon Aug 27 23:33:38 2012 +0900
+++ b/tests/test-install.t	Fri Aug 31 20:40:13 2012 -0500
@@ -1,6 +1,7 @@
 hg debuginstall
   $ hg debuginstall
   checking encoding (ascii)...
+  checking Python lib (*lib*)... (glob)
   checking installed modules (*mercurial)... (glob)
   checking templates (*mercurial?templates)... (glob)
   checking commit editor...
@@ -10,6 +11,7 @@
 hg debuginstall with no username
   $ HGUSER= hg debuginstall
   checking encoding (ascii)...
+  checking Python lib (*lib*)... (glob)
   checking installed modules (*mercurial)... (glob)
   checking templates (*mercurial?templates)... (glob)
   checking commit editor...
--- a/tests/test-verify.t	Mon Aug 27 23:33:38 2012 +0900
+++ b/tests/test-verify.t	Fri Aug 31 20:40:13 2012 -0500
@@ -61,10 +61,22 @@
   $ cd ../../..
   $ cd ..
 
-test revlog corruption
+test changelog without a manifest
 
   $ hg init b
   $ cd b
+  $ hg branch foo
+  marked working directory as branch foo
+  (branches are permanent and global, did you want a bookmark?)
+  $ hg ci -m branchfoo
+  $ hg verify
+  checking changesets
+  checking manifests
+  crosschecking files in changesets and manifests
+  checking files
+  0 files, 1 changesets, 0 total revisions
+
+test revlog corruption
 
   $ touch a
   $ hg add a
@@ -79,12 +91,12 @@
   checking manifests
   crosschecking files in changesets and manifests
   checking files
-   a@0: broken revlog! (index data/a.i is corrupted)
+   a@1: broken revlog! (index data/a.i is corrupted)
   warning: orphan revlog 'data/a.i'
-  1 files, 1 changesets, 0 total revisions
+  1 files, 2 changesets, 0 total revisions
   1 warnings encountered!
   1 integrity errors encountered!
-  (first damaged changeset appears to be 0)
+  (first damaged changeset appears to be 1)
   [1]
 
   $ cd ..