使用svnkit对svn新增代码统计、代码查询
来源:互联网 发布:ios越狱mac版 编辑:程序博客网 时间:2024/05/19 02:21
引入包:svnkit
https://mvnrepository.com/artifact/org.tmatesoft.svnkit/svnkit
<!-- https://mvnrepository.com/artifact/org.tmatesoft.svnkit/svnkit -->
<dependency>
<groupId>org.tmatesoft.svnkit</groupId>
<artifactId>svnkit</artifactId>
<version>1.8.14</version>
</dependency>
代码demo
package com.yy.svn;import java.io.BufferedReader;import java.io.ByteArrayOutputStream;import java.io.File;import java.io.FileOutputStream;import java.io.FileReader;import java.io.IOException;import java.io.OutputStream;import java.nio.charset.Charset;import java.util.ArrayList;import java.util.Collection;import java.util.Date;import java.util.List;import java.util.Map;import java.util.Random;import java.util.Set;import org.tmatesoft.svn.core.ISVNLogEntryHandler;import org.tmatesoft.svn.core.SVNDirEntry;import org.tmatesoft.svn.core.SVNException;import org.tmatesoft.svn.core.SVNLogEntry;import org.tmatesoft.svn.core.SVNLogEntryPath;import org.tmatesoft.svn.core.SVNNodeKind;import org.tmatesoft.svn.core.SVNProperties;import org.tmatesoft.svn.core.SVNURL;import org.tmatesoft.svn.core.auth.ISVNAuthenticationManager;import org.tmatesoft.svn.core.internal.wc.DefaultSVNOptions;import org.tmatesoft.svn.core.io.SVNRepository;import org.tmatesoft.svn.core.io.SVNRepositoryFactory;import org.tmatesoft.svn.core.wc.SVNDiffClient;import org.tmatesoft.svn.core.wc.SVNLogClient;import org.tmatesoft.svn.core.wc.SVNRevision;import org.tmatesoft.svn.core.wc.SVNWCUtil;public class SvnkitDemo {private String userName = "user";private String password = "password";private String urlString = "svn url";boolean readonly = true;private String tempDir = System.getProperty("java.io.tmpdir");private DefaultSVNOptions options = SVNWCUtil.createDefaultOptions( readonly );private Random random = new Random();private SVNRepository repos;private ISVNAuthenticationManager authManager;public SvnkitDemo() {try {init();} catch (SVNException e) {// TODO Auto-generated catch blocke.printStackTrace();}}public void init() throws SVNException{ISVNAuthenticationManager authManager = SVNWCUtil.createDefaultAuthenticationManager(new File(tempDir+"/auth"), userName, password.toCharArray());options.setDiffCommand("-x -w");repos = SVNRepositoryFactory.create(SVNURL .parseURIEncoded(urlString));repos.setAuthenticationManager(authManager);System.out.println("init completed");}/**获取一段时间内,所有的commit记录 * @param st开始时间 * @param et结束时间 * @return * @throws SVNException */public SVNLogEntry[] getLogByTime(Date st, Date et) throws SVNException{long startRevision = repos.getDatedRevision(st); long endRevision = repos.getDatedRevision(et); @SuppressWarnings("unchecked")Collection<SVNLogEntry> logEntries = repos.log(new String[]{""}, null, startRevision, endRevision, true, true); SVNLogEntry[] svnLogEntries = logEntries.toArray(new SVNLogEntry[0]); return svnLogEntries;}/**获取版本比较日志,并存入临时文件 * @param startVersion * @param endVersion * @return * @throws SVNException * @throws IOException */public File getChangeLog(long startVersion, long endVersion) throws SVNException, IOException{SVNDiffClient diffClient = new SVNDiffClient(authManager, options);diffClient.setGitDiffFormat(true);File tempLogFile = null;OutputStream outputStream = null; String svnDiffFile = null; do { svnDiffFile = tempDir + "/svn_diff_file_"+startVersion+"_"+endVersion+"_"+random.nextInt(10000)+".txt"; tempLogFile = new File(svnDiffFile);} while (tempLogFile != null && tempLogFile.exists()); try { tempLogFile.createNewFile(); outputStream = new FileOutputStream(svnDiffFile);diffClient.doDiff(SVNURL.parseURIEncoded(urlString), SVNRevision.create(startVersion), SVNURL.parseURIEncoded(urlString), SVNRevision.create(endVersion), org.tmatesoft.svn.core.SVNDepth.UNKNOWN, true, outputStream);} catch (Exception e) {e.printStackTrace();}finally {if(outputStream!=null)try {outputStream.close();} catch (IOException e) {e.printStackTrace();}} return tempLogFile;}/**分析变更的代码,统计代码增量 * @param file * @return * @throws Exception */ public int staticticsCodeAdd(File file) throws Exception{ System.out.println("开始统计修改代码行数"); FileReader fileReader = new FileReader(file);BufferedReader in = new BufferedReader(fileReader);int sum = 0;String line = null;StringBuffer buffer = new StringBuffer(1024);boolean start = false;while((line=in.readLine()) != null){if(line.startsWith("Index:")){if(start){ChangeFile changeFile = parseChangeFile(buffer);int oneSize = staticOneFileChange(changeFile);System.out.println("filePath="+changeFile.getFilePath()+" changeType="+changeFile.getChangeType()+" addLines="+oneSize);sum += oneSize;buffer.setLength(0);}start = true;}buffer.append(line).append('\n');}if(buffer.length() > 0){ChangeFile changeFile = parseChangeFile(buffer);int oneSize = staticOneFileChange(changeFile);System.out.println("filePath="+changeFile.getFilePath()+" changeType="+changeFile.getChangeType()+" addLines="+oneSize);sum += oneSize;}in.close();fileReader.close();boolean deleteFile = file.delete();System.out.println("-----delete file-----"+deleteFile);return sum;} /**统计单个文件的增加行数,(先通过过滤器,如文件后缀、文件路径等等),也可根据修改类型来统计等,这里只统计增加或者修改的文件 * @param changeFile * @return */ public int staticOneFileChange(ChangeFile changeFile){ char changeType = changeFile.getChangeType(); if(changeType == 'A'){ return countAddLine(changeFile.getFileContent()); }else if(changeType == 'M'){return countAddLine(changeFile.getFileContent());} return 0; }/**解析单个文件变更日志 * @param str * @return */public ChangeFile parseChangeFile(StringBuffer str){int index = str.indexOf("\n@@");if(index > 0){String header = str.substring(0, index);String[] headers = header.split("\n");String filePath = headers[0].substring(7);char changeType = 'U';boolean oldExist = !headers[2].endsWith("(nonexistent)");boolean newExist = !headers[3].endsWith("(nonexistent)");if(oldExist && !newExist){changeType = 'D';}else if(!oldExist && newExist){changeType = 'A';}else if(oldExist && newExist){changeType = 'M';}int bodyIndex = str.indexOf("@@\n")+3;String body = str.substring(bodyIndex);ChangeFile changeFile = new ChangeFile(filePath, changeType, body);return changeFile;}else{String[] headers = str.toString().split("\n");String filePath = headers[0].substring(7);ChangeFile changeFile = new ChangeFile(filePath, 'U', null);return changeFile;}}/**通过比较日志,统计以+号开头的非空行 * @param content * @return */public int countAddLine(String content){int sum = 0;if(content !=null){content = '\n' + content +'\n';char[] chars = content.toCharArray();int len = chars.length;//判断当前行是否以+号开头boolean startPlus = false;//判断当前行,是否为空行(忽略第一个字符为加号)boolean notSpace = false;for(int i=0;i<len;i++){char ch = chars[i];if(ch =='\n'){//当当前行是+号开头,同时其它字符都不为空,则行数+1if(startPlus && notSpace){sum++;notSpace = false;}//为下一行做准备,判断下一行是否以+头if(i < len-1 && chars[i+1] == '+'){startPlus = true;//跳过下一个字符判断,因为已经判断了i++;}else{startPlus = false;}}else if(startPlus && ch > ' '){//如果当前行以+开头才进行非空行判断notSpace = true;}}}return sum;}/**统计一段时间内代码增加量 * @param st * @param et * @return * @throws Exception */public int staticticsCodeAddByTime(Date st, Date et) throws Exception{int sum = 0;SVNLogEntry[] logs = getLogByTime(st, et);if(logs.length > 0){long lastVersion = logs[0].getRevision()-1;for(SVNLogEntry log:logs){File logFile = getChangeLog(lastVersion, log.getRevision());int addSize = staticticsCodeAdd(logFile);sum+=addSize;lastVersion = log.getRevision();}}return sum;}/**获取某一版本有变动的文件路径 * @param version * @return * @throws SVNException */public List<SVNLogEntryPath> getChangeFileList(long version) throws SVNException{List<SVNLogEntryPath> result = new ArrayList<>();SVNLogClient logClient = new SVNLogClient( authManager, options );SVNURL url = SVNURL.parseURIEncoded(urlString);String[] paths = { "." };SVNRevision pegRevision = SVNRevision.create( version ); SVNRevision startRevision = SVNRevision.create( version ); SVNRevision endRevision = SVNRevision.create( version );boolean stopOnCopy = false; boolean discoverChangedPaths = true; long limit = 9999l;ISVNLogEntryHandler handler = new ISVNLogEntryHandler() { /** * This method will process when doLog() is done */ @Override public void handleLogEntry( SVNLogEntry logEntry ) throws SVNException { System.out.println( "Author: " + logEntry.getAuthor() ); System.out.println( "Date: " + logEntry.getDate() ); System.out.println( "Message: " + logEntry.getMessage() ); System.out.println( "Revision: " + logEntry.getRevision() ); System.out.println("-------------------------"); Map<String, SVNLogEntryPath> maps = logEntry.getChangedPaths(); Set<Map.Entry<String, SVNLogEntryPath>> entries = maps.entrySet(); for(Map.Entry<String, SVNLogEntryPath> entry : entries){ //System.out.println(entry.getKey()); SVNLogEntryPath entryPath = entry.getValue(); result.add(entryPath); System.out.println(entryPath.getType()+" "+entryPath.getPath()); } } }; // Do log try { logClient.doLog( url, paths, pegRevision, startRevision, endRevision, stopOnCopy, discoverChangedPaths, limit, handler ); } catch ( SVNException e ) { System.out.println( "Error in doLog() " ); e.printStackTrace(); } return result;}/**获取指定文件内容 * @param urlsvn地址 * @return */public String checkoutFileToString(String url){//"", -1, null try { SVNDirEntry entry = repos.getDir("", -1, false, null); int size = (int)entry.getSize(); ByteArrayOutputStream outputStream = new ByteArrayOutputStream(size); SVNProperties properties = new SVNProperties(); repos.getFile("", -1, properties, outputStream); String doc = new String(outputStream.toByteArray(),Charset.forName("utf-8")); return doc; } catch (SVNException e) { e.printStackTrace(); } return null; }/**列出指定SVN 地址目录下的子目录 * @param url * @return * @throws SVNException */ public List<SVNDirEntry> listFolder(String url){ if(checkPath(url)==1){ try { Collection<SVNDirEntry> list = repos.getDir("", -1, null, (List<SVNDirEntry>)null); List<SVNDirEntry> dirs = new ArrayList<SVNDirEntry>(list.size()); dirs.addAll(list); return dirs; } catch (SVNException e) { e.printStackTrace(); } } return null; } /**检查路径是否存在 * @param url * @return 1:存在 0:不存在 -1:出错 */ public int checkPath(String url){ SVNNodeKind nodeKind; try { nodeKind = repos.checkPath("", -1); boolean result = nodeKind == SVNNodeKind.NONE ? false : true; if(result) return 1; } catch (SVNException e) { e.printStackTrace(); return -1; } return 0; }public static void main(String[] args) {SvnkitDemo demo = new SvnkitDemo();Date now = new Date();Date twoDayAgo = new Date(now.getTime()-2*24*3600000);try {//int sum = demo.staticticsCodeAddByTime(now, twoDayAgo);//System.out.println("sum="+sum);demo.getChangeFileList(487837L);} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}}}class ChangeFile {private String filePath;private String fileType;/**A表示增加文件,M表示修改文件,D表示删除文件,U表示末知 * */private Character changeType;private String fileContent;public ChangeFile() {}public ChangeFile(String filePath) {this.filePath = filePath;this.fileType = getFileTypeFromPath(filePath);}public ChangeFile(String filePath, Character changeType, String fileContent) {this.filePath = filePath;this.changeType = changeType;this.fileContent = fileContent;this.fileType = getFileTypeFromPath(filePath);}public String getFilePath() {return filePath;}public void setFilePath(String filePath) {this.filePath = filePath;}public String getFileType() {return fileType;}public void setFileType(String fileType) {this.fileType = fileType;}public Character getChangeType() {return changeType;}public void setChangeType(Character changeType) {this.changeType = changeType;}public String getFileContent() {return fileContent;}public void setFileContent(String fileContent) {this.fileContent = fileContent;} private static String getFileTypeFromPath(String path) { String FileType = ""; int idx = path.lastIndexOf("."); if (idx > -1) { FileType = path.substring(idx + 1).trim().toLowerCase(); } return FileType; }}
0 0
- 使用svnkit对svn新增代码统计、代码查询
- 使用项目管理工具对Svn代码查看和统计
- 基于SVNkit的项目代码贡献量统计
- 使用statsvn统计svn中的代码量
- 使用statsvn统计svn代码量方法
- SVN代码行数统计
- svn 代码统计方案
- svn有效代码统计
- svn统计代码行数
- Svn代码统计
- SVNKIT一段代码的分析
- SVN代码统计工具statsvn
- StatSvn 统计SVN代码信息
- svn代码量统计工具
- StatSvn 统计SVN代码信息
- SVN代码统计工具statsvn
- SVN代码提交数量统计
- SVN代码统计工具statsvn
- GridView的使用
- 使用VNC连接远程服务器
- 响铃:迎风而起的布料B2B平台,谁才是决定生死的命脉?
- React 初步学习(一)
- 开始尝试用C++写算法
- 使用svnkit对svn新增代码统计、代码查询
- 亲自动手制作来自MyBatis-Spring官网的chm格式帮助文件
- 关于TbSchedule任务调度管理框架的整合部署
- 阿里的 com.alibaba.fastjson的日常使用
- View的dispatchTouchEvent总结
- 使用adb shell dumpsys检测Android的Activity任务栈
- 详解Swift中enum类型的用法
- 照片的选择+照片Gridview展示(拖拽排序、删除)+照片viewpager演示(放大、缩小)
- LaTex数学符号公式