【JGit 】一个完整的使用案例

需求

生成一系列结构相同的项目代码,将这些项目的代码推送至一个指定的 Git 仓库,每个项目独占一个分支。

推送时若仓库不存在,则自动创建仓库。

分析

生成代码使用 Java 程序模拟,每个项目中模拟三个文件。Project.cppProject.hREADME

使用 JGit 实现代码版本管理与推送。

代码实现

以下代码包含了代码生成,Git 仓库初始化、代码克隆、分支检出、代码修改、暂存、提交及推送等操作。

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.apache.commons.lang.StringUtils;
import org.eclipse.jgit.api.CheckoutCommand;
import org.eclipse.jgit.api.CreateBranchCommand;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.ListBranchCommand;
import org.eclipse.jgit.api.PushCommand;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.transport.CredentialsProvider;
import org.eclipse.jgit.transport.PushResult;
import org.eclipse.jgit.transport.URIish;
import org.eclipse.jgit.transport.UsernamePasswordCredentialsProvider;

import cn.hutool.core.io.FileUtil;

public class JgitTest3 {

    private static String DEFAULE_REMOTE_NAME = "origin";
    private static String DEFAULE_BRANCH_NAME = "master";

    private static String gitUrl = "http://192.168.181.1:3000/root/a-test.git";

    private static String username = "root";
    private static String password = "123456";

    /**
     * 创建认证信息
     * 
     * @return
     */
    public static CredentialsProvider getCredentialsProvider() {
        return new UsernamePasswordCredentialsProvider(username, password);
    }

    public static void main(String[] args) throws Exception {

        List<String> branches = Stream.of("branchA", "branchB").collect(Collectors.toList());

        for (String branchName : branches) {

            System.out.println("\r\n ==========================<<" + branchName + ">>==========================\r\n");
            // 生成代码
            File codeDir = genCode(branchName);
            System.out.println(" >>>>>>>>>>>>>>> CodeDir: " + codeDir);

            // 判断仓库是否存在
            boolean remoteRepositoryExist = remoteRepositoryExist(gitUrl, username, password);
            if (remoteRepositoryExist) {
                pushOnRepoExist(branchName, codeDir);
            } else {
                pushOnRepoNotExist(branchName, codeDir);
            }

            // 清理生成的文件
            FileUtil.del(codeDir);
        }
    }

    private static void pushOnRepoNotExist(String branchName, File codeDir) throws Exception {
        // 将源码库初始化为Git仓库
        Git git = Git.init().setDirectory(codeDir).call();

        // 添加远程仓库
        git.remoteAdd()
                .setName(DEFAULE_REMOTE_NAME)
                .setUri(new URIish(gitUrl))
                .call();

        // 初始化提交
        git.add().addFilepattern(".").call();
        git.commit().setMessage("Initial commit").call();

        // 切换分支
        checkoutBranch(git, branchName);

        // 提交推送
        pushToRepo(git, branchName);

        // 关闭资源
        git.close();
    }

    private static void pushOnRepoExist(String branchName, File codeDir) throws Exception {

        // 创建临时工作目录
        File localDir = Files.createTempDirectory("Jgit-work-dir-").toFile();
        System.out.println("\r\n >>>>>>>>>>>>>>> Work dir is: " + localDir + "\r\n");

        // 克隆到本地
        Git git = Git.cloneRepository()
                .setDirectory(localDir)
                .setURI(gitUrl)
                .setCredentialsProvider(getCredentialsProvider())
                .call();

        // 切换到分支
        checkoutBranch(git, branchName);

        // 更新代码
        deleteContent(localDir.toPath(), ".git");
        // git.add().addFilepattern(".").setUpdate(true).call();
        // git.commit().setMessage("rm origin files").call();

        FileUtil.copyContent(codeDir, localDir, true);

        // 提交、推送
        pushToRepo(git, branchName);

        // 关闭资源
        git.close();

        FileUtil.del(localDir);
    }

    /**
     * 推送到远端分支
     * 
     * @param git
     * @param branchName 远端分支
     * @throws Exception
     */
    private static Iterable<PushResult> pushToRepo(Git git, String branchName) throws Exception {
        // 加入暂存区
        git.add().addFilepattern(".").call();
        git.add().addFilepattern(".").setUpdate(true).call();
        // 提交
        git.commit().setMessage(" Commit at : " + LocalDateTime.now()).call();

        // 构建推送命令
        PushCommand pushCmd = git.push()
                .setRemote(DEFAULE_REMOTE_NAME)
                .setCredentialsProvider(getCredentialsProvider());

        Ref remoteBranchRef = git.getRepository().findRef("refs/remotes/" + DEFAULE_REMOTE_NAME + "/" + branchName);
        if (Objects.isNull(remoteBranchRef)) {
            pushCmd.add(branchName);
        } else {
            pushCmd.setForce(true);
        }

        // 推送
        return pushCmd.call();
    }

