SVNKit中怎样使用不同的仓库访问协议?
当你下载了最新版的SVNKit二进制文件并且准备使用它时,一个问题出现了,要创建一个库需要做哪些初始化的步骤?直接与Subversion仓库交互已经在低级层API中实现,主要的仓库访问驱动的接口就是SVNRepository抽象类。这个驱动实现了一些协议,一个协议一个实现。每个驱动由一个抽象工厂类-SVNRepositoryFactory 创建,抽象工厂类也有每一种协议的实现。下面的表格将一种协议和工厂类的实现类一一对应:
svn://(svns://) | SVNRepositoryFactoryImpl |
http://(https://) | DAVRepositoryFactory |
file:/// | FSRepositoryFactory |
SVNKit初始化的操作
在使用SVNKit库前,你必须为某一特定的协议创建一个合适的SVNRepositryFactory对象。例如,如果你想使用 svn:// 协议来和仓库交互,你必须注册一下SVNRepositoryFactoryImpl工厂:
try {
SVNRepositoryFactoryImpl.setup();
...
} catch (SVNException e) {
//handle exception
}
这一步之后,由于SVNKit包含了注册的工厂对象,SVNRepositoryFactory知道了怎样给svn:// 协议创建SVNRepository驱动。接下来你就可以为它创建一个驱动了:
try {
...
SVNURL url = SVNURL.parseURIDecoded( "svn://host/path_to_repository_root/inner_path" );
SVNRepository repository = SVNRepositoryFactory.create( url, null );
...
} catch ( SVNException e ) {
//handle exception
}
在SVNKit中,所有的仓库url由SVNURL类来表示,如果一个路径字符串不是UTF-8编码的,可以使用SVNURL的parseURIDecoded()方法来创建一个新的url(如果需要编码,它会重新编码)。然后你可以通过这个url来在SVNRepositoryFactory中创建一个新的SVNRepository驱动。这样,你可以绑定驱动到任何一个你想访问的仓库地址。
使用高级层API
当你使用SVNKit管理工作拷贝时,由于高级层API使用低级层API来与仓库交互,你也需要创建合适的工厂类,如果你遗漏了这一初始化步骤,可能会抛出一个SVNKit不能给提供的url创建SVNRepository对象的异常。
当然就想我们使用其他svn客户端或者是svn插件一样。我们对 Repository进行操作的时候是需要身份验证的,使用SVNKit也是一样。我们需要提供身份信息:
<span style="white-space:pre"> </span>/*
* 对版本库设置认证信息。
*/
ISVNAuthenticationManager authManager = SVNWCUtil.createDefaultAuthenticationManager(name, password);
repository.setAuthenticationManager(authManager);
实现DisplayFile:
<span style="font-size:18px;">import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.SVNLogEntry;
import org.tmatesoft.svn.core.SVNNodeKind;
import org.tmatesoft.svn.core.SVNProperties;
import org.tmatesoft.svn.core.SVNProperty;
import org.tmatesoft.svn.core.SVNURL;
import org.tmatesoft.svn.core.auth.ISVNAuthenticationManager;
import org.tmatesoft.svn.core.internal.io.dav.DAVRepositoryFactory;
import org.tmatesoft.svn.core.internal.io.fs.FSRepositoryFactory;
import org.tmatesoft.svn.core.internal.io.svn.SVNRepositoryFactoryImpl;
import org.tmatesoft.svn.core.io.SVNRepository;
import org.tmatesoft.svn.core.io.SVNRepositoryFactory;
import org.tmatesoft.svn.core.wc.SVNWCUtil;
public class DisplayFile {
/**
* @param args
*/
public static void main(String[] args) {
//初始化库。 必须先执行此操作。具体操作封装在setupLibrary方法中。
setupLibrary();
/*
* 相关变量赋值
*/
String url = "https://hy/svn/svnkittest/branches";
String name = "hanyi";
String password = "hanyi";
String filePath = "doImport.txt";
//定义svn版本库的URL。
SVNURL repositoryURL = null;
//定义版本库。
SVNRepository repository = null;
try {
//获取SVN的URL。
repositoryURL=SVNURL.parseURIEncoded(url);
//根据URL实例化SVN版本库。
repository = SVNRepositoryFactory.create(repositoryURL);
} catch (SVNException svne) {
/*
* 打印版本库实例创建失败的异常。
*/
System.err
.println("创建版本库实例时失败,版本库的URL是 '"
+ url + "': " + svne.getMessage());
System.exit(1);
}
/*
* 对版本库设置认证信息。
*/
ISVNAuthenticationManager authManager = SVNWCUtil.createDefaultAuthenticationManager(name, password);
repository.setAuthenticationManager(authManager);
//此变量用来存放要查看的文件的属性名/属性值列表。
SVNProperties fileProperties = new SVNProperties();
//此输出流用来存放要查看的文件的内容。
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
//获得版本库中文件的类型状态(是否存在、是目录还是文件),参数-1表示是版本库中的最新版本。
SVNNodeKind nodeKind = repository.checkPath(filePath, -1);
if (nodeKind == SVNNodeKind.NONE) {
System.err.println("要查看的文件在 '" + url + "'中不存在.");
System.exit(1);
} else if (nodeKind == SVNNodeKind.DIR) {
System.err.println("要查看对应版本的条目在 '" + url
+ "'中是一个目录.");
System.exit(1);
}
//获取要查看文件的内容和属性,结果保存在baos和fileProperties变量中。
repository.getFile(filePath, -1, fileProperties, baos);
} catch (SVNException svne) {
System.err.println("在获取文件内容和属性时发生错误: " + svne.getMessage());
System.exit(1);
}
//获取文件的mime-type
String mimeType = fileProperties.getStringValue(SVNProperty.MIME_TYPE);
//判断此文件是否是文本文件
boolean isTextType = SVNProperty.isTextMimeType(mimeType);
/*
* 显示文件的所有属性
*/
Iterator iterator = fileProperties.nameSet().iterator();
while (iterator.hasNext()) {
String propertyName = (String) iterator.next();
String propertyValue = fileProperties.getStringValue(propertyName);
System.out.println("文件的属性: " + propertyName + "="
+ propertyValue);
}
/*
* 如果文件是文本类型,则把文件的内容显示到控制台。
*/
if (isTextType) {
System.out.println("File contents:");
System.out.println();
try {
baos.writeTo(System.out);
} catch (IOException ioe) {
ioe.printStackTrace();
}
} else {
System.out
.println("因为文件不是文本文件,无法显示!");
}
System.out.println("");
/*
* 获得版本库的最新版本号。
*/
long latestRevision = -1;
try {
latestRevision = repository.getLatestRevision();
List<SVNLogEntry> entries = new ArrayList<SVNLogEntry>();
try
{
repository.log(new String[]{""},//为过滤的文件路径前缀,为空表示不进行过滤
entries,
-1,//-1代表最新的版本号,初始版本号为0
-1,
true,
true);
}
catch (SVNException e)
{
e.printStackTrace();
}
System.out.println("当前log信息数量:"+entries.size());
String message=entries.get(0).getMessage().toString();
System.out.println("提交的message信息:"+message);
} catch (SVNException svne) {
System.err.println("获取最新版本号时出错: " + svne.getMessage());
System.exit(1);
}
System.out.println("");
System.out.println("---------------------------------------------");
System.out.println("版本库的最新版本号: " + latestRevision);
System.exit(0);
}
/*
* 初始化库
*/
private static void setupLibrary() {
/*
* For using over http:// and https://
*/
DAVRepositoryFactory.setup();
/*
* For using over svn:// and svn+xxx://
*/
SVNRepositoryFactoryImpl.setup();
/*
* For using over file:///
*/
FSRepositoryFactory.setup();
}
}</span><span style="font-weight: bold; font-size: 16pt;">
</span>
打印的结果:
文件的属性: svn:entry:uuid=bf3500c6-b8a2-f84e-86b3-86d6154c1411hello the first svnkit demo
当前log信息数量:1
提交的message信息:韩义:svnkit demo test
---------------------------------------------
版本库的最新版本号: 2
实现DisplayRepositoryTree:
import java.util.Collection;
import java.util.Iterator;
import org.tmatesoft.svn.core.SVNDirEntry;
import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.SVNNodeKind;
import org.tmatesoft.svn.core.SVNURL;
import org.tmatesoft.svn.core.auth.ISVNAuthenticationManager;
import org.tmatesoft.svn.core.internal.io.dav.DAVRepositoryFactory;
import org.tmatesoft.svn.core.internal.io.svn.SVNRepositoryFactoryImpl;
import org.tmatesoft.svn.core.io.SVNRepository;
import org.tmatesoft.svn.core.io.SVNRepositoryFactory;
import org.tmatesoft.svn.core.wc.SVNWCUtil;
public class DisplayRepositoryTree {
/**
* @param args
*/
public static void main(String[] args) {
/*
* For using over http:// and https://
*/
DAVRepositoryFactory.setup();
/*
* 相关变量赋值
*/
String url = "https://hy/svn/svnkittest";
String name = "hanyi";
String password = "hanyi";
//定义svn版本库的URL。
SVNURL repositoryURL = null;
//定义版本库。
SVNRepository repository = null;
/*
* 实例化版本库类
* */
try {
//获取SVN的URL。
repositoryURL=SVNURL.parseURIEncoded(url);
//根据URL实例化SVN版本库。
repository = SVNRepositoryFactory.create(repositoryURL);
} catch (SVNException svne) {
/*
* 打印版本库实例创建失败的异常。
*/
System.err
.println("创建版本库实例时失败,版本库的URL是 '"
+ url + "': " + svne.getMessage());
System.exit(1);
}
/*
* 对版本库设置认证信息。
*/
ISVNAuthenticationManager authManager = SVNWCUtil.createDefaultAuthenticationManager(name, password);
repository.setAuthenticationManager(authManager);
/*
* 上面的代码基本上是固定的操作。
* 下面的部分根据任务不同,执行不同的操作。
* */
try {
//打印版本库的根
System.out.println("Repository Root: " + repository.getRepositoryRoot(true));
//打印出版本库的UUID
System.out.println("Repository UUID: " + repository.getRepositoryUUID(true));
System.out.println("");
//打印版本库的目录树结构
listEntries(repository, "");
} catch (SVNException svne) {
System.err.println("打印版本树时发生错误: "
+ svne.getMessage());
System.exit(1);
}
/*
* 获得版本库的最新版本树
*/
long latestRevision = -1;
try {
latestRevision = repository.getLatestRevision();
} catch (SVNException svne) {
System.err
.println("获取最新版本号时出错: "
+ svne.getMessage());
System.exit(1);
}
System.out.println("");
System.out.println("---------------------------------------------");
System.out.println("版本库的最新版本是: " + latestRevision);
System.exit(0);
}
/*
* 此函数递归的获取版本库中某一目录下的所有条目。
*/
public static void listEntries(SVNRepository repository, String path)
throws SVNException {
//获取版本库的path目录下的所有条目。参数-1表示是最新版本。
Collection entries = repository.getDir(path, -1, null,
(Collection) null);
Iterator iterator = entries.iterator();
while (iterator.hasNext()) {
SVNDirEntry entry = (SVNDirEntry) iterator.next();
System.out.println("/" + (path.equals("") ? "" : path + "/")
+ entry.getName() + " (author: '" + entry.getAuthor()
+ "'; revision: " + entry.getRevision() + "; date: " + entry.getDate() + ")");
/*
* 检查此条目是否为目录,如果为目录递归执行
*/
if (entry.getKind() == SVNNodeKind.DIR) {
listEntries(repository, (path.equals("")) ? entry.getName()
: path + "/" + entry.getName());
}
}
}
}
打印的结果:
Repository Root: https://hy/svn/svnkittest
Repository UUID: bf3500c6-b8a2-f84e-86b3-86d6154c1411
/branches (author: 'hanyi'; revision: 2; date: Wed Apr 29 23:53:24 CST 2015)
/branches/doImport.txt (author: 'hanyi'; revision: 2; date: Wed Apr 29 23:53:24 CST 2015)
/tags (author: 'VisualSVN Server'; revision: 1; date: Wed Apr 29 14:14:01 CST 2015)
/trunk (author: 'VisualSVN Server'; revision: 1; date: Wed Apr 29 14:14:01 CST 2015)
---------------------------------------------
版本库的最新版本是: 2
其他的操作包括CheckOut,DoCommit,DoDiff,DoImport,DoUpdate我就不一一的写出了。上传一个包含所有操作的小例子,方便大家在以后的工作中学习使用:SVNKitTest(猛戳这里)
总结:
在学习SVNKit的过程中让我想起了我使用过的一些成型的产品,包括fisheye,Jenkins他们的底层与svn的集成或许就是通过SVNKit来实现的。或者是类似的产品实现的。对于我们更好的理解这些工具的使用提供了很大的帮助。