Bulk copying locks is a similar issue to bulk copying revprops. There is no easy way to bulk copy locks from a repository to a copy of the repository (even hotcopy has problems: issue 3750).
As with revprops I can write a script using the bindings (see below). However this script is less useful that the one to copy revprops. It has a performance problem when the number of locks is large due to the O(N^2) behaviour of the index. It may be possible to mitigate this by collecting the locks and using the _many API although I suspect the bindings need to be enhanced first. Another problem is that Subversion's current API doesn't allow setting the lock's creation date, the date is always set from the local clock. That means there is no way to write code using the current API that will copy locks. It is possible that the best way to copy locks is to do an OS copy of the entire locks subdir from an offline repository and rely on the fact that the on-disk representation remains valid across FSFS formats. We should have a better method. At a minimum we need a new FS API that allows the lock's creation date to be specified. We don't have dump/load support for locks but we probably don't need it. 'svnadmin lslocks' is effectively a dump for locks. The lock order is lexical MD5 of the path, which is probably not optimal for adding locks in a bulk load. Getting a better order might be tricky as is deciding how to break the list into batches. As with revprops making sure the FS layer can detect an add that doesn't change anything and then avoid all disk writes will probably help. #!/usr/bin/python import sys from svn import core, fs, repos src_path = core.svn_path_canonicalize(sys.argv[1]) dst_path = core.svn_path_canonicalize(sys.argv[2]) src_repo = repos.open(src_path) dst_repo = repos.open(dst_path) src_fs = repos.fs(src_repo) dst_fs = repos.fs(dst_repo) dst_head = fs.youngest_rev(dst_fs) def add_locks(src_lock, pool): dst_lock = fs.get_lock(dst_fs, src_lock.path) if (dst_lock and src_lock.token == dst_lock.token and src_lock.comment == dst_lock.comment and src_lock.is_dav_comment == dst_lock.is_dav_comment and src_lock.expiration_date == dst_lock.expiration_date): print "elide: " + src_lock.path return access = fs.create_access(src_lock.owner) fs.set_access(dst_fs, access) fs.lock(dst_fs, src_lock.path, src_lock.token, src_lock.comment, src_lock.is_dav_comment, src_lock.expiration_date, dst_head, True) print "set: " + src_lock.path fs.get_locks(src_fs, "", add_locks) def rm_locks(dst_lock, pool): src_lock = fs.get_lock(src_fs, dst_lock.path) if not src_lock: fs.unlock(dst_fs, dst_lock.path, dst_lock.token, True) print "rm: " + dst_lock.path access = fs.create_access("dummy") fs.set_access(dst_fs, access) fs.get_locks(dst_fs, "", rm_locks) -- Philip Martin WANdisco