subrepo: handle svn externals and meta changes (issue1982)
- Detect changes to meta on regular and external entries
- Do not try to commit external entries
--- a/mercurial/subrepo.py Thu Jan 21 15:13:40 2010 +0100
+++ b/mercurial/subrepo.py Thu Jan 21 13:26:26 2010 +0100
@@ -282,27 +282,45 @@
return 0
return int(entries[0].getAttribute('revision') or 0)
- def _wcclean(self):
+ 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.
+ """
output = self._svncommand(['status', '--xml'])
+ externals, changes = [], []
doc = xml.dom.minidom.parseString(output)
- for s in doc.getElementsByTagName('wc-status'):
- st = s.getAttribute('item')
- if st and st != 'unversioned':
- return False
- props = s.getAttribute('props')
- if props and props != 'none':
- return False
- return True
+ for e in doc.getElementsByTagName('entry'):
+ s = e.getElementsByTagName('wc-status')
+ if not s:
+ continue
+ item = s[0].getAttribute('item')
+ props = s[0].getAttribute('props')
+ path = e.getAttribute('path')
+ if item == 'external':
+ externals.append(path)
+ if (item not in ('', 'normal', 'unversioned', 'external')
+ or props not in ('', 'none')):
+ 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
def dirty(self):
- if self._wcrev() == self._state[1] and self._wcclean():
+ if self._wcrev() == self._state[1] and not self._wcchanged()[0]:
return False
return True
def commit(self, text, user, date):
# user and date are out of our hands since svn is centralized
- if self._wcclean():
+ changed, extchanged = self._wcchanged()
+ if not changed:
return self._wcrev()
+ if extchanged:
+ # Do not try to commit externals
+ raise util.Abort(_('cannot commit svn externals'))
commitinfo = self._svncommand(['commit', '-m', text])
self._ui.status(commitinfo)
newrev = re.search('Committed revision ([\d]+).', commitinfo)
--- a/tests/test-subrepo-svn Thu Jan 21 15:13:40 2010 +0100
+++ b/tests/test-subrepo-svn Thu Jan 21 13:26:26 2010 +0100
@@ -23,9 +23,19 @@
svnadmin create svn-repo
svn co $SVNREPO svn-wc
cd svn-wc
-echo alpha > alpha
-svn add alpha
+mkdir src
+echo alpha > src/alpha
+svn add src
+mkdir externals
+echo other > externals/other
+svn add externals
svn ci -m 'Add alpha'
+svn up
+cat > extdef <<EOF
+externals -r1 $SVNREPO/externals
+EOF
+svn propset -F extdef svn:externals src
+svn ci -m 'Setting externals'
cd ..
echo % create hg repo
@@ -39,8 +49,8 @@
hg ci -Am0
echo % add first svn sub
-echo "s = [svn]$SVNREPO" >> .hgsub
-svn co --quiet $SVNREPO s
+echo "s = [svn]$SVNREPO/src" >> .hgsub
+svn co --quiet $SVNREPO/src s
hg add .hgsub
hg ci -m1
echo % debugsub
@@ -60,14 +70,32 @@
echo
echo % add a commit from svn
-cd "$WCROOT"
+cd "$WCROOT"/src
svn up
echo xyz >> alpha
+svn propset svn:mime-type 'text/xml' alpha
svn ci -m 'amend a from svn'
-cd ../sub/t
+cd ../../sub/t
+
echo % this commit from hg will fail
echo zzz >> s/alpha
hg ci -m 'amend alpha from hg'
+svn revert -q s/alpha
+
+echo % this commit fails because of meta changes
+svn propset svn:mime-type 'text/html' s/alpha
+hg ci -m 'amend alpha from hg'
+svn revert -q s/alpha
+
+echo % this commit fails because of externals changes
+echo zzz > s/externals/other
+hg ci -m 'amend externals from hg'
+svn revert -q s/externals/other
+
+echo % this commit fails because of externals meta changes
+svn propset svn:mime-type 'text/html' s/externals/other
+hg ci -m 'amend externals from hg'
+svn revert -q s/externals/other
echo
echo % clone
--- a/tests/test-subrepo-svn.out Thu Jan 21 15:13:40 2010 +0100
+++ b/tests/test-subrepo-svn.out Thu Jan 21 13:26:26 2010 +0100
@@ -1,9 +1,20 @@
% create subversion repo
Checked out revision 0.
-A alpha
-Adding alpha
-Transmitting file data .
+A src
+A src/alpha
+A externals
+A externals/other
+Adding externals
+Adding externals/other
+Adding src
+Adding src/alpha
+Transmitting file data ..
Committed revision 1.
+At revision 1.
+property 'svn:externals' set on 'src'
+Sending src
+
+Committed revision 2.
% create hg repo
% first revision, no sub
adding a
@@ -11,38 +22,66 @@
committing subrepository s
% debugsub
path s
- source file:///root/svn-repo
- revision 1
+ source file:///root/svn-repo/src
+ revision 2
% change file in svn and hg, commit
committing subrepository s
Sending s/alpha
Transmitting file data .
-Committed revision 2.
-At revision 2.
+Committed revision 3.
+
+Fetching external item into 's/externals'
+External at revision 1.
+
+At revision 3.
path s
- source file:///root/svn-repo
- revision 2
+ source file:///root/svn-repo/src
+ revision 3
% should be empty despite change to s/a
% add a commit from svn
U alpha
-Updated to revision 2.
-Sending alpha
+
+Fetching external item into 'externals'
+A externals/other
+Updated external to revision 1.
+
+Updated to revision 3.
+property 'svn:mime-type' set on 'alpha'
+Sending src/alpha
Transmitting file data .
-Committed revision 3.
+Committed revision 4.
% this commit from hg will fail
committing subrepository s
abort: svn: Commit failed (details follow):
-svn: File '/alpha' is out of date
+svn: File '/src/alpha' is out of date
+% this commit fails because of meta changes
+property 'svn:mime-type' set on 's/alpha'
+committing subrepository s
+abort: svn: Commit failed (details follow):
+svn: File '/src/alpha' is out of date
+% this commit fails because of externals changes
+committing subrepository s
+abort: cannot commit svn externals
+% this commit fails because of externals meta changes
+property 'svn:mime-type' set on 's/externals/other'
+committing subrepository s
+abort: cannot commit svn externals
% clone
updating to branch default
A s/alpha
-Checked out revision 2.
+ U s
+
+Fetching external item into 's/externals'
+A s/externals/other
+Checked out external at revision 1.
+
+Checked out revision 3.
3 files updated, 0 files merged, 0 files removed, 0 files unresolved
% debugsub in clone
path s
- source file:///root/svn-repo
- revision 2
+ source file:///root/svn-repo/src
+ revision 3