最近项目中需要对SVN进行一些操作,因而使用到了SVNKit。本文主要对使用到的High Level API和Low Level API进行一些介绍。

High Level API

Through SVNClientManager class you get access to a number of interfaces that allow you to perform virtually everything that a Subversion user may need. This includes but not limited to checking out, updating, committing, getting history, differences and browsing repository. API is easy to use and at the same time is fine grained, thus it provides high level of customization if needed. Take a look at the sample code.

通过SVNClientManager,用户可以获取到一系列接口去操作svn,包括但不限于检出、更新、提交、获取历史版本、比较差异、浏览等。

接口名 SVN命令
SVNAdminClient svnadmin svnsync
SVNChangelistClient changelist
SVNCommitClient commit import delete mkdir
SVNCopyClient copy move
SVNDiffClient diff merge mergeinfo
SVNLogClient log list blame
SVNLookClient look
SVNMoveClient move
SVNStatusClient status
SVNUpdateClient update checkout switch export
SVNWCClient add delete cleanup cat info lock unclock revert resolved propset propedit propdel propget proplist

示例代码SVNUtil.java

/**
 * SVNKIT工具类
 * @author Adlun Zhan
 */
public class SVNUtil {

    private static Logger logger = TraceLoggerFactory.getLogger(SVNUtil.class);

    private SVNClientManager ourClientManager = null;

    private String userName = null;// 用户名
    private String passwd = null;// 密码

    private void init(String userName, String passwd) {
        SVNRepositoryFactoryImpl.setup();
        DAVRepositoryFactory.setup();
        FSRepositoryFactory.setup();
        ISVNOptions options = SVNWCUtil.createDefaultOptions(true);
        this.ourClientManager = SVNClientManager.newInstance(
                (DefaultSVNOptions) options, userName, passwd);
    }

    public SVNUtil(String userName, String passwd) {
        this.userName = userName;
        this.passwd = passwd;
        init(this.userName, this.passwd);
    }

    /**
     * 创建分支
     * 
     * @param comment
     * @param srcpath
     * @param despath
     */
    public void createBranch(String srcBranchPath, String desBranchPath,
            String comment){
        try {
            SVNURL srcURL = SVNURL.parseURIEncoded(srcBranchPath); // trunk地址
            SVNURL dstURL = SVNURL.parseURIEncoded(desBranchPath); // branch地址
            SVNCopySource copySource = new SVNCopySource(SVNRevision.HEAD,
                    SVNRevision.HEAD, srcURL);
            // 创建分支
            SVNCopyClient copyClient = ourClientManager.getCopyClient();
            logger.info("正在创建" + desBranchPath);
            copyClient.doCopy(new SVNCopySource[] { copySource }, dstURL,
                    false, // isMove
                    false, // make parents
                    true, // failWhenDstExists
                    comment, // commit message
                    null); // SVNProperties
            logger.info("创建成功");
        } catch (SVNException e) {
            logger.error("创建" + desBranchPath + e.toString());
            throw new DevOpsException("SVNKITException", "创建分支失败", new String[]{"from"+srcBranchPath+"to"+desBranchPath});
        }
    }

    /**
     * svn merge
     * 
     * @param srcBranchPath
     * @param desBranchPath
     */
    public void merge(String srcBranchPath, String desBranchPath) {
        try {
            // checkout分支到本地
            SVNURL srcURL = SVNURL.parseURIEncoded(srcBranchPath); // trunk地址
            SVNURL dstURL = SVNURL.parseURIEncoded(desBranchPath); // branch地址
            String localpath = System.getProperty("user.dir") + File.separator
                    + UUID.randomUUID().toString();
            final File destPath = new File(localpath);
            System.out.println(localpath);
            if (!destPath.exists()) {
                destPath.mkdirs();
            }
            SVNUpdateClient updateClient = ourClientManager.getUpdateClient();
            updateClient.doCheckout(dstURL, destPath, SVNRevision.HEAD,
                    SVNRevision.HEAD, SVNDepth.INFINITY, false);
            logger.info("检出" + desBranchPath + "到" + localpath);
            // 获取SVNDiffClient
            SVNDiffClient diffClient = ourClientManager.getDiffClient();
            // 合并branch到本地trunk
            diffClient = ourClientManager.getDiffClient();
            SVNRevisionRange rangeToMerge = new SVNRevisionRange(
                    SVNRevision.create(1), SVNRevision.HEAD);
            diffClient.doMerge(dstURL, SVNRevision.HEAD, srcURL,
                    SVNRevision.HEAD, destPath, SVNDepth.INFINITY, false, true,
                    false, false); // dryRun
            logger.info("合并" + srcBranchPath + "到" + localpath);
            // commit
            ourClientManager.getCommitClient().doCommit(
                    new File[] { destPath }, true, // keepLocks,
                    "update", // commitMessage,
                    null, null, false, false, SVNDepth.fromRecurse(true));
            logger.info("合并到SVN成功");
            logger.info("删除本地working copy:"+destPath);
            // 删除本地
            new Thread() {
                @Override
                public void run() {
                    FileUtil.deleteFile(destPath);
                }
            }.start();
        } catch (SVNException e) {
            e.printStackTrace();
        }

    }