    /**
     * 切换分支
     * <p>
     * <ul>
     * <li>先判断本地分支是否存在,存在则直接切换,不存在则下一步。</li>
     * <li>判断远程分支是否存在,存在则直接切换,不存在则在切换时创建分支。</li>
     * </ul>
     * 
     * </p>
     * 
     * @param git
     * @param branchName
     */
    private static void checkoutBranch(Git git, String branchName) throws Exception {

        CheckoutCommand checkoutCmd = git.checkout().setName(branchName);

        Repository repository = git.getRepository();
        Ref branchRef = repository.findRef("refs/heads/" + branchName);
        if (Objects.isNull(branchRef)) {
            Ref remoteBranchRef = repository.findRef("refs/remotes/" + DEFAULE_REMOTE_NAME + "/" + branchName);
            if (Objects.isNull(remoteBranchRef)) {
                CreateBranchCommand createBranchCmd = git.branchCreate().setName(branchName);
                // 先切换到已有分支,以获取提交记录,设置提交点辅助创建新的分支
                List<Ref> branches = git.branchList()
                        .setListMode(ListBranchCommand.ListMode.REMOTE)
                        .call();
                if (Objects.nonNull(branches) && branches.size() > 0) {
                    Ref remoteRef = branches.get(0);
                    String bName = Repository.shortenRefName(remoteRef.getName());
                    git.checkout().setName(bName).call();
                    RevCommit latestCommit = git.log().setMaxCount(1).call().iterator().next();
                    if (Objects.nonNull(latestCommit)) {
                        createBranchCmd.setStartPoint(latestCommit);
                    }
                }

                createBranchCmd.call();
            } else {
                checkoutCmd.setCreateBranch(true);
            }
        }

        checkoutCmd.call();
    }

