SVNKit学习——使用低级别的API(ISVNEditor接口)直接操作Repository的目录和文件(五)
本文是参考官方文档的实现,官方wiki:https://wiki.svnkit.com/Committing_To_A_Repository
本文核心使用的是ISVNEditor这个接口直接对Repository进行各种AM操作~
以下两张示例图分别代表我们操作前、操作后仓库的结构:
具体实现:

package com.demo; import com.google.gson.Gson;
import org.tmatesoft.svn.core.*;
import org.tmatesoft.svn.core.auth.ISVNAuthenticationManager;
import org.tmatesoft.svn.core.internal.io.dav.DAVRepositoryFactory;
import org.tmatesoft.svn.core.io.ISVNEditor;
import org.tmatesoft.svn.core.io.SVNRepository;
import org.tmatesoft.svn.core.io.SVNRepositoryFactory;
import org.tmatesoft.svn.core.io.diff.SVNDeltaGenerator;
import org.tmatesoft.svn.core.wc.SVNWCUtil;
import java.io.ByteArrayInputStream;
import java.io.UnsupportedEncodingException; /**
* 提交到仓库
* 这块看官方demno的意思如果不用权限认证,会使用a session user name作为提交的author,但是我试了会报错401,author required~
* 本例是基于初始仓库图A转换为目标仓库图B的过程,我们需要执行的操作有:
* 1.删除nodeB/itemB1
* 2.编辑nodeC/itemC1
* 3.新增nodeC/itemC2,并设置itemC2的文件属性
* 4.新增nodeB子节点nodeD
*/
public class CommitToRepository {
public static void main(String[] args) throws Exception{
//1.根据访问协议初始化工厂
DAVRepositoryFactory.setup();;
//2.初始化仓库,由于我们所有的操作都是基于nodeB节点以下的,所以我们将nodeB作为本次操作的root节点
String url = "https://wlyfree-PC:8443/svn/svnkitRepository2/trunk/nodeB";
SVNRepository svnRepository = SVNRepositoryFactory.create(SVNURL.parseURIEncoded(url));
//3.初始化权限
String username = "wly";
String password = "wly";
char[] pwd = password.toCharArray();
ISVNAuthenticationManager isvnAuthenticationManager = SVNWCUtil.createDefaultAuthenticationManager(username,pwd);
svnRepository.setAuthenticationManager(isvnAuthenticationManager);
//====================================DEMO START=========================================
ISVNEditor editor = null;
long revisionNo = -1; //指定版本号为最新版本
//4.1.删除nodeB/itemB1
try{
//获取编辑器
editor = svnRepository.getCommitEditor("delete file",null,true,null);
String itemB1Path = "itemB1";//要删除的文件路径
SVNCommitInfo svnCommitInfo = deleteFile(editor,revisionNo);//执行删除并返回执行结果
System.out.println("执行删除操作的返回结果:" + svnCommitInfo);
}catch (SVNException e){
//发生异常需要终止操作
editor.abortEdit();
e.printStackTrace();;
}
//4.2.编辑nodeC/itemC1
try{
//获取编辑器
editor = svnRepository.getCommitEditor("modify file",null,true,null);
SVNCommitInfo svnCommitInfo = modifyFile(editor,revisionNo);
System.out.println("执行编辑操作的返回结果:" + svnCommitInfo);
}catch(SVNException e){
//发生异常需要终止操作
editor.abortEdit();
e.printStackTrace();;
}
//4.3.新增nodeC/itemC2,并设置itemC2的文件属性
try{
editor = svnRepository.getCommitEditor("add file",null,true,null);
SVNCommitInfo svnCommitInfo = addFile(editor,revisionNo);
System.out.println("执行新增文件操作的返回结果:" + svnCommitInfo);
//校验nodeC/itemC2的属性是否成功设置进去
SVNProperties s = new SVNProperties();
svnRepository.getFile("nodeC/itemC2",-1,s,null);
Gson gson = new Gson();
System.err.println(gson.toJson(s));
}catch (SVNException e){
editor.abortEdit();
e.printStackTrace();
} //4.4.新增nodeB子节点nodeD
try{
editor = svnRepository.getCommitEditor("add dir",null,true,null);
SVNCommitInfo svnCommitInfo = addDir(editor,revisionNo);
System.out.println("执行新增目录操作的返回结果:" + svnCommitInfo);
}catch (SVNException e){
editor.abortEdit();
e.printStackTrace();
}
} /**
* 删除文件
* @param editor 编辑器
* @param revisionNo 修订版版本号
* @return SVNCommitInfo 提交结果信息
* @throws SVNException
*/
private static SVNCommitInfo deleteFile(ISVNEditor editor,long revisionNo) throws SVNException{
// 进入Root节点,即nodeB
editor.openRoot(revisionNo);
//4.3.删除文件
editor.deleteEntry("itemB1",revisionNo);
//操作完成要关闭编辑器,并返回操作结果
return editor.closeEdit();
} /**
* 编辑文件
* @param editor 编辑器
* @param revisionNo 修订版版本号
* @return SVNCommitInfo 提交结果信息
* @throws SVNException
*/
private static SVNCommitInfo modifyFile(ISVNEditor editor,long revisionNo) throws SVNException{
// 进入Root节点,即nodeB
editor.openRoot(revisionNo);
//.进入nodeC节点
editor.openDir("nodeC",revisionNo);
// 编辑nodeC/itemC1的内容
String itemC1Path = "nodeC/itemC1";//路径都是相对于root的
editor.openFile(itemC1Path,revisionNo);
//确保客户端这个文件的内容和服务端的是一样的,如果不一致的话是不允许提交的。底层实现使用MD5
String baseChecksum = null;
editor.applyTextDelta(itemC1Path,baseChecksum);
//提交文件变更的数据,windows默认是100kb大小
byte[] oldData = new byte[]{};
byte[] newData = null;
try {
newData = "我来测试一下编辑2".getBytes("utf-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
ByteArrayInputStream baseData = new ByteArrayInputStream(oldData);
ByteArrayInputStream workingData = new ByteArrayInputStream(newData);
SVNDeltaGenerator svnDeltaGenerator = new SVNDeltaGenerator();//100KB-windows generator
String checksum = svnDeltaGenerator.sendDelta(itemC1Path,baseData,0,workingData,editor,true);
// 关闭文件
editor.closeFile(itemC1Path,checksum);
// 关闭目录nodeC
editor.closeDir();
// 关闭根目录nodeB
editor.closeDir();
// 关闭编辑器,并返回执行结果
return editor.closeEdit();
} /**
* 新增文件
* @param editor
* @param revisionNo
* @return
* @throws SVNException
*/
private static SVNCommitInfo addFile(ISVNEditor editor,long revisionNo) throws SVNException{
// 进入Root节点,即nodeB
editor.openRoot(revisionNo);
//.进入nodeC节点
editor.openDir("nodeC",revisionNo);
// 新增itemC2文件
editor.addFile("nodeC/itemC2",null,revisionNo);
//确保客户端这个文件的内容和服务端的是一样的,如果不一致的话是不允许提交的。底层实现使用MD5
String itemC2Path = "nodeC/itemC2";
String baseChecksum = null;
editor.applyTextDelta(itemC2Path,baseChecksum);
//提交文件变更的数据,windows默认是100kb大小
byte[] oldData = new byte[]{};//旧数据
byte[] newData = null;//新数据
try {
newData = "我来测试一下 - addFile".getBytes("utf-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
ByteArrayInputStream baseData = new ByteArrayInputStream(oldData);
ByteArrayInputStream workingData = new ByteArrayInputStream(newData);
SVNDeltaGenerator svnDeltaGenerator = new SVNDeltaGenerator();//100KB-windows generator
String checksum = svnDeltaGenerator.sendDelta(itemC2Path,baseData,0,workingData,editor,true);
//设置文件的属性,key是字符串,值被包装成SVNProperyValue了
editor.changeFileProperty("nodeC/itemC2","properName1",SVNPropertyValue.create("properValue1"));
editor.changeFileProperty("nodeC/itemC2","properName2",SVNPropertyValue.create("properValue2"));
System.out.println("checksum:" + checksum );
//关闭文件
editor.closeFile("nodeC/itemC2",checksum);
//关闭目录nodeC
editor.closeDir();
//关闭root
editor.closeDir();
return editor.closeEdit();
} /**
* 新增目录
* @param editor 编辑器
* @param revisionNo 修订版本号
* @return SVNCommitInfo 提交结果信息
* @throws SVNException
*/
private static SVNCommitInfo addDir(ISVNEditor editor,long revisionNo) throws SVNException{
// 进入Root节点,即nodeB
editor.openRoot(revisionNo);
//新增目录
editor.addDir("nodeD",null,revisionNo);
editor.closeDir();//nodeD
editor.closeDir();//nodeB
return editor.closeEdit();
}
}

运行效果:

执行删除操作的返回结果:r51 by 'wly' at Wed Dec 07 13:48:15 CST 2016
执行编辑操作的返回结果:r52 by 'wly' at Wed Dec 07 13:48:15 CST 2016
checksum:a107fb58070bfbaf11513c8750f87466
执行新增文件操作的返回结果:r53 by 'wly' at Wed Dec 07 13:48:15 CST 2016
{"myProperties":{"svn:entry:uuid":{"myValue":"e5dd1e38-0390-574a-b68d-e269ce50c382"},"svn:entry:revision":{"myValue":"53"},"properName1":{"myData":[112,114,111,112,101,114,86,97,108,117,101,49]},"svn:entry:committed-date":{"myValue":"2016-12-07T05:48:15.464756Z"},"properName2":{"myData":[112,114,111,112,101,114,86,97,108,117,101,50]},"svn:wc:ra_dav:version-url":{"myValue":"/svn/svnkitRepository2/!svn/ver/53/trunk/nodeB/nodeC/itemC2"},"svn:entry:checksum":{"myValue":"a107fb58070bfbaf11513c8750f87466"},"svn:entry:committed-rev":{"myValue":"53"},"svn:entry:last-author":{"myValue":"wly"}}}
执行新增目录操作的返回结果:r54 by 'wly' at Wed Dec 07 13:48:15 CST 2016

总结:
其实走读一遍代码就知道,无论进行什么操作都是有一定规律性的。
无论是操作目录还是文件,大的框架可以大体总结为以下几步:

//1.根据访问协议初始化工厂
//2.初始化仓库,由于我们所有的操作都是基于nodeB节点以下的,所以我们将nodeB作为本次操作的root节点
//3.初始化权限
//4.获取编辑器对象
//5.进入目录/文件
//6.执行操作
//7.关闭目录/文件
//8.关闭编辑器

实际工作中,感觉这种方式不是特别灵活,不一定适用于普通的应用场景,相对来讲,High-Level API更倾向于用户和SVN的交互。
SVNKit学习——使用低级别的API(ISVNEditor接口)直接操作Repository的目录和文件(五)的更多相关文章
- Vue学习笔记-Django REST framework3后端接口API学习
一 使用环境 开发系统: windows 后端IDE: PyCharm 前端IDE: VSCode 数据库: msyql,navicat 编程语言: python3.7 (Windows x86- ...
- [ Java学习基础 ] Java的抽象类与接口
一.抽象类 1. 抽象类 Java语言提供了两种类:一种是具体类:另一种是抽象子类. 2. 抽象类概念: 在面向对象的概念中,所有的对象都是通过类来描绘的,但是反过来,并不是所有的类都是用来描绘对象的 ...
- node-webkit学习(3)Native UI API概览
node-webkit学习(3)Native UI API概览 文/玄魂 目录 node-webkit学习(3)Native UI API概览 前言 3.1 Native UI api概览 Exte ...
- ecCodes 学习 利用ecCodes Python API对GRIB文件进行读写
参考 https://www.ecmwf.int/assets/elearning/eccodes/eccodes2/story_html5.htmlhttps://confluence.ecmwf. ...
- 使用TensorFlow低级别的API进行编程
Tensorflow的低级API要使用张量(Tensor).图(Graph).会话(Session)等来进行编程.虽然从一定程度上来看使用低级的API非常的繁重,但是它能够帮助我们更好的理解Tenso ...
- SVNKit学习——wiki+简介(二)
这篇文章是参考SVNKit官网在wiki的文档,做了个人的理解~ 首先抛出一个疑问,Subversion是做什么的,SVNKit又是用来干什么的? 相信一般工作过的同学都用过或了解过svn,不了解的同 ...
- 【开源】.Net Api开放接口文档网站
开源地址:http://git.oschina.net/chejiangyi/ApiView 开源QQ群: .net 开源基础服务 238543768 ApiView .net api的接口文档查看 ...
- 免费手机号码归属地API查询接口和PHP使用实例分享
免费手机号码归属地API查询接口和PHP使用实例分享 最近在做全国性的行业分类信息网站,需要用到手机号归属地显示功能,于是就穿梭于各大权威站点之间偷来了API的接口地址. 分享出来,大家可以用到就拿去 ...
- Mybatis学习总结(二)—使用接口实现数据的增删改查
在这一篇中,让我们使用接口来实现一个用户数据的增删改查. 完成后的项目结构如下图所示: 在这里,person代表了一个用户的实体类.在该类中,描述了相关的信息,包括id.name.age.id_num ...
随机推荐
- kafka的安装及基本使用
1.安装zookeeper # 解压缩 [root@localhost zookeeper]# .tar.gz [root@localhost zookeeper]# zk_simple # 复制zo ...
- 转 zabbix 用户建立和中文化
1. 1 登陆和配置用户 简介 本章你会学习如何登陆Zabbix,以及在Zabbix内建立一个系统用户. 登陆 这是Zabbix的“欢迎”界面.输入用户名 Admin 以及密码 zabbix 以作 ...
- 转 RMAN: RAC Backup, Restore and Recovery using RMAN
PURPOSE The purpose of this document is to give a quick guide for using RMAN on RAC databases. We wi ...
- SpringCloud---服务容错保护---Spring Cloud Hystrix
1.概述 1.1 在分布式架构中,存在着许多的服务单元,若一个单元出现故障,很容易因依赖关系引发故障的蔓延,最终导致整个系统的瘫痪: 为了解决这样的问题,产生了断路器等服务保护机制: 1.2 分布式架 ...
- JMeter工具接口性能压力测试分析与优化
最近公司做的项目,要求对相关接口做性能压力测试,在这里记录一下分析解决过程. 压力测试过程中,如果因为资源使用瓶颈等问题引发最直接性能问题是业务交易响应时间偏大,TPS逐渐降低等.而问题定位分析通常情 ...
- 加载 Firefox 配置
有小伙伴在用脚本启动浏览器时候发现原来下载的插件不见了,无法用 firebug在打开的页面上继续定位页面元素,调试起来不方便 .加载浏览器配置,需要用 FirefoxProfile(profile_d ...
- 【javascript/css】关于鼠标事件onmousexxx和css伪类hover
在运用鼠标移入移出事件时,一般有两种做法,一种是DOM事件的"onmouseover"和"onmouseout",还有一种是css的伪类":hover ...
- ASP.NET MVC 域名泛解析设置
最近有个需求要做一个动态二级域名的网站,我们可以通过这样的方式去访问我们的网站 http://用户名.blog.com.而这里的用户名是根据程序的需要动态生成的.这里就会涉及到DNS服务器,要做相应的 ...
- 使用自动化恶意软件分析cuckoo分析exe程序
Cuckoo是一款监控函数调用,监控文件读写,监控注册表读写等的自动化恶意分析软件. 包括apk.exe.pdf等多种文件的分析,将任务提交给数据库,host从数据库中读取任务,将样本放入虚拟机中运行 ...
- Centos 下搭建FTP上传下载服务器
首先判断你服务器上是否安装了vsftpd 安装vsftpd #yum -y install vsftpd 安装完成之后就要重启vsftpd服务 到vsftpd的主配置文件里面 把这个改为NO 默认 ...