DevOps系列文章 之 Java使用jgit管理git仓库

本文介绍了如何利用Java的JGit库来实现GitOps的持续集成和部署(CICD)方案,包括初始化和操作Git仓库、克隆、提交、推送以及读取仓库日志的功能。JGit是一个纯Java实现的库,可以方便地在应用中集成Git操作。文章提供了具体的代码示例,如凭证管理、仓库操作以及读取日志等。
摘要由CSDN通过智能技术生成

最近设计基于gitops新的CICD方案,需要通过java读写git仓库,这里简单记录下。

在jgit中,存在最核心的三个组件:Git类,Repository类。Git类中包含了push commit之类的常见git操作,而Repository则实现了仓库的初始化和基本的管理功能。
Git类的实例都会持有一个Repository实例。

Repository类的初始化

针对一个git仓库,我们一般会有三种方式获得
1.新建一个空仓库

 Git git = Git.init().setDirectory(localPath).call()

2.加载一个已存在的仓库

Repository repository = builder.setGitDir(repoDir)
                .readEnvironment() // scan environment GIT_* variables
                .findGitDir() // scan up the file system tree
                .build()

3.从远程仓库下载

Git result = Git.cloneRepository()
                .setURI(REMOTE_URL)
                .setDirectory(localPath)
                .call()

JGit是一款pure java的软件包,可以读写git仓库,下面介绍基本使用。

引入jgit#

maven引入:

        <!-- jgit -->
        <dependency>
            <groupId>org.eclipse.jgit</groupId>
            <artifactId>org.eclipse.jgit</artifactId>
            <version>5.8.0.202006091008-r</version>
        </dependency>
        <dependency>
            <groupId>commons-io</groupId>
            <artifactId>commons-io</artifactId>
            <version>2.6</version>
        </dependency>

jgit 有一个Git类,可以用来执行常规的git操作

凭证管理#

通过CredentialsProvider管理凭证,常用的是UsernamePasswordCredentialsProvider

通过下面代码初始化:

public static CredentialsProvider createCredential(String userName, String password) {
        return new UsernamePasswordCredentialsProvider(userName, password);
}

clone远程仓库#

git 命令:

git clone {repoUrl}

通过Git.cloneRepository 来clone远程仓库,如果需要凭证,则需要指定credentialsProvider

 public static Git fromCloneRepository(String repoUrl, String cloneDir, CredentialsProvider provider) throws GitAPIException {
        Git git = Git.cloneRepository()
            .setCredentialsProvider(provider)
            .setURI(repoUrl)
            .setDirectory(new File(cloneDir)).call();
        return git;
}

commit#

git 命令:

git commit -a -m '{msg}'

commit比较简单,对应commit方法, 注意需要先add

public static void commit(Git git, String message, CredentialsProvider provider) throws GitAPIException {
        git.add().addFilepattern(".").call();
        git.commit()
            .setMessage(message)
            .call();
}

push#

git 命令:

git push origin branchName

push直接调用push即可, 需要指定credentialsProvider

   public static void push(Git git, CredentialsProvider provider) throws GitAPIException, IOException {
        push(git,null,provider);
    }

    public static void push(Git git, String branch, CredentialsProvider provider) throws GitAPIException, IOException {
        if (branch == null) {
            branch = git.getRepository().getBranch();
        }
        git.push()
            .setCredentialsProvider(provider)
            .setRemote("origin").setRefSpecs(new RefSpec(branch)).call();
    }

读取已有仓库#

如果git已经clone了,想直接读取,怎么办?

 public static Repository getRepositoryFromDir(String dir) throws IOException {
        return new FileRepositoryBuilder()
            .setGitDir(Paths.get(dir, ".git").toFile())
            .build();
 }

读取仓库日志#

可以通过RevWalk读取仓库日志。

  • revWalk.parseCommit 可读取一条commit
  • 遍历revWalk,可读取所有日志
 public static List<String> getLogs(Repository repository) throws IOException {
        return getLogsSinceCommit(repository, null, null);
    }

    public static List<String> getLogsSinceCommit(Repository repository, String commit) throws IOException {
        return getLogsSinceCommit(repository, null, commit);
    }

    public static List<String> getLogsSinceCommit(Repository repository, String branch, String commit) throws IOException {
        if (branch == null) {
            branch = repository.getBranch();
        }
        Ref head = repository.findRef("refs/heads/" + branch);
        List<String> commits = new ArrayList<>();
        if (head != null) {
            try (RevWalk revWalk = new RevWalk(repository)) {
                revWalk.markStart(revWalk.parseCommit(head.getObjectId()));
                for (RevCommit revCommit : revWalk) {
                    if (revCommit.getId().getName().equals(commit)) {
                        break;
                    }
                    commits.add(revCommit.getFullMessage());
                    System.out.println("\nCommit-Message: " + revCommit.getFullMessage());
                }
                revWalk.dispose();
            }
        }

        return commits;
    }

测试#

我们来先clone仓库,然后修改,最后push

package com.devops.autocicdstore.git;

import org.apache.commons.io.FileUtils;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.transport.CredentialsProvider;

import java.io.File;
import java.io.IOException;
import java.nio.file.Paths;

import static com.devops.autocicdstore.git.GetRepositoryMgr.*;

/**
 * @Author 虎哥
 * @Description //TODO
 * |要带着问题去学习,多猜想多验证|
 **/
public class TestMain {
    public static void main(String[] args) throws GitAPIException, IOException {
        String yaml = "dependencies:\n" +
                "- name: springboot-rest-demo\n" +
                "  version: 0.0.5\n" +
                "  repository: http://hub.hubHOST.com/chartrepo/ainote\n" +
                "  alias: demo\n" +
                "- name: exposecontroller\n" +
                "  version: 2.3.82\n" +
                "  repository: http://chartmuseum.jenkins-x.io\n" +
                "  alias: cleanup\n";
        CredentialsProvider provider = createCredential("USR_NAME", "PASSWORD");

        String cloneDir = "/tmp/test";

        Git git = fromCloneRepository("https://gitee.com/JavaBigDataStudy/auto-cicd-store.git", cloneDir, provider);

        // 修改文件

        FileUtils.writeStringToFile(Paths.get(cloneDir, "env", "requirements.yaml").toFile(), yaml, "utf-8");

        // 提交
        commit(git, "deploy(app): deploy  springboot-rest-demo:0.0.5 to env test", provider);
        // push 到远程仓库
        push(git, "master", provider);

        git.clean().call();
        git.close();

        FileUtils.deleteDirectory(new File(cloneDir));
    }
}

package com.devops.autocicdstore.git;

import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
import org.eclipse.jgit.transport.CredentialsProvider;
import org.eclipse.jgit.transport.RefSpec;
import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;

import java.io.File;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;

/**
 * @Author 虎哥
 * @Description //TODO
 * |要带着问题去学习,多猜想多验证|
 **/
public class GetRepositoryMgr {
    public static CredentialsProvider createCredential(String userName, String password) {
        return new UsernamePasswordCredentialsProvider(userName, password);
    }

    public static void main(String[] args) throws GitAPIException, IOException {
//        String localPath = "D:\\SoftwareDev\\Code\\auto-cicd-store\\git-res";
//        String remotePath = "https://gitee.com/JavaBigDataStudy/auto-cicd-store.git";
//        CredentialsProvider provider = createCredential("XXXX","XXX");
//        //1
//
//        Git git = fromCloneRepository(remotePath,localPath,provider);
//        //2
//        commit(git,"test",provider);
//        //3
//        push(git,"dev",provider);
//        //4
//      //  getLogs()l

        Repository repository = getRepositoryFromDir("D:\\\\SoftwareDev\\\\Code\\\\auto-cicd-store\\\\git-res");
        List<String> logs = getLogs(repository);
        System.out.println(logs);

    }

    public static Git fromCloneRepository(String repoUrl, String cloneDir, CredentialsProvider provider) throws GitAPIException {
        Git git = Git.cloneRepository()
                .setCredentialsProvider(provider)
                .setURI(repoUrl)
                .setDirectory(new File(cloneDir)).call();
        return git;
    }
    public static Repository getRepositoryFromDir(String dir) throws IOException {
        return new FileRepositoryBuilder()
                .setGitDir(Paths.get(dir, ".git").toFile())
                .build();
    }
    public static void commit(Git git, String message, CredentialsProvider provider) throws GitAPIException {
        git.add().addFilepattern(".").call();
        git.commit()
                .setMessage(message)
                .call();
    }

    public static void push(Git git, CredentialsProvider provider) throws GitAPIException, IOException {
        push(git,null,provider);
    }

    public static void push(Git git, String branch, CredentialsProvider provider) throws GitAPIException, IOException {
        if (branch == null) {
            branch = git.getRepository().getBranch();
        }
        git.push()
                .setCredentialsProvider(provider)
                .setRemote("origin").setRefSpecs(new RefSpec(branch)).call();
    }

    public static List<String> getLogs(Repository repository) throws IOException {
        return getLogsSinceCommit(repository, null, null);
    }

    public static List<String> getLogsSinceCommit(Repository repository, String commit) throws IOException {
        return getLogsSinceCommit(repository, null, commit);
    }

    public static List<String> getLogsSinceCommit(Repository repository, String branch, String commit) throws IOException {
        if (branch == null) {
            branch = repository.getBranch();
        }
        Ref head = repository.findRef("refs/heads/" + branch);
        List<String> commits = new ArrayList<>();
        if (head != null) {
            try (RevWalk revWalk = new RevWalk(repository)) {
                revWalk.markStart(revWalk.parseCommit(head.getObjectId()));
                for (RevCommit revCommit : revWalk) {
                    if (revCommit.getId().getName().equals(commit)) {
                        break;
                    }
                    commits.add(revCommit.getFullMessage());
                    System.out.println("\nCommit-Message: " + revCommit.getFullMessage());
                }
                revWalk.dispose();
            }
        }

        return commits;
    }

}

读取已有仓库的日志:

 Repository repository = getRepositoryFromDir("GIT_DIR");
        List<String> logs = getLogs(repository);
        System.out.println(logs);

        RevCommit head = getLastCommit(repository);
        System.out.println(head.getFullMessage());

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Coder_Boy_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值