    /**
     * 删除目录中的所有文件
     * <ul>
     * <li>文件</li>
     * <li>文件夹</li>
     * <li>子文件</li>
     * <li>子文件夹</li>
     * </ul>
     * 
     * @param folderPath  目标文件夹
     * @param ignoreFiles 忽略的文件或文件夹
     */
    public static void deleteContent(Path folderPath, String... ignoreFiles) {
        try {
            Files.walk(folderPath)
                    .filter(path -> !path.equals(folderPath))
                    .filter(path -> {
                        if (Objects.isNull(ignoreFiles) || ignoreFiles.length == 0) {
                            return false;
                        }
                        for (String ig : ignoreFiles) {
                            if (StringUtils.contains(path.toAbsolutePath().toString(), ig)) {
                                return false;
                            }
                        }
                        return true;
                    })
                    .forEach(path -> {
                        try {
                            if (path.toFile().isDirectory()) {
                                deleteContent(path, ignoreFiles);
                            } else {
                                Files.deleteIfExists(path);
                            }
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    });
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 生成代码
     * 
     * @param branchName
     * @return
     * @throws Exception
     */
    private static File genCode(String branchName) throws Exception {

        File codeDir = Files.createTempDirectory("Jgit-source-dir-").toFile();
        String codeDirAbsPath = codeDir.getAbsolutePath();

        // 生成 README
        File addNewFile = new File((codeDirAbsPath.concat(File.separator).concat("README.md")));
        String readmeContent = "Project for " + branchName + "\r\nWrite By Code JGitTest ";
        Files.write(addNewFile.toPath(), readmeContent.getBytes());

        // 生成文件
        File cppFile = new File(codeDirAbsPath.concat(File.separator).concat(branchName.concat(".cpp")));
        String cppContent = "Cpp Code for " + branchName + "\r\n Write By Code JGitTest ";
        Files.write(cppFile.toPath(), cppContent.getBytes());

        // 生成文件
        File hFile = new File(codeDirAbsPath.concat(File.separator).concat(branchName.concat(".h")));
        String hContent = "Header code for " + branchName + "\r\nWrite By Code JGitTest ";
        Files.write(hFile.toPath(), hContent.getBytes());

        return codeDir;
    }

    /**
     * 判断远程仓库是不是存在
     *
     * @param remoteUrl 远程仓库地址
     * @return true(存在)/false(不存在)
     */
    public static boolean remoteRepositoryExist(String remoteUrl, String username, String password) {
        try {
            Collection<Ref> refs = (Collection<Ref>) Git.lsRemoteRepository()
                    .setHeads(true)
                    .setTags(true)
                    .setCredentialsProvider(getCredentialsProvider(username, password))
                    .setRemote(remoteUrl)
                    .call();
            if (refs.isEmpty()) {
                return false;
            } else {
                return true;
            }
        } catch (Exception e) {
            log.warn("仓库{}不存在", remoteUrl);
            return false;
        }
    }

}

成果展示

在这里插入图片描述

1、JGit 版本

        <!-- https://mvnrepository.com/artifact/org.eclipse.jgit/org.eclipse.jgit -->
        <dependency>
            <groupId>org.eclipse.jgit</groupId>
            <artifactId>org.eclipse.jgit</artifactId>
            <version>5.1.3.201810200350-r</version>
        </dependency>

2、Gitea 安装

  • Win 下 Docker 安装 Gitea 实践:windows docker desktop部署gitea

3、JGit 资料

  • 【JGit】简述及学习资料整理
  • 【Gitea】Java 使用 JGit 创建 Git 代码仓库
  • 【Git】 删除远程分支
  • 【Gitea】配置 Push To Create

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/415811.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

CUMT---图像处理与视觉感知---期末复习重点

文章目录 一、概述 本篇文章会随课程的进行持续更新中&#xff01; 一、概述 1. 图像的概念及分类。  图像是用各种观测系统以不同形式和手段观测客观世界而获得的、可以直接或间接作用于人的视觉系统而产生的视知觉实体。  图像分为模拟图像和数字图像&#xff1a;(1) 模拟图…

Leetcode 第 385 场周赛题解

Leetcode 第 385 场周赛题解 Leetcode 第 385 场周赛题解题目1&#xff1a;3042. 统计前后缀下标对 I思路代码复杂度分析 题目2&#xff1a;3043. 最长公共前缀的长度思路代码复杂度分析 题目3&#xff1a;3044. 出现频率最高的质数思路代码复杂度分析 题目4&#xff1a;3045. …

【新书推荐】8.4 逻辑运算指令

本节内容&#xff1a;逻辑运算指令。8086 CPU逻辑运算指令包括NOT、AND、OR、XOR&#xff0c;除NOT指令外&#xff0c;均有两个操作数。逻辑运算指令影响状态标志位。 ■否操作指令NOT指令格式&#xff1a;NOT OPRD。将OPRD取反&#xff0c;然后送回OPRD。操作数可以是8位/16位…

Jetson系统烧录环境搭建

一 序言 Jetson 系列产品烧录系统的方法一般有两种&#xff0c;一种为使用 NVIDIA 官方提供 的 SDK manager 软件给 Jetson 设备烧录系统&#xff08;请查看说明文档《Jetson 产品使用 SDKmanager 烧录系统》&#xff09;。另一种即为当前文档所描述的&#xff0c;在安装 Ubun…

GZ036 区块链技术应用赛项赛题第10套

2023年全国职业院校技能大赛 高职组 “区块链技术应用” 赛项赛卷&#xff08;10卷&#xff09; 任 务 书 参赛队编号&#xff1a; 背景描述 养老保险是对于老年人的最基本的生活保障。各种数据显示&#xff0c;当前的养老金市场规模庞大。2016年美国的养老金资…

403页面绕过

403页面绕过 文章目录 403页面绕过姿势一: 端口利用姿势二&#xff1a;修改HOST姿势三&#xff1a;覆盖请求URL姿势四&#xff1a;Referer标头绕过姿势五&#xff1a;代理IP姿势六&#xff1a;扩展名绕过 姿势一: 端口利用 拿到客户给的地址后&#xff0c;首先进行信息收集。端…

MySQL存储引擎及索引机制

MySQL技术——存储引擎和索引机制 一、存储引擎概述二、常见存储引擎的区别三、索引机制四、索引的底层实现原理五、InnoDB主键和二级索引六、聚集索引和非聚集索引七、哈希索引八、InnoDB的自适应哈希索引九、索引常见问题十、慢查询日志总结 一、存储引擎概述 插件式存储引擎…

【C++私房菜】序列式容器的迭代器失效问题

目录 一、list的迭代器失效 二、vector的迭代器失效 1、空间缩小操作 2、空间扩大操作 三、总结 在C中&#xff0c;当对容器进行插入或删除操作时&#xff0c;可能会导致迭代器失效的问题。所谓迭代器失效指的是&#xff0c;原先指向容器中某个元素的迭代器&#xff0c;在…

IDEA基础——Maven配置tomcat

配置方案 一、配置maven-tomcat plugin插件&#xff08;只最高支持到tomcat 8&#xff09;~~1.添加镜像源&#xff0c;获取tomcat 8插件配置~~~~1.1 在pom.xml里先添加镜像源~~~~1.2 添加tomcat插件配置~~ 2. 添加tomact官方发布的插件配置&#xff08;无需添加镜像源&#xff…

回溯算法,你“回”了吗

目录 一、什么是回溯算法 二、应用场景 三、一般解题步骤 1、确定回溯方法以及参数 2、确定回溯的终止条件 3、确定搜索过程 四、力扣例题 1、题目描述 2、解题思路 3、代码示例 五、总结 一、什么是回溯算法 回溯算法&#xff0c;又称为试探法&#xff0c;是一种…

用友 NC 23处接口XML实体注入漏洞复现

0x01 产品简介 用友 NC 是用友网络科技股份有限公司开发的一款大型企业数字化平台。 0x02 漏洞概述 用友 NC 多处接口存在XML实体注入漏洞,未经身份验证攻击者可通过该漏洞读取系统重要文件(如数据库配置文件、系统配置文件)、数据库配置文件等等,导致网站处于极度不安全…

【Redis】深入理解 Redis 常用数据类型源码及底层实现(5.详解List数据结构)

本文是深入理解 Redis 常用数据类型源码及底层实现系列的第5篇&#xff5e;前4篇可移步(&#xffe3;∇&#xffe3;)/ 【Redis】深入理解 Redis 常用数据类型源码及底层实现&#xff08;1.结构与源码概述&#xff09;-CSDN博客 【Redis】深入理解 Redis 常用数据类型源码及底…

Ubuntu22.04.3LTS源码编译安装ffmpeg6.x

1.官网ffmpeg下载源码 https://ffmpeg.org/download.html#build-windows 安装 libx264 开发库&#xff08;一个开源的视频压缩库&#xff0c;用于编码视频流为 H.264/MPEG-4 AVC 视频格式&#xff09;。这是编译 FFmpeg 时如果要支持 H.264 编码必须的。 sudo apt install l…

Liunx前后端项目部署(小白也可安装)

文章目录 一、CentOS服务器的安装二、jdk安装三、Tomcat安装四、MySQL安装、五、nginX安装六、多个项目负载均衡&#xff0c;部署后端项目七、前端项目部署 一、CentOS服务器的安装 选择liunx&#xff0c;下面选择CentOS 7 ![在这里插入图片描述](https://img-blog.csdnimg.cn…

预训练概念

预训练是指在特定任务之前&#xff0c;在大规模数据集上对神经网络进行训练以学习通用的表示形式或特征。这些通用表示可以捕捉数据中的统计结构和语义信息&#xff0c;使得神经网络能够更好地理解和处理输入数据。 在大规模预训练模型中&#xff0c;通常会使用无监督或弱监督的…

python脚本实现全景站点矩阵转欧拉角

效果 脚本 import re import numpy as np import math import csv from settings import * # 以下是一个示例代码,可以输入3*3旋转矩阵,然后输出旋转角度:# ,输入3*3旋转矩阵# 计算x,y,z旋转角def rotation_matrix_to_euler_angles(R):

JVM(2)

JVM类加载 指的是java进程运行时,需要把.class文件从硬盘加载到内存,并进行一系列校验解析的过程. 核心: .class文件>类对象; 硬盘>内存. 类加载过程 在整个JVM的执行流程中,和程序员关系最密切的就是类加载的过程了,所以我们来看一下类加载的执行流程. 对于一个类…

【清理mysql数据库服务器二进制日志文件】

清理前后比对 清理前占用 86% &#xff1a; 清理后占用 29% &#xff1a; 排查占用磁盘较大的文件 检测磁盘空间占用 TOP 10 # 检测磁盘空间占用 TOP 10 $ sudo du -S /var/log/ | > sort -rn | # -n选项允许按数字排序。-r选项会先列出最大数字&#xff08;逆序&#x…

Tomcat架构分析

Tomcat的核心组件 Tomcat将请求器和处理器分离&#xff0c;使用多种请求器支持不同的网络协议&#xff0c;而处理器只有一个。从而网络协议和容器解耦。 Tomcat的容器 Host&#xff1a;Tomcat提供多个域名的服务&#xff0c;其将每个域名都视为一个虚拟的主机&#xff0c;在…

git忽略某些文件(夹)更改说明

概述 在项目中,常有需要忽略的文件、文件夹提交到代码仓库中,在此做个笔录。 一、在项目根目录内新建文本文件,并重命名为.gitignore,该文件语法如下 # 以#开始的行,被视为注释. # 忽略掉所有文件名是 a.txt的文件. a.txt # 忽略所有生成的 java文件, *.java # a.j…