changeset 16544:3d81780deb78 stable

merge with i18n
author Wagner Bruna <wbruna@yahoo.com>
date Sat, 28 Apr 2012 13:22:52 -0300
parents 39d1f83eb05d (diff) 715a9fb8ef22 (current diff)
children 4b093c30a5f0
files
diffstat 18 files changed, 289 insertions(+), 76 deletions(-) [+]
line wrap: on
line diff
--- a/hgext/rebase.py	Sun Apr 29 00:48:22 2012 +0900
+++ b/hgext/rebase.py	Sat Apr 28 13:22:52 2012 -0300
@@ -446,6 +446,7 @@
     mqrebase = {}
     mq = repo.mq
     original_series = mq.fullseries[:]
+    skippedpatches = set()
 
     for p in mq.applied:
         rev = repo[p.node].rev()
@@ -453,6 +454,9 @@
             repo.ui.debug('revision %d is an mq patch (%s), finalize it.\n' %
                                         (rev, p.name))
             mqrebase[rev] = (p.name, isagitpatch(repo, p.name))
+        else:
+            # Applied but not rebased, not sure this should happen
+            skippedpatches.add(p.name)
 
     if mqrebase:
         mq.finish(repo, mqrebase.keys())
@@ -464,14 +468,17 @@
                 repo.ui.debug('import mq patch %d (%s)\n' % (state[rev], name))
                 mq.qimport(repo, (), patchname=name, git=isgit,
                                 rev=[str(state[rev])])
+            else:
+                # Rebased and skipped
+                skippedpatches.add(mqrebase[rev][0])
 
-        # restore missing guards
-        for s in original_series:
-            pname = mq.guard_re.split(s, 1)[0]
-            if pname in mq.fullseries:
-                repo.ui.debug('restoring guard for patch %s' % (pname))
-                mq.fullseries[mq.fullseries.index(pname)] = s
-                mq.series_dirty = True
+        # Patches were either applied and rebased and imported in
+        # order, applied and removed or unapplied. Discard the removed
+        # ones while preserving the original series order and guards.
+        newseries = [s for s in original_series
+                     if mq.guard_re.split(s, 1)[0] not in skippedpatches]
+        mq.fullseries[:] = newseries
+        mq.seriesdirty = True
         mq.savedirty()
 
 def updatebookmarks(repo, nstate, originalbookmarks, **opts):
--- a/mercurial/base85.c	Sun Apr 29 00:48:22 2012 +0900
+++ b/mercurial/base85.c	Sat Apr 28 13:22:52 2012 -0300
@@ -109,7 +109,7 @@
 			if (c < 0)
 				return PyErr_Format(
 					PyExc_ValueError,
-					"Bad base85 character at position %d", i);
+					"bad base85 character at position %d", i);
 			acc = acc * 85 + c;
 		}
 		if (i++ < len)
@@ -118,13 +118,13 @@
 			if (c < 0)
 				return PyErr_Format(
 					PyExc_ValueError,
-					"Bad base85 character at position %d", i);
+					"bad base85 character at position %d", i);
 			/* overflow detection: 0xffffffff == "|NsC0",
 			 * "|NsC" == 0x03030303 */
 			if (acc > 0x03030303 || (acc *= 85) > 0xffffffff - c)
 				return PyErr_Format(
 					PyExc_ValueError,
-					"Bad base85 sequence at position %d", i);
+					"bad base85 sequence at position %d", i);
 			acc += c;
 		}
 
--- a/mercurial/discovery.py	Sun Apr 29 00:48:22 2012 +0900
+++ b/mercurial/discovery.py	Sat Apr 28 13:22:52 2012 -0300
@@ -153,7 +153,10 @@
         branches = set(repo[n].branch() for n in outgoing.missing)
 
         # 2. Check for new branches on the remote.
