Created
March 2, 2022 08:25
-
-
Save HydrangeaPurple/288bf45205a84931b85468687e907e27 to your computer and use it in GitHub Desktop.
svn统级一段时间内提交的代码行数
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.example.demo; | |
import java.io.BufferedOutputStream; | |
import java.io.BufferedReader; | |
import java.io.FileNotFoundException; | |
import java.io.FileOutputStream; | |
import java.io.FileReader; | |
import java.io.IOException; | |
import java.text.ParseException; | |
import java.text.SimpleDateFormat; | |
import java.util.ArrayList; | |
import java.util.Date; | |
import java.util.HashMap; | |
import java.util.HashSet; | |
import java.util.List; | |
import java.util.Map; | |
import java.util.Set; | |
import org.tmatesoft.svn.core.ISVNLogEntryHandler; | |
import org.tmatesoft.svn.core.SVNDepth; | |
import org.tmatesoft.svn.core.SVNException; | |
import org.tmatesoft.svn.core.SVNLogEntry; | |
import org.tmatesoft.svn.core.SVNURL; | |
import org.tmatesoft.svn.core.internal.wc.DefaultSVNOptions; | |
import org.tmatesoft.svn.core.wc.ISVNOptions; | |
import org.tmatesoft.svn.core.wc.SVNClientManager; | |
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 SVNContributionCounter { | |
static String SVN_URL = "http://ip:port/path"; | |
static String USER_NAME = "username"; | |
static String PASSWORD = "password"; | |
static String START_DATA = "2022-01-01"; | |
static String END_DATA = "2022-02-01"; | |
// implementation group: 'org.tmatesoft.svnkit', name: 'svnkit', version: '1.10.4' | |
public static void main(String[] args) { | |
SVNContributionCounter counter = new SVNContributionCounter(); | |
String diffFile = System.getProperty("java.io.tmpdir")+"different.txt"; //temporary file to save line differences between two revisions, it can be set to arbitrary directory in your disk | |
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd"); | |
Date start = null; | |
Date end = null; | |
try { | |
start = format.parse(START_DATA); | |
end = format.parse(END_DATA); | |
} catch (ParseException e) { | |
e.printStackTrace(); | |
} | |
List<SVNCommittedResult> resList = counter.getCountResult(SVN_URL, USER_NAME, PASSWORD, start, end, diffFile); | |
for (SVNCommittedResult res : resList) { | |
System.out.println("Author " + res.getAuthor() + " has changed " + res.getTotalCount()+ " lines by " + res.getDate()); | |
} | |
int totalCount = 0; | |
for (SVNCommittedResult res : resList) { | |
totalCount += res.getTotalCount(); | |
} | |
System.out.println("Total Count " + totalCount); | |
} | |
/* | |
* Count modified lines between adjacent revisions in SVNLogEntry list for a specified period, and sum up the add\delete\total count to each author. | |
*/ | |
public List<SVNCommittedResult> getCountResult(String svnUrl, String username, String password, final Date start, | |
final Date end, String diffFile) { | |
List<SVNCommittedResult> resultList = new ArrayList<SVNCommittedResult>(); | |
SVNClientManager manager = getClientManager(username, password); | |
List<SVNLogEntry> logList = getLogByDate(manager, svnUrl, start, end); | |
Set<String> authorSet = new HashSet<String>(); | |
for (SVNLogEntry svnLogEntry : logList) { | |
authorSet.add(svnLogEntry.getAuthor()); | |
} | |
List<String> authorList = new ArrayList<String>(authorSet); | |
for (int i = 0; i < authorList.size(); i++) { | |
int addSum = 0; | |
int deleteSum = 0; | |
Date lastCommitTime = null; | |
SVNCommittedResult res = new SVNCommittedResult(); | |
for (int j = 0; j < logList.size(); j++) { | |
SVNLogEntry currLog = logList.get(j); | |
if (currLog.getAuthor().equals(authorList.get(i))) { | |
SVNRevision v1; | |
if(j==0){ //the last entry in logList should compare with its former revision(not in the specified period) | |
v1 = SVNRevision.create(currLog.getRevision()-1); | |
}else{ | |
v1 = SVNRevision.create(logList.get(j - 1).getRevision()); | |
} | |
SVNRevision v2 = SVNRevision.create(currLog.getRevision()); | |
Map<String, Integer> countMap = getDiffByRevision(manager, svnUrl, v1, v2, diffFile); | |
addSum += countMap.get("add"); | |
deleteSum += countMap.get("delete"); | |
lastCommitTime = currLog.getDate(); | |
} | |
} | |
res.setAddCount(addSum); | |
res.setDeleteCount(deleteSum); | |
res.setTotalCount(addSum + deleteSum); | |
res.setAuthor(authorList.get(i)); | |
res.setDate(lastCommitTime); | |
resultList.add(res); | |
} | |
return resultList; | |
} | |
/* | |
* get SVNClientManager to call LogClient and DiffClient | |
*/ | |
private SVNClientManager getClientManager(String username, String password) { | |
ISVNOptions options = SVNWCUtil.createDefaultOptions(true); | |
SVNClientManager manager = SVNClientManager.newInstance((DefaultSVNOptions) options, username, password); | |
return manager; | |
} | |
/* | |
* get contributor login list | |
*/ | |
private List<SVNLogEntry> getLogByDate(SVNClientManager manager, String svnUrl, final Date start, final Date end) { | |
final List<SVNLogEntry> logList = new ArrayList<SVNLogEntry>(); | |
SVNLogClient logClient = manager.getLogClient(); | |
ISVNLogEntryHandler handler = new ISVNLogEntryHandler() { | |
@Override | |
public void handleLogEntry(SVNLogEntry logEntry) throws SVNException { | |
if (logEntry.getDate().after(start) && logEntry.getDate().before(end)) { | |
logList.add(logEntry); | |
} | |
} | |
}; | |
try { | |
SVNURL repositoryURL = SVNURL.parseURIEncoded(svnUrl); | |
String[] paths = new String[] { "" }; | |
logClient.doLog(repositoryURL, paths, SVNRevision.HEAD, SVNRevision.create(1), SVNRevision.HEAD, false, | |
true, 0, handler); | |
} catch (SVNException e) { | |
e.printStackTrace(); | |
} | |
return logList; | |
} | |
/* | |
* get modification count by line between two revisions | |
*/ | |
private Map<String, Integer> getDiffByRevision(SVNClientManager manager, String svnUrl, SVNRevision v1, | |
SVNRevision v2, String diffFile) { | |
SVNDiffClient diffClient = manager.getDiffClient(); | |
Map<String, Integer> countMap = new HashMap<String, Integer>(); | |
try { | |
SVNURL repositoryURL = SVNURL.parseURIEncoded(svnUrl); | |
BufferedOutputStream result = new BufferedOutputStream(new FileOutputStream(diffFile)); | |
diffClient.doDiff(repositoryURL, SVNRevision.HEAD, v1, v2, SVNDepth.INFINITY, true, result); | |
result.close(); | |
} catch (FileNotFoundException e) { | |
e.printStackTrace(); | |
} catch (IOException ioe) { | |
ioe.printStackTrace(); | |
} catch (SVNException svne) { | |
svne.printStackTrace(); | |
} | |
FileReader fr = null; | |
int addCount = 0; | |
int deleteCount = 0; | |
try { | |
fr = new FileReader(diffFile); | |
BufferedReader br = new BufferedReader(fr); | |
String s = br.readLine(); | |
while (s != null) { | |
if (s.startsWith("+") && !s.startsWith("+++")) { | |
addCount++; | |
} else if (s.startsWith("-") && !s.startsWith("---")) { | |
deleteCount++; | |
} | |
s = br.readLine(); | |
} | |
br.close(); | |
fr.close(); | |
} catch (FileNotFoundException e) { | |
e.printStackTrace(); | |
} catch (IOException e) { | |
e.printStackTrace(); | |
} | |
countMap.put("add", addCount); | |
countMap.put("delete", deleteCount); | |
return countMap; | |
} | |
} | |
class SVNCommittedResult { | |
String author; | |
Date date; | |
int addCount; | |
int deleteCount; | |
int totalCount; | |
public String getAuthor() { | |
return author; | |
} | |
public void setAuthor(String author) { | |
this.author = author; | |
} | |
public Date getDate() { | |
return date; | |
} | |
public void setDate(Date date) { | |
this.date = date; | |
} | |
public int getAddCount() { | |
return addCount; | |
} | |
public void setAddCount(int addCount) { | |
this.addCount = addCount; | |
} | |
public int getDeleteCount() { | |
return deleteCount; | |
} | |
public void setDeleteCount(int deleteCount) { | |
this.deleteCount = deleteCount; | |
} | |
public int getTotalCount() { | |
return totalCount; | |
} | |
public void setTotalCount(int totalCount) { | |
this.totalCount = totalCount; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment