java中使用svnkit实现文件的版本管理
java中使用svnkit实现文件的版本管理
- 一、引入svnKit依赖
- 二、初始化仓库工厂类
- 二、使用svnkit创建本地存储仓库
- 三、svn基本原子操作
- 四、通过原子方法实现简单svn相应操作
一、引入svnKit依赖
<dependency><groupId>org.tmatesoft.svnkit</groupId><artifactId>svnkit</artifactId><version>1.9.3</version></dependency>
二、初始化仓库工厂类
本文参考来自于svnkit官网
在使用svn客户端进行各种操作时第一步需要初始化仓库工厂
/** Initializes the library to work with a repository via* different protocols.*/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();}
二、使用svnkit创建本地存储仓库
try {String tgtPath = "d:/modelFiles/repos";SVNURL tgtURL = SVNRepositoryFactory.createLocalRepository( new File( tgtPath ), true , false );} catch ( SVNException e ) {//handle exception}
执行完这一段代码之后,我们可以在本地目录下发现以下目录结构
三、svn基本原子操作
private static SVNClientManager ourClientManager;private static ISVNEventHandler myCommitEventHandler;private static ISVNEventHandler myUpdateEventHandler;private static ISVNEventHandler myWCEventHandler;/** Puts directories and files under version control scheduling them for addition* to a repository. They will be added in a next commit. Like 'svn add PATH'* command. It's done by invoking** SVNWCClient.doAdd(File path, boolean force,* boolean mkdir, boolean climbUnversionedParents, boolean recursive)** which takes the following parameters:** path - an entry to be scheduled for addition;** force - set to true to force an addition of an entry anyway;** mkdir - if true doAdd(..) creates an empty directory at path and schedules* it for addition, like 'svn mkdir PATH' command;** climbUnversionedParents - if true and the parent of the entry to be scheduled* for addition is not under version control, then doAdd(..) automatically schedules* the parent for addition, too;** recursive - if true and an entry is a directory then doAdd(..) recursively* schedules all its inner dir entries for addition as well.*/// 将文件纳入版本控制private static void addEntry(File wcPath) throws SVNException {ourClientManager.getWCClient().doAdd(wcPath, false, false, false, true);}/** Updates a working copy (brings changes from the repository into the working copy).* Like 'svn update PATH' command; It's done by invoking** SVNUpdateClient.doUpdate(File file, SVNRevision revision, boolean recursive)** which takes the following parameters:** file - a working copy entry that is to be updated;** revision - a revision to which a working copy is to be updated;** recursive - if true and an entry is a directory then doUpdate(..) recursively* updates the entire directory, otherwise - only child entries of the directory;*/// 将本地文件更新到指定版本,前提是本地有该文件的其他版本private static long update(File wcPath,SVNRevision updateToRevision, boolean isRecursive)throws SVNException {SVNUpdateClient updateClient = ourClientManager.getUpdateClient();/** sets externals not to be ignored during the update*/updateClient.setIgnoreExternals(false);/** returns the number of the revision wcPath was updated to*/return updateClient.doUpdate(wcPath, updateToRevision, isRecursive);}/** Checks out a working copy from a repository. Like 'svn checkout URL[@REV] PATH (-r..)'* command; It's done by invoking** SVNUpdateClient.doCheckout(SVNURL url, File dstPath, SVNRevision pegRevision,* SVNRevision revision, boolean recursive)** which takes the following parameters:** url - a repository location from where a working copy is to be checked out;** dstPath - a local path where the working copy will be fetched into;** pegRevision - an SVNRevision representing a revision to concretize* url (what exactly URL a user means and is sure of being the URL he needs); in other* words that is the revision in which the URL is first looked up;** revision - a revision at which a working copy being checked out is to be;** recursive - if true and url corresponds to a directory then doCheckout(..) recursively* fetches out the entire directory, otherwise - only child entries of the directory;*/// svn检出操作,即从svn仓库拉取指定版本的代码private static long checkout(SVNURL url,SVNRevision revision, File destPath, boolean isRecursive)throws SVNException {SVNUpdateClient updateClient = ourClientManager.getUpdateClient();/** sets externals not to be ignored during the checkout*/updateClient.setIgnoreExternals(false);/** returns the number of the revision at which the working copy is*/return updateClient.doCheckout(url, destPath, revision, revision, isRecursive);}/** Committs changes in a working copy to a repository. Like* 'svn commit PATH -m "some comment"' command. It's done by invoking** SVNCommitClient.doCommit(File[] paths, boolean keepLocks, String commitMessage,* boolean force, boolean recursive)** which takes the following parameters:** paths - working copy paths which changes are to be committed;** keepLocks - if true then doCommit(..) won't unlock locked paths; otherwise they will* be unlocked after a successful commit;** commitMessage - a commit log message;** force - if true then a non-recursive commit will be forced anyway;** recursive - if true and a path corresponds to a directory then doCommit(..) recursively* commits changes for the entire directory, otherwise - only for child entries of the* directory;*/// svn提交操作,将本地文件提交到svn仓库private static SVNCommitInfo commit(File wcPath, boolean keepLocks, String commitMessage)throws SVNException {/** Returns SVNCommitInfo containing information on the new revision committed* (revision number, etc.)*/return ourClientManager.getCommitClient().doCommit(new File[] { wcPath }, keepLocks,commitMessage, false, true);}/** Imports an unversioned directory into a repository location denoted by a* destination URL (all necessary parent non-existent paths will be created* automatically). This operation commits the repository to a new revision.* Like 'svn import PATH URL (-N) -m "some comment"' command. It's done by* invoking** SVNCommitClient.doImport(File path, SVNURL dstURL, String commitMessage, boolean recursive)** which takes the following parameters:** path - a local unversioned directory or singal file that will be imported into a* repository;** dstURL - a repository location where the local unversioned directory/file will be* imported into; this URL path may contain non-existent parent paths that will be* created by the repository server;** commitMessage - a commit log message since the new directory/file are immediately* created in the repository;** recursive - if true and path parameter corresponds to a directory then the directory* will be added with all its child subdirictories, otherwise the operation will cover* only the directory itself (only those files which are located in the directory).*/// 本地目录初始提交到svn仓库private static SVNCommitInfo importDirectory(File localPath, SVNURL dstURL, String commitMessage, boolean isRecursive) throws SVNException{/** Returns SVNCommitInfo containing information on the new revision committed* (revision number, etc.)*/return ourClientManager.getCommitClient().doImport(localPath, dstURL, commitMessage, isRecursive);}/** Schedules directories and files for deletion from version control upon the next* commit (locally). Like 'svn delete PATH' command. It's done by invoking** SVNWCClient.doDelete(File path, boolean force, boolean dryRun)** which takes the following parameters:** path - an entry to be scheduled for deletion;** force - a boolean flag which is set to true to force a deletion even if an entry* has local modifications;** dryRun - set to true not to delete an entry but to check if it can be deleted;* if false - then it's a deletion itself.*/// svn删除操作private static void delete(File wcPath, boolean force) throws SVNException {ourClientManager.getWCClient().doDelete(wcPath, force, false);}// svn删除整个工作目录操作public static SVNCommitInfo deleteDir(ISVNEditor editor , String dirPath ) throws SVNException {editor.openRoot( -1 );editor.deleteEntry( dirPath , -1 );//Closes the root directory.editor.closeDir( );return editor.closeEdit( );}// 创建指定版本分支private static SVNCommitInfo copy(SVNURL srcURL, SVNURL dstURL,SVNRevision revision,boolean isMove, String commitMessage) throws SVNException {/** SVNRevision.HEAD means the latest revision.* Returns SVNCommitInfo containing information on the new revision committed* (revision number, etc.)*/SVNCopySource[] sources = {new SVNCopySource(null, revision, srcURL)};return ourClientManager.getCopyClient().doCopy(sources , dstURL, false, false, true, commitMessage, null);}/** Called recursively to obtain all entries that make up the repository tree* repository - an SVNRepository which interface is used to carry out the* request, in this case it's a request to get all entries in the directory* located at the path parameter;* * path is a directory path relative to the repository location path (that* is a part of the URL used to create an SVNRepository instance);* */// 打印指定版本下的文件列表信息public static void listEntries(SVNRepository repository, String path, Long version)throws SVNException {/** Gets the contents of the directory specified by path at the latest* revision (for this purpose -1 is used here as the revision number to* mean HEAD-revision) getDir returns a Collection of SVNDirEntry* elements. SVNDirEntry represents information about the directory* entry. Here this information is used to get the entry name, the name* of the person who last changed this entry, the number of the revision* when it was last changed and the entry type to determine whether it's* a directory or a file. If it's a directory listEntries steps into a* next recursion to display the contents of this directory. The third* parameter of getDir is null and means that a user is not interested* in directory properties. The fourth one is null, too - the user* doesn't provide its own Collection instance and uses the one returned* by getDir.*/Collection entries = repository.getDir(path, version, 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() + ")");/** Checking up if the entry is a directory.*/if (entry.getKind() == SVNNodeKind.DIR) {listEntries(repository, (path.equals("")) ? entry.getName(): path + "/" + entry.getName());}}}
四、通过原子方法实现简单svn相应操作
// svn 工作目录private static String copyPath = "C:/modelFiles/copy/";// svn 仓库目录private static String reposPath= "C:/modelFiles/repos/";// 临时文件存放目录private static String tmpPath= "C:/modelFiles/tmp/";// 初始提交本地copyPath下文件夹到svn仓库public static long commitFile(String dirName) throws SVNException {File sourcePath = new File(copyPath+dirName);SVNURL targetURL = SVNURL.parseURIEncoded("file:///"+reposPath+dirName);committedRevision = importDirectory(sourcePath, targetURL, "上传模型文件夹 "+dirName, true).getNewRevision();return committedRevision;}// 检出指定版本到指定目录// 其中 SVNRevision 为版本对象,可以通过SVNRevision.create(1) 形式创建版本id为1的版本对象// svn版本从1开始往后迭代,为长整型,0表示最新版本用 SVNRevision.HEAD表示,其等同于 SVNRevision.create(0)public static void checkOut(String dirName,String basePath,SVNRevision svnRevision) throws SVNException {SVNURL repository = SVNURL.parseURIEncoded("file:///"+reposPath);File wcDir = new File(basePath+"/"+dirName);checkout(repository.appendPath(dirName,false), svnRevision, wcDir, true);}// svn工作目录下新增文件夹或文件后提交至svn仓库public static long commitNewFile(String dirName,String newDir) throws SVNException {// svn工作区目录File wcDir = new File(copyPath+dirName);// svn工作目录下新增的文件夹File NewDir = new File(copyPath+newDir);// 为了防止当前不是最新版本先从svn仓库更新下最新代码,其实也可以不进行这一步操作update(wcDir, SVNRevision.HEAD, true);// 将当前新增的目录加入版本控制addEntry(NewDir);// 提交至svn仓库long newRevision = commit(wcDir, false,"在 " + dirName + " 目录下新增 " + newDir).getNewRevision();log.info("在 "+dirName+" 目录下新增 "+newDir);return newRevision;}// 删除svn工作目录下某个文件夹并提交svn仓库public static long deleteFile(String dirName,String delDir) throws SVNException {File wcDir = new File(copyPath+dirName);File DelDir = new File(copyPath+delDir);delete(DelDir, false);long newRevision = commit(wcDir, false,"从 " + dirName + " 目录下删除 " + delDir).getNewRevision();log.info("从 "+dirName+" 目录下删除 "+delDir);//删除后更新下update(wcDir, SVNRevision.HEAD, true);return newRevision;}// svn删除整个工作目录操作public static void deleteFileFromRepos(String dirName){try {SVNRepository svnRepository = FSRepositoryFactory.create(SVNURL.parseURIEncoded("file:///" + reposPath));ISVNEditor editor = svnRepository.getCommitEditor( "删除目录 "+dirName , null );try {deleteDir(editor, dirName);} catch ( SVNException svne ) {editor.abortEdit( );throw svne;}} catch (Exception e) {e.printStackTrace();}}/*** @description 创建指定版本的分支*/public static Long createBranchByCopy(String dirName,Long revisionNum) {try {SVNURL srcURL = SVNURL.parseURIEncoded("file:///"+reposPath+dirName);SVNURL dstURL = SVNURL.parseURIEncoded("file:///"+reposPath+dirName+"-分支");SVNCommitInfo copyInfo = copy(srcURL,dstURL,SVNRevision.create(revisionNum),true," 创建分支:" + dirName+"-分支");checkOut(getBranchName(dirName+"-分支",copyPath);return copyInfo.getNewRevision();} catch (SVNException e) {log.info("创建分支失败:"+e.getMessage());throw new RuntimeException(e);}}// 获取当前模型仓库的最新版本编号public static long getLatestRevision() throws SVNException {SVNRepository svnRepository = FSRepositoryFactory.create(SVNURL.parseURIEncoded("file:///" + reposPath));return svnRepository.getLatestRevision();}
相关文章:

java中使用svnkit实现文件的版本管理
java中使用svnkit实现文件的版本管理 一、引入svnKit依赖二、初始化仓库工厂类二、使用svnkit创建本地存储仓库三、svn基本原子操作四、通过原子方法实现简单svn相应操作 一、引入svnKit依赖 <dependency><groupId>org.tmatesoft.svnkit</groupId><artifa…...

了解 Linux 网络卡绑定:提高网络性能与冗余性
在现代 IT 基础设施中,网络性能和可靠性至关重要。对于许多企业和个人用户来说,确保网络的高可用性和冗余性是首要任务之一。Linux 提供了一个强大的解决方案——网络卡绑定(Network Interface Card Bonding,简称 NIC Bonding&…...

2024年618购物狂欢节即将来袭!精选五款超值入手数码好物!
618购物狂欢盛宴即将落幕,是时候展现我们的购物智慧了!在追求价格优惠的同时,我们更应看重商品的品质与实用性。面对琳琅满目的选择,如何筛选出真正值得拥有的好物呢?为了让大家的购物之旅更加轻松愉快,以下…...
中国AI独角兽资本大冒险
成立不过一年多时间,月之暗面已然成为中国大模型赛道上,最炙手可热的明星公司。 5月21日,华尔街见闻获悉,月之暗面将按照投前估值30亿美元(合217.3亿人民币)进行融资,完成后依然会是当前中国估…...

项目十二:简单的python基础爬虫训练
许久未见,甚是想念,今日好运,为你带好运。ok,废话不多说,希望这门案例能带你直接快速了解并运用。🎁💖 基础流程 第一步:安装需要用到的requests库,命令如下 pip inst…...
OpenGL学习入门及开发环境搭建
最近学习OpenGL开发,被各种openGL库搞得晕头转向,什么glut, glew glfw glad等等。 可以参考这边博客:OpenGL 下面的 glut freeglut glfw 都是个啥_glx wgl的中文-CSDN博客 glfw是glut的升级版,跨平台的主要处理窗口 事件相关。 glad是glew…...

three.js能实现啥效果?看过来,这里都是它的菜(08)
在Three.js中实现旋转动画的原理是通过修改对象的旋转属性来实现的,通常使用渲染循环(render loop)来更新对象的旋转状态,从而实现动画效果。 具体的原理包括以下几个步骤: 创建对象:首先创建一个需要旋转…...
SpringBoot(九)之整合mybatis
SpringBoot(九)之整合mybatis 文章目录 SpringBoot(九)之整合mybatisSpring整合mybatis回顾1. 引入依赖2. mybatis-config.xml SpringBoot整合mybatis1.引入依赖2. 配置数据源和 MyBatis 属性3. 配置 Mapper 接口4. 配置mapper.xm…...

【实战教程】使用Spring AOP和自定义注解监控接口调用
一、背景 随着项目的长期运行和迭代,积累的功能日益繁多,但并非所有功能都能得到用户的频繁使用或实际上根本无人问津。 为了提高系统性能和代码质量,我们往往需要对那些不常用的功能进行下线处理。 那么,该下线哪些功能呢&…...
算法学习之:Raft-分布式一致性/共识算法
基础介绍 Raft是什么? Raft is a consensus algorithm that is designed to be easy to understand. Its equivalent to Paxos in fault-tolerance and performance. The difference is that its decomposed into relatively independent subproblems, and it clea…...

彩色进度条(C语言版本)
.h文件 #include<stdio.h> #include<windows.h>#define NUM 101 #define LOAD_UP 50 #define LOAD_DOWN 60 #define SLEEP_SLOW 300 #define SLEEP_FAST 70 版本1:(初始版) //v1 #include "progress.h" int main() …...
C#和C++有什么区别?
C#和C都是广泛使用的编程语言,但它们在设计理念、应用场景和语法上有许多显著的区别。以下是一些关键区别的详细介绍: 1. 设计理念和目的 C: 设计目的:C是一种面向系统编程和应用程序开发的语言,具有高效性和灵活性…...

微信小程序报错:notifyBLECharacteristicValueChange:fail:nodescriptor的解决办法
文章目录 一、发现问题二、分析问题二、解决问题 一、发现问题 微信小程序报错:notifyBLECharacteristicValueChange:fail:nodescriptor 二、分析问题 这个提示有点问题,应该是该Characteristic的Descriptor有问题,而不能说nodescriptor。 …...
富格林:可信攻略阻止遭遇欺诈
富格林悉知,在投资市场中,如何阻止遭遇欺诈情况应该是每位投资者都想要了解的一个知识点。事实上,现货黄金市场相对来说会其他市场复杂多变,因此要想盈利出金还是得要先学会阻止遭遇欺诈情况。据富格林所知,目前市面上…...

搭建淘宝扭蛋机小程序:技术选型与最佳实践
随着移动互联网的快速发展,小程序作为一种轻量级应用,以其无需安装、即用即走的特点,受到了广大用户的喜爱。在电商领域,淘宝作为国内最大的电商平台之一,也积极拥抱小程序技术,为用户提供更加便捷、个性化…...

【线性回归】梯度下降
文章目录 [toc]数据数据集实际值估计值 梯度下降算法估计误差代价函数学习率参数更新 Python实现导包数据预处理迭代过程结果可视化完整代码 结果可视化线性拟合结果代价变化 数据 数据集 ( x ( i ) , y ( i ) ) , i 1 , 2 , ⋯ , m \left(x^{(i)} , y^{(i)}\right) , i 1 ,…...

GMSL图像采集卡,适用于无人车、自动驾驶、自主机器、数据采集等场景,支持定制
基于各种 系列二代 G MS L 图像采集卡(以下简称 二代图像采集卡)是一款自主研发的一款基于 F P G A 的高速图像产品,二代图像采集卡相比一代卡,由于采用PCIe G en 3 技术,速度和带宽都相应的有了成 倍的提高。该图像…...

docker不删除容器更改其挂载目录
场景:docker搭建的jenkins通常需要配置很多开发环境,当要更换挂载目录,每次都需要删除容器重新运行,不在挂载目录的环境通常不会保留。 先给一个参考博客docker不删除容器,修改容器挂载或其他_jenkins 修改容器挂载do…...

K8s Service 背后是怎么工作的?
kube-proxy 是 Kubernetes 集群中负责服务发现和负载均衡的组件之一。它是一个网络代理,运行在每个节点上, 用于 service 资源的负载均衡。它有两种模式:iptables 和 ipvs。 iptables iptables 是 Linux 系统中的一个用户空间实用程序,用于…...

ClickHouse配置与使用
静态IP配置 # 修改网卡配置文件 vim /etc/sysconfig/network-scripts/ifcfg-ens33# 修改文件内容 TYPEEthernet PROXY_METHODnone BROWSER_ONLYno BOOTPROTOstatic IPADDR192.168.18.128 NETMASK255.255.255.0 GATEWAY192.168.18.2 DEFROUTEyes IPV4_FAILURE_FATALno IPV6INIT…...

接口测试中缓存处理策略
在接口测试中,缓存处理策略是一个关键环节,直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性,避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明: 一、缓存处理的核…...
脑机新手指南(八):OpenBCI_GUI:从环境搭建到数据可视化(下)
一、数据处理与分析实战 (一)实时滤波与参数调整 基础滤波操作 60Hz 工频滤波:勾选界面右侧 “60Hz” 复选框,可有效抑制电网干扰(适用于北美地区,欧洲用户可调整为 50Hz)。 平滑处理&…...
Leetcode 3576. Transform Array to All Equal Elements
Leetcode 3576. Transform Array to All Equal Elements 1. 解题思路2. 代码实现 题目链接:3576. Transform Array to All Equal Elements 1. 解题思路 这一题思路上就是分别考察一下是否能将其转化为全1或者全-1数组即可。 至于每一种情况是否可以达到…...
FFmpeg 低延迟同屏方案
引言 在实时互动需求激增的当下,无论是在线教育中的师生同屏演示、远程办公的屏幕共享协作,还是游戏直播的画面实时传输,低延迟同屏已成为保障用户体验的核心指标。FFmpeg 作为一款功能强大的多媒体框架,凭借其灵活的编解码、数据…...

大数据零基础学习day1之环境准备和大数据初步理解
学习大数据会使用到多台Linux服务器。 一、环境准备 1、VMware 基于VMware构建Linux虚拟机 是大数据从业者或者IT从业者的必备技能之一也是成本低廉的方案 所以VMware虚拟机方案是必须要学习的。 (1)设置网关 打开VMware虚拟机,点击编辑…...
在四层代理中还原真实客户端ngx_stream_realip_module
一、模块原理与价值 PROXY Protocol 回溯 第三方负载均衡(如 HAProxy、AWS NLB、阿里 SLB)发起上游连接时,将真实客户端 IP/Port 写入 PROXY Protocol v1/v2 头。Stream 层接收到头部后,ngx_stream_realip_module 从中提取原始信息…...
生成 Git SSH 证书
🔑 1. 生成 SSH 密钥对 在终端(Windows 使用 Git Bash,Mac/Linux 使用 Terminal)执行命令: ssh-keygen -t rsa -b 4096 -C "your_emailexample.com" 参数说明: -t rsa&#x…...

DIY|Mac 搭建 ESP-IDF 开发环境及编译小智 AI
前一阵子在百度 AI 开发者大会上,看到基于小智 AI DIY 玩具的演示,感觉有点意思,想着自己也来试试。 如果只是想烧录现成的固件,乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外,还提供了基于网页版的 ESP LA…...
【git】把本地更改提交远程新分支feature_g
创建并切换新分支 git checkout -b feature_g 添加并提交更改 git add . git commit -m “实现图片上传功能” 推送到远程 git push -u origin feature_g...
Rust 异步编程
Rust 异步编程 引言 Rust 是一种系统编程语言,以其高性能、安全性以及零成本抽象而著称。在多核处理器成为主流的今天,异步编程成为了一种提高应用性能、优化资源利用的有效手段。本文将深入探讨 Rust 异步编程的核心概念、常用库以及最佳实践。 异步编程基础 什么是异步…...