-        remotemap = remote.branchmap()
+        if remote.local():
+            remotemap = phases.visiblebranchmap(remote)
+        else:
+            remotemap = remote.branchmap()
         newbranches = branches - set(remotemap)
         if newbranches and not newbranch: # new branch requires --new-branch
             branchnames = ', '.join(sorted(newbranches))
--- a/mercurial/merge.py	Sun Apr 29 00:48:22 2012 +0900
+++ b/mercurial/merge.py	Sat Apr 28 13:22:52 2012 -0300
@@ -83,7 +83,7 @@
 
 def _checkunknownfile(repo, wctx, mctx, f):
     return (not repo.dirstate._ignore(f)
-        and os.path.exists(repo.wjoin(f))
+        and os.path.isfile(repo.wjoin(f))
         and repo.dirstate.normalize(f) not in repo.dirstate
         and mctx[f].cmp(wctx[f]))
 
--- a/mercurial/patch.py	Sun Apr 29 00:48:22 2012 +0900
+++ b/mercurial/patch.py	Sat Apr 28 13:22:52 2012 -0300
@@ -1022,9 +1022,10 @@
 
 class binhunk(object):
     'A binary patch file. Only understands literals so far.'
-    def __init__(self, lr):
+    def __init__(self, lr, fname):
         self.text = None
         self.hunk = ['GIT binary patch\n']
+        self._fname = fname
         self._read(lr)
 
     def complete(self):
@@ -1034,30 +1035,36 @@
         return [self.text]
 
     def _read(self, lr):
-        line = lr.readline()
-        self.hunk.append(line)
+        def getline(lr, hunk):
+            l = lr.readline()
+            hunk.append(l)
+            return l.rstrip('\r\n')
+
+        line = getline(lr, self.hunk)
         while line and not line.startswith('literal '):
-            line = lr.readline()
-            self.hunk.append(line)
+            line = getline(lr, self.hunk)
         if not line:
-            raise PatchError(_('could not extract binary patch'))
+            raise PatchError(_('could not extract "%s" binary data')
+                             % self._fname)
         size = int(line[8:].rstrip())
         dec = []
-        line = lr.readline()
-        self.hunk.append(line)
+        line = getline(lr, self.hunk)
         while len(line) > 1:
             l = line[0]
             if l <= 'Z' and l >= 'A':
                 l = ord(l) - ord('A') + 1
             else:
                 l = ord(l) - ord('a') + 27
-            dec.append(base85.b85decode(line[1:-1])[:l])
-            line = lr.readline()
-            self.hunk.append(line)
+            try:
+                dec.append(base85.b85decode(line[1:])[:l])
+            except ValueError, e:
+                raise PatchError(_('could not decode "%s" binary patch: %s')
+                                 % (self._fname, str(e)))
+            line = getline(lr, self.hunk)
         text = zlib.decompress(''.join(dec))
         if len(text) != size:
-            raise PatchError(_('binary patch is %d bytes, not %d') %
-                             len(text), size)
+            raise PatchError(_('"%s" length is %d bytes, should be %d')
+                             % (self._fname, len(text), size))
         self.text = text
 
 def parsefilename(str):
@@ -1196,7 +1203,7 @@
                 gitpatches[-1].ispatching(afile, bfile)):
                 gp = gitpatches.pop()
             if x.startswith('GIT binary patch'):
-                h = binhunk(lr)
+                h = binhunk(lr, gp.path)
             else:
                 if context is None and x.startswith('***************'):
                     context = True
@@ -1207,7 +1214,7 @@
                 yield 'file', (afile, bfile, h, gp and gp.copy() or None)
             yield 'hunk', h
         elif x.startswith('diff --git'):
-            m = gitre.match(x)
+            m = gitre.match(x.rstrip(' \r\n'))
             if not m:
                 continue
             if gitpatches is None:
