大家好,使用ai写代码已经现在很火的技术,作为一名工程师,更应该与时俱进,今天演示一下通过Bito-chatgpt来完成一个功能,ai已经能完成大部分工作了,只需要小调整就可以。
接下来来看交互的过程。
任务问题:使用jgit统计每个工程师的代码提交的行数
Bito的回答:
要使用 JGit 统计每个工程师代码提交的行数,可以按照以下步骤来实现:
1. 获取 Git 仓库:需要初始化 Git
对象,并设置 Git 仓库的路径。
FileRepositoryBuilder builder = new FileRepositoryBuilder();
Repository repository = builder.setGitDir(new File("path/to/git/repo"))
.readEnvironment() // scan environment GIT_* variables
.findGitDir() // scan up the file system tree
.build();
Git git = new Git(repository);
2. 获取提交记录:使用 git.log().all().call()
方法获取仓库中所有的提交记录。
Iterable<RevCommit> commits = git.log().all().call();
3. 遍历提交记录,统计每个工程师的行数。
统计每个工程师的行数,可以通过解析提交记录中的作者信息来实现,例如:
Map<String, Integer> authorToLineCount = new HashMap<>();
for (RevCommit commit : commits) {
String authorName = commit.getAuthorIdent().getName();
int linesAdded = 0;
int linesDeleted = 0;
TreeWalk treeWalk = new TreeWalk(repository);
treeWalk.addTree(commit.getTree());
if (commit.getParentCount() > 0) {
treeWalk.addTree(commit.getParent(0).getTree());
}
treeWalk.setRecursive(true);
while (treeWalk.next()) {
if (treeWalk.isSubtree()) {
treeWalk.enterSubtree();
continue;
}
FileMode fileMode = treeWalk.getFileMode(0);
if (fileMode == FileMode.REGULAR_FILE) {
ObjectId objectId = treeWalk.getObjectId(0);
ObjectLoader loader = repository.open(objectId);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
loader.copyTo(outputStream);
String content = new String(outputStream.toByteArray());
linesAdded += countLinesAdded(content);
linesDeleted += countLinesDeleted(content);
}
}
int lineCount = linesAdded - linesDeleted;
if (authorToLineCount.containsKey(authorName)) {
lineCount += authorToLineCount.get(authorName);
}
authorToLineCount.put(authorName, lineCount);
}
在上面的代码中,首先遍历提交记录中的每个提交,然后获取提交作者的姓名,并初始化一个 Map
对象来存储每个作者的代码行数。接下来,遍历提交记录中的每个文件,计算该文件中新增和删除的代码行数,并将其累加到作者的代码行数中。最后,输出每个作者的代码行数。
统计新增和删除的代码行数,可以编写一个简单的帮助函数。例如,以下函数可以计算文件中新增的代码行数:
private static int countLinesAdded(String content) {
int count = 0;
Scanner scanner = new Scanner(content);
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
if (line.startsWith("+")) {
count++;
}
}
scanner.close();
return count;
}
同理,以下函数可以计算文件中删除的代码行数:
private static int countLinesDeleted(String content) {
int count = 0;
Scanner scanner = new Scanner(content);
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
if (line.startsWith("-")) {
count++;
}
}
scanner.close();
return count;
}
完整的代码示例如下:
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.lib.*;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.treewalk.TreeWalk;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
public class CommitStats {
public static void main(String[] args) throws Exception {
FileRepositoryBuilder builder = new FileRepositoryBuilder();
Repository repository = builder.setGitDir(new File("path/to/git/repo"))
.readEnvironment() // scan environment GIT_* variables
.findGitDir() // scan up the file system tree
.build();
try (Git git = new Git(repository)) {
Iterable<RevCommit> commits = git.log().all().call();
Map<String, Integer> authorToLineCount = new HashMap<>();
for (RevCommit commit : commits) {
String authorName = commit.getAuthorIdent().getName();
int linesAdded = 0;
int linesDeleted = 0;
TreeWalk treeWalk = new TreeWalk(repository);
treeWalk.addTree(commit.getTree());
if (commit.getParentCount() > 0) {
treeWalk.addTree(commit.getParent(0).getTree());
}
treeWalk.setRecursive(true);
while (treeWalk.next()) {
if (treeWalk.isSubtree()) {
treeWalk.enterSubtree();
continue;
}
FileMode fileMode = treeWalk.getFileMode(0);
if (fileMode == FileMode.REGULAR_FILE) {
ObjectId objectId = treeWalk.getObjectId(0);
ObjectLoader loader = repository.open(objectId);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
loader.copyTo(outputStream);
String content = new String(outputStream.toByteArray());
linesAdded += countLinesAdded(content);
linesDeleted += countLinesDeleted(content);
}
}
int lineCount = linesAdded - linesDeleted;
if (authorToLineCount.containsKey(authorName)) {
lineCount += authorToLineCount.get(authorName);
}
authorToLineCount.put(authorName, lineCount);
}
for (Map.Entry<String, Integer> entry : authorToLineCount.entrySet()) {
System.out.println(entry.getKey() + ": " + entry.getValue());
}
}
}
private static int countLinesAdded(String content) {
int count = 0;
Scanner scanner = new Scanner(content);
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
if (line.startsWith("+")) {
count++;
}
}
scanner.close();
return count;
}
private static int countLinesDeleted(String content) {
int count = 0;
Scanner scanner = new Scanner(content);
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
if (line.startsWith("-")) {
count++;
}
}
scanner.close();
return count;
}
}
在这个示例代码中,我们假设提交者的姓名唯一标识每个工程师,并且使用姓名作为 key 存储每个工程师提交的代码量。
把代码拷到程序文件中,运行,报错了,如下:
Exception in thread "main" org.eclipse.jgit.api.errors.NoHeadException: No HEAD exists and no explicit starting revision was specified
继续请教Bito:
AI: This error message indicates that the Git repository in question does not have a valid HEAD reference, and no starting revision was specified for the operation being performed. To resolve this issue, you may need to create a new branch or reset the repository to a known good state. It is also possible that there is a problem with the Git client or server configuration. Please refer to the Git documentation or seek assistance from a Git expert for further guidance.
那么这个git的GitDir要如何传入呢?
继续问:FileRepositoryBuilder.setGitDir 如何设置?
AI:
FileRepositoryBuilder.setGitDir
is a method used to set the directory of the git repository. You can use it to specify the path to the.git
directory of the repository that you want to access on your local machine. Here's an example of how to use it:
File gitDir = new File("/path/to/your/git/repository/.git");
FileRepositoryBuilder builder = new FileRepositoryBuilder();
Repository repo = builder
.setGitDir(gitDir)
.readEnvironment()
.findGitDir()
.build();
In this example, we create a
File
object pointing to the.git
directory of the repository, and then use thesetGitDir
method to set it as the directory for theFileRepositoryBuilder
. This sets up thebuilder
with the repository configuration, and we can then use it to create aRepository
object that represents access to the repository.
通过提示,需要配置到指定的目录下的.git目录才行。
修改读取的gitdir目录,运行成功。
调整后的代码如下:
public static void main(String[] args) throws Exception {
FileRepositoryBuilder builder = new FileRepositoryBuilder();
Repository repository = builder.setGitDir(new File("/xxx/xx/xx/.git"))
.readEnvironment() // scan environment GIT_* variables
.findGitDir() // scan up the file system tree
.build();
try (Git git = new Git(repository)) {
Iterable<RevCommit> commits = git.log().all().call();
Map<String, Map<String, Integer>> authorToLineCount = new HashMap<>();
for (RevCommit commit : commits) {
String authorName = commit.getAuthorIdent().getName();
int linesAdded = 0;
int linesDeleted = 0;
TreeWalk treeWalk = new TreeWalk(repository);
treeWalk.addTree(commit.getTree());
if (commit.getParentCount() > 0) {
treeWalk.addTree(commit.getParent(0).getTree());
}
treeWalk.setRecursive(true);
while (treeWalk.next()) {
if (treeWalk.isSubtree()) {
treeWalk.enterSubtree();
continue;
}
FileMode fileMode = treeWalk.getFileMode(0);
if (fileMode == FileMode.REGULAR_FILE) {
ObjectId objectId = treeWalk.getObjectId(0);
ObjectLoader loader = repository.open(objectId);
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
loader.copyTo(outputStream);
String content = new String(outputStream.toByteArray());
linesAdded += countLinesAdded(content);
linesDeleted += countLinesDeleted(content);
}
}
//int lineCount = linesAdded - linesDeleted;
if (authorToLineCount.containsKey(authorName)) {
linesAdded += authorToLineCount.get(authorName).get("ADD");
linesDeleted += authorToLineCount.get(authorName).get("DEL");
}
Map<String, Integer> lines = new HashMap<>();
lines.put("ADD", linesAdded);
lines.put("DEL", linesDeleted);
authorToLineCount.put(authorName, lines);
}
for (Map.Entry<String, Map<String, Integer>> entry : authorToLineCount.entrySet()) {
System.out.println(entry.getKey() + "添加: " + entry.getValue().get("ADD") + ",删除:" + entry.getValue().get("DEL"));
}
}
}
private static int countLinesAdded(String content) {
int count = 0;
Scanner scanner = new Scanner(content);
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
if (!Objects.equals(line, "") && !line.startsWith("-")) {
count++;
}
}
scanner.close();
return count;
}
private static int countLinesDeleted(String content) {
int count = 0;
Scanner scanner = new Scanner(content);
while (scanner.hasNextLine()) {
String line = scanner.nextLine();
if (line.startsWith("-")) {
count++;
}
}
scanner.close();
return count;
}
统计了一个线上项目的情况如下:
ai提示写代码已经很不错了,要学习并去使用它,让它为你而做。接下来会写利用Bito来开发一个简单的系统,只要你略微懂点技术就可以。