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))