最近在工作上提出了一个需求,需要将各个团队的Subversion仓库进行集中管理。也就是需要在一台机器上的一个仓库里面导入上百个已经存在的部分仓库。在这里简单的总结一下这一块的工作。工作的重点主要涉及以下两个方面:

  • 根据SVNUrl、SVNUserName、SVNPassword信息把远程仓库的子目录内容dump到本地
  • 在本地创建子目录,将dumpFile读取到本地仓库的固定路径下

dump远程仓库内容到本地

Subversion 1.7 引入了一个新工具, svnrdump. 它提供了较为特殊的功能, 本质上就是 svnadmin dumpsvnadmin load (见 the section called “使用 svnadmin 迁移仓库数据”) 的跨网络版本.

svnrdump dump 从一个远程仓库转储数据, 打印到标准输出; svnrdump load 从标准输入读取转储数据, 加载到一个远程仓库上. svnrdump 可以像 svnadmin dump 那样生成增量转储, 甚至可以只转储仓库的某个子目录, svnadmin 却无法做到这一点.

svnadmin 与 svnrdump 之间 最关键的区别在于后者不需要直接访问仓库, svnrdump 使用与 Subversion 客户端相同的仓库访问 (Repository Access, 简称 RA) 协议完成操作 的远程执行, 因此用户可能需要提供认证证书, 除此之外, 远程交互可能还会受到 Subversion 服务器的授权限制. ——Subversion的官方手册

通过以上文档,可以发现子目录跨网络的svnrdump命令符合我们的需求,我们可以通过该命令实现将远程仓库的子目录数据保存到本地仓库,其具体命令如下:

svnrdummp dump https://url/to/remote/repository/sub/directory > tempFile --trust-server-cert --non-interactive --username *** --password ***

--trust-server-cert:Used with --non-interactive to accept any unknown SSL server certificates without prompting.

--non-interactive:In the case of an authentication failure or insufficient credentials, prevents prompting for credentials (e.g., username or password). This is useful if you're running Subversion inside an automated script and it's more appropriate to have Subversion fail than to prompt for more information.

可能碰到的问题

hostName Not Match

可能碰到如下错误:

