[PATCH] convert: svn-sink: apply property changes after adding dirs/files
Maxim Dounin
mdounin at mdounin.ru
Wed Dec 26 18:28:29 CST 2007
Hello!
On Sat, 15 Dec 2007, Maxim Dounin wrote:
> When subversion used as a conversion sink, current code tries to set
> svn:executable property in putfile() hook. This may happen before apropriate
> file or dir was added to subversion, and so conversion will crash.
>
> Attached patch fixes it by moving actual work into putcommit().
Updated version of the patch. It also addresses similar issue with copy to
new directory.
Note: test-convert-svn-sink is expected to fail unless patch-rename.txt
from thread "[PATCH] convert: svn-sink: test if execute bit was actually
stored" also applied.
Maxim Dounin
# HG changeset patch
# User Maxim Dounin <mdounin at mdounin.ru>
# Date 1198714486 -10800
# Node ID a7da468d57897e7685c8c6ecb1b80bd20c0c151e
# Parent 1ce185f3c640a0b7210004e3d2145ef64e853a9c
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().
diff -r 1ce185f3c640 -r a7da468d5789 hgext/convert/subversion.py
--- a/hgext/convert/subversion.py Wed Dec 26 23:03:32 2007 +0100
+++ b/hgext/convert/subversion.py Thu Dec 27 03:14:46 2007 +0300
@@ -725,6 +725,9 @@ class svn_sink(converter_sink, commandli
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 @@ class svn_sink(converter_sink, commandli
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 @@ class svn_sink(converter_sink, commandli
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 @@ class svn_sink(converter_sink, commandli
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 @@ class svn_sink(converter_sink, commandli
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)
diff -r 1ce185f3c640 -r a7da468d5789 tests/test-convert-svn-sink
--- a/tests/test-convert-svn-sink Wed Dec 26 23:03:32 2007 +0100
+++ b/tests/test-convert-svn-sink Thu Dec 27 03:14:46 2007 +0300
@@ -59,6 +59,29 @@ 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/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
diff -r 1ce185f3c640 -r a7da468d5789 tests/test-convert-svn-sink.out
--- a/tests/test-convert-svn-sink.out Wed Dec 26 23:03:32 2007 +0100
+++ b/tests/test-convert-svn-sink.out Thu Dec 27 03:14:46 2007 +0300
@@ -195,6 +195,65 @@ At revision 5.
</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
More information about the Mercurial-devel
mailing list