--- a/hgext/mq.py Sat Apr 30 03:00:38 2011 -0500
+++ b/hgext/mq.py Sat Apr 30 03:44:31 2011 -0500
@@ -852,7 +852,7 @@
raise util.Abort(_("local changes found"))
return m, a, r, d
- _reserved = ('series', 'status', 'guards')
+ _reserved = ('series', 'status', 'guards', '.', '..')
def check_reserved_name(self, name):
if (name in self._reserved or name.startswith('.hg')
or name.startswith('.mq') or '#' in name or ':' in name):
--- a/mercurial/subrepo.py Sat Apr 30 03:00:38 2011 -0500
+++ b/mercurial/subrepo.py Sat Apr 30 03:44:31 2011 -0500
@@ -10,6 +10,7 @@
from i18n import _
import config, scmutil, util, node, error, cmdutil, url, bookmarks
hg = None
+propertycache = util.propertycache
nullstate = ('', '', 'empty')
@@ -511,7 +512,6 @@
self._ui = ctx._repo.ui
def _svncommand(self, commands, filename=''):
- path = os.path.join(self._ctx._repo.origroot, self._path, filename)
cmd = ['svn']
# Starting in svn 1.5 --non-interactive is a global flag
# instead of being per-command, but we need to support 1.4 so
@@ -521,7 +521,9 @@
commands[0] in ('update', 'checkout', 'commit')):
cmd.append('--non-interactive')
cmd.extend(commands)
- cmd.append(path)
+ if filename is not None:
+ path = os.path.join(self._ctx._repo.origroot, self._path, filename)
+ cmd.append(path)
env = dict(os.environ)
# Avoid localized output, preserve current locale for everything else.
env['LC_MESSAGES'] = 'C'
@@ -534,6 +536,14 @@
raise util.Abort(stderr)
return stdout
+ @propertycache
+ def _svnversion(self):
+ output = self._svncommand(['--version'], filename=None)
+ m = re.search(r'^svn,\s+version\s+(\d+)\.(\d+)', output)
+ if not m:
+ raise util.Abort(_('cannot retrieve svn tool version'))
+ return (int(m.group(1)), int(m.group(2)))
+
def _wcrevs(self):
# Get the working directory revision as well as the last
# commit revision so we can compare the subrepo state with
@@ -628,7 +638,11 @@
def get(self, state, overwrite=False):
if overwrite:
self._svncommand(['revert', '--recursive'])
- status = self._svncommand(['checkout', state[0], '--revision', state[1]])
+ args = ['checkout']
+ if self._svnversion >= (1, 5):
+ args.append('--force')
+ args.extend([state[0], '--revision', state[1]])
+ status = self._svncommand(args)
if not re.search('Checked out revision [0-9]+.', status):
raise util.Abort(status.splitlines()[-1])
self._ui.status(status)
--- a/tests/hghave Sat Apr 30 03:00:38 2011 -0500
+++ b/tests/hghave Sat Apr 30 03:44:31 2011 -0500
@@ -121,6 +121,15 @@
except ImportError:
return False
+def getsvnversion():
+ m = matchoutput('svn --version 2>&1', r'^svn,\s+version\s+(\d+)\.(\d+)')
+ if not m:
+ return (0, 0)
+ return (int(m.group(1)), int(m.group(2)))
+
+def has_svn15():
+ return getsvnversion() >= (1, 5)
+
def has_svn():
return matchoutput('svn --version 2>&1', r'^svn, version') and \
matchoutput('svnadmin --version 2>&1', r'^svnadmin, version')
@@ -204,6 +213,7 @@
"pygments": (has_pygments, "Pygments source highlighting library"),
"ssl": (has_ssl, "python >= 2.6 ssl module and python OpenSSL"),
"svn": (has_svn, "subversion client and admin tools"),
+ "svn15": (has_svn15, "subversion client and admin tools >= 1.5"),
"svn-bindings": (has_svn_bindings, "subversion python bindings"),
"symlink": (has_symlink, "symbolic links"),
"tla": (has_tla, "GNU Arch tla client"),
--- a/tests/test-mq-qnew.t Sat Apr 30 03:00:38 2011 -0500
+++ b/tests/test-mq-qnew.t Sat Apr 30 03:44:31 2011 -0500
@@ -15,6 +15,8 @@
> hg qnew series
> hg qnew status
> hg qnew guards
+ > hg qnew .
+ > hg qnew ..
> hg qnew .hgignore
> hg qnew .mqfoo
> hg qnew 'foo#bar'
@@ -102,6 +104,8 @@
abort: "series" cannot be used as the name of a patch
abort: "status" cannot be used as the name of a patch
abort: "guards" cannot be used as the name of a patch
+ abort: "." cannot be used as the name of a patch
+ abort: ".." cannot be used as the name of a patch
abort: ".hgignore" cannot be used as the name of a patch
abort: ".mqfoo" cannot be used as the name of a patch
abort: "foo#bar" cannot be used as the name of a patch
@@ -167,6 +171,8 @@
abort: "series" cannot be used as the name of a patch
abort: "status" cannot be used as the name of a patch
abort: "guards" cannot be used as the name of a patch
+ abort: "." cannot be used as the name of a patch
+ abort: ".." cannot be used as the name of a patch
abort: ".hgignore" cannot be used as the name of a patch
abort: ".mqfoo" cannot be used as the name of a patch
abort: "foo#bar" cannot be used as the name of a patch
--- a/tests/test-subrepo-svn.t Sat Apr 30 03:00:38 2011 -0500
+++ b/tests/test-subrepo-svn.t Sat Apr 30 03:44:31 2011 -0500
@@ -438,3 +438,54 @@
$ svnversion
2
$ cd ..
+
+Test case where subversion would fail to update the subrepo because there
+are unknown directories being replaced by tracked ones (happens with rebase).
+
+ $ cd $WCROOT/src
+ $ mkdir dir
+ $ echo epsilon.py > dir/epsilon.py
+ $ svn add dir
+ A dir
+ A dir/epsilon.py
+ $ svn ci -m 'Add dir/epsilon.py'
+ Adding src/dir
+ Adding src/dir/epsilon.py
+ Transmitting file data .
+ Committed revision 6.
+ $ cd ../..
+ $ hg init rebaserepo
+ $ cd rebaserepo
+ $ svn co -r5 --quiet "$SVNREPO"/src s
+ $ echo "s = [svn] $SVNREPO/src" >> .hgsub
+ $ hg add .hgsub
+ $ hg ci -m addsub
+ committing subrepository s
+ $ echo a > a
+ $ hg ci -Am adda
+ adding a
+ $ hg up 0
+ 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
+ $ svn up -r6 s
+ A s/dir
+ A s/dir/epsilon.py
+
+ Fetching external item into 's/externals'
+ Updated external to revision 1.
+
+ Updated to revision 6.
+ $ hg ci -m updatesub
+ committing subrepository s
+ created new head
+ $ echo pyc > s/dir/epsilon.pyc
+ $ hg up 1
+ D $TESTTMP/rebaserepo/s/dir
+
+ Fetching external item into '$TESTTMP/rebaserepo/s/externals'
+ Checked out external at revision 1.
+
+ Checked out revision 5.
+ 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
+ $ if "$TESTDIR/hghave" -q svn15; then
+ > hg up 2 >/dev/null 2>&1 || echo update failed
+ > fi