最近在工作上提出了一个需求,需要将各个团队的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. react服务端渲染同构报错Browser history needs a DOM

    https://github.com/nozzle/react-static/issues/343 去掉了browserRouter就不报错了,但是又会有其他报错..

  2. OpenGL 获取当前屏幕坐标的三维坐标(gluUnProject使用例子 Qt)

    之前使用VS+glut实现了gluUnProject使用例子,用于渲染管道的逆过程,将屏幕坐标转换为opengl三维坐标,本文将尝试使用QT来实现. 代码如下:  main.cpp  12345678 ...

  3. eclipse.ini 修改默认编码为 UTF-8

    eclipse.ini 修改默认编码为 UTF-8 打开您的eclipse安装目录,找到eclipse.ini文件 打开eclipse.ini文件,在最下面加入一行代码:-Dfile.encoding ...

  4. Phoenix 5.0 hbase 2.0 org.apache.hadoop.security.authentication.util.KerberosUtil.hasKerberosKeyTab

    <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://mave ...

  5. Go学习笔记(五)Go命令工具

    上篇Go学习笔记(四)Go自动化测试框架 1.go build 这个命令可以直接使用,也可以带上代码包或源码文件使用. 如果是直接使用,表示试图编译当前目录所对应的代码包,如果当前目录不是一个有效的代 ...

  6. 【CF446D】DZY Loves Games 高斯消元+矩阵乘法

    [CF446D]DZY Loves Games 题意:一张n个点m条边的无向图,其中某些点是黑点,1号点一定不是黑点,n号点一定是黑点.问从1开始走,每次随机选择一个相邻的点走过去,经过恰好k个黑点到 ...

  7. Jmeter中使用SSH插件,连接远程linux机器执行命令

    一.Why 在云主机测试中,需要使用SSH协议连接云主机进行相关操作 在python中使用paramiko库很好实现,在如果要使用jmeter做性能测试时,怎么做? 二.解决 既然原生jmeter没有 ...

  8. mssql for xml path使用

    准备工作: CREATE TABLE [dbo].[Students]( [id] [int] IDENTITY(1,1) NOT NULL, [names] [varchar](50) NULL, ...

  9. vue里在自定义的组件上定义的事件

    事件分为原生事件和自定义事件. vue里在自定义的组件上定义的事件,都被认为是自定义事件,必须用$emit()来触发. 这也是子组件向父传值的原理. 如果想作为原生事件,需要在原生事件后面加上.nat ...

  10. 关于histry的pushstate 和 popstate事件的应用

    这篇文章是基础:http://www.cnblogs.com/kaituorensheng/p/3776527.html: histry的单页面应用有两个写法:哈希值和?: 哈希值例子: 实现效果:点 ...