绝了,一句话写完一个功能,用Bito初体验。

简介: 绝了,一句话写完一个功能,用Bito初体验。

大家好,使用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 the setGitDir method to set it as the directory for the FileRepositoryBuilder . This sets up the builder with the repository configuration, and we can then use it to create a Repository 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;
}

统计了一个线上项目的情况如下:

image.png

ai提示写代码已经很不错了,要学习并去使用它,让它为你而做。接下来会写利用Bito来开发一个简单的系统,只要你略微懂点技术就可以。

目录
相关文章
|
13天前
|
存储 缓存 自然语言处理
《VitePress 简易速速上手小册》第7章 高级功能与动态内容(2024 最新版)(下)
《VitePress 简易速速上手小册》第7章 高级功能与动态内容(2024 最新版)
28 1
|
9月前
|
XML Java 数据格式
HarmonyOS学习路之开发基础——快速入门(创建另一个页面)
在上一节中,我们用XML的方式编写了一个包含文本和按钮的页面。为了帮助开发者熟悉在代码中创建布局的方式,接下来我们使用代码的方式编写第二个页面。
|
10月前
|
iOS开发
CTMediator 的初体验
​ 现在对于iOS开发的要求随着时代的发展,也在渐渐地演变。这几天看到了很多JD的要求,多多少少都会提到这样的一个名字-组件化。
|
存储 网络安全 文件存储
UNRAID系统初体验
UNRAID系统初体验
465 0
UNRAID系统初体验
|
开发者
服务器初体验
初次使用服务器的体验
|
开发者
使用服务器初体验
阿里让我真真正正的走进服务器的大门,有了阿里云的帮助让我的学习事半功倍。
|
人工智能 Cloud Native 算法
阿里云使用初体验
阿里云作为全球领先的科技公司,在云计算与人工智能方面很有建树,为许多国家与企业提供便利的服务与强有力的技术支撑。
163 0
|
Java Linux Docker
阿里云的使用初体验
学生党在面对虚拟机的时候首先还是推荐使用阿里云的虚拟机,原因让我娓娓道来;
|
Rust 资源调度 JavaScript
桌面端开发(Tauri)开启第一篇
桌面端开发(Tauri)开启第一篇
1135 0
桌面端开发(Tauri)开启第一篇
|
监控 C#
我的阿里云初体验
一名大学生利用阿里云服务器做了内网穿透