There's a repo online that has 13k commits, but I'm only interested in last 1000 of them. Is it possible to copy them with svnsync?
I want to be able to checkout within the last 1000 commits from this local repository, and it should be faster than from the server
Revision numbers must be preserved.
svnsync
must be able to sync the future revisions normally into the local repository.
In the following example I save last 45 commits of a repo. The helper python script is below.
# svnsync 1.6.11
# rhel 6 x86_64
# params
svn_baserepourl="http://svn.igniterealtime.org/svn/repos"
svn_subdir="spark/trunk"
reponame=spark
skipuntil=13774
# well-known svnsync preparation
repopath=`pwd`/$reponame.svn
svnadmin create "$repopath"
echo '#!/bin/sh' >"$repopath"/hooks/pre-revprop-change
chmod +x "$repopath"/hooks/pre-revprop-change
svnsync init file://"$repopath" "$svn_baserepourl/$svn_subdir"
expectedfmt="4
layout sharded 1000"
if [ x"$expectedfmt" != x"$(cat "$repopath/db/format")" ]; then
echo unknown db format
fi
# create database folder structure
( cd "$repopath/db" && echo $(for (( i=0; i<=$((skipuntil / 1000)) ; i++ )) ; do mkdir -p revprops/$i revs/$i; done ) )
# don't create last skipped revision
skipuntil=$((skipuntil - 1))
# create dummy revision files
( cd "$repopath/db" && for (( i=0; i<=$skipuntil; i++ )) ; do echo revprops/$((i/1000))/$i; echo revs/$((i/1000))/$i; done | xargs touch )
# update revision counter
echo $skipuntil >"$repopath/db/current"
# we need a valid revision file
cp "$repopath/db/revs/0/0" "$repopath/db/revs/$((skipuntil/1000))/$skipuntil"
# last skipped revision number
skipuntil=$((skipuntil + 1))
if false; then
# TODO: if svnrdump available
# mkdir in local repo
# svnrdump last skipped revision and subdir
# svnadmin load --parent-dir subdir
:
else
# checkout last skipped revision
rm -rf temptree
svn co -r $skipuntil "$svn_baserepourl/$svn_subdir" "temptree/$svn_subdir"
cd temptree
pushd "$svn_subdir"
# save properties
svn proplist --xml -v -R | ~/svnprops.py >/tmp/propset.sh
# remove .svn folders
find . -name .svn -print0 | xargs -0 rm -rf
popd
# checkout our copy
svn co "file://$repopath" .
# add the files
svn add --no-ignore --force .
# delete automatic props
for p in $(svn proplist -q -R | sort -u); do svn propdel -q -R $p; done
# restore original props
pushd "$svn_subdir"
sh /tmp/propset.sh
popd
# commit the last skipped revision
svn commit -m"shallow root"
cd ..
rm -rf temptree
fi
# update svnsync counters
svn propset --revprop -r 0 svn:sync-last-merged-rev $skipuntil "file://$repopath"
svn propset --revprop -r 0 svn:sync-currently-copying $((skipuntil+1)) "file://$repopath"
# sync!
svnsync sync "file://$repopath"
This is some old svnprops.py to copy svn properties between repos:
#!/usr/bin/env python
import sys
import xml.sax
import xml.sax.handler
"""
<?xml version="1.0"?>
<properties>
<target
path="file:///.snapshots/persist/builds/cyg-apt/cyg-apt.svn/trunk">
<property
name="svn:ignore">build
</property>
</target>
</properties>
"""
class Subhandler:
def __init__(self, mainHandler, parenthandler):
self.mainHandler = mainHandler
self.parenthandler = parenthandler
self.subhandler = None
self.lvl = 0
def startElement(self, name, attributes):
self.lvl = self.lvl + 1
def characters(self, data):
pass
def endElement(self, name):
self.lvl = self.lvl - 1
class Subhandler_properties(Subhandler):
def startElement(self, name, attributes):
pass
def characters(self, data):
pass
def endElement(self, name):
pass
class P1ropertiesDocHandler(xml.sax.handler.ContentHandler):
def __init__(self):
self.subhandler = None
def startElement(self, name, attributes):
if subhandler != None:
subhandler.startElement(name, attributes)
elif name == "properties":
Subhandler_properties(self)
def endElement(self, name):
if subhandler != None:
subhandler.endElement(name)
def characters(self, data):
if subhandler != None:
subhandler.characters(data)
class PropertiesDocHandler(xml.sax.handler.ContentHandler):
def __init__(self):
self.target = None
self.property = None
def startElement(self, name, attributes):
if name == "target":
self.target = attributes["path"]
elif name == "property":
self.property = attributes["name"]
self.propval = ""
def endElement(self, name):
if name == "target":
self.target = None
elif name == "property":
print("svn ps \"" + self.property.replace("\"","\\\"") + "\" \"" + self.propval.replace("\"","\\\"") + "\" \"" + self.target.replace("\"","\\\"") + "\"")
self.property = None
self.propval = None
def characters(self, data):
if self.property != None:
self.propval += data
parser = xml.sax.make_parser()
handler = PropertiesDocHandler()
parser.setContentHandler(handler)
#print("aa\"ass".replace("\"","\\\""))
parser.parse(sys.stdin)