--- a/mercurial/phases.py	Sun Apr 29 00:48:22 2012 +0900
+++ b/mercurial/phases.py	Sat Apr 28 13:22:52 2012 -0300
@@ -263,6 +263,28 @@
         vheads = repo.heads()
     return vheads
 
+def visiblebranchmap(repo):
+    """return a branchmap for the visible set"""
+    # XXX Recomputing this data on the fly is very slow.  We should build a
+    # XXX cached version while computin the standard branchmap version.
+    sroots = repo._phaseroots[secret]
+    if sroots:
+        vbranchmap = {}
+        for branch, nodes in  repo.branchmap().iteritems():
+            # search for secret heads.
+            for n in nodes:
+                if repo[n].phase() >= secret:
+                    nodes = None
+                    break
+            # if secreat heads where found we must compute them again
+            if nodes is None:
+                s = repo.set('heads(branch(%s) - secret())', branch)
+                nodes = [c.node() for c in s]
+            vbranchmap[branch] = nodes
+    else:
+        vbranchmap = repo.branchmap()
+    return vbranchmap
+
 def analyzeremotephases(repo, subset, roots):
     """Compute phases heads and root in a subset of node from root dict
 
--- a/mercurial/revlog.py	Sun Apr 29 00:48:22 2012 +0900
+++ b/mercurial/revlog.py	Sat Apr 28 13:22:52 2012 -0300
@@ -812,7 +812,7 @@
         else:
             df = self.opener(self.datafile)
 
-        readahead = max(_chunksize, length)
+        readahead = max(65536, length)
         df.seek(offset)
         d = df.read(readahead)
         df.close()
--- a/mercurial/revset.py	Sun Apr 29 00:48:22 2012 +0900
+++ b/mercurial/revset.py	Sat Apr 28 13:22:52 2012 -0300
@@ -341,23 +341,26 @@
 def checkstatus(repo, subset, pat, field):
     m = None
     s = []
-    fast = not matchmod.patkind(pat)
+    hasset = matchmod.patkind(pat) == 'set'
+    fname = None
     for r in subset:
         c = repo[r]
-        if fast:
-            if pat not in c.files():
+        if not m or hasset:
+            m = matchmod.match(repo.root, repo.getcwd(), [pat], ctx=c)
+            if not m.anypats() and len(m.files()) == 1:
+                fname = m.files()[0]
+        if fname is not None:
+            if fname not in c.files():
                 continue
         else:
-            if not m or matchmod.patkind(pat) == 'set':
-                m = matchmod.match(repo.root, repo.getcwd(), [pat], ctx=c)
             for f in c.files():
                 if m(f):
                     break
             else:
                 continue
         files = repo.status(c.p1().node(), c.node())[field]
-        if fast:
-            if pat in files:
+        if fname is not None:
+            if fname in files:
                 s.append(r)
         else:
             for f in files:
@@ -911,19 +914,23 @@
     """``matching(revision [, field])``
     Changesets in which a given set of fields match the set of fields in the
     selected revision or set.
+
     To match more than one field pass the list of fields to match separated