    /**
     * 验证分支是否存在
     * 
     * @param username
     * @param password
     * @param branchpath
     * @return
     */
    @SuppressWarnings("deprecation")
    public boolean isBranchExists(String branchpath) {
        boolean exists = false;
        try {
            SVNRepository repository = SVNRepositoryFactoryImpl.create(SVNURL
                    .parseURIEncoded(branchpath));
            ISVNAuthenticationManager authManager = SVNWCUtil
                    .createDefaultAuthenticationManager(this.userName,
                            this.passwd);
            repository.setAuthenticationManager(authManager);
            String root = repository.getRepositoryRoot().toString();
            // 检查路径是否存在,NONE,FILE,DIR,UNKNOWN
            SVNNodeKind node = repository.checkPath(
                    branchpath.replace(root, ""), repository.INVALID_REVISION);
            if (!SVNNodeKind.NONE.equals(node)) {
                exists = true;
                logger.info(branchpath + "存在,类型为" + node.toString());
            } else {
                logger.info(branchpath + "不存在");
            }
        } catch (SVNException e) {
            logger.error(e.toString());
        }
        return exists;
    }

    /**
     * 比较分支差异
     * 
     * @param userName
     * @param passwd
     * @param trunkpath
     * @param branchpath
     * @return
     */
    public String getDifference(String srcBranchPath, String desBranchPath) {
        final StringBuilder a = new StringBuilder();
        try {
            // checkout主分支到本地
            SVNURL srcURL = SVNURL.parseURIEncoded(srcBranchPath); // trunk地址
            SVNURL dstURL = SVNURL.parseURIEncoded(desBranchPath); // branch地址
            // diff
            // 获取SVNDiffClient
            SVNDiffClient diffClient = ourClientManager.getDiffClient();
            diffClient.doDiffStatus(dstURL, SVNRevision.HEAD, srcURL,
                    SVNRevision.HEAD, SVNDepth.INFINITY, false,
                    new ISVNDiffStatusHandler() {
                        public void handleDiffStatus(SVNDiffStatus status)
                                throws SVNException {
                            a.append(status.getPath() + "   "
                                    + status.getModificationType() + "\r\n");
                        }
                    });
        } catch (SVNException e) {
            e.printStackTrace();
        }
        return a.toString();
    }

    /**
     * 删除分支
     * 
     * @param userName
     * @param passwd
     * @param url
     * @param msg
     */
    public void deleteBranch(String url, String msg) {
        try {
            SVNURL srcURL = SVNURL.parseURIEncoded(url); // 地址
            SVNCommitClient commitClient = ourClientManager.getCommitClient();
            commitClient.doDelete(new SVNURL[] { srcURL }, msg);
        } catch (SVNException e) {
            e.printStackTrace();
        }
    }

    /**
     * 列出url路径下一级文件
     * 
     * @param url
     * @throws SVNException
     */
    public List<String> getFiles(String url) throws SVNException {
        SVNURL srcURL = SVNURL.parseURIEncoded(url); // svn地址
        final List list = new LinkedList<String>();
        SVNLogClient logClient = ourClientManager.getLogClient();
        logClient.doList(srcURL, SVNRevision.HEAD, SVNRevision.HEAD, false,
                false, new ISVNDirEntryHandler() {
                    public void handleDirEntry(SVNDirEntry entry)
                            throws SVNException {
                        if (entry.getName() != null
                                && !entry.getName().equals("")) {
                            list.add(entry.getName());
                        }
                    }
                });
        return list;
    }

    /**
     * 验证用户名密码
     * 
     * @param url
     * @return
     */
    public boolean validateAccount(String url) {
        boolean result = true;
        SVNRepository repository;
        try {
            repository = SVNRepositoryFactoryImpl.create(SVNURL
                    .parseURIEncoded(url));
            ISVNAuthenticationManager authManager = SVNWCUtil
                    .createDefaultAuthenticationManager(this.userName,
                            this.passwd);
            repository.setAuthenticationManager(authManager);
            repository.getDir("trunk", -1, null, (Collection) null);
        } catch (SVNException e) {
            result = false;
        }

        return result;
    }

    /**
     * 获取revision
     * 
     * @param url
     * @return
     */
    public String getRevision(String url) {
        long revision = 0;
        try {
            SVNURL srcURL = SVNURL.parseURIEncoded(url);
            SVNWCClient wc = ourClientManager.getWCClient();
            revision = wc.doGetRevisionProperty(srcURL, null, SVNRevision.HEAD,
                    null);
        } catch (SVNException e) {
            logger.error(e);
        }
        return revision + "";
    }
}

注意事项

发表评论

电子邮件地址不会被公开。 必填项已用*标注