diff --git a/hgext/mq.py b/hgext/mq.py --- a/hgext/mq.py +++ b/hgext/mq.py @@ -852,7 +852,7 @@ class queue(object): 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): diff --git a/mercurial/subrepo.py b/mercurial/subrepo.py --- a/mercurial/subrepo.py +++ b/mercurial/subrepo.py @@ -10,6 +10,7 @@ import stat, subprocess, tarfile from i18n import _ import config, scmutil, util, node, error, cmdutil, url, bookmarks hg = None +propertycache = util.propertycache nullstate = ('', '', 'empty') @@ -511,7 +512,6 @@ class svnsubrepo(abstractsubrepo): 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 @@ class svnsubrepo(abstractsubrepo): 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 @@ class svnsubrepo(abstractsubrepo): 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 @@ class svnsubrepo(abstractsubrepo): 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) diff --git a/tests/hghave b/tests/hghave --- a/tests/hghave +++ b/tests/hghave @@ -121,6 +121,15 @@ def has_docutils(): 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 @@ checks = { "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"), diff --git a/tests/test-mq-qnew.t b/tests/test-mq-qnew.t --- a/tests/test-mq-qnew.t +++ b/tests/test-mq-qnew.t @@ -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 @@ plain headers 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 @@ hg headers 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 diff --git a/tests/test-subrepo-svn.t b/tests/test-subrepo-svn.t --- a/tests/test-subrepo-svn.t +++ b/tests/test-subrepo-svn.t @@ -438,3 +438,54 @@ Test subrepo already at intended revisio $ 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