-    by spaces (e.g. 'author description').
-    Valid fields are most regular revision fields and some special fields:
-    * regular fields:
-      - description, author, branch, date, files, phase, parents,
-      substate, user.
-      Note that author and user are synonyms.
-    * special fields: summary, metadata.
-      - summary: matches the first line of the description.
-      - metatadata: It is equivalent to matching 'description user date'
-        (i.e. it matches the main metadata fields).
-    metadata is the default field which is used when no fields are specified.
-    You can match more than one field at a time.
+    by spaces (e.g. ``author description``).
+
+    Valid fields are most regular revision fields and some special fields.
+
+    Regular revision fields are ``description``, ``author``, ``branch``,
+    ``date``, ``files``, ``phase``, ``parents``, ``substate`` and ``user``.
+    Note that ``author`` and ``user`` are synonyms.
+
+    Special fields are ``summary`` and ``metadata``:
+    ``summary`` matches the first line of the description.
+    ``metatadata`` is equivalent to matching ``description user date``
+    (i.e. it matches the main metadata fields).
+
+    ``metadata`` is the default field which is used when no fields are
+    specified. You can match more than one field at a time.
     """
     l = getargs(x, 1, 2, _("matching takes 1 or 2 arguments"))
 
--- a/mercurial/subrepo.py	Sun Apr 29 00:48:22 2012 +0900
+++ b/mercurial/subrepo.py	Sat Apr 28 13:22:52 2012 -0300
@@ -366,7 +366,7 @@
         pass
 
     def forget(self, ui, match, prefix):
-        return []
+        return ([], [])
 
     def revert(self, ui, substate, *pats, **opts):
         ui.warn('%s: reverting %s subrepos is unsupported\n' \
@@ -680,12 +680,13 @@
         return self._wcrevs()[0]
 
     def _wcchanged(self):
-        """Return (changes, extchanges) where changes is True
-        if the working directory was changed, and extchanges is
-        True if any of these changes concern an external entry.
+        """Return (changes, extchanges, missing) where changes is True
+        if the working directory was changed, extchanges is
+        True if any of these changes concern an external entry and missing
+        is True if any change is a missing entry.
         """
         output, err = self._svncommand(['status', '--xml'])
-        externals, changes = [], []
+        externals, changes, missing = [], [], []
         doc = xml.dom.minidom.parseString(output)
         for e in doc.getElementsByTagName('entry'):
             s = e.getElementsByTagName('wc-status')
@@ -696,14 +697,16 @@
             path = e.getAttribute('path')
             if item == 'external':
                 externals.append(path)
+            elif item == 'missing':
+                missing.append(path)
             if (item not in ('', 'normal', 'unversioned', 'external')
                 or props not in ('', 'none', 'normal')):
                 changes.append(path)
         for path in changes:
             for ext in externals:
                 if path == ext or path.startswith(ext + os.sep):
-                    return True, True
-        return bool(changes), False
+                    return True, True, bool(missing)
+        return bool(changes), False, bool(missing)
 
     def dirty(self, ignoreupdate=False):
         if not self._wcchanged()[0]:
@@ -716,16 +719,26 @@
 
     def commit(self, text, user, date):
         # user and date are out of our hands since svn is centralized
-        changed, extchanged = self._wcchanged()
+        changed, extchanged, missing = self._wcchanged()
         if not changed:
             return self._wcrev()
         if extchanged:
             # Do not try to commit externals
             raise util.Abort(_('cannot commit svn externals'))
+        if missing:
+            # svn can commit with missing entries but aborting like hg
+            # seems a better approach.
+            raise util.Abort(_('cannot commit missing svn entries'))
         commitinfo, err = self._svncommand(['commit', '-m', text])
         self._ui.status(commitinfo)
         newrev = re.search('Committed revision ([0-9]+).', commitinfo)
         if not newrev:
+            if not commitinfo.strip():
+                # Sometimes, our definition of "changed" differs from
+                # svn one. For instance, svn ignores missing files
+                # when committing. If there are only missing files, no
+                # commit is made, no output and no error code.
+                raise util.Abort(_('failed to commit svn changes'))
             raise util.Abort(commitinfo.splitlines()[-1])
         newrev = newrev.groups()[0]
         self._ui.status(self._svncommand(['update', '-r', newrev])[0])
@@ -767,7 +780,7 @@
         status, err = self._svncommand(args, failok=True)
         if not re.search('Checked out revision [0-9]+.', status):
             if ('is already a working copy for a different URL' in err
-                and (self._wcchanged() == (False, False))):
+                and (self._wcchanged()[:2] == (False, False))):
                 # obstructed but clean working copy, so just blow it away.
                 self.remove()
                 self.get(state, overwrite=False)
