convert: svn-sink: copy and set properties after adding dirs/files
We can't store properties for files we haven't added to repo. Similarly,
we can't copy file to directory we haven't added to svn yet. Remember
needed changes and apply them in putcommit().
--- a/hgext/convert/subversion.py Thu Dec 27 19:59:44 2007 +0300
+++ b/hgext/convert/subversion.py Thu Dec 27 03:14:46 2007 +0300
@@ -725,6 +725,9 @@
converter_sink.__init__(self, ui, path)
commandline.__init__(self, ui, 'svn')
self.delete = []
+ self.setexec = []
+ self.delexec = []
+ self.copies = []
self.wc = None
self.cwd = os.getcwd()
@@ -792,15 +795,18 @@
util.set_exec(self.wjoin(filename), 'x' in flags)
if was_exec:
if 'x' not in flags:
- self.run0('propdel', 'svn:executable', filename)
+ self.delexec.append(filename)
else:
if 'x' in flags:
- self.run0('propset', 'svn:executable', '*', filename)
-
+ self.setexec.append(filename)
+
def delfile(self, name):
self.delete.append(name)
def copyfile(self, source, dest):
+ self.copies.append([source, dest])
+
+ def _copyfile(self, source, dest):
# SVN's copy command pukes if the destination file exists, but
# our copyfile method expects to record a copy that has
# already occurred. Cross the semantic gap.
@@ -831,15 +837,18 @@
dirs.add(f[:i])
return dirs
- def add_files(self, files):
+ def add_dirs(self, files):
add_dirs = [d for d in self.dirs_of(files)
if not os.path.exists(self.wjoin(d, '.svn', 'entries'))]
if add_dirs:
add_dirs.sort()
self.run('add', non_recursive=True, quiet=True, *add_dirs)
+ return add_dirs
+
+ def add_files(self, files):
if files:
self.run('add', quiet=True, *files)
- return files.union(add_dirs)
+ return files
def tidy_dirs(self, names):
dirs = list(self.dirs_of(names))
@@ -857,7 +866,7 @@
def revid(self, rev):
return u"svn:%s@%s" % (self.uuid, rev)
-
+
def putcommit(self, files, parents, commit):
for parent in parents:
try:
@@ -865,12 +874,24 @@
except KeyError:
pass
entries = set(self.delete)
+ files = util.frozenset(files)
+ entries.update(self.add_dirs(files.difference(entries)))
+ if self.copies:
+ for s, d in self.copies:
+ self._copyfile(s, d)
+ self.copies = []
if self.delete:
self.run0('delete', *self.delete)
self.delete = []
- files = util.frozenset(files)
entries.update(self.add_files(files.difference(entries)))
entries.update(self.tidy_dirs(entries))
+ if self.delexec:
+ self.run0('propdel', 'svn:executable', *self.delexec)
+ self.delexec = []
+ if self.setexec:
+ self.run0('propset', 'svn:executable', '*', *self.setexec)
+ self.setexec = []
+
fd, messagefile = tempfile.mkstemp(prefix='hg-convert-')
fp = os.fdopen(fd, 'w')
fp.write(commit.desc)
--- a/tests/test-convert-svn-sink Thu Dec 27 19:59:44 2007 +0300
+++ b/tests/test-convert-svn-sink Thu Dec 27 03:14:46 2007 +0300
@@ -59,6 +59,29 @@
(cd a-hg-wc; svn up; svn st -v; svn log --xml -v --limit=1 | sed 's,<date>.*,<date/>,')
test -x a-hg-wc/c && echo executable || echo not executable
+echo % executable in new directory
+
+rm -rf a a-hg a-hg-wc
+hg init a
+
+mkdir a/d1
+echo a > a/d1/a
+chmod +x a/d1/a
+hg --cwd a ci -d '0 0' -A -m 'add executable file in new directory'
+
+hg convert -d svn a
+(cd a-hg-wc; svn up; svn st -v; svn log --xml -v --limit=1 | sed 's,<date>.*,<date/>,')
+test -x a-hg-wc/d1/a && echo executable || echo not executable
+
+echo % copy to new directory
+
+mkdir a/d2
+hg --cwd a cp d1/a d2/a
+hg --cwd a ci -d '1 0' -A -m 'copy file to new directory'
+
+hg convert -d svn a
+(cd a-hg-wc; svn up; svn st -v; svn log --xml -v --limit=1 | sed 's,<date>.*,<date/>,')
+
echo % branchy history
hg init b
--- a/tests/test-convert-svn-sink.out Thu Dec 27 19:59:44 2007 +0300
+++ b/tests/test-convert-svn-sink.out Thu Dec 27 03:14:46 2007 +0300
@@ -195,6 +195,65 @@
</logentry>
</log>
executable
+% executable in new directory
+adding d1/a
+assuming destination a-hg
+initializing svn repo 'a-hg'
+initializing svn wc 'a-hg-wc'
+scanning source...
+sorting...
+converting...
+0 add executable file in new directory
+At revision 1.
+ 1 1 test .
+ 1 1 test d1
+ 1 1 test d1/a
+<?xml version="1.0"?>
+<log>
+<logentry
+ revision="1">
+<author>test</author>
+<date/>
+<paths>
+<path
+ action="A">/d1</path>
+<path
+ action="A">/d1/a</path>
+</paths>
+<msg>add executable file in new directory</msg>
+</logentry>
+</log>
+executable
+% copy to new directory
+assuming destination a-hg
+initializing svn wc 'a-hg-wc'
+scanning source...
+sorting...
+converting...
+0 copy file to new directory
+At revision 2.
+ 2 2 test .
+ 2 1 test d1
+ 2 1 test d1/a
+ 2 2 test d2
+ 2 2 test d2/a
+<?xml version="1.0"?>
+<log>
+<logentry
+ revision="2">
+<author>test</author>
+<date/>
+<paths>
+<path
+ action="A">/d2</path>
+<path
+ copyfrom-path="/d1/a"
+ copyfrom-rev="1"
+ action="A">/d2/a</path>
+</paths>
+<msg>copy file to new directory</msg>
+</logentry>
+</log>
% branchy history
adding b
adding left-1