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的交互。

  

原文地址:https://www.cnblogs.com/firstdream/p/8467314.html

时间: 2024-11-14 03:55:19

SVNKit学习——使用低级别的API(ISVNEditor接口)直接操作Repository的目录和文件(五)的相关文章

淘宝API学习之道:简单介绍淘宝API功能接口作用

前一阵子按照上级指示,根据淘宝API开发符合自已应用的系统,比如批量上传,批量修改名称,价格等功能什么的,在此就将我的开发历程写一写,为自己前段时间的工作做个总结. 淘宝开发平台(http://www.taobao.com/theme/tao_source/#prev),向第三方开发者提供API接口和相关开发环境的平台,使开发者可以开发属于自已的系统应用于淘宝店铺和阿里上,同时,运用SAAS模式,开发者开发的系统也可以在该平台上进行销售. 为进行开发做的准备,得在开发同盟网站注册帐号(http:

Linux程序设计学习笔记----网络通信编程API及其示例应用

转载请注明出处, http://blog.csdn.net/suool/article/details/38702855. BSD Socket 网络通信编程 BSD TCP 通信编程流程 图为面向连接的Socket通信的双方执行函数流程.使用TCP协议的通信双方实现数据通信的基本流程如下 建立连接的步骤 1.首先服务器端需要以下工作: (1)调用socket()函数,建立Socket对象,指定通信协议. (2)调用bind()函数,将创建的Socket对象与当前主机的某一个IP地址和TCP端口

SVNKit学习——wiki+简介(一)

这篇文章是参考SVNKit官网在wiki的文档,做了个人的理解~ 首先抛出一个疑问,Subversion是做什么的,SVNKit又是用来干什么的? 相信一般工作过的同学都用过或了解过svn,不了解的同学可以到官网看下,这里不作为本文重点. 需要理解的概念: 仓库(Repository):是一个特殊的结构,记录文件版本管理的状态. 工作副本(Working Copy):本地从仓库检出的文件. 修订版(Revision):用于记录仓库数据的变更状态,初始化版本为0,每执行一次操作版本号+1,每执行一

SVNKit学习——wiki+简介(二)

这篇文章是参考SVNKit官网在wiki的文档,做了个人的理解~ 首先抛出一个疑问,Subversion是做什么的,SVNKit又是用来干什么的? 相信一般工作过的同学都用过或了解过svn,不了解的同学可以到官网看下,这里不作为本文重点. 需要理解的概念: 仓库(Repository):是一个特殊的结构,记录文件版本管理的状态. 工作副本(Working Copy):本地从仓库检出的文件. 修订版(Revision):用于记录仓库数据的变更状态,初始化版本为0,每执行一次操作版本号+1,每执行一

微信公众号API测试——接口调用频率限制

接口频率限制[1] 公众号调用接口并不是无限制的.为了防止公众号的程序错误而引发微信服务器负载异常,默认情况下,每个公众号调用接口都不能超过一定限制,当超过一定限制时,调用对应接口会收到如下错误返回码: {"errcode":45009,"errmsg":"api freq out of limit"} 各接口调用频率限制如下: 接口 每日限额 获取access_token 2000 自定义菜单创建 1000 自定义菜单查询 10000 自定义菜

JavaSE入门学习21:Java面向对象之接口(interface)(二)

一接口实现的多态 在上一篇博文:JavaSE入门学习20:Java面向对象之接口(interface)(一)中提到了接口的实现存在多态性,那么 这一篇主要就要分析接口实现的多态. 实例一 Test.java源文件代码: public class Test{ public static void main(String[] args){ //实现接口Singer Singer s1 = new Student("Amy"); s1.sing(); s1.sleep(); s1.study

Mybatis学习总结(二)—使用接口实现数据的增删改查

在这一篇中,让我们使用接口来实现一个用户数据的增删改查. 完成后的项目结构如下图所示: 在这里,person代表了一个用户的实体类.在该类中,描述了相关的信息,包括id.name.age.id_num信息.而personMapper则是该实体类的一个配置文件.需要注意的是,在上一篇博文中,namespace属性的值是其本身,而在这一篇中,使用的是接口.那么两者有什么区别呢?使用接口,那么相关的操作方法不用自己去实现,只需要调用该接口的相关的方法就能够实现相应的功能. 那么,在这里就有一个问题,接

基于百度风云榜开发的API数据接口-为APP资讯资讯服务

是基于百度搜索风云榜采集的新闻信息,,该资讯会更好的体现人们关注的人多事件与热词 通过数据采集,同时发布相信的数据开放API接口 1.取得热词信息列表 如:api.yi18.net/top/list 2.取得热词信息详细 如:api.yi18.net/top/show?id=1 更多的API文档 doc.yi18.net/topwendang 数据镜像网站:  top.yi18.net API数据接口的免费开放,希望为更多的APP开发者提供更专业的数据 接口.为APP开发提供更简单的新闻热点板块

药品API免费接口开放-APP数据接口

药品直达 ( drug.yi18.net )是医药吧网(www.yi18.net) 旗下的药品信息网. 打造药品信息查询平台,提供最全的药品信息.用于药品功能,价格,说明书, 使用手册的简单介绍. 药品直达API ,主要开放药品信息.API提供主要是为了更好的数据开放,同时 API不仅提供APP调用,同时也可以支持网站调用.免费开放,永久支持! API文档地址:doc.yi18.net/drugwendang 药品API接口的开放,为APP提供专门的数据接口,就可以简单快速的创建 自己的APP应