--- a/mercurial/wireproto.py	Sun Apr 29 00:48:22 2012 +0900
+++ b/mercurial/wireproto.py	Sat Apr 28 13:22:52 2012 -0300
@@ -396,7 +396,7 @@
     return "".join(r)
 
 def branchmap(repo, proto):
-    branchmap = repo.branchmap()
+    branchmap = phases.visiblebranchmap(repo)
     heads = []
     for branch, nodes in branchmap.iteritems():
         branchname = urllib.quote(encoding.fromlocal(branch))
@@ -555,7 +555,7 @@
     their_heads = decodelist(heads)
 
     def check_heads():
-        heads = repo.heads()
+        heads = phases.visibleheads(repo)
         heads_hash = util.sha1(''.join(sorted(heads))).digest()
         return (their_heads == ['force'] or their_heads == heads or
                 their_heads == ['hashed', heads_hash])
--- a/tests/test-convert-svn-source.t	Sun Apr 29 00:48:22 2012 +0900
+++ b/tests/test-convert-svn-source.t	Sat Apr 28 13:22:52 2012 -0300
@@ -34,10 +34,10 @@
   $ cd ..
 
   $ svnurl="file://$svnpath/svn-repo/proj%20B"
-  $ svn import -m "init projB" projB "$svnurl" | fixpath
+  $ svn import -m "init projB" projB "$svnurl" | fixpath | sort
+  
   Adding         projB/mytrunk
   Adding         projB/tags
-  
   Committed revision 1.
 
 Update svn repository
--- a/tests/test-import-git.t	Sun Apr 29 00:48:22 2012 +0900
+++ b/tests/test-import-git.t	Sat Apr 28 13:22:52 2012 -0300
@@ -362,6 +362,77 @@
   A binary2
     text2
   R text2
+
+Invalid base85 content
+
+  $ hg rollback
+  repository tip rolled back to revision 15 (undo import)
+  working directory now based on revision 15
+  $ hg revert -aq
+  $ hg import -d "1000000 0" -m invalid-binary - <<"EOF"
+  > diff --git a/text2 b/binary2
+  > rename from text2
+  > rename to binary2
+  > index 78981922613b2afb6025042ff6bd878ac1994e85..10efcb362e9f3b3420fcfbfc0e37f3dc16e29757
+  > GIT binary patch
+  > literal 5
+  > Mc$`b*O.$Pw00T?_*Z=?k
+  > 
+  > EOF
+  applying patch from stdin
+  abort: could not decode "binary2" binary patch: bad base85 character at position 6
+  [255]
+
+  $ hg revert -aq
+  $ hg import -d "1000000 0" -m rename-as-binary - <<"EOF"
+  > diff --git a/text2 b/binary2
+  > rename from text2
+  > rename to binary2
+  > index 78981922613b2afb6025042ff6bd878ac1994e85..10efcb362e9f3b3420fcfbfc0e37f3dc16e29757
+  > GIT binary patch
+  > literal 6
+  > Mc$`b*O5$Pw00T?_*Z=?k
+  > 
+  > EOF
+  applying patch from stdin
+  abort: "binary2" length is 5 bytes, should be 6
+  [255]
+
+  $ hg revert -aq
+  $ hg import -d "1000000 0" -m rename-as-binary - <<"EOF"
+  > diff --git a/text2 b/binary2
+  > rename from text2
+  > rename to binary2
+  > index 78981922613b2afb6025042ff6bd878ac1994e85..10efcb362e9f3b3420fcfbfc0e37f3dc16e29757
+  > GIT binary patch
+  > Mc$`b*O5$Pw00T?_*Z=?k
+  > 
+  > EOF
+  applying patch from stdin
+  abort: could not extract "binary2" binary data
+  [255]
+
+Simulate a copy/paste turning LF into CRLF (issue2870)
+
+  $ hg revert -aq
+  $ cat > binary.diff <<"EOF"
+  > diff --git a/text2 b/binary2
+  > rename from text2
+  > rename to binary2
+  > index 78981922613b2afb6025042ff6bd878ac1994e85..10efcb362e9f3b3420fcfbfc0e37f3dc16e29757
+  > GIT binary patch
+  > literal 5
+  > Mc$`b*O5$Pw00T?_*Z=?k
+  > 
+  > EOF
+  >>> fp = file('binary.diff', 'rb')
+  >>> data = fp.read()
+  >>> fp.close()
+  >>> file('binary.diff', 'wb').write(data.replace('\n', '\r\n'))
+  $ rm binary2
+  $ hg import --no-commit binary.diff
+  applying binary.diff
+
   $ cd ..
 
 Consecutive import with renames (issue2459)
