【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();// 生成 READMEFile 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.hqwc.cn/news/506221.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C习题002:澡堂洗澡

问题 输入样例 在这里给出一组输入。例如&#xff1a; 2 5 1 3 3 2 3 3 输出样例 在这里给出相应的输出。例如&#xff1a; No代码长度限制 16 KB 时间限制 400 ms 内存限制 64 MB 栈限制 8192 KB 代码 #include<stdio.h> int main() {int N,W,s,t,p;int arr_s[…

将任何网页变成桌面应用,全平台支持 | 开源日报 No.184

tw93/Pake Stars: 20.9k License: MIT Pake 是利用 Rust 轻松构建轻量级多端桌面应用的工具。 与 Electron 包大小相比几乎小了 20 倍&#xff08;约 5M&#xff01;&#xff09;使用 Rust Tauri&#xff0c;Pake 比基于 JS 的框架更轻量和更快内置功能包括快捷方式传递、沉浸…

测试需求平台9-Table 组件应用产品列表优化

✍此系列为整理分享已完结入门搭建《TPM提测平台》系列的迭代版&#xff0c;拥抱Vue3.0将前端框架替换成字节最新开源的arco.design&#xff0c;其中约60%重构和20%新增内容&#xff0c;定位为从 0-1手把手实现简单的测试平台开发教程&#xff0c;内容将囊括基础、扩展和实战&a…

(每日持续更新)信息系统项目管理(第四版)(高级项目管理)考试重点整理 第13章 项目资源管理(一)

项目建议与立项申请、初步可行性研究、详细可行性研究、评估与决策是项目投资前使其的四个阶段。在实际工作中&#xff0c;初步可行性研究和详细可行性研究可以依据项目的规模和繁简程度合二为一&#xff0c;但详细可行性研究是不可缺少的。升级改造项目制作初步和详细研究&…

2024年十大前景职业揭晓!提前布局,抢占未来职场制高点!

随着科技的飞速发展和社会的不断进步&#xff0c;各行各业都在经历着翻天覆地的变化。2024年即将到来&#xff0c;哪些职业将会成为未来的热门选择呢&#xff1f;本文将为您揭晓2024年十大前景职业&#xff0c;助您提前布局&#xff0c;抢占未来职场制高点&#xff01; 一、人…

Covalent Network(CQT)将链下收入引入链上,在全新阶段开启 Token 回购

Covalent Network&#xff08;CQT&#xff09;&#xff0c;是 Web3 领域跨越 225 个链的领先数据索引服务商&#xff0c;通过统一 API 的方式提供结构化数据可用性服务&#xff0c;并正在成为 AI、DeFi、分析和治理等多样化需求的关键参与者。为了支持去中心化技术的采用&#…

分布式系统中常用的缓存方案

1. 引言 随着互联网应用的发展和规模的不断扩大&#xff0c;分布式系统中的缓存成为了提升性能和扩展性的重要手段之一。本文将介绍几种在分布式系统中常用的缓存方案&#xff0c;包括分布式内存缓存、分布式键值存储、分布式对象存储和缓存网关等。 1.1 缓存在分布式系统中的…

基于 Amazon EKS 的 Stable Diffusion ComfyUI 部署方案

01 背景介绍 Stable Diffusion 作为当下最流行的开源 AI 图像生成模型在游戏行业有着广泛的应用实践&#xff0c;无论是 ToC 面向玩家的游戏社区场景&#xff0c;还是 ToB 面向游戏工作室的美术制作场景&#xff0c;都可以发挥很大的价值&#xff0c;如何更好地使用 Stable Dif…

【高级数据结构】Trie树

原理 介绍 高效地存储和查询字符串的数据结构。所以其重点在于&#xff1a;存储、查询两个操作。 存储操作 示例和图片来自&#xff1a;https://blog.csdn.net/qq_42024195/article/details/88364485 假设有这么几个字符串&#xff1a;b&#xff0c;abc&#xff0c;abd&…

LVDS电平标准与LCD屏的LVDS数据格式

LVDS&#xff0c;全称Low-Voltage Differential Signaling&#xff0c;即“低电压差分信号”&#xff0c;有两种含义&#xff08;LVDS电平与LVDS协议&#xff09;&#xff0c;要根据具体的情况来区分对方说的是LCD屏的LVDS协议或者仅指LVDS电平标准。 举例&#xff1a;示波器测…

AI大预言模型——ChatGPT在地学、GIS、气象、农业、生态、环境应用

原文链接&#xff1a;AI大预言模型——ChatGPT在地学、GIS、气象、农业、生态、环境应用 一开启大模型 1 开启大模型 1)大模型的发展历程与最新功能 2)大模型的强大功能与应用场景 3)国内外经典大模型&#xff08;ChatGPT、LLaMA、Gemini、DALLE、Midjourney、Stable Diff…

aop监控spring cloud接口超时,并记录到数据库

引入pom <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0" xmlns:xsi"http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation"http://maven.apache.org/POM/4.0.0…