我对svn2git 转换器有一个非常奇怪的问题。
我有 2 个 svn 存储库(都是 svn 1.7 和在 Windows 中开发的)。我创建了一个 python3 脚本来自动同步 repos 并每天将其推送到我们的 gitlab 服务器(转换器在虚拟 ubuntu 实例上运行)。一切正常,但今天我看到我的回购搞砸了。第一个 repo 包含来自第二个 repo 的内容,第二个 repo 包含来自第一个 repo 的内容。怎么可能???
有人对svn2git有这种问题吗?有没有人知道一个很好的工具来自动检查每次提交(svn vs git)以确保每次提交都很好?
编辑:这是我使用的脚本(它有点 hacky :-))
# convert.py
import os,sys,subprocess
__filedir = os.path.dirname(os.path.realpath(__file__))
__migratescript = os.path.join(__filedir,"svn2git_repo/bin/svn2git")
__authors = os.path.join(__filedir,"authors.txt")
__repodir = os.path.join(__filedir,"repos")
class CurDirScope:
def __init__(self,newdir):
self.newdir = newdir
self.olddir = os.getcwd()
def __enter__(self):
self.__chdir((self.newdir))
def __exit__(self,type,value,traceback):
self.__chdir(self.olddir)
def __chdir(self,dir):
if(os.path.exists(dir)):
print("change current directory to {0}".format(dir))
os.chdir(dir)
def gitSVNClone(directory,repo):
dir = os.path.join(__repodir,directory)
print("try clone {0} to {1}".format(repo,dir))
gitpath = os.path.join(dir,".git")
if(os.path.exists(gitpath)):
raise Exception("repo directory does already exists {}".format(gitpath))
print("create directory {0}".format(dir))
os.makedirs(dir)
with CurDirScope(dir) as scope:
cmd = ["svn2git",repo,"--authors=" + __authors]
print("start git svn clone")
rc=subprocess.call(cmd)
print("end of clone")
if(rc != 0):
raise Exception("git svn clone failed - rc: {0}".format(rc))
def syncRepo(directory):
dirs = []
if(directory == "all"):
dirs = os.listdir(__repodir)
else:
dirs =[directory]
if(len(dirs) <= 0):
print("nothing to sync")
return
errors = []
for dir in dirs:
try:
absdir = os.path.join(__repodir,dir)
if(os.path.exists(absdir) == False):
raise Exception("directory does not exists '{0}'".format(absdir))
print(absdir)
with CurDirScope(absdir) as scope:
cmd = ["svn2git","--rebase","--authors=" + __authors]
print("start git repo sync {0}".format(absdir))
print(str(cmd))
rc=subprocess.call(cmd,shell=False)
print("end of sync")
if(rc != 0):
raise Exception("rebase repo failed - rc: {0}".format(rc))
except BaseException as ex:
errors.append(str(ex))
if(len(errors) > 0):
print("# Error: ")
for msg in errors:
print(msg)
raise Exception("{0} error(s) happend".format(str(len(errors))))
def pushRepo(directory,TagsOnly=False):
dirs = []
if(directory == "all"):
dirs = os.listdir(__repodir)
else:
dirs =[directory]
if(len(dirs) <= 0):
print("nothing to push")
return
pushcommand = "--all"
if(TagsOnly):
pushcommand = "--tags"
errors = []
for dir in dirs:
try:
absdir = os.path.join(__repodir,dir)
if(os.path.exists(absdir) == False):
raise Exception("directory does not exists '{0}'".format(absdir))
print(absdir)
with CurDirScope(absdir) as scope:
cmd = ["git","push","origin",pushcommand]
print("start git repo push to origin '{0}'".format(absdir))
print(str(cmd))
rc=subprocess.call(cmd,shell=False)
print("end of push")
if(rc != 0):
raise Exception("push repo {0} failed - rc: {1}".format(dir,rc))
except BaseException as ex:
errors.append(str(ex))
if(len(errors) > 0):
print("# Error: ")
for msg in errors:
print(msg)
raise Exception("{0} error(s) happend".format(str(len(errors))))
if __name__ == "__main__":
try:
args = sys.argv[1:]
print(str(args))
al = len(args)
if(al <= 0):
raise Exception("not enough arguments")
cmd = args[0]
args = args[1:]
al = len(args)
if(os.path.exists(__repodir) == False):
os.makedirs(__repodir)
if(cmd == "clone"):
if(al < 2):
raise Exception("not enough arguments for clone")
dir = args[0]
repo = args[1]
gitSVNClone(dir,repo)
elif(cmd == "sync"):
if(al < 1):
raise Exception("not enough arguments for sync")
dir = args[0]
syncRepo(dir)
elif(cmd == "push" or cmd == "pushtags"):
if(al < 1):
raise Exception("not enough arguments for sync")
tagsonly = False
if(cmd == "pushtags"):
tagsonly = True
dir = args[0]
pushRepo(dir,tagsonly)
else:
raise Exception("unknown command '{0}'".format(cmd))
except BaseException as ex:
if(ex == None):
ex = "internal error"
print("Error: {0}".format(str(ex)))
sys.exit(1)
克隆示例:
python3 convert.py clone MyLocalDir http://mysvnrepopath
它使用本地目录名称MyLocalDir将我的 svn-repo 克隆到我的 local-repo 目录(存储所有转换的 repos 的地方)
同步示例:
python3 convert.py sync all
参数 all 同步我的 repo 目录中的每个 repo。我也可以使用目录名称而不是 MyLocalDir,但我使用了 99% 的 all 参数
推送示例:
python3 convert.py push all
推送标签示例:
python3 convert.py pushtags all
问候唐卡