--- a/tests/test-phases-exchange.t	Sun Apr 29 00:48:22 2012 +0900
+++ b/tests/test-phases-exchange.t	Sat Apr 28 13:22:52 2012 -0300
@@ -833,12 +833,20 @@
   o  0 public a-A - 054250a37db4
   
 
-pushing a locally public and draft changesets remotly secret should make them appear on the remote side
+pushing a locally public and draft changesets remotly secret should make them
+appear on the remote side.
+
 
   $ hg -R ../mu phase --secret --force 967b449fbc94
   $ hg push -r 435b5d83910c ../mu
   pushing to ../mu
   searching for changes
+  abort: push creates new remote head 435b5d83910c!
+  (did you forget to merge? use push -f to force)
+  [255]
+  $ hg push -fr 435b5d83910c ../mu # because the push will create new visible head
+  pushing to ../mu
+  searching for changes
   adding changesets
   adding manifests
   adding file changes
--- a/tests/test-phases.t	Sun Apr 29 00:48:22 2012 +0900
+++ b/tests/test-phases.t	Sat Apr 28 13:22:52 2012 -0300
@@ -135,6 +135,39 @@
   2 1 C
   1 0 B
   0 0 A
+
+(Issue3303)
+Check that remote secret changeset are ignore when checking creation of remote heads
+
+We add a secret head into the push destination.  This secreat head shadow a
+visible shared between the initial repo and the push destination.
+
+  $ hg up -q 4 # B'
+  $ mkcommit Z --config phases.new-commit=secret
+  $ hg phase .
+  5: secret
+
+# We now try to push a new public changeset that descend from the common public
+# head shadowed by the remote secret head.
+
+  $ cd ../initialrepo
+  $ hg up -q 6 #B'
+  $ mkcommit I
+  created new head
+  $ hg push ../push-dest
+  pushing to ../push-dest
+  searching for changes
+  adding changesets
+  adding manifests
+  adding file changes
+  added 1 changesets with 1 changes to 1 files (+1 heads)
+
+:note: The "(+1 heads)" is wrong as we do not had any visible head
+
+
+Restore condition prior extra insertion.
+  $ hg -q --config extensions.mq= strip .
+  $ hg up -q 7
   $ cd ..
 
 Test secret changeset are not pull
--- a/tests/test-rebase-mq.t	Sun Apr 29 00:48:22 2012 +0900
+++ b/tests/test-rebase-mq.t	Sat Apr 28 13:22:52 2012 -0300
@@ -247,30 +247,41 @@
 Create mq repo with guarded patches foo and bar and empty patch:
 
   $ hg qinit
-  $ hg qnew foo
-  $ hg qguard foo +baz
+  $ echo guarded > guarded
+  $ hg add guarded
+  $ hg qnew guarded
+  $ hg qnew empty-important -m 'important commit message'
+  $ echo bar > bar
+  $ hg add bar
+  $ hg qnew bar
   $ echo foo > foo
   $ hg add foo
-  $ hg qref
-  $ hg qpop
+  $ hg qnew foo
+  $ hg qpop -a
   popping foo
+  popping bar
+  popping empty-important
+  popping guarded
   patch queue now empty
-
-  $ hg qnew empty-important -m 'important commit message'
-
-  $ hg qnew bar
+  $ hg qguard guarded +guarded
   $ hg qguard bar +baz
-  $ echo bar > bar
-  $ hg add bar
-  $ hg qref
+  $ hg qguard foo +baz
+  $ hg qselect baz
+  number of unguarded, unapplied patches has changed from 1 to 3
+  $ hg qpush bar
+  applying empty-important
+  patch empty-important is empty
+  applying bar
+  now at: bar
 
   $ hg qguard -l
+  guarded: +guarded
   empty-important: unguarded
   bar: +baz
   foo: +baz
 
   $ hg tglog
-  @  2: '[mq]: bar' tags: bar qtip tip
+  @  2: 'imported patch bar' tags: bar qtip tip
   |
   o  1: 'important commit message' tags: empty-important qbase
   |
@@ -303,18 +314,21 @@
 removed from the series):
 
   $ hg qseries
+  guarded
   empty-important
   bar
   foo
   $ [ -f .hg/patches/empty-important ]
   $ hg -q rebase -d 2
   $ hg qseries
+  guarded
   bar
   foo
   $ [ -f .hg/patches/empty-important ]
   [1]
 
   $ hg qguard -l
+  guarded: +guarded
   bar: +baz
   foo: +baz
 
--- a/tests/test-revset.t	Sun Apr 29 00:48:22 2012 +0900
+++ b/tests/test-revset.t	Sat Apr 28 13:22:52 2012 -0300
@@ -305,6 +305,13 @@
   6
   $ log 'modifies(b)'
   4
+  $ log 'modifies("path:b")'
+  4
+  $ log 'modifies("*")'
+  4
+  6
+  $ log 'modifies("set:modified()")'
+  4
   $ log 'id(5)'
   2
   $ log 'outgoing()'
--- a/tests/test-subrepo-git.t	Sun Apr 29 00:48:22 2012 +0900
+++ b/tests/test-subrepo-git.t	Sat Apr 28 13:22:52 2012 -0300
@@ -507,3 +507,8 @@
   da5f5b1d8ffcf62fb8327bcd3c89a4367a6018e7
   $ cd ..
 
+Test forgetting files, not implemented in git subrepo, used to
+traceback
+  $ hg forget 'notafile*'
+  notafile*: No such file or directory
+  [1]
--- a/tests/test-subrepo-svn.t	Sun Apr 29 00:48:22 2012 +0900
+++ b/tests/test-subrepo-svn.t	Sat Apr 28 13:22:52 2012 -0300
@@ -120,6 +120,15 @@
    source   file://*/svn-repo/src (glob)
    revision 2
 
+missing svn file, commit should fail
+
+  $ rm s/alpha
+  $ hg commit --subrepos -m 'abort on missing file'
+  committing subrepository s
+  abort: cannot commit missing svn entries
+  [255]
+  $ svn revert s/alpha > /dev/null
+
 add an unrelated revision in svn and update the subrepo to without
 bringing any changes.
 
@@ -272,13 +281,13 @@
   Checked out revision 3.
   1 files updated, 0 files merged, 0 files removed, 0 files unresolved
   $ cd t/s
-  $ svn status
+  $ svn status | sort
+  
   ? *    a (glob)
-  X *    externals (glob)
   ? *    f1 (glob)
   ? *    f2 (glob)
-  
   Performing status on external item at 'externals'* (glob)
+  X *    externals (glob)
 
 Sticky subrepositories, no changes
   $ cd $TESTTMP/sub/t
@@ -548,3 +557,10 @@
   archiving (s): 2/2 files (100.00%)
   archiving (recreated): 0/1 files (0.00%)
   archiving (recreated): 1/1 files (100.00%)
+
+Test forgetting files, not implemented in svn subrepo, used to
+traceback
+
+  $ hg forget 'notafile*'
+  notafile*: No such file or directory
+  [1]