# HG changeset patch # User Patrick Mezard # Date 1335264641 -7200 # Node ID ecd2fbe68b25487b8b813de4fa0380c502003ce7 # Parent c7c9473fcc4626581ebbeed10bdccd635073dd0a convert/svn: make svn sink work with svn 1.7 "svn add file" now fails if "file" is already tracked. To filter them we have to mirror the svn manifest in the sink. Tested with svn 1.6.12 and 1.7.4. diff -r c7c9473fcc46 -r ecd2fbe68b25 hgext/convert/subversion.py --- a/hgext/convert/subversion.py Wed Apr 25 23:28:54 2012 +0200 +++ b/hgext/convert/subversion.py Tue Apr 24 12:50:41 2012 +0200 @@ -2,17 +2,14 @@ # # Copyright(C) 2007 Daniel Holth et al -import os -import re -import sys +import os, re, sys, tempfile, urllib, urllib2, xml.dom.minidom import cPickle as pickle -import tempfile -import urllib -import urllib2 from mercurial import strutil, scmutil, util, encoding from mercurial.i18n import _ +propertycache = util.propertycache + # Subversion stuff. Works best with very recent Python SVN bindings # e.g. SVN 1.5 or backports. Thanks to the bzr folks for enhancing # these bindings. @@ -1057,6 +1054,29 @@ def wjoin(self, *names): return os.path.join(self.wc, *names) + @propertycache + def manifest(self): + # As of svn 1.7, the "add" command fails when receiving + # already tracked entries, so we have to track and filter them + # ourselves. + m = set() + output = self.run0('ls', recursive=True, xml=True) + doc = xml.dom.minidom.parseString(output) + for e in doc.getElementsByTagName('entry'): + for n in e.childNodes: + if n.nodeType != n.ELEMENT_NODE or n.tagName != 'name': + continue + name = ''.join(c.data for c in n.childNodes + if c.nodeType == c.TEXT_NODE) + # Entries are compared with names coming from + # mercurial, so bytes with undefined encoding. Our + # best bet is to assume they are in local + # encoding. They will be passed to command line calls + # later anyway, so they better be. + m.add(encoding.tolocal(name.encode('utf-8'))) + break + return m + def putfile(self, filename, flags, data): if 'l' in flags: self.wopener.symlink(data, filename) @@ -1099,6 +1119,7 @@ try: self.run0('copy', source, dest) finally: + self.manifest.add(dest) if exists: try: os.unlink(wdest) @@ -1117,13 +1138,16 @@ def add_dirs(self, files): add_dirs = [d for d in sorted(self.dirs_of(files)) - if not os.path.exists(self.wjoin(d, '.svn', 'entries'))] + if d not in self.manifest] if add_dirs: + self.manifest.update(add_dirs) self.xargs(add_dirs, 'add', non_recursive=True, quiet=True) return add_dirs def add_files(self, files): + files = [f for f in files if f not in self.manifest] if files: + self.manifest.update(files) self.xargs(files, 'add', quiet=True) return files @@ -1133,6 +1157,7 @@ wd = self.wjoin(d) if os.listdir(wd) == '.svn': self.run0('delete', d) + self.manifest.remove(d) deleted.append(d) return deleted @@ -1170,6 +1195,8 @@ self.copies = [] if self.delete: self.xargs(self.delete, 'delete') + for f in self.delete: + self.manifest.remove(f) self.delete = [] entries.update(self.add_files(files.difference(entries))) entries.update(self.tidy_dirs(entries))