有一个在线回购有 13k 次提交,但我只对其中的最后 1000 个感兴趣。是否可以使用 svnsync 复制它们?
我希望能够在此本地存储库的最后 1000 次提交中签出,它应该比从服务器更快
必须保留修订号。
svnsync
必须能够将未来的修订正常同步到本地存储库中。
将这些最后 1000 次修订复制到哪里?svnsync
工具用于存储库复制,而不是“复制”修订。如果您想远程获取最后 1000 个修订,请使用可以指定修订范围的svnrdump
工具。
在以下示例中,我保存了回购的最后 45 次提交。辅助python脚本如下。
# 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"
这是一些旧的 svnprops.py 在 repos 之间复制 svn 属性:
#!/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)