java实现svn,svnkit框架的简单应用
2017-03-27 00:00
169 查看
SvnKit
地址:https://svnkit.com/download.php
项目需要做了个简单的demo,可以进行基础操作。demo可以运行,但是更多高级更多实现需要自己在扩展。因为这个项目已经进入Thread.sleep :( ,开展新项目了 :(
功能
1.实现了几个基础操作
2.提供了日志操作
项目结构
首先我们先创建3个对象来为后面服务
创建svn基础服务接口
建立主功能接口
当然我们还有通用的工具接口
为了满足上级要求我们提供了db接口
到上面为止我们的接口全部做好。这是一个Java项目是希望做为一个工具jar的存在,demo中只做了一套基础的实现,按照这个思路根据不同需求可以慢慢扩展
工具类
其实这里自己写了个简单的错误匹配,主要是针对svnkit的errorCode转义,当然也可以用log4j等开源日志。不过毕竟是demo么 :)
这里主要是输出文本比对时差异信息
说实话版本冲突这里我svn是可以对列表进行更新或写操作的时候,批量返回错误信息,而svn提供的cmd入口及svnkit对其cmd命令的实现,都是提供的单条问题抛出,譬如我update一个文件目录,在第3,第5个文件会出现冲突,则接口在第三个文件直接就exception了,无法往下进行了。当然你可以递归从第四条再更新执行,最后把结果合并显示 :)
这里是自定义的错误信息
这里不仅为小工厂提供了选项,还提供了对抽象db日志的数据设置
实现类来了。。。拦不住的implements
提供了对通用工具接口的实现,为什么要那么复杂呢。因为例如add接口,必须要先提交最底层的文件夹目录从深层提交到高层,然后再提交其文件,以此类推,说白了就是你没有文件夹时无法建立文件的。
服务接口实现类,快乐的建立库容器
因为整个项目保持开闭原则,让你用的你随便用,不让你用的你就老实点:)
一次创建整个实例都能在开闭原则下快乐的使用各种创建好的实例/各种服务类
其实这里本来还想写个池服务。。不过时间关系就没写。毕竟demo没有后续跟进计划了。以后有机会再补
这里..这里就是业务实现了,其实就是对svnkit进行了一个封装,让他更符合项目要求
实现代码比较多。不要慌
仔细看看加断点看看
加锁解锁还有一些接口的高级应用并没有深入去写,因为毕竟是demo。上级觉得技术上是可以搞定这个功能的,虽然因为其他原因项目阉割了 :( 所以也没有后续进行深层开发
https://svnkit.com/documentation.html 这个是svnkit 文档,不过文档比svnkit.jar版本要老 :((
关于参数中
可以让使用者提供一个ISvnDbLog的实现,来进行日志保存,无论是db还是file
最后我们提供一个简单纺织小工厂
来一个测试函数吧
其实创建版本库,操作对象,初始化实例,close都可以做的更简洁,然后做到事务中,切面管理.. :)
就这样吧。demo而已看个用法和思路。具体优化及细节也没有时间去做了,毕竟是demo :)
下载地址
http://download.csdn.net/detail/crazyzxljing0621/9755958
地址:https://svnkit.com/download.php
项目需要做了个简单的demo,可以进行基础操作。demo可以运行,但是更多高级更多实现需要自己在扩展。因为这个项目已经进入Thread.sleep :( ,开展新项目了 :(
功能
1.实现了几个基础操作
2.提供了日志操作
项目结构
首先我们先创建3个对象来为后面服务
package com.svn.model; /** * Svn账号信息 * * @author Allen * @date 2016年8月8日 */ public class SvnAccountPojo implements java.io.Serializable { /** * */ private static final long serialVersionUID = 1L; private String svnAccount;// svn账号 private String svnPassword;// svn密码 protected SvnAccountPojo() { // TODO Auto-generated constructor stub } public SvnAccountPojo(String svnAccount, String svnPassword) { super(); this.svnAccount = svnAccount; this.svnPassword = svnPassword; } public String getSvnAccount() { return svnAccount; } public void setSvnAccount(String svnAccount) { this.svnAccount = svnAccount; } public String getSvnPassword() { return svnPassword; } public void setSvnPassword(String svnPassword) { this.svnPassword = svnPassword; } }
package com.svn.model; /** * Svn链接状态信息 * * @author Allen * @date 2016年8月8日 */ public class SvnLinkPojo extends SvnAccountPojo { /** * */ private static final long serialVersionUID = 1L; private String repoPath;// 库链接路径 public SvnLinkPojo(String repoPath, String svnAccount, String svnPassword) { super(svnAccount, svnPassword); this.repoPath = repoPath; } public SvnLinkPojo(String svnAccount, String svnPassword) { super(svnAccount, svnPassword); } public String getRepoPath() { return repoPath; } public void setRepoPath(String repoPath) { this.repoPath = repoPath; } }
package com.svn.model; import java.util.Date; /** * SVN资源库对象 * * @author Allen * @date 2016年8月8日 */ public class SvnRepoPojo implements java.io.Serializable { /** * */ private static final long serialVersionUID = 1L; private String commitMessage; // 提交信息 private Date date; // 提交日期 private String kind; // 提交方式 dir目录 file文件 none空 unknown 未知 private String name;// 目录名 private String repositoryRoot; // 资源库路径 private long revision; // 提交的svn版本号 private long size; // 提交的文件数 private String url; // 更变的目录地址 private String author;// 作者 private String state;// 状态 public String getCommitMessage() { return commitMessage; } public void setCommitMessage(String commitMessage) { this.commitMessage = commitMessage; } public Date getDate() { return date; } public void setDate(Date date) { this.date = date; } public String getKind() { return kind; } public void setKind(String kind) { this.kind = kind; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getRepositoryRoot() { return repositoryRoot; } public void setRepositoryRoot(String repositoryRoot) { this.repositoryRoot = repositoryRoot; } public long getRevision() { return revision; } public void setRevision(long revision) { this.revision = revision; } public long getSize() { return size; } public void setSize(long size) { this.size = size; } public String getUrl() { return url; } public void setUrl(String url) { this.url = url; } public String getAuthor() { return author; } public void setAuthor(String author) { this.author = author; } public String getState() { return state; } public void setState(String state) { this.state = state; } }
创建svn基础服务接口
package com.svn.inf.service; /** * svn主服务创建 * * @author Allen * @date 2016年8月8日 */ public interface ISvnService { /** * 创建SNV版本库服务 * * @author Allen * @date 2016年8月11日 */ public void createSVNRepository(); /** * 关闭版本库容器,便于刷新重连等 * * @author Allen * @date 2016年8月11日 */ public void closeRepo(); /** * 创建svn客户操作服务 * * @author Allen * @date 2016年8月11日 */ public void createSVNClientManager(); }
建立主功能接口
package com.svn.inf; import java.io.File; import java.util.List; import com.svn.inf.service.ISvnDbLog; import com.svn.inf.service.ISvnService; import com.svn.model.SvnRepoPojo; /** * svn操作大全 * * @author Allen * @date 2016年8月8日 */ public interface ISvn extends ISvnService { /** * 获取目标路径下版本库数据信息 * * @param openPath * 需要查看的版本库路径 * @return 版本库列表 {@link SvnRepoPojo} * @author Allen * @date 2016年8月11日 */ public List<SvnRepoPojo> getRepoCatalog(String openPath); /** * 检出到目录 * * @param checkUrl * 检出目标URL * @param savePath * 检出到本地路径 * @return true|false * @author Allen * @date 2016年8月11日 */ public boolean checkOut(String checkUrl, String savePath); /** * 添加到版本库 * * @see 先添加文件夹再添加文件 * @param paths * 提交文件路径 * @param message * 提交信息 * @param uLocks * 是否解锁 * @param isvnLog * 数据持久化接口 {@link ISvnDbLog} * @return trun|false * @author Allen * @date 2016年8月11日 */ public <T> boolean add(String[] paths, String message, boolean uLocks, ISvnDbLog<? extends T> isvnLog); /** * 提交到版本库(所有写操作已在内部调用过COMMIT,自行调用则需要手动同步到DbLog) * * @param files * 提交的文件路径 * @param message * 提交信息 * @param uLocks * 是否解锁 * @return 返回提交后版本号-1为提交失败 * @author Allen * @date 2016年8月11日 */ public Long commit(File[] files, String message, boolean uLocks); /** * 删除到版本库 * * @see 先删除文件再删除文件夹 * @param paths * 提交文件路径 * @param localDelete * <ul> * <li>如果是true则在本地也删除此文件,false则只删除版本库中的此文件</li> * <li>删除实体文件时要注意</li> * <li>删除文件夹时其目录下所有内容都要提交到<b>参数paths</b>中,否则无法删除实体文件</li> * </ul> * @param message * 提交内容解释 * @param uLock * 是否解锁 * @param isvnLog * 数据持久化接口 {@link ISvnDbLog} * @return true|false * @author Allen * @date 2016年8月11日 */ public <T> boolean delete(String[] paths, boolean localDelete, String message, boolean uLock, ISvnDbLog<? extends T> isvnLog); /** * 更新到版本库 * * @param path * 要更新的文件目录 * @param message * 提交内容解释 * @param uLock * 是否解锁 * @param isvnLog * 数据持久化接口 {@link ISvnDbLog} * @return true|false * @author Allen * @date 2016年8月11日 */ public <T> boolean update(String path, String message, boolean uLock, ISvnDbLog<? super T> isvnLog); /** * 比对目录下内容信息 * * @see 返回delete,update文件列表 * @param file * 待比对的目标文件路径 * @return 返回有差异的文件路径否则为null * @author Allen * @date 2016年8月11日 */ public List<String> diffPath(File file); /** * 清理目录 * * @param file * 待清理目录 * @return true|false * @author Allen * @date 2016年8月17日 */ public boolean cleanUp(File file); public boolean doLock(); public boolean unLock(); }
当然我们还有通用的工具接口
package com.svn.inf.service; import java.io.File; import java.util.List; /** * Svn功能组件 * * @author Allen * @date 2016年8月12日 * */ public interface ISvnCommon { /** * 组装file[]分离文件与文件夹 * * @param files * 待重组的文件列表 * @return 文件容器组</br>index:0 文件夹</br> index:1 文件 * @author Allen * @date 2016年8月11日 */ public List<List<File>> bindFile(File[] files); /** * 排序</br> 父级 ->子级 * * @param files * 待排序文件数组 * @return 排序后文件数组 * @author Allen * @date 2016年8月11日 */ public File[] sortF_S(File[] files); /** * 排序</br> 子级 ->父级 * * @param files * 待排序文件数组 * @return 排序后文件数组 * @author Allen * @date 2016年8月11日 */ public File[] sortS_F(File[] files); /** * 检查文件路径信息并组装到文件容器 * * @param paths * 待组装文件路径 * @return 文件数组 * @throws Exception * 文件路径中有寻找不到的地址 * @author Allen * @date 2016年8月11日 */ public File[] checkFilePaths(String[] paths) throws Exception; }
为了满足上级要求我们提供了db接口
package com.svn.inf.service; import java.io.File; import java.util.Date; import java.util.List; import com.svn.conf.SvnConfig; /** * 记录svn操作人 * * @author Allen * @date 2016年8月8日 */ public interface ISvnDbLog<T> { /** * 添加日志 * * @param name * 操作人账号 * @param dbType * 数据类型{@link SvnConfig} * @param versionId * 版本号 * @param files * 操作的文件组 * @return true|false * @author Allen * @date 2016年8月11日 */ public boolean addLog(String name, SvnConfig dbType, long versionId, File[] files); /** * 获取日志 * * @param name * 操作人账号 * @param startTime * 日志开始时间 * @param endTime * 日志结束时间 * @return T 类型列表 * @author Allen * @date 2016年8月11日 */ public List<? super T> getLog(String name, Date startTime, Date endTime); }
到上面为止我们的接口全部做好。这是一个Java项目是希望做为一个工具jar的存在,demo中只做了一套基础的实现,按照这个思路根据不同需求可以慢慢扩展
工具类
其实这里自己写了个简单的错误匹配,主要是针对svnkit的errorCode转义,当然也可以用log4j等开源日志。不过毕竟是demo么 :)
package com.svn.tools; import java.io.File; import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.Date; /** * 控制台输出log信息 * * @author Allen * @date 2016年8月8日 */ public class ConsoleLog { protected boolean log = false; /** * 错误编码 */ private String[] errorCode = { "E155010", "E200005", "E204899", "E200009", "E155015","E155004" }; /** * 编码解释 */ private String[] errorInfo = { "找不到文件或文件夹,其所在目录未被纳入版本控制的", "文件没有被纳入版本控制", "无法访问的目录", "文件没有被纳入版本控制", "svn冲突!","文件被锁定,可能是因为上次操作意外中断导致,请执行cleanup" }; /** * 输出log到console * * @param msg * 输出信息 */ protected void log(String msg, String... content) { if (log) { StackTraceElement stack[] = (new Throwable()).getStackTrace(); String time = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss").format(new Date()); System.out.println(new StringBuffer("[").append(time).append("]").append(stack[1].getClassName()).append(".").append(stack[1].getMethodName()).append(" line:") .append(stack[1].getLineNumber())); System.out.println(new StringBuffer("[").append(time).append("]").append(msg)); } } protected void log(Exception e) { StringBuffer sbf = new StringBuffer("【SVN-ERROR】"); for (int i = 0; i < errorCode.length; i++) { if (e.getMessage().indexOf(errorCode[i]) != -1) this.log(sbf.append(errorInfo[i]).toString()); } } }
这里主要是输出文本比对时差异信息
说实话版本冲突这里我svn是可以对列表进行更新或写操作的时候,批量返回错误信息,而svn提供的cmd入口及svnkit对其cmd命令的实现,都是提供的单条问题抛出,譬如我update一个文件目录,在第3,第5个文件会出现冲突,则接口在第三个文件直接就exception了,无法往下进行了。当然你可以递归从第四条再更新执行,最后把结果合并显示 :)
package com.svn.tools; import java.io.IOException; import java.io.OutputStream; import java.util.List; /** * Output输出到字符串 * * @author Allen * @date 2016年8月11日 * */ public final class StringOutputSteam extends OutputStream { public List<String> s; public StringOutputSteam(List<String> s) { this.s = s; } @Override public void write(int b) throws IOException { } @Override public void write(byte b[], int off, int len) throws IOException { String temp = new String(b); String[] temps = temp.split("\r\n"); //System.out.println(temp); boolean flag = false; for (int i = 0; i < temps.length; i++) { // 根据svn命令返回Index: xxxx(path)获取所有包含delete update的path获取 if (temps[i].split(" ")[0].equalsIgnoreCase("Index:")) { String p = temps[i].substring(7, temps[i].length()); if (s.indexOf(p) == -1) { s.add(p); flag = true; continue; } } // 以Index:为开始点来判定svn diff返回的Log信息 // LogFormat: // Index: path // ============================= // xxxxxxx // Index: path // ============================= // xxxxxxx if (flag) { String state = ""; for (int j = i; j < temps.length; j++) { if (temps[j].split(" ")[0].equalsIgnoreCase("Index:")) break; if (temps[j].split(" ")[0].equalsIgnoreCase("---")) state = "冲突"; else if (state.equals("")) state = "删除"; } s.add(state); flag = false; } } } }
这里是自定义的错误信息
package com.svn.conf; /** * 错误信息库 * * @author Allen * @date 2016年8月8日 * */ public final class ErrorVal { public final static String SVNRepository_is_null = "版本库未被创建"; public final static String SVNClientManager = ""; public final static String SVNRepository_is_having = "版本库已存在 ,可以调用closeRepo进行[库服务清理]"; public final static String ISVNAuthenticationManager_is_null = "身份验证器还未被创建"; public final static String Path_no_having = "目标地址路径不存在"; public final static String Url_no_having = "目标库路径 不存在"; public final static String File_not_exist_repo = "文件所在目录没有被svn版本控制"; public final static String SvnConfig_is_null = "错误的配置"; public final static String Commit_error = "提交错误[==请确认文件是否已有其他版本操作,请检查文件是否不存在==]"; public final static String AddDbLog_error = "添加到数据日志错误"; public final static String File_Repo_no_having = "文件不存在版本库中"; public final static String Repo_Status_error = "版本状态错误"; public final static String Update_no_change = "没有变化的更新"; public final static String File_is_not_directory = "File不是一个目录"; }
这里不仅为小工厂提供了选项,还提供了对抽象db日志的数据设置
package com.svn.conf; /** * 系统参数设置 * * @see 外部通过<b>SvnConfig.xx</b>来一个<b>SvnConfig</b>类型传入不同的配置 * @see 外部通过<b>SvnConfig.xx.get</b>来以<b>String</b>类型得到不同的配置 * @author Allen * @date 2016年8月8日 * */ public class SvnConfig { /** * 选择非日志模式 */ public static final SvnConfig normal = new SvnConfig("normal"); /** * 选择console日志模式 */ public static final SvnConfig log = new SvnConfig("log"); /** * 数据存储类型Add */ public static final SvnConfig add = new SvnConfig("add"); /** * 数据存储类型Update */ public static final SvnConfig update = new SvnConfig("update"); /** * 数据存储类型Delete */ public static final SvnConfig delete = new SvnConfig("delete"); private String val; public String getVal() { return val; } private SvnConfig() { } private SvnConfig(String val) { this.val = val; } }
实现类来了。。。拦不住的implements
提供了对通用工具接口的实现,为什么要那么复杂呢。因为例如add接口,必须要先提交最底层的文件夹目录从深层提交到高层,然后再提交其文件,以此类推,说白了就是你没有文件夹时无法建立文件的。
package com.svn.impl.service; import java.io.File; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import com.svn.conf.ErrorVal; import com.svn.inf.service.ISvnCommon; import com.svn.tools.ConsoleLog; /** * {@link ISvnCommon} * * @author Allen * @date 2016年8月12日 * */ public class SvnCommonImpl extends ConsoleLog implements ISvnCommon { @Override public List<List<File>> bindFile(File[] files) { List<List<File>> fileList = new ArrayList<List<File>>(1); fileList.add(new ArrayList<File>()); fileList.add(new ArrayList<File>()); for (File f : files) { if (f.isDirectory()) // 0是文件目录,先提交文件目录让再提交文件 fileList.get(0).add(f); else fileList.get(1).add(f); } for (int i = 0; i < fileList.size(); i++) { if (fileList.get(i).size() == 0) fileList.remove(i); } return fileList; } @Override public File[] sortF_S(File[] files) { Arrays.sort(files); return files; } @Override public File[] sortS_F(File[] files) { files = sortF_S(files); File[] f = new File[files.length]; for (int i = 0; i < files.length;) { f[i] = files[files.length - (++i)]; } return f; } @Override public File[] checkFilePaths(String[] paths) throws Exception { if (paths == null | paths.length == 0) throw new Exception(ErrorVal.Path_no_having); File[] files = new File[paths.length]; for (int i = 0; i < paths.length; i++) { if (!(files[i] = new File(paths[i])).exists()) throw new Exception(ErrorVal.Path_no_having); } return files; } }
服务接口实现类,快乐的建立库容器
因为整个项目保持开闭原则,让你用的你随便用,不让你用的你就老实点:)
一次创建整个实例都能在开闭原则下快乐的使用各种创建好的实例/各种服务类
package com.svn.impl.service; import org.tmatesoft.svn.core.SVNException; import org.tmatesoft.svn.core.SVNURL; import org.tmatesoft.svn.core.auth.ISVNAuthenticationManager; import org.tmatesoft.svn.core.io.SVNRepository; import org.tmatesoft.svn.core.io.SVNRepositoryFactory; import org.tmatesoft.svn.core.wc.SVNClientManager; import org.tmatesoft.svn.core.wc.SVNWCUtil; import com.svn.conf.ErrorVal; import com.svn.inf.service.ISvnService; /** * {@link ISvnService} * * @author Allen * @date 2016年8月8日 */ public class SvnServiceImpl extends SvnCommonImpl implements ISvnService { protected String svnAccount; // svn账号 protected String svnPassword;// svn密码 protected String svnRepoPath;// svn版本库根目录 protected boolean logStatus = false;// 日志状态 protected SVNRepository repository = null;// 版本库服务 protected ISVNAuthenticationManager authManager;// 身份验证器 protected SVNClientManager clientManager;// svn客户操作服务 /** * * @param account * 账号 * @param password * 密码 * @param logStatus * 是否开启日志状态(默认false) * @param repoPath * svn库根目录 * */ public SvnServiceImpl(String account, String password, boolean logStatus, String repoPath) { this.svnAccount = account; this.svnPassword = password; this.svnRepoPath = repoPath; super.log = logStatus; } @Override public void createSVNRepository() { try { if (repository != null) throw new Exception(ErrorVal.SVNRepository_is_having); // 创建库连接 SVNRepository repository = SVNRepositoryFactory.create(SVNURL.parseURIEncoded(this.svnRepoPath)); super.log("创建版本库连接"); // 身份验证 this.authManager = SVNWCUtil.createDefaultAuthenticationManager(this.svnAccount, this.svnPassword.toCharArray()); super.log("创建身份验证"); // 创建身份验证管理器 repository.setAuthenticationManager(authManager); this.repository = repository; super.log("设置版本库身份验证"); } catch (SVNException e) { super.log(e); e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } } @Override public void closeRepo() { if (repository == null) try { throw new NullPointerException(ErrorVal.SVNRepository_is_null); } catch (Exception e) { e.printStackTrace(); } else { repository.closeSession(); repository = null; super.log("关闭版本库"); } } @Override public void createSVNClientManager() { if (authManager == null) try { throw new NullPointerException(ErrorVal.ISVNAuthenticationManager_is_null); } catch (Exception e) { e.printStackTrace(); } clientManager = SVNClientManager.newInstance(SVNWCUtil.createDefaultOptions(true), authManager); super.log("创建svn客户操作服务"); } }
其实这里本来还想写个池服务。。不过时间关系就没写。毕竟demo没有后续跟进计划了。以后有机会再补
package com.svn.impl.service; import com.svn.impl.service.SvnCommonImpl; import com.svn.inf.service.ISvnService; /** * {@link ISvnService} 池的实现 * * @author Allen * @date 2016年8月8日 */ public class SvnServicePoolImpl extends SvnCommonImpl implements ISvnService { @Override public void createSVNRepository() { // TODO Auto-generated method stub } @Override public void closeRepo() { // TODO Auto-generated method stub } @Override public void createSVNClientManager() { // TODO Auto-generated method stub } }
这里..这里就是业务实现了,其实就是对svnkit进行了一个封装,让他更符合项目要求
package com.svn.impl; import java.io.File; import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.List; import org.tmatesoft.svn.core.SVNDepth; import org.tmatesoft.svn.core.SVNDirEntry; import org.tmatesoft.svn.core.SVNException; import org.tmatesoft.svn.core.SVNURL; import org.tmatesoft.svn.core.wc.SVNDiffClient; import org.tmatesoft.svn.core.wc.SVNRevision; import org.tmatesoft.svn.core.wc.SVNStatus; import org.tmatesoft.svn.core.wc.SVNStatusType; import org.tmatesoft.svn.core.wc.SVNUpdateClient; import com.svn.conf.ErrorVal; import com.svn.conf.SvnConfig; import com.svn.impl.service.SvnServiceImpl; import com.svn.inf.ISvn; import com.svn.inf.service.ISvnDbLog; import com.svn.inf.service.ISvnService; import com.svn.model.SvnRepoPojo; import com.svn.tools.StringOutputSteam; /** * * {@link ISvnService} * * @author Allen * @date 2016年8月8日 * */ public class SvnBaseImpl extends SvnServiceImpl implements ISvn { public SvnBaseImpl(String account, String password, boolean logStatus, String repoPath) { super(account, password, logStatus, repoPath); } @SuppressWarnings("unchecked") @Override public List<SvnRepoPojo> getRepoCatalog(String openPath) { try { if (repository == null) throw new Exception(ErrorVal.SVNRepository_is_null); Collection<SVNDirEntry> entries = repository.getDir(openPath, -1, null, (Collection<SVNDirEntry>) null); List<SvnRepoPojo> svns = new ArrayList<SvnRepoPojo>(); Iterator<SVNDirEntry> it = entries.iterator(); while (it.hasNext()) { SVNDirEntry entry = it.next(); SvnRepoPojo svn = new SvnRepoPojo(); svn.setCommitMessage(entry.getCommitMessage()); svn.setDate(entry.getDate()); svn.setKind(entry.getKind().toString()); svn.setName(entry.getName()); svn.setRepositoryRoot(entry.getRepositoryRoot().toString()); svn.setRevision(entry.getRevision()); svn.setSize(entry.getSize() / 1024); svn.setUrl(openPath.equals("") ? new StringBuffer("/").append(entry.getName()).toString() : new StringBuffer(openPath).append("/").append(entry.getName()).toString()); svn.setAuthor(entry.getAuthor()); svn.setState(svn.getKind() == "file" ? null : "closed"); svns.add(svn); } super.log("获得版本库文件信息"); return svns; } catch (SVNException e) { super.log(e); e.printStackTrace(); return null; } catch (Exception e) { super.log(e); e.printStackTrace(); return null; } } @Override public boolean checkOut(String checkUrl, String savePath) { SVNUpdateClient updateClient = clientManager.getUpdateClient(); updateClient.setIgnoreExternals(false); try { if (savePath == null || savePath.trim().equals("")) throw new Exception(ErrorVal.Path_no_having); else if (checkUrl == null || checkUrl.trim().equals("")) throw new Exception(ErrorVal.Url_no_having); File save = new File(savePath); if (!save.isDirectory()) save.mkdir(); updateClient.doCheckout(SVNURL.parseURIEncoded(checkUrl), save, SVNRevision.HEAD, SVNRevision.HEAD, SVNDepth.INFINITY, false); super.log("检出版本库信息"); return true; } catch (SVNException e) { super.log(e); e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } return false; } /** * 此实现自动对Add后的数据进行提交 */ @Override public <T> boolean add(String[] paths, String message, boolean uLocks, ISvnDbLog<? extends T> isvnLog) { try { File[] files = checkFilePaths(paths); files = sortF_S(files); SVNStatus status; List<File> targetList = new ArrayList<File>(); List<List<File>> fileList = bindFile(files); for (int i = 0; i < fileList.size(); i++) { for (File f : fileList.get(i)) { if ((status = clientManager.getStatusClient().doStatus(f, true, true)) != null && status.getContentsStatus() != SVNStatusType.STATUS_UNVERSIONED && status.getContentsStatus() != (SVNStatusType.STATUS_NONE)) continue; else if (f.isFile()) { clientManager.getWCClient().doAdd(f, true, false, true, SVNDepth.fromRecurse(true), false, false, true); targetList.add(f); super.log("添加文件到提交队列"); } else if (f.isDirectory()) { // SVNDepth.empty 保证不递归文件夹下文件 clientManager.getWCClient().doAdd(f, false, false, false, SVNDepth.EMPTY, false, false, false); targetList.add(f); super.log("添加文件夹到提交队列"); } } } long versionId = commit(targetList.toArray(new File[targetList.size()]), message, uLocks); if (versionId == -1) throw new Exception(ErrorVal.Commit_error); if (!isvnLog.addLog(this.svnAccount, SvnConfig.add, versionId, files)) throw new Exception(ErrorVal.AddDbLog_error); return true; } catch (SVNException e) { super.log(e); e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } return false; } @Override public Long commit(File[] files, String message, boolean uLocks) { try { if (files.length == 0) { super.log("无效的提交信息"); return -1l; } long versionId = clientManager.getCommitClient().doCommit(files, uLocks, message, null, null, false, false, SVNDepth.INFINITY).getNewRevision(); super.log("提交队列中预处理的操作操作 => 版本号: " + versionId); return versionId; } catch (SVNException e) { super.log(e); e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } return -1l; } @Override public <T> boolean delete(String[] paths, boolean localDelete, String message, boolean uLock, ISvnDbLog<? extends T> isvnLog) { try { File[] files = checkFilePaths(paths); files = sortS_F(files); SVNStatus status = null; { List<File> targetList = new ArrayList<File>(); List<List<File>> fileList = bindFile(files); for (int i = fileList.size() - 1; i >= 0; i--) { for (File f : fileList.get(i)) { if ((status = clientManager.getStatusClient().doStatus(f, true, true)) == null) throw new Exception(ErrorVal.File_Repo_no_having); else if (status.getContentsStatus() != SVNStatusType.STATUS_NORMAL) throw new Exception(ErrorVal.Repo_Status_error + status.getContentsStatus().toString()); else { clientManager.getWCClient().doDelete(f, false, localDelete, false); if (f.isFile()) super.log("添加文件到删除队列"); else super.log("添加文件夹到删除队列"); targetList.add(f); } } } long versionId = commit(targetList.toArray(new File[targetList.size()]), message, uLock); if (versionId == -1) throw new Exception(ErrorVal.Commit_error); if (!isvnLog.addLog(this.svnAccount, SvnConfig.delete, versionId, files)) throw new Exception(ErrorVal.AddDbLog_error); } return true; } catch (SVNException e) { super.log(e); e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } return false; } @Override public <T> boolean update(String path, String message, boolean uLocks, ISvnDbLog<? super T> isvnLog) { try { File[] files = checkFilePaths(new String[] { path }); // diffPath(files); long[] l = clientManager.getUpdateClient().doUpdate(files, SVNRevision.HEAD, SVNDepth.INFINITY, true, false); super.log("更新文件到操作队列"); long versionId = l[0];// commit(files, message, uLocks); if (versionId == -1) throw new Exception(ErrorVal.Update_no_change); if (!isvnLog.addLog(this.svnAccount, SvnConfig.update, versionId, files)) throw new Exception(ErrorVal.AddDbLog_error); } catch (SVNException e) { super.log(e); e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } return false; } @Override public List<String> diffPath(File file) { try { if (file == null || !file.exists()) throw new Exception(ErrorVal.Path_no_having); // 获取SVNDiffClient SVNDiffClient diffClient = clientManager.getDiffClient(); diffClient.setIgnoreExternals(false); StringOutputSteam os = new StringOutputSteam(new ArrayList<String>()); diffClient.doDiff(new File[] { file }, SVNRevision.HEAD, SVNRevision.BASE, null, SVNDepth.INFINITY, true, os, null); super.log("比对库路径"); return os.s; } catch (SVNException e) { super.log(e); e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } return null; } @Override public boolean cleanUp(File file) { try { if (!file.exists()) throw new Exception(ErrorVal.Path_no_having); else if (!file.isDirectory()) throw new Exception(ErrorVal.File_is_not_directory); clientManager.getWCClient().doCleanup(file, false, false, false, true, true, true); super.log("清理完成"); } catch (SVNException e) { super.log(e); e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); } return false; } @Override public boolean doLock() { // TODO Auto-generated method stub return false; } @Override public boolean unLock() { // TODO Auto-generated method stub return false; } }
实现代码比较多。不要慌
仔细看看加断点看看
加锁解锁还有一些接口的高级应用并没有深入去写,因为毕竟是demo。上级觉得技术上是可以搞定这个功能的,虽然因为其他原因项目阉割了 :( 所以也没有后续进行深层开发
https://svnkit.com/documentation.html 这个是svnkit 文档,不过文档比svnkit.jar版本要老 :((
关于参数中
ISvnDbLog<? super T> isvnLog
可以让使用者提供一个ISvnDbLog的实现,来进行日志保存,无论是db还是file
最后我们提供一个简单纺织小工厂
package com.svn.factory; import com.svn.conf.ErrorVal; import com.svn.conf.SvnConfig; import com.svn.impl.SvnBaseImpl; import com.svn.inf.ISvn; import com.svn.model.SvnLinkPojo; /** * DemoSvn主体 * * @author Allen * @date 2016年8月8日 */ public final class DemoSvn { SvnLinkPojo svnLink; public SvnLinkPojo getSvnLink() { return svnLink; } /** * 私有构造 */ public DemoSvn() { } public DemoSvn(String svnAccount, String svnPassword, String repoPath) { this.svnLink = new SvnLinkPojo(repoPath, svnAccount, svnPassword); } /** * 获取SVN操作 * * @param val * default 不设置日志状态 log 开启console日志状态 * @throws 没有操作匹配 * @return {@link ISvn} */ public ISvn execute(SvnConfig val) throws Exception { ISvn is = null; if (val == null) throw new Exception(ErrorVal.SvnConfig_is_null); switch (val.getVal()) { case "normal": is = new SvnBaseImpl(svnLink.getSvnAccount(), svnLink.getSvnPassword(), false, svnLink.getRepoPath()); break; case "log": is = new SvnBaseImpl(svnLink.getSvnAccount(), svnLink.getSvnPassword(), true, svnLink.getRepoPath()); break; default: throw new Exception(ErrorVal.SvnConfig_is_null); } return is; } }
来一个测试函数吧
其实创建版本库,操作对象,初始化实例,close都可以做的更简洁,然后做到事务中,切面管理.. :)
package com.svn; import java.io.File; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.Date; import com.svn.conf.SvnConfig; import com.svn.factory.DemoSvn; import com.svn.inf.ISvn; import com.svn.inf.service.ISvnDbLog; import com.svn.model.SvnRepoPojo; /** * 测试类 * * @author Allen * @date 2016年8月8日 */ public class exmple { String account = "allen"; String password = "123456"; String path = "http://192.168.1.xx/svn/abc"; String targetHead = "e:/测试"; ISvn svn; /** * 样例 * * @throws Exception * @author Allen * @date 2016年8月12日 */ private void testCore() throws Exception { // 初始化实例 DemoSvn ts = new DemoSvn(account, password, path); // 获得操作对象 this.svn = ts.execute(SvnConfig.log); // 得到版本库信息 svn.createSVNRepository(); // 得到基础操作对象 svn.createSVNClientManager(); /** 测试--Start-- **/ testGetRepo(); testCheckOut(); testAdd(); testDel(); testCleanUp(); testUpdate(); testDiff(); /** 测试 --End-- **/ // 关闭库容器 svn.closeRepo(); } /** * 获得版本路径文件信息 * * @author Allen * @date 2016年8月12日 */ private void testGetRepo() { print(svn.getRepoCatalog("")); } /** * 检出到本地路径 * * @author Allen * @date 2016年8月12日 */ private void testCheckOut() { svn.checkOut("xxx", targetHead); } /** * 添加文件到svn * * @author Allen * @date 2016年8月12日 */ private void testAdd() { String[] strs = new String[] { targetHead + "/4/a/", targetHead + "/4/", targetHead + "/4/a/b/", targetHead + "/4/a/b/b.txt" }; svn.add(strs, "haha", false, new ISvnDbLog<String>() { @Override public boolean addLog(String name, SvnConfig dbType, long versionId, File[] files) { System.out.println("Add 到 DB 了"); return true; } @Override public List<String> getLog(String name, Date startTime, Date endTime) { System.out.println("get 到 log 了"); return null; } }); } /** * 删除文件到svn * * @author Allen * @date 2016年8月12日 */ private void testDel() { String[] strs = new String[] { targetHead + "/4/a/", targetHead + "/4/", targetHead + "/4/a/b/", targetHead + "/4/a/b/b.txt" }; svn.delete(strs, true, "haha", false, new ISvnDbLog<String>() { @Override public boolean addLog(String name, SvnConfig dbType, long versionId, File[] files) { System.out.println("del 到 DB 了"); return true; } @Override public List<String> getLog(String name, Date startTime, Date endTime) { System.out.println("get 到 log 了"); return null; } }); } /** * 更新文件到svn * * @author Allen * @date 2016年8月12日 */ private void testUpdate() { String strs = targetHead + "/4/a/b/"; svn.update(strs, "哈哈", false, new ISvnDbLog<String>() { @Override public boolean addLog(String name, SvnConfig dbType, long versionId, File[] files) { System.out.println("update 到 DB 了"); return true; } @Override public List<String> getLog(String name, Date startTime, Date endTime) { System.out.println("get 到 log 了"); return null; } }); } /** * 测试库比对 * * @author Allen * @date 2016年8月12日 */ private void testDiff() { String[] strs = new String[] { targetHead + "/4/a/b/" }; List<String> s = svn.diffPath(new File(strs[0])); for (String t : s) System.out.println(t); } private void testCleanUp() { String[] strs = new String[] { targetHead + "/4/a/b/" }; svn.cleanUp(new File(strs[0])); } /** * 打印当前版本库路径目录 */ private void print(List<SvnRepoPojo> paramList) { System.out.print("commitMessage "); System.out.print("\t\t date \t "); System.out.print("\t kind \t "); System.out.print("\t name \t "); System.out.print("\t repositoryRoot \t "); System.out.print("\t revision \t "); System.out.print("\t size \t "); System.out.print("\t url \t "); System.out.print("\t author \t "); System.out.println("\t state \t "); Collections.sort(paramList, new Comparator<SvnRepoPojo>() { @Override public int compare(SvnRepoPojo o1, SvnRepoPojo o2) { return o1.getName().compareTo(o2.getName()); } }); for (SvnRepoPojo pojo : paramList) { System.out.print("\t" + pojo.getCommitMessage() + "\t"); System.out.print("\t" + pojo.getDate().getTime() + "\t"); System.out.print("\t" + pojo.getKind() + "\t"); System.out.print("\t" + pojo.getName() + "\t"); System.out.print("\t" + pojo.getRepositoryRoot() + "\t"); System.out.print("\t" + pojo.getRevision() + "\t"); System.out.print("\t" + pojo.getSize() + "\t"); System.out.print("\t" + pojo.getUrl() + "\t"); System.out.print("\t" + pojo.getAuthor() + "\t"); System.out.print("\t" + pojo.getState() + "\t"); System.out.print("\r\n"); } } public static void main(String[] args) throws Exception { new exmple().testCore(); } }
就这样吧。demo而已看个用法和思路。具体优化及细节也没有时间去做了,毕竟是demo :)
下载地址
http://download.csdn.net/detail/crazyzxljing0621/9755958
相关文章推荐
- Java 调用svnkit实现svn功能
- Java 调用svnkit实现svn功能
- Java 反射学习(四)反射技术开发框架原理简单实现
- Java回顾:用一个Demo来说明继承抽象类和实现接口的简单框架模型
- java Swing框架应用,计算器的设计实现
- JAVA应用XFire框架来实现WebServie的大文件传输功能之一(下载)
- Java远程调用(二)实现一个简单的服务框架
- Java Calendar类简单应用:实现可视化日历
- Java实现局部内部类的简单应用
- struts采用JavaServlet/JSP技术,实现了基于Java EEWeb应用的MVC设计模式的应用框架
- 史上最简单的MultiHashMap的实现(使用JAVA已有的容器框架)
- SVN+ANT实现远程Java WEB应用的更新
- JAVA调用svnkit实现checkout
- java调用svnkit实现svn功能
- [零基础学JAVA]Java SE应用部分-31.Java IO操作(05)IO操作实例讲解之实现简单MIS 推荐
- Java 调用svnkit实现svn功能
- JAVA应用XFire框架来实现WebServie的大文件传输功能之一(下载)
- java简单多线程方式+实现文件上传(spring mvc + jquery.form.js 框架)
- Java小品——简单的JDBC应用实现。
- Dom4j解析XML简单应用,XStream实现Java、XML转换