公司有一个需求:用户上传zip压缩包,然后后端接收该zip压缩包,然后进行解压到git目录,然后使用JGit操作Git把解压后的内容push到Git远程分支
Maven依赖如下:
<dependency>
<groupId>org.eclipse.jgit</groupId>
<artifactId>org.eclipse.jgit</artifactId>
<version>4.8.0.201706111038-r</version>
</dependency>
Controller层如下:
@PostMapping("/add/as/skin")
public ResultVO addAsSkin(@RequestParam("zipFile") MultipartFile file,
@Validated AddAsSkinReq req) {
AddAsSkinDTO dto = new AddAsSkinDTO();
BeanUtils.copyProperties(req, dto);
if (file.isEmpty()) {
// 这里自己定义返回的错误码
return ResultVO.failure(ResultCode.ERROR_CODE_100004);
}
byte[] zipFileBytes = null;
try {
zipFileBytes = IOUtils.toByteArray(file.getInputStream()); // IOUtils属于package org.apache.commons.io;
} catch (Exception e) {
// // 这里自己定义返回的错误码
e.printStackTrace();
return ResultVO.failure(ResultCode.ERROR_CODE_100000);
}
return rpcGmService.addAsSkin(zipFileBytes, dto, file.getOriginalFilename());
}
Service层如下:
@Override
public ResultVO addAsSkin(byte[] zipFileBytes, AddAsSkinDTO dto, String fileFullName) {
// 文件名(不包括扩展名)
String fileNameNoExtensionName = fileFullName.substring(0, fileFullName.lastIndexOf("."));
try {
// 用户上传的压缩包解压,然后git push到git远程分支
commonGameService.uploadZipAndUnzipAndGitPush(zipFileBytes, dto.getGameTemplateCode(), fileNameNoExtensionName);
return ResultVO.success();
} catch (Exception e) {
e.printStackTrace();
log.info("上传皮肤资源zip出现错误", e);
return ResultVO.failure(ResultCode.ERROR_CODE_100004);
}
}
uploadZipAndUnzipAndGitPush()方法如下:
public void uploadZipAndUnzipAndGitPush(byte[] zipFileBytes, String gameTemplateCode, String fileNameNoExtensionName) throws IOException, GitAPIException {
// 判断目录是否存在
boolean exist = FileUtil.exist(gitRefreshBean.getGmGitPath() + "\\" + ".git"); // FileUtil是Hutool的工具类,可以百度
if (exist) {
log.info("git路径{}存在,所以pull", gitRefreshBean.getGmGitPath());
Git git = Git.open(new File(gitRefreshBean.getGmGitPath()));
git.pull()
.setRemoteBranchName(gitRefreshBean.getGmGitRemoteBranchName())
.setCredentialsProvider(new UsernamePasswordCredentialsProvider(gitRefreshBean.getGmGitUser(), gitRefreshBean.getGmGitPassword()))
.call();
log.info("git pull远程分支{}成功", gitRefreshBean.getGmGitRemoteBranchName());
} else {
log.info("git路径{}不存在,所以clone", gitRefreshBean.getGmGitPath());
Git git = Git.cloneRepository()
.setURI(gitRefreshBean.getGmGitRemoteRepoUrl())
.setCredentialsProvider(new UsernamePasswordCredentialsProvider(gitRefreshBean.getGmGitUser(), gitRefreshBean.getGmGitPassword()))
.setBranch(gitRefreshBean.getGmGitRemoteBranchName()).setDirectory(new File(gitRefreshBean.getGmGitPath()))
.call();
log.info("git clone远程分支{}成功", gitRefreshBean.getGmGitRemoteBranchName());
}
// 删除git上原来的文件夹里面的文件(删除是因为万一用户删除了一些皮肤资源包, 而git不进行删除的, 会导致一直都在)
String gitFilePath = gitRefreshBean.getGmGitPath() + "\\" + "skin" + "\\" + gameTemplateCode;
String delPath = gitFilePath + "\\" + fileNameNoExtensionName;
FileUtil.del(delPath); // FileUtil是Hutool的工具类
log.info("删除目录{}成功", delPath);
// 解压zip文件到git路径
InputStream input = new ByteArrayInputStream(zipFileBytes);
ZipUtil.unzip(input, new File(gitFilePath), CharsetUtil.CHARSET_GBK); // ZipUtil是Hutool的工具类
log.info("解压成功,解压到目录{}", gitFilePath);
// push文件到git远程分支
gitPushMethod(gameTemplateCode + ":" + fileNameNoExtensionName);
}
gitPushMethod()方法如下:
private void gitPushMethod(String commitMsg) throws IOException, GitAPIException {
// 操作git的用户名
String user = gitRefreshBean.getGmGitUser();
// 密码
String password = gitRefreshBean.getGmGitPassword();
// git添加新的文件
Git gitPush = Git.open(new File(gitRefreshBean.getGmGitPath()));
AddCommand addCommand = gitPush.add();
// add操作 add -A操作在jgit不知道怎么用 没有尝试出来 有兴趣的可以看下JGit的API研究一下 欢迎留言
addCommand.addFilepattern(".").call();
Status status = gitPush.status().call();
int add = status.getAdded().size();
log.info("新增{}个文件", add);
int chang = status.getChanged().size();
log.info("变更{}个文件", chang);
int remove = status.getRemoved().size();
log.info("移除{}个文件", remove);
int miss = status.getMissing().size();
log.info("缺失{}个文件", miss);
int modified = status.getModified().size();
log.info("修改{}个文件", modified);
int conflicting = status.getConflicting().size();
log.info("有{}个冲突", conflicting);
int ignored = status.getIgnoredNotInIndex().size();
log.info("忽略{}个文件", ignored);
if (add == 0 && chang == 0 && remove == 0 && miss == 0 && modified == 0 && conflicting == 0 && ignored == 0) {
log.info("文件没有任何变动");
}
RmCommand rm = gitPush.rm();
// 循环add missing 的文件 没研究出missing和remove的区别 就是删除的文件也要提交到git
Set<String> missing = status.getMissing();
for(String m : missing) {
rm.addFilepattern(m).call();
// 需重新获取rm不然会报错
rm = gitPush.rm();
// 需重新获取status不然会报错
status = gitPush.status().call();
}
// 循环add remove 的文件
Set<String> removed = status.getRemoved();
for(String r : removed) {
rm.addFilepattern(r).call();
// 需重新获取rm不然会报错
rm = gitPush.rm();
// 需重新获取status不然会报错
status = gitPush.status().call();
}
// 提交
gitPush.commit().setMessage(commitMsg).call(); // 这里可以自己定义commit的消息
log.info("commit成功,commit的消息是{}", commitMsg);
// 推送
gitPush.push().setCredentialsProvider(new UsernamePasswordCredentialsProvider(user, password)).call();
log.info("push成功");
}
gitRefreshBean(是使用@Autowired注入的)如下:
@Component
@RefreshScope
@Data
public class GitRefreshBean {
/**
* git路径
*/
@Value("${gm.git.path}")
private String gmGitPath;
/**
* 远程分支地址
*/
@Value("${gm.git.remote.repo.uri}")
private String gmGitRemoteRepoUrl;
/**
* 操作git的用户名
*/
@Value("${gm.git.user}")
private String gmGitUser;
/**
* 操作git的密码
*/
@Value("${gm.git.password}")
private String gmGitPassword;
/**
* 分支名字
*/
@Value("${gm.git.remote.branch.name}")
private String gmGitRemoteBranchName;
}