0

有一个在线回购有 13k 次提交,但我只对其中的最后 1000 个感兴趣。是否可以使用 svnsync 复制它们?

我希望能够在此本地存储库的最后 1000 次提交中签出,它应该比从服务器更快

必须保留修订号。
svnsync必须能够将未来的修订正常同步到本地存储库中。

4

2 回答 2

1

将这些最后 1000 次修订复制到哪里?svnsync工具用于存储库复制,而不是“复制”修订。如果您想远程获取最后 1000 个修订,请使用可以指定修订范围的svnrdump工具。

于 2013-11-27T09:00:29.330 回答
1

在以下示例中,我保存了回购的最后 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)
于 2013-11-27T12:18:41.300 回答