Java工具类-JGit基本功能实现

一、简介

最近在写一个web前端代码覆盖率的工程(react),主要是负责后台的管理功能。目前的一个需求就是获取增量代码的覆盖率;需要去获取代码提交前后的代码差异,将代码差异信息提供给前端同事进行处理计算此覆盖率; 通过使用GitLab的API和Java提供的JGit后发现,java提供的JGit效果更好,差异的信息也准确;
此工具类基于Jacoc二开代码,修改部分代码,实现自己需要的功能的一个工具类。也仅仅只获取了java工程的代码差异,react工程的代码差异与此原理差不多,删除掉几个不重要的文件即可。
主要实现以下功能

  • 远程拉取分支信息
  • 切换分支
  • 获取当前分支的所有commit信息(merge的commit信息)
  • 对比当前分支与master分支的最新代码差异
  • 对比当前分支与master分支某个commit时刻的代码差异
  • 校验本地分支是否是最新版本

注: 查阅此文档前可能需要先了解下Jgit的基本操作

二、工程代码

1. pom.xml pom依赖
		<dependency>
            <groupId>org.eclipse.jdt</groupId>
            <artifactId>org.eclipse.jdt.core</artifactId>
            <version>3.19.0</version>
        </dependency>
        <dependency>
            <groupId>org.eclipse.jgit</groupId>
            <artifactId>org.eclipse.jgit</artifactId>
            <version>5.9.0.202009080501-r</version>
        </dependency>
        <dependency>
            <groupId>org.bouncycastle</groupId>
            <artifactId>bcprov-jdk16</artifactId>
            <version>1.46</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
2. ClassInfo.java

保存差异类信息的实体类

@Data
@ToString
public class ClassInfo {
   
    /**
     * java文件
     */
    private String classFile;
    /**
     * 类名
     */
    private String className;
    /**
     * 包名
     */
    private String packages;

    /**
     * 类中的方法
     */
    private List<MethodInfo> methodInfos;

    /**
     * 新增的行数
     */
    private List<Integer> addLines;

    /**
     * 删除的行数
     */
    private List<Integer> delLines;

    /**
     * 修改类型
     */
    private String type;
}
3. MethodInfo.java

保存差异文件中的差异方法信息

@Data
@ToString
public class MethodInfo {
   
    /**
     * 方法的md5
     */
    public String md5;
    /**
     * 方法名
     */
    public String methodName;
    /**
     * 方法参数
     */
    public String parameters;
}
4. GitAdapter.java

Git工具操作类

public class GitAdapter {
   
    private static final Logger logger = LoggerFactory.getLogger(GitAdapter.class);

    private final static String REF_HEADS = "refs/heads/";
    private final static String MASTER_BRANCH = "master";
    // 远程仓库路径  用的就是.git
    private String remotePath;

    // 本地仓库路径  包含了项目工程名projectName
    private String localPath;

    private String localGitPath;

    private Git git;

    private Repository repository;

    private Ref branchRef;

    public String branchName;
    //  Git授权
    private static UsernamePasswordCredentialsProvider usernamePasswordCredentialsProvider;

    /**
     * 构造函数:没有传分支信息则默认拉取master代码
     * @param remotePath
     * @param localPath
     */
    public GitAdapter(String remotePath, String localPath) {
   
        this(remotePath,localPath,MASTER_BRANCH);
    }

    public GitAdapter(String remotePath, String localPath, String branchName) {
   
        this.remotePath = remotePath;
        this.localPath = localPath;
        this.branchName = branchName;
        localGitPath = this.localPath+"/.git";
        // 鉴权账户密码可用自己gitHub的账户密码,或者是设置token
        this.usernamePasswordCredentialsProvider = new UsernamePasswordCredentialsProvider("account","password");
        // 初始化git
//        this.initGit();
//        repository = new FileRepository(localGitPath);
    }

    /**
     * 使用Git时需要先初始化git
     * 默认初始化的时候会自动拉取 @branchName 的最新代码
     * @return
     */
    public  Git initGit() {
   
        File file = new File(localPath);
        System.out.println("文件路径"+localPath);
        // 如果文件存在 说明已经拉取过代码,则拉取最新代码
        if(file.exists()) {
   
            try {
   
                git = Git.open(new File(localPath));
                // 判断是否是最新代码 判断是否是最新代码好像耗时更久??!
                boolean isLatest = checkBranchNewVersion(git.getRepository().exactRef(REF_HEADS+branchName));
                if (isLatest==true) {
   
                    logger.info("the local version is latest, need not pull it");
                } else {
   
                    // 拉取最新的提交
                    git.pull().setCredentialsProvider(usernamePasswordCredentialsProvider).call();
                    logger.info("pull success");
                }
            } catch (GitAPIException e) {
   
                logger.info("pull failure");
                e.printStackTrace();
            } catch (IOException e) {
   
                logger.info("pull failure");
                e.printStackTrace();
            }
        }
        // 文件不存在,说明未拉取过代码 则拉取最新代码
        else {
   
            try {
   
                git = Git.cloneRepository()
                        .setCredentialsProvider(usernamePasswordCredentialsProvider)
                        .setURI(remotePath)
                        .setBranch(branchName)
                        .setDirectory(new File(localPath))
                        .call();
                // 拉取最新的提交
                git.pull().setCredentialsProvider(usernamePasswordCredentialsProvider).call();
                logger.info("down success");
            } catch (GitAPIException e) {
   
                logger.error("远程仓库下载异常");
                e.printStackTrace();
            }
        }
        repository = git.getRepository();
        return git;
    }

    /**
     * 获取ref信息
     * @return
     * @throws IOException
     */
    public Ref getBranchRef() throws IOException {
   
        return getBranchRef(this.branchName);
    }

    /**
     * 根据branch 获取ref信息
     * @param branchName
     * @return
     */
    public Ref getBranchRef(String branchName) {
   
        try {
   
            return this.branchRef = git.getRepository().exactRef(REF_HEADS+branchName);
        } catch (IOException e) {
   
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获取指定分支的指定文件内容
     * @param branchName        分支名称
     * @param javaPath          文件路径
     * @return  java类
     * @throws IOException
     */
    public String getBranchSpecificFileContent(String branchName, String javaPath) throws IOException {
   
        Ref branch = repository.exactRef( REF_HEADS + branchName);
        ObjectId objId = branch.getObjectId();
        RevWalk walk = new RevWalk(repository);
        RevTree tree = walk.parseTree(objId);
        return  getFileContent(javaPath,tree,walk);
    }

    /**
     * 获取指定分支指定的指定文件内容
     * @param javaPath      件路径
     * @param tree          git RevTree
     * @param walk          git RevWalk
     * @return  java类
     * @throws IOException
     */
    private String getFileContent(String javaPath,RevTree tree,RevWalk walk) throws IOException {
   
        TreeWalk treeWalk = TreeWalk.forPath(repository, javaPath, tree);
        ObjectId blobId = treeWalk.getObjectId(0);
        ObjectLoader loader = repository.open
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值