背景

由于公司会统计每个人每个月提交的代码行数,提交代码次数等信息,本人基于此情况,开发了一个自动化统计小组内代码提交信息的code;自己之前也在网上找了一些相关信息,绝大多数都是采用linux命令统计的方式,我自己试了一下,发现不是特别准,并且信息也不完整;所以自己采用java的JGit框架开发了完整的代码,以下是具体的开发流程;

开发流程

1.建表

CREATE TABLE `git_commit_info2` (`data_dt` date DEFAULT NULL COMMENT '跑数日期',`project_name` varchar(255) DEFAULT '' COMMENT '项目名称',`branch_name` varchar(50) DEFAULT NULL COMMENT '分支名称',`commit_id` varchar(100) NOT NULL COMMENT '提交的id',`commit_name` varchar(50) DEFAULT NULL COMMENT '提交人',`commit_email` varchar(100) DEFAULT NULL COMMENT '提交人的email',`commit_comment` varchar(255) DEFAULT NULL COMMENT '提交备注',`add_lines` int(11) DEFAULT '0' COMMENT '相对于上次提交新增行数',`sub_lines` int(11) DEFAULT '0' COMMENT '相对于上次提交减少行数',`commit_time` timestamp NULL DEFAULT NULL COMMENT '提交时间',`create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '写入时间',`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',PRIMARY KEY (`commit_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='git提交参数信息';

2.代码开发
在代码开发之前,需要提供一些公用的class;
CommitLogInfo类用于记录单次commit的详细信息
CommitLines用于记录单次提交代码新增的行数和删除的行数;

public class CommitLogInfo {// 项目名称public String projectName;// 分支public String branchName;// 提交的commit idpublic String commitID;// 提交的次数public int commitNum;//提交人public String commitUserName;//提交的邮箱public String commitEmail;//提交的备注public String commitComment;//提交时间public Timestamp commitTime;// 新增行数public int addLines;// 删除行数public int subLines;public CommitLogInfo() {}public CommitLogInfo(String commitUserName, String commitEmail, String commitComment, Timestamp commitTime) {this.commitUserName = commitUserName;this.commitEmail = commitEmail;this.commitComment = commitComment;this.commitTime = commitTime;}public int getAddLines() {return addLines;}public void setAddLines(int addLines) {this.addLines = addLines;}public int getSubLines() {return subLines;}public void setSubLines(int subLines) {this.subLines = subLines;}public String getProjectName() {return projectName;}public void setProjectName(String projectName) {this.projectName = projectName;}public String getBranchName() {return branchName;}public void setBranchName(String branchName) {this.branchName = branchName;}public int getCommitNum() {return commitNum;}public void setCommitNum(int commitNum) {this.commitNum = commitNum;}public String getCommitID() {return commitID;}public void setCommitID(String commitID) {this.commitID = commitID;}@Overridepublic String toString() {return "CommitLogInfo{" +"commitUserName='" + commitUserName + '\'' +", commitEmail='" + commitEmail + '\'' +", commitComment='" + commitComment + '\'' +", commitTime=" + commitTime +'}';}public String getCommitUserName() {return commitUserName;}public void setCommitUserName(String commitUserName) {this.commitUserName = commitUserName;}public String getCommitEmail() {return commitEmail;}public void setCommitEmail(String commitEmail) {this.commitEmail = commitEmail;}public String getCommitComment() {return commitComment;}public void setCommitComment(String commitComment) {this.commitComment = commitComment;}public Timestamp getCommitTime() {return commitTime;}public void setCommitTime(Timestamp commitTime) {this.commitTime = commitTime;}
}public class CommitLines{public int addLines;public int subLines;public CommitLines() {}public CommitLines(int addLines, int subLines) {this.addLines = addLines;this.subLines = subLines;}public int getAddLines() {return addLines;}public void setAddLines(int addLines) {this.addLines = addLines;}public int getSubLines() {return subLines;}public void setSubLines(int subLines) {this.subLines = subLines;}
}

具体代码:

public class GitDemo2 {public static void main(String[] args) throws GitAPIException, IOException, SQLException {// 1.获取git操作对象String dir = "xxx";String projectName = dir.substring(dir.lastIndexOf('\\') + 1);Git git  = null;Repository repository = null;try{repository = new FileRepositoryBuilder().setGitDir(Paths.get(dir,".git").toFile()).build();git = new Git(repository);}catch(IOException e){e.printStackTrace();}// 2.执行git pull操作,获取其他人的操作信息git.pull();ArrayList<CommitLogInfo> results = new ArrayList<>();// 3.执行git log查看日志信息,并进行过滤,只查询最近15天的所有的数据LogCommand logCommand = git.log();Iterable<RevCommit> call = logCommand.call();java.util.Date nowDate = new java.util.Date();Calendar calendar = Calendar.getInstance();calendar.setTime(nowDate);calendar.add(Calendar.DAY_OF_MONTH, -15);java.util.Date yesterday = calendar.getTime();Timestamp yesterdayTimestamp = new Timestamp(yesterday.getTime());String branchName = git.getRepository().getBranch();calendar.setTime(nowDate);calendar.add(Calendar.DAY_OF_MONTH, -366);java.util.Date yearTime = calendar.getTime();Timestamp yearTimestamp = new Timestamp(yearTime.getTime());ArrayList<RevCommit> arrayList = new ArrayList<>();for(RevCommit revCommit : call){long commitTime = revCommit.getCommitTime() * 1000L;Timestamp runningTimestamp = new Timestamp(commitTime);//需要添加初始节点,解决第一次处理的问题if(runningTimestamp.compareTo(yearTimestamp) < 0){arrayList.add(revCommit);break;}else{arrayList.add(revCommit);}}int length = arrayList.size();for(int i = 0; i <= length - 2; i++){RevCommit revCommit = arrayList.get(i);RevCommit prevCommit = arrayList.get(i + 1);String commitID = revCommit.getId().toString().split(" ")[1];String commitComment = revCommit.getFullMessage().replaceAll("'","").replaceAll("\n","\t");PersonIdent personIdent = revCommit.getCommitterIdent();String commitName = personIdent.getName();String commitEmail = personIdent.getEmailAddress();long commitTime = revCommit.getCommitTime() * 1000L;Timestamp runningTimestamp = new Timestamp(commitTime);// 只获取15天的数据if(runningTimestamp.compareTo(yesterdayTimestamp) >= 0){// 获取变化的行数CommitLines commitLines = getCommitLines2(git,prevCommit,revCommit,repository);CommitLogInfo commitLogInfo = new CommitLogInfo();commitLogInfo.setProjectName(projectName);commitLogInfo.setBranchName(branchName);commitLogInfo.setCommitID(commitID);commitLogInfo.setCommitUserName(commitName);commitLogInfo.setCommitEmail(commitEmail);commitLogInfo.setCommitComment(commitComment);commitLogInfo.setCommitTime(runningTimestamp);commitLogInfo.setAddLines(commitLines.getAddLines());commitLogInfo.setSubLines(commitLines.getSubLines());results.add(commitLogInfo);}}// 4.mysql写入数据库中InputStream inputStream = new BufferedInputStream(new FileInputStream("src/resources/config.properties"));Properties properties = new Properties();properties.load(inputStream);String username = properties.getProperty("username");String password = properties.getProperty("password");String driverClass = properties.getProperty("driverClass");String url = properties.getProperty("url");Connection connection = JDBCUtils.createConnection(driverClass, url, username, password);String stmtStr = "insert into git_commit_info2(data_dt,project_name,branch_name,commit_id,commit_name,commit_email,commit_comment,add_lines,sub_lines,commit_time) values";long num = 0;int bulkNum = 20;Statement statement = connection.createStatement();for(CommitLogInfo commitLogInfo : results){String sql_val = String.format("(%s,\'%s\',\'%s\',\'%s\',\'%s\',\'%s\',\'%s\',\'%s\',\'%s\',\'%s\'),","current_date",commitLogInfo.getProjectName(),commitLogInfo.getBranchName(),commitLogInfo.getCommitID(), commitLogInfo.getCommitUserName(),commitLogInfo.getCommitEmail(),commitLogInfo.getCommitComment(),commitLogInfo.getAddLines(),commitLogInfo.getSubLines(),commitLogInfo.getCommitTime());stmtStr = stmtStr + sql_val;num = num + 1;if(num % bulkNum == 0 || num == results.size()){stmtStr = stmtStr.substring(0,stmtStr.lastIndexOf(","));stmtStr = stmtStr + " ON DUPLICATE KEY UPDATE update_time=current_timestamp";statement.addBatch(stmtStr);if(num % bulkNum == 0 || num == results.size()){System.out.println(stmtStr);statement.executeBatch();statement.clearBatch();}stmtStr ="insert into git_commit_info2(data_dt,project_name,branch_name,commit_id,commit_name,commit_email,commit_comment,add_lines,sub_lines,commit_time) values";}}}/**** @param git* @param headCommit* @param currentCommit* @param repository* @return* @throws GitAPIException* @throws IOException*/public static CommitLines getCommitLines2(Git git,RevCommit headCommit,RevCommit currentCommit, Repository repository) throws GitAPIException, IOException {List<DiffEntry> diffs = null;AbstractTreeIterator oldTreeIter = prepareTreeParser(repository, headCommit);AbstractTreeIterator newTreeIter = prepareTreeParser(repository, currentCommit);diffs = git.diff().setNewTree(newTreeIter).setOldTree(oldTreeIter).call();ByteArrayOutputStream out = new ByteArrayOutputStream();DiffFormatter df = new DiffFormatter(out);df.setDiffComparator(RawTextComparator.WS_IGNORE_ALL);df.setRepository(repository);
//        int sum = 0;int addLines = 0;int subLines = 0;for(DiffEntry diffEntry: diffs){df.format(diffEntry);String diffText = out.toString("UTF-8");FileHeader fileHeader = df.toFileHeader(diffEntry);List<HunkHeader> hunks = (List<HunkHeader>)fileHeader.getHunks();int addSize = 0;int subSize = 0;for(HunkHeader hunkHeader : hunks){EditList editList = hunkHeader.toEditList();for(Edit edit : editList){subSize = subSize + edit.getEndA() - edit.getBeginA();addSize = addSize + edit.getEndB() - edit.getBeginB();}}out.reset();addLines += addSize;subLines += subSize;}return new CommitLines(addLines, subLines);}public static AbstractTreeIterator prepareTreeParser(Repository repository,RevCommit commit){System.out.println(commit.getId());try (RevWalk walk = new RevWalk(repository)) {System.out.println(commit.getTree().getId());RevTree tree = walk.parseTree(commit.getTree().getId());CanonicalTreeParser oldTreeParser = new CanonicalTreeParser();try (ObjectReader oldReader = repository.newObjectReader()) {oldTreeParser.reset(oldReader, tree.getId());}walk.dispose();return oldTreeParser;}catch (Exception e) {e.printStackTrace();}return null;}
}

注:
(1) 我们在开发过程中,发现获取git log时是按照时间从近到远来的,并且是严格按照时间从近到远来的;因此这边的程序是直接遍历实现的;
(2) 其实代码的整体逻辑不是很复杂,最复杂的是获取commit的行数,在这上面我们花了不少的时间,这边说一下大致的逻辑;在数据库中,我们add_lines和sub_lines列记录的是本次commit,我们添加了多少的行数和删除了多少行;我们的处理逻辑是将本次commit和上次commit进行比较,确定本次提交了多少行数;
(3)我们每个迭代都会建一个分支,该分支是用我们历史创建的null分支来生成的,因为我们采用时间方式找出本迭代第一次commit的信息;当committime和当前时间比超过一年,即认为是初始化的commit;
(4)我们在数据库中记录的是单次提交行数,因此可以采用sql来查询本迭代提交的行数,具体sql如下:

--统计本迭代一共添加了多少行和删除了多少行
select commit_email,sum(add_lines),sum(sub_lines) from git_commit_info2
where project_name='xxx'
and branch_name='xxx'
group by commit_email;--统计本迭代一共有多少天提交了代码
select t1.commit_email,count(1) from (select distinct commit_email,date(commit_time)  from git_commit_info2where project_name='xxx'and branch_name='xxx'
) t1
group by t1.commit_email

利用java操作JGit教程相关推荐

  1. 利用Java操作Office2007成为可能

    利用Java操作Office2007成为可能 之前从来都没有想过使用Java来操作Office,今天在InfoQ中文站上逛悠了一圈,发现了一篇名为<用Java操作Office 2007>的 ...

  2. java操作jedis_Redis教程 —— Java池化JedisPool操作Jedis

    今天再学习一下Redis的池化操作jedis,接着上一篇文章 Redis教程 -- Java操作Redis增删改查(基础操作) 我是用的是jedis2.9版本,池化操作依赖与common-pool2. ...

  3. excel中用java语言_利用 JAVA 操作 EXCEL 文件

    Java Excel 是一开放源码项目,通过它 Java 开发人员可以读取 Excel 文件的内容.创建新的 Excel 文件.更新已经存在的 Excel 文件.使用该 API 非 Windows 操 ...

  4. HBase(2) Java 操作 HBase 教程

    一.简介 在上一篇文章 HBase 基础入门 中,我们已经介绍了 HBase 的一些基本概念,以及如何安装使用的方法. 那么,作为一名 Javaer,自然是希望用 Java 的方式来与 HBase 进 ...

  5. c mysql封装 jdbc_利用Java针对MySql封装的jdbc框架类 JdbcUtils 完整实现

    最近看老罗的视频,跟着完成了利用Java操作MySql数据库的一个框架类JdbcUtils.java,完成对数据库的增删改查.其中查询这块,包括普通的查询和利用反射完成的查询,主要包括以下几个函数接口 ...

  6. 利用Java针对MySql封装的jdbc框架类 JdbcUtils 完整实现(包含增删改查、JavaBean反射原理,附源码)...

    最近看老罗的视频,跟着完成了利用Java操作MySQL数据库的一个框架类JdbcUtils.java,完成对数据库的增删改查.其中查询这块,包括普通的查询和利用反射完成的查询,主要包括以下几个函数接口 ...

  7. mysql封装 javabean,利用Java针对MySql封装的jdbc框架类JdbcUtils完整实现(包含增删改查、JavaBean反射原理,附源码)...

    最近看老罗的视频,跟着完成了利用Java操作MySql数据库的一个框架类JdbcUtils.java,完成对数据库的增删改查.其中查询这块,包括普通的查询和利用反射完成的查询,主要包括以下几个函数接口 ...

  8. java mysql jdbc 封装_利用Java针对MySql封装的jdbc框架类 JdbcUtils 完整实现(包括增删改查、JavaBean反射原理,附源代码)...

    近期看老罗的视频,跟着完毕了利用Java操作MySql数据库的一个框架类JdbcUtils.java,完毕对数据库的增删改查.当中查询这块,包含普通的查询和利用反射完毕的查询,主要包含以下几个函数接口 ...

  9. java excel 边框_【web开发】☆★之利用POI操作Excel表格系列教程【9】单元格边框处理...

    [web开发]☆★之利用POI操作Excel表格系列教程[9]单元格边框处理 package csg.xiaoye.poidemo; import java.io.FileOutputStream; ...

最新文章

  1. ​2018深度学习引用数最高的十大论文
  2. mysql数据库-主主配置
  3. flutter 人脸检测_【转载】opencv实现人脸检测
  4. Vue 项目实现按钮级别权限管理
  5. 【转摘】Word中查找与替换的妙用
  6. 五十、微信小程序云开发中的云数据库
  7. rs232读取智能电表_没想到物联网电表这么智能!插卡预付费电表该升级了!
  8. 【图】IPAVS多媒体网络×××
  9. 无限循环小数转化为分数形式
  10. 考研失败了,该何去何从?
  11. ABBYY FineReader 12PDF选项卡之图像及文字设置
  12. Python用正则表达式匹配ABAC和AABB的词语
  13. python re —— 自然语言处理与正则表达式
  14. P4171 [JSOI2010]满汉全席
  15. SQL本地事务、asp.net事务、DTC
  16. Base64原理和转换会变大33%左右的原因
  17. ArcGIS软件操作问题及解决方法总结
  18. 第11期-通过斗鱼直播爬取弹幕
  19. 7-1 输出n个数 (10 分)
  20. android电视安全模式,电视安全模式怎么解除

热门文章

  1. JUC系列之CyclicBarrier详解
  2. 人工智能Java SDK:kafka-情感倾向分析【英文】
  3. 腾讯子公司自动化测试三轮面试经历,希望对你有所帮助
  4. 在英特尔做了一年 AI 研发,真的很香
  5. citycode映射表(2018)
  6. 如何升级至HTTPS
  7. C++实现自适应二值化
  8. linux安装DM7数据库和初始化实例--无图形界面
  9. 研一小白记录第一次在实验室服务器上跑深度学习的代码全过程(实验室服务器上跑代码详细全过程哦)
  10. CS162操作系统课程第二课-4个核心OS概念