SVN(Subvision)版本管理器,大家应该都熟悉,在公司参与项目都会用到这个软件,于是,自己试着用java代码调用SVN,但是代码不多,能学习的就一点,写的最好的恐怕是czw1029612他的博客了,写得很好,但是代码还是不全,Servlet和JSP文件等。他的地址:http://blog.csdn.net/czw1029612/article/details/6086689,自己还是愚笨,不能参悟透,先从点滴开始学吧,于是找来网上的SVNKit快速开发手册,http://wenku.baidu.com/link?url=VJilfz0IJ6CVg_nr_ixYYF5SiPa9QAu0ApRa1MUaq63GSlVv24MnfEmhHDlCrADFS9HJVg_4o297KEpAnPvZbrqvjRreasvaoXhYCrPWWj_
第一步当然是引入需要的jar包。
自己试试写一写调用的过程结果发现Caused by: org.tmatesoft.sqljet.core.SqlJetException: BUSY: error code is BUSY这个错误,
org.tmatesoft.svn.core.SVNException: svn: E200030: SQLite error
我的代码:
public class SVNDemo { /* * 第二步: * 声明客户端管理类SVNClientManager */ private static SVNClientManager ourClientManager; private static void setupLibrary() { // 对于使用http://和https:// DAVRepositoryFactory.setup(); //对于使用svn:/ /和svn+xxx:/ / SVNRepositoryFactoryImpl.setup(); //对于使用file:// FSRepositoryFactory.setup(); } public static void main(String[] args) { /* * 第三步 * 对版本库进行初始化操作(在用版本库进行其它操作前,必须进行初始化) * 对于通过使用http://和https://访问,执行DAVRepositoryFactory.setup() * 对于通过使用svn://和svn+xxx://访问,执行SVNRepositoryFactoryImpl.setup() * 对于通过使用file://访问,执行FSRepositoryFactory.setup(); * 本程序框架用https://来访问 */ setupLibrary(); /* * 第四步 * 要访问版本库的相关变量设置 */ //版本库的URL地址 SVNURL repositoryURL = null; try { repositoryURL = SVNURL.parseURIEncoded("https://xxxx"); } catch (SVNException e) { e.printStackTrace(); } //版本库的用户名 String name = "XXXX"; String password = "XXXX"; //工作副本目录 String myWorkingCopyPath="D:/MyWorkingCopy"; //驱动选项 ISVNOptions options = SVNWCUtil.createDefaultOptions(true); /* * 第五步 * 创建SVNClientManager的实例。提供认证信息(用户名和密码) * 和驱动选项 */ ourClientManager = SVNClientManager.newInstance((DefaultSVNOptions)options,name,password); /* * 第六步: * 通过SVNClientManager的实例获得要进行操作的client实例(如 * SVNUpdateClient) * 通过client实例来执行相关的操作。 * 此框架以checkout操作进行说明,其它操作类似 */ /* * 工作副本目录创建 */ File wcDir = new File(myWorkingCopyPath); if(wcDir.exists()){ System.out.println("the destination directory '"+wcDir.getAbsolutePath()+"' already exists!"); }else{ wcDir.mkdirs(); } /* * 递归的把工作副本从repositoryURL check out 到wcDir目录 * SVNRevision.HEAD意味着把最新的版本checked out出来 */ SVNUpdateClient updateClient = ourClientManager.getUpdateClient(); updateClient.setIgnoreExternals(false); try { updateClient.doCheckout(repositoryURL, wcDir, SVNRevision.HEAD, SVNRevision.HEAD, SVNDepth.INFINITY,true); } catch (SVNException e) { e.printStackTrace(); } } }
谷歌之,才发现是同步问题。地址:http://issues.tmatesoft.com/issue/SVNKIT-317
然后查看源码,可以看到这句:
/* * If the btree is already in a write-transaction, or it is already * in a read-transaction and a read-transaction is requested, this * is a no-op. */
do { try { if (pBt.pPage1 == null) { do { lockBtree(); } while (pBt.pPage1 == null); } if (mode != SqlJetTransactionMode.READ_ONLY) { if (pBt.readOnly) { throw new SqlJetException(SqlJetErrorCode.READONLY); } else { pBt.pPager.begin(mode == SqlJetTransactionMode.EXCLUSIVE); newDatabase(); } } if (mode != SqlJetTransactionMode.READ_ONLY) pBt.inStmt = false; } catch (SqlJetException e) { rc = e; pBt.unlockBtreeIfUnused(); } } while (rc != null && rc.getErrorCode() == SqlJetErrorCode.BUSY && pBt.inTransaction == TransMode.NONE && invokeBusyHandler(nBusy) && (nBusy++) > -1);
For Subversion case, it means that all write operations, if they meet any concurrent access, will fail
对于它的理解不深,只能理解为这个目录树已经在写的业务中,或者它已经在一个读的业务中,且读的操作正在被请求,也就是我本地有的该目录,绿色箭头标记的,就是该业务一直在读和写。
国内,对于这个错误解释很少或者基本没有,这个是因为存在并发访问的原因,我在本地已经Checked out 该目录,再另外建目录导出,就会出现这个问题。
当然可以选择另外一个盘符进行导出操作,这种操作是不带绿色箭头的,即无法和资源库保持同步,但实现了检出功能。这样也就解决了那个错误,记录一下继续下面的学习。
理解不深,有很多错误的地方还请见谅,毕竟还是菜鸟水准。
学着czw1029612的方法做了一次,算是大体完成了功能,就差历史版本和下载功能没实现。正在持续进行。日期格式正修改,这个问题不大。