svnrdump:E175002: Unable to connect to a repository at URL 'http://***'
svnrdump:E175002: OPTIONS of 'http://***': could not resolve hostname '***': Host not found (http://***)

当客户端收到服务器证书时, 它需要验证服务器身份的真实性, OpenSSL 完成验证的方法是检查服务器证书的签发人, 也就是 证书颁发机构 (certificate authority, 简称 CA). 如果 OpenSSL 无法自动信任 CA, 或者是发生的错误 (例如认证超时或主机名不匹配), 那么 Subversion 客户端工具将询问用户是否要信任服务器的证书:

$ svn list https://host.example.com/repos/project

Error validating server certificate for 'https://host.example.com:443':

  • The certificate is not issued by a trusted authority. Use the

    fingerprint to validate the certificate manually!
  • The certificate hostname does not match.

    Certificate information:
  • Hostname: host.example.com
  • Valid: from Jan 30 19:23:56 2004 GMT until Jan 30 19:23:56 2006 GMT
  • Issuer: CA, example.com, Sometown, California, US
  • Fingerprint: 7d:e1:a9:34:33:39:ba:6a:e9:a5:c4:22:98:7b:76:5c:92:a0:9c:7b

    (R)eject, accept (t)emporarily or accept (p)ermanently?

用户可能会在网页浏览器看到相同的对话框 (浏览器只是一个 HTTP 客户端), 如果选择 p, Subversion 将把 服务器证书缓存在本地的 auth/ 目录内, 你的用户名和密码也缓存在这里 (见 the section called “缓存证书”), 今后再次 连接服务器时, 将会自动信任证书. ——Subversion客户端SSL证书管理

假如用户碰到如上的错误,说明你使用的svnUrl中的前缀和Subversion服务器端返回的证书中的hostname不同,这种情况只能修改hosts文件、svnUrl,保证svnUrl的前缀和证书中的hostname相同,同时在hosts文件中将前缀和访问的ip做映射。

svnurl转码出现问题

如果不对svnUrl进行处理,直接放到命令行中执行可能会有各种问题。在这里使用cn.hutool.core.net.URLEncoder类对svnurl进行编码处理,但是需要考虑svnurl已经被处理过的情况,这种情况下需要将斜线、冒号、点号、百分号替换回来,具体代码如下:

URLEncoder urlEncoder = new URLEncoder();
Charset charset = Charset.forname("utf8");
svnUrl = urlEncoder.encode(svnUrl, charset);
svnUrl = svnUrl.replace("%2F","/").replace("%3A",":").replace("%2E",".").replace("%25","%");

增量导入的问题

再实际的导入过程中,如果每次导入失败都进行重新导入,势必会在仓库中造成很多冗余的数据。这种情况一般选择在错误的地方进行增量导入。需要记住上一次出错的版本号,下一次从该版本号进行dump(出错意味着这一次commit失败了,所以下一次从出错的版本号进行dump)。

svnrdump dump /remote/url -r startNum:endNum --incremental > dumpFile --trust-server-cert --non-interactive --username XXX --password XXX

除了记住上一次出错的版本号,还需要查找远程仓库总的版本号,使用svn info命令即可:

svn info /remote/repository/url --trust-server-cert --non-interactive --username XXX --password XXX

将dumpFile导入到本地仓库

在导入到本地仓库之前,你必须先创建好本地仓库的路径,才能将dumpFile导入到你指定的路径下面,创建本地仓库子路径的命令如下(注意-m参数中尽量不要有空格,空格可能导致在某些执行命令行的工具包中出问题):

svn mkdir --parents -m 'makeSubversion' file:///base/repository/path/to/sub/directory

创建子目录后,将dumpFile Load到本地仓库中即可,使用如下命令:

svnadmin load /repository/path --parent-dir /subdirectory/path < dumpFile

可能碰到的问题

缺失路径的问题

svnadmin: File not found: transaction 'XXX' , path '/repository/to/sub/directory/dirA'

一般来说这种问题很少碰到,具体什么原因导致这种问题也暂时没有搞清楚,主要的解决方法是在导入出错后,使用svn mkdir手动创建/repository/to/sub/directory目录,然后再导入。或者再失败的版本号进行增量导入(推荐)。

空格导致的错误

error: type 'svnrdump help' for usage.

这种错误是由于svnUrl中存在空格导致的,需要对svnUrl进行url编码,参考上一章节中的SvnUrl转码问题

如何获取控制台信息

对于在java程序中运行命令行命令,输出日志中的信息尤为重要。一旦调用第三方的命令,一切都显得不可控,目前在项目中通过java.lang.Process类进行处理,具体代码如下:

Process process = Runtime.getRuntime().exec(new String[]{"/bin/sh", "-c",command}, null, null);
InputStream inputStream = process.getInputStream();
try(InputStreamReader isr = new InputStreamReader(inputStream);
BufferedReader br = new BufferedReader(isr)){
String line = null;
while((line = br.readline()) != null ){
//写日志
}
} catch (IOException e){
//写错误日志
}
int exitVal = process.waitFor();
int (exitVal == 1){
//说明命令行执行出错
}

需要注意的是,如果写出的日志信息太多,会导致进程阻塞从而无法看到日志输出。这种情况可以另外启动一个线程用于专门读取日志输出流。具体代码如下所示:

Process process = Runtime.getRuntime().exec(new String[]{"/bin/sh", "-c",command}, null, null);
StreamGobbler errorGobbler = new StreamGobbler(process.getErrorStream(), "Error");
StreamGobbler outputGobbler = new StreamGobbler(process.getInputStream(), "OutPut"); public class StreamGobbler extends Thread {
InputStream is;
String type;
public StreamGobbler(InputStream is, String type){
this.is = is;
this.type = type;
} public void run() throws Exception{
try(InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BuggeredReader(isr)){
String line = null;
while((line = br.readline) != null) {
if(type.equals("Error")){
//输出带Error字样的日志
} else {
//输出带Debug字样的日志
}
}
}
}
}

Subverion仓库迁移知识点整理的更多相关文章

  1. git仓库迁移和更新远程仓库地址

    一.git仓库迁移 1,从原仓库clone或pull到本地仓库 git clone project_name ​[old_remote_repository_address] 2,​在新的git创建一 ...

  2. ACM个人零散知识点整理

    ACM个人零散知识点整理 杂项: 1.输入输出外挂 //读入优化 int 整数 inline int read(){ int x=0,f=1; char ch=getchar(); while(ch& ...

  3. Android 零散知识点整理

    Android 零散知识点整理 为什么Android的更新试图操作必须在主线程中进行? 这是因为Android系统中的视图组件并不是线程安全的.通常应该让主线程负责创建.显示和更新UI,启动子线程,停 ...

  4. vue前端面试题知识点整理

    vue前端面试题知识点整理 1. 说一下Vue的双向绑定数据的原理 vue 实现数据双向绑定主要是:采用数据劫持结合发布者-订阅者模式的方式,通过 Object.defineProperty() 来劫 ...

  5. nexus(Maven仓库私服)的安装、配置、使用和仓库迁移

    简介 Nexus下载:点击进入 Nexus 是Maven仓库管理器,如果你使用Maven,你可以从Maven中央仓库 下载所需要的构件(artifact),但这通常不是一个好的做法,你应该在本地架设一 ...

  6. git 仓库迁移,git remote 更改源

    git仓库迁移 我们有时候需要迁移git仓库,但又想保留每次commit的记录,所以我们只需要更改git remote [源]的问题即可 首先查看你的remote的地址 git remote -vv ...

  7. kafka知识点整理总结

    kafka知识点整理总结 只不过是敷衍 2017-11-22 21:39:59 kafka知识点整理总结,以备不时之需. 为什么要使用消息系统: 解耦 并行 异步通信:想向队列中放入多少消息就放多少, ...

  8. Nexus 3.X(Maven仓库私服)仓库迁移与备份

    Linux 仓库迁移 Nexus的构件仓库都保存在sonatype-work目录中,该目录的位置由nexus/conf/nexus.properties配置文件指定.仓库迁移需要两个过程:备份和还原 ...

  9. git仓库迁移的两种解决方案

    Git仓库迁移而不丢失log的方法 要求能保留原先的commit记录,应该如何迁移呢? 同时,本地已经clone了原仓库,要配置成新的仓库地址,该如何修改呢? 注意:如果使用了代码审核工具Gerrit ...

随机推荐

  1. 通过java递归思想实现以树形方式展现出该目录中的所有子目录和文件

    当初在开始接触Java时  学习File部分的一个小练习  挺有意思 一开始是通过看 北京圣思园 张龙老师的视频开始学校java的,必须强烈推荐,真很棒. 功能实现:主要实现以树形方式展现出该目录中的 ...

  2. dedecms模板中 if else怎么写

    在制作dedecms模板时,有时需要使用IF  ELSE判断语句,但是dedecms模板中是无法使用使用IF语句的,否则会报错. 那么如何在dedecms模板中使用 if else呢?这就需要我们多走 ...

  3. PHPExcel所遇到问题的知识点总结

    工作中进行excel的时候遇到了两个问题, 1.excel表中列值过大,由于没有进行特殊处理,程序没法正常运行: 2.列值中含有日期格式的文本,不能正确读取: 所以通过网络搜索,并解决了问题,记录一下 ...

  4. My google script which based on Google Sheet and Form

    My google script which based on Google Sheet and Form // get sheet data function getSpreadsheetData( ...

  5. Windows10环境下使用VisualSVN server搭建SVN服务器

    参考: Windows10环境下使用VisualSVN server搭建SVN服务器 要搭建个svn用.之前自己的服务器用的乌龟.后来用了这个VisualSVN server. 具体教程见上链接.暂无 ...

  6. C - The kth great number 优先队列

    Xiao Ming and Xiao Bao are playing a simple Numbers game. In a round Xiao Ming can choose to write d ...

  7. lxml xpath 爬取并正常显示中文内容

    在使用python爬虫提取中文网页的内容,为了能正确显示中文的内容,在转为字符串时一定要声明编码为utf-8,否则无法正常显示中文,而是显示原编码的字符,并没有正确转换.比如下面这个简单的爬取百度页面 ...

  8. Python3.6连接mysql(一)

    初次学习python,因为python连接mysql的时候,需要安装mysql驱动模块 之前按照廖雪峰网站上的方法安装mysql驱动的方法: MySQL官方提供了mysql-connector-pyt ...

  9. vue中的图标字体引入

    网址:https://icomoon.io/app/#/select: 特点:样式多,免费 操作: 1.相中的,随便点,不要钱,generat fonts然后download,得到一个压缩文件,解压, ...

  10. Java进程与线程的区别

    每个进程都独享一块内存空间,一个应用程序可以同时启动多个进程.比如浏览器,打开一个浏览器就相当于启动了一个进程. 线程指进程中的一个执行流程,一个进程可以包含多个线程. 每个进程都需要操作系统为其分配 ...