refactor: application 模块代码重构,将部分 jgit 代码拆分开
This commit is contained in:
@@ -1,7 +1,6 @@
|
||||
package net.geedge.asw.module.app.controller;
|
||||
|
||||
import cn.hutool.json.JSONObject;
|
||||
import cn.hutool.log.Log;
|
||||
import jakarta.servlet.http.HttpServletResponse;
|
||||
import net.geedge.asw.common.util.ASWException;
|
||||
import net.geedge.asw.common.util.R;
|
||||
@@ -25,14 +24,100 @@ import java.util.stream.Collectors;
|
||||
@RequestMapping("/api/v1/workspace")
|
||||
public class ApplicationController {
|
||||
|
||||
private static final Log log = Log.get();
|
||||
|
||||
@Autowired
|
||||
private IWorkspaceService workspaceService;
|
||||
|
||||
@Autowired
|
||||
private IApplicationService applicationService;
|
||||
|
||||
@GetMapping("/{workspaceId}/branch/{branchName}/application/{applicationName}")
|
||||
public R infoApplication(@PathVariable("workspaceId") String workspaceId,
|
||||
@PathVariable("branchName") String branchName,
|
||||
@PathVariable("applicationName") String applicationName) {
|
||||
Map<Object, Object> record = applicationService.infoApplication(workspaceId, branchName, applicationName);
|
||||
return R.ok().putData("record", record);
|
||||
}
|
||||
|
||||
@GetMapping("/{workspaceId}/branch/{branchName}/application")
|
||||
public R listApplication(@PathVariable("workspaceId") String workspaceId,
|
||||
@PathVariable("branchName") String branchName,
|
||||
@RequestParam(value = "q", required = false) String q) {
|
||||
List<Map<Object, Object>> records = applicationService.listApplication(workspaceId, branchName, q);
|
||||
return R.ok().putData("records", records);
|
||||
}
|
||||
|
||||
@PostMapping("/{workspaceId}/branch/{branchName}/application")
|
||||
public synchronized R newApplication(@PathVariable("workspaceId") String workspaceId,
|
||||
@PathVariable("branchName") String branchName,
|
||||
@RequestBody Map<String, String> body) {
|
||||
String applicationName = T.MapUtil.getStr(body, "name");
|
||||
T.VerifyUtil.is(applicationName).notEmpty(RCode.PARAM_CANNOT_EMPTY);
|
||||
|
||||
applicationService.newApplication(workspaceId, branchName, applicationName);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
|
||||
@PostMapping("/{workspaceId}/branch/{branchName}/application/commit")
|
||||
public synchronized R updateApplication(@PathVariable("workspaceId") String workspaceId,
|
||||
@PathVariable("branchName") String branchName,
|
||||
@RequestBody Map<String, Object> body) {
|
||||
String lastCommitId = T.MapUtil.getStr(body, "lastCommitId");
|
||||
String message = T.MapUtil.getStr(body, "message");
|
||||
|
||||
T.VerifyUtil.is(lastCommitId).notEmpty(RCode.PARAM_CANNOT_EMPTY)
|
||||
.and(message).notEmpty(RCode.PARAM_CANNOT_EMPTY);
|
||||
|
||||
List<Map<String, String>> files = T.MapUtil.get(body, "files", List.class, T.ListUtil.list(true));
|
||||
if (T.CollUtil.isEmpty(files)) {
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
for (Map<String, String> file : files) {
|
||||
String action = T.MapUtil.getStr(file, "action");
|
||||
String path = T.MapUtil.getStr(file, "path");
|
||||
if (T.StrUtil.hasEmpty(action, path)) {
|
||||
return R.error(RCode.PARAM_CANNOT_EMPTY);
|
||||
}
|
||||
if (T.StrUtil.equalsAny(action, "create", "update")) {
|
||||
String content = T.MapUtil.getStr(file, "content");
|
||||
T.VerifyUtil.is(content).notEmpty(RCode.PARAM_CANNOT_EMPTY);
|
||||
}
|
||||
}
|
||||
applicationService.updateApplication(workspaceId, branchName, lastCommitId, message, files);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@DeleteMapping("/{workspaceId}/branch/{branchName}/application/{applicationName}")
|
||||
public synchronized R deleteApplication(@PathVariable("workspaceId") String workspaceId,
|
||||
@PathVariable("branchName") String branchName,
|
||||
@PathVariable("applicationName") String applicationName) {
|
||||
applicationService.deleteApplication(workspaceId, branchName, applicationName);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
|
||||
@GetMapping("/{workspaceId}/branch/{branchName}/application/{applicationName}/commit")
|
||||
public R listApplicationCommit(@PathVariable("workspaceId") String workspaceId,
|
||||
@PathVariable("branchName") String branchName,
|
||||
@PathVariable("applicationName") String applicationName,
|
||||
@RequestParam(required = false) String file) {
|
||||
List<Map<Object, Object>> records = applicationService.listApplicationCommit(workspaceId, branchName, applicationName, file);
|
||||
return R.ok().putData("records", records);
|
||||
}
|
||||
|
||||
|
||||
@GetMapping("/{workspaceId}/branch/{branchName}/application/{applicationName}/commit/{commitId}/content")
|
||||
public R infoApplicationFileContent(@PathVariable("workspaceId") String workspaceId,
|
||||
@PathVariable("branchName") String branchName,
|
||||
@PathVariable("applicationName") String applicationName,
|
||||
@PathVariable("commitId") String commitId,
|
||||
@RequestParam(required = true) String file) {
|
||||
Map<Object, Object> record = applicationService.infoApplicationFileContent(workspaceId, branchName, applicationName, commitId, file);
|
||||
return R.ok().putData("record", record);
|
||||
}
|
||||
|
||||
|
||||
@PostMapping("/{workspaceId}/branch/{branchName}/application/import")
|
||||
public synchronized R importApplication(@PathVariable("workspaceId") String workspaceId,
|
||||
@PathVariable("branchName") String branchName,
|
||||
@@ -85,7 +170,7 @@ public class ApplicationController {
|
||||
@RequestParam(defaultValue = "tsg2402") String format,
|
||||
HttpServletResponse response) throws IOException {
|
||||
// validate
|
||||
List<ApplicationEntity> appList = applicationService.queryList(workspaceId, branchName, T.StrUtil.splitToArray(names, ","));
|
||||
List<ApplicationEntity> appList = applicationService.listApplication(workspaceId, branchName, T.StrUtil.splitToArray(names, ","));
|
||||
T.VerifyUtil.is(appList).notEmpty(RCode.APP_NOT_EXIST);
|
||||
|
||||
// format
|
||||
@@ -95,4 +180,4 @@ public class ApplicationController {
|
||||
T.ResponseUtil.downloadFile(response, T.StrUtil.concat(true, "application_", System.currentTimeMillis() + ".json"), bytes);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
package net.geedge.asw.module.app.controller;
|
||||
|
||||
import net.geedge.asw.common.util.ASWException;
|
||||
import net.geedge.asw.common.util.R;
|
||||
import net.geedge.asw.common.util.RCode;
|
||||
import net.geedge.asw.common.util.T;
|
||||
import net.geedge.asw.module.app.service.IBranchService;
|
||||
import net.geedge.asw.module.app.util.JGitUtils;
|
||||
import net.geedge.asw.module.workspace.service.IWorkspaceService;
|
||||
import org.eclipse.jgit.lib.Repository;
|
||||
import org.eclipse.jgit.revwalk.RevCommit;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/v1/workspace")
|
||||
public class BranchController {
|
||||
|
||||
@Autowired
|
||||
private IBranchService branchService;
|
||||
|
||||
@Autowired
|
||||
private IWorkspaceService workspaceService;
|
||||
|
||||
@GetMapping("/{workspaceId}/branch")
|
||||
public R listBranch(@PathVariable("workspaceId") String workspaceId,
|
||||
@RequestParam(value = "search", required = false) String search) {
|
||||
List<Map<Object, Object>> list = branchService.listBranch(workspaceId, search);
|
||||
return R.ok().putData("records", list);
|
||||
}
|
||||
|
||||
@GetMapping("/{workspaceId}/branch/{branchName}")
|
||||
public R infoBranch(@PathVariable("workspaceId") String workspaceId, @PathVariable("branchName") String branchName) {
|
||||
Map<Object, Object> record = branchService.infoBranch(workspaceId, branchName);
|
||||
return R.ok().putData("record", record);
|
||||
}
|
||||
|
||||
@PostMapping("/{workspaceId}/branch")
|
||||
public synchronized R newBranch(@PathVariable("workspaceId") String workspaceId, @RequestBody Map<String, String> requestBody) {
|
||||
String branch = T.MapUtil.getStr(requestBody, "branch", "");
|
||||
String ref = T.MapUtil.getStr(requestBody, "ref", "");
|
||||
if (T.StrUtil.hasEmpty(branch, ref)) {
|
||||
throw new ASWException(RCode.PARAM_CANNOT_EMPTY);
|
||||
}
|
||||
|
||||
Map<Object, Object> record = branchService.newBranch(workspaceId, branch, ref);
|
||||
return R.ok().putData("record", record);
|
||||
}
|
||||
|
||||
@DeleteMapping("/{workspaceId}/branch/{branchName}")
|
||||
public synchronized R deleteBranch(@PathVariable("workspaceId") String workspaceId, @PathVariable("branchName") String branchName) {
|
||||
branchService.deleteBranch(workspaceId, branchName);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@GetMapping("/{workspaceId}/branch/{branchName}/commits")
|
||||
public R listBranchCommit(@PathVariable("workspaceId") String workspaceId,
|
||||
@PathVariable("branchName") String branchName,
|
||||
@RequestParam(required = false) String path,
|
||||
@RequestParam(required = false) Integer current,
|
||||
@RequestParam(required = false) Integer size) {
|
||||
List<Map<Object, Object>> records = branchService.listBranchCommit(workspaceId, branchName, path);
|
||||
long total = T.CollUtil.size(records);
|
||||
if (null != current && null != size) {
|
||||
int fromIndex = (current - 1) * size;
|
||||
int toIndex = Math.min(fromIndex + size, records.size());
|
||||
records = records.subList(fromIndex, toIndex);
|
||||
}
|
||||
return R.ok().putData("records", records).put("total", total);
|
||||
}
|
||||
|
||||
@GetMapping({
|
||||
"/{workspaceId}/branch/{branchName}/commit/{commitId}/diff",
|
||||
"/{workspaceId}/branch/{branchName}/commit/{commitId}/diff/{oldCommitId}"
|
||||
})
|
||||
public R branchCommitDiff(@PathVariable("workspaceId") String workspaceId,
|
||||
@PathVariable("branchName") String branchName,
|
||||
@PathVariable("commitId") String newCommitId,
|
||||
@PathVariable(value = "oldCommitId", required = false) String oldCommitId) throws IOException {
|
||||
|
||||
File gitDir = workspaceService.getGitDir(workspaceId);
|
||||
try (Repository repository = JGitUtils.openRepository(gitDir)) {
|
||||
if (T.StrUtil.isEmpty(oldCommitId)) {
|
||||
// oldCommitId 为空默认对比 parent commitId
|
||||
RevCommit parentCommit = JGitUtils.getParentCommit(repository, branchName, newCommitId);
|
||||
oldCommitId = parentCommit.getName();
|
||||
}
|
||||
|
||||
RevCommit oldCommit = JGitUtils.infoCommit(repository, oldCommitId);
|
||||
RevCommit newCommit = JGitUtils.infoCommit(repository, newCommitId);
|
||||
|
||||
List<Map<Object, Object>> diffList = JGitUtils.getDiffFileListInCommits(repository, newCommitId, oldCommitId);
|
||||
Map<Object, Object> record = T.MapUtil.builder()
|
||||
.put("oldBranch", branchName)
|
||||
.put("newBranch", branchName)
|
||||
.put("oldCommitId", oldCommitId)
|
||||
.put("newCommitId", newCommitId)
|
||||
.put("oldCommit", JGitUtils.buildAswCommitInfo(oldCommit))
|
||||
.put("newCommit", JGitUtils.buildAswCommitInfo(newCommit))
|
||||
.put("files", diffList)
|
||||
.build();
|
||||
return R.ok().putData("record", record);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,277 +0,0 @@
|
||||
package net.geedge.asw.module.app.controller;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import net.geedge.asw.common.util.ASWException;
|
||||
import net.geedge.asw.common.util.R;
|
||||
import net.geedge.asw.common.util.RCode;
|
||||
import net.geedge.asw.common.util.T;
|
||||
import net.geedge.asw.module.app.entity.ApplicationMergeEntity;
|
||||
import net.geedge.asw.module.app.service.IApplicationMergeService;
|
||||
import net.geedge.asw.module.app.service.IGitService;
|
||||
import net.geedge.asw.module.app.service.impl.ApplicationMergeServiceImpl.MergeRequestStatus;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/v1/workspace")
|
||||
public class GitController {
|
||||
|
||||
@Autowired
|
||||
private IGitService gitService;
|
||||
|
||||
@Autowired
|
||||
private IApplicationMergeService applicationMergeService;
|
||||
|
||||
@GetMapping("/{workspaceId}/branch")
|
||||
public R listBranch(@PathVariable("workspaceId") String workspaceId,
|
||||
@RequestParam(value = "search", required = false) String search) {
|
||||
List<Map<Object, Object>> list = gitService.listBranch(workspaceId, search);
|
||||
return R.ok().putData("records", list);
|
||||
}
|
||||
|
||||
@GetMapping("/{workspaceId}/branch/{branchName}")
|
||||
public R infoBranch(@PathVariable("workspaceId") String workspaceId, @PathVariable("branchName") String branchName) {
|
||||
Map<Object, Object> record = gitService.infoBranch(workspaceId, branchName);
|
||||
return R.ok().putData("record", record);
|
||||
}
|
||||
|
||||
@PostMapping("/{workspaceId}/branch")
|
||||
public R newBranch(@PathVariable("workspaceId") String workspaceId, @RequestBody Map<String, String> requestBody) {
|
||||
String branch = T.MapUtil.getStr(requestBody, "branch", "");
|
||||
String ref = T.MapUtil.getStr(requestBody, "ref", "");
|
||||
if (T.StrUtil.hasEmpty(branch, ref)) {
|
||||
throw new ASWException(RCode.PARAM_CANNOT_EMPTY);
|
||||
}
|
||||
|
||||
Map<Object, Object> record = gitService.newBranch(workspaceId, branch, ref);
|
||||
return R.ok().putData("record", record);
|
||||
}
|
||||
|
||||
@DeleteMapping("/{workspaceId}/branch/{branchName}")
|
||||
public R deleteBranch(@PathVariable("workspaceId") String workspaceId, @PathVariable("branchName") String branchName) {
|
||||
gitService.deleteBranch(workspaceId, branchName);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@GetMapping("/{workspaceId}/branch/{branchName}/commits")
|
||||
public R listBranchCommit(@PathVariable("workspaceId") String workspaceId,
|
||||
@PathVariable("branchName") String branchName,
|
||||
@RequestParam(required = false) String path,
|
||||
@RequestParam(required = false) Integer current,
|
||||
@RequestParam(required = false) Integer size) {
|
||||
List<Map<Object, Object>> records = gitService.listBranchCommit(workspaceId, branchName, path);
|
||||
long total = T.CollUtil.size(records);
|
||||
if (null != current && null != size) {
|
||||
int fromIndex = (current - 1) * size;
|
||||
int toIndex = Math.min(fromIndex + size, records.size());
|
||||
records = records.subList(fromIndex, toIndex);
|
||||
}
|
||||
return R.ok().putData("records", records).put("total", total);
|
||||
}
|
||||
|
||||
@GetMapping({
|
||||
"/{workspaceId}/branch/{branchName}/commit/{commitId}/diff",
|
||||
"/{workspaceId}/branch/{branchName}/commit/{commitId}/diff/{oldCommitId}"
|
||||
})
|
||||
public R branchCommitDiff(@PathVariable("workspaceId") String workspaceId,
|
||||
@PathVariable("branchName") String branchName,
|
||||
@PathVariable("commitId") String newCommitId,
|
||||
@PathVariable(value = "oldCommitId", required = false) String oldCommitId) {
|
||||
|
||||
if (T.StrUtil.isEmpty(oldCommitId)) {
|
||||
// oldCommitId 为空默认对比 parent commitId
|
||||
oldCommitId = gitService.getParentCommitId(workspaceId, branchName, newCommitId);
|
||||
}
|
||||
|
||||
Map<Object, Object> oldCommit = gitService.infoCommit(workspaceId, oldCommitId);
|
||||
Map<Object, Object> newCommit = gitService.infoCommit(workspaceId, newCommitId);
|
||||
|
||||
List<Map<Object, Object>> diffList = gitService.getDiffFileListInCommits(workspaceId, newCommitId, oldCommitId);
|
||||
Map<Object, Object> record = T.MapUtil.builder()
|
||||
.put("oldBranch", branchName)
|
||||
.put("newBranch", branchName)
|
||||
.put("oldCommitId", oldCommitId)
|
||||
.put("newCommitId", newCommitId)
|
||||
.put("oldCommit", oldCommit)
|
||||
.put("newCommit", newCommit)
|
||||
.put("files", diffList)
|
||||
.build();
|
||||
return R.ok().putData("record", record);
|
||||
}
|
||||
|
||||
@GetMapping("/{workspaceId}/branch/{branchName}/application")
|
||||
public R listApplication(@PathVariable("workspaceId") String workspaceId,
|
||||
@PathVariable("branchName") String branchName,
|
||||
@RequestParam(value = "q", required = false) String q) {
|
||||
List<Map<Object, Object>> records = gitService.listApplication(workspaceId, branchName, q);
|
||||
return R.ok().putData("records", records);
|
||||
}
|
||||
|
||||
@GetMapping("/{workspaceId}/branch/{branchName}/application/{applicationName}")
|
||||
public R infoApplication(@PathVariable("workspaceId") String workspaceId,
|
||||
@PathVariable("branchName") String branchName,
|
||||
@PathVariable("applicationName") String applicationName) {
|
||||
Map<Object, Object> record = gitService.infoApplication(workspaceId, branchName, applicationName);
|
||||
return R.ok().putData("record", record);
|
||||
}
|
||||
|
||||
@PostMapping("/{workspaceId}/branch/{branchName}/application")
|
||||
public synchronized R newApplication(@PathVariable("workspaceId") String workspaceId,
|
||||
@PathVariable("branchName") String branchName,
|
||||
@RequestBody Map<String, String> body) {
|
||||
String applicationName = T.MapUtil.getStr(body, "name");
|
||||
T.VerifyUtil.is(applicationName).notEmpty(RCode.PARAM_CANNOT_EMPTY);
|
||||
|
||||
gitService.newApplication(workspaceId, branchName, applicationName);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
|
||||
@PostMapping("/{workspaceId}/branch/{branchName}/application/commit")
|
||||
public synchronized R updateApplication(@PathVariable("workspaceId") String workspaceId,
|
||||
@PathVariable("branchName") String branchName,
|
||||
@RequestBody Map<String, Object> body) {
|
||||
String lastCommitId = T.MapUtil.getStr(body, "lastCommitId");
|
||||
String message = T.MapUtil.getStr(body, "message");
|
||||
|
||||
T.VerifyUtil.is(lastCommitId).notEmpty(RCode.PARAM_CANNOT_EMPTY)
|
||||
.and(message).notEmpty(RCode.PARAM_CANNOT_EMPTY);
|
||||
|
||||
List<Map<String, String>> files = T.MapUtil.get(body, "files", List.class, T.ListUtil.list(true));
|
||||
if (T.CollUtil.isEmpty(files)) {
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
for (Map<String, String> file : files) {
|
||||
String action = T.MapUtil.getStr(file, "action");
|
||||
String path = T.MapUtil.getStr(file, "path");
|
||||
if (T.StrUtil.hasEmpty(action, path)) {
|
||||
return R.error(RCode.PARAM_CANNOT_EMPTY);
|
||||
}
|
||||
if (T.StrUtil.equalsAny(action, "create", "update")) {
|
||||
String content = T.MapUtil.getStr(file, "content");
|
||||
T.VerifyUtil.is(content).notEmpty(RCode.PARAM_CANNOT_EMPTY);
|
||||
}
|
||||
}
|
||||
gitService.updateApplication(workspaceId, branchName, lastCommitId, message, files);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@DeleteMapping("/{workspaceId}/branch/{branchName}/application/{applicationName}")
|
||||
public synchronized R deleteApplication(@PathVariable("workspaceId") String workspaceId,
|
||||
@PathVariable("branchName") String branchName,
|
||||
@PathVariable("applicationName") String applicationName) {
|
||||
gitService.deleteApplication(workspaceId, branchName, applicationName);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
|
||||
@GetMapping("/{workspaceId}/branch/{branchName}/application/{applicationName}/commit")
|
||||
public R listApplicationCommit(@PathVariable("workspaceId") String workspaceId,
|
||||
@PathVariable("branchName") String branchName,
|
||||
@PathVariable("applicationName") String applicationName,
|
||||
@RequestParam(required = false) String file) {
|
||||
List<Map<Object, Object>> records = gitService.listApplicationCommit(workspaceId, branchName, applicationName, file);
|
||||
return R.ok().putData("records", records);
|
||||
}
|
||||
|
||||
|
||||
@GetMapping("/{workspaceId}/branch/{branchName}/application/{applicationName}/commit/{commitId}/content")
|
||||
public R infoApplicationFileContent(@PathVariable("workspaceId") String workspaceId,
|
||||
@PathVariable("branchName") String branchName,
|
||||
@PathVariable("applicationName") String applicationName,
|
||||
@PathVariable("commitId") String commitId,
|
||||
@RequestParam(required = true) String file) {
|
||||
Map<Object, Object> record = gitService.infoApplicationFileContent(workspaceId, branchName, applicationName, commitId, file);
|
||||
return R.ok().putData("record", record);
|
||||
}
|
||||
|
||||
@GetMapping("/{workspaceId}/mr")
|
||||
public R listMr(@PathVariable("workspaceId") String workspaceId, @RequestParam Map<String, Object> params) {
|
||||
// workspaceId
|
||||
params = T.MapUtil.defaultIfEmpty(params, new HashMap<>());
|
||||
params.put("workspaceId", workspaceId);
|
||||
|
||||
Page page = applicationMergeService.queryList(params);
|
||||
return R.ok(page);
|
||||
}
|
||||
|
||||
@GetMapping("/{workspaceId}/mr/{mrId}")
|
||||
public R infoMr(@PathVariable("mrId") String mrId) {
|
||||
ApplicationMergeEntity record = applicationMergeService.queryInfo(mrId);
|
||||
return R.ok().putData("record", record);
|
||||
}
|
||||
|
||||
@GetMapping("/{workspaceId}/mr/{mrId}/commits")
|
||||
public R listMrCommit(@PathVariable("mrId") String mrId) {
|
||||
List<Map<Object, Object>> records = applicationMergeService.listMrCommit(mrId);
|
||||
return R.ok().putData("records", records);
|
||||
}
|
||||
|
||||
@GetMapping("/{workspaceId}/mr/{mrId}/diffs")
|
||||
public R mrDiff(@PathVariable("mrId") String mrId) {
|
||||
Map<Object, Object> record = applicationMergeService.mrCommitDiff(mrId);
|
||||
return R.ok().putData("record", record);
|
||||
}
|
||||
|
||||
@GetMapping("/{workspaceId}/mr/{mrId}/conflicts")
|
||||
public R getMrConflictList(@PathVariable("mrId") String mrId) {
|
||||
Map<Object, Object> record = applicationMergeService.getMrConflictList(mrId);
|
||||
return R.ok().putData("record", record);
|
||||
}
|
||||
|
||||
@PostMapping("/{workspaceId}/mr/{mrId}/conflicts")
|
||||
public R resolveMrConflicts(@PathVariable("mrId") String mrId, @RequestBody Map<String, Object> body) {
|
||||
String commitId = T.MapUtil.getStr(body, "commitId");
|
||||
String commitMessage = T.MapUtil.getStr(body, "commitMessage");
|
||||
List<Map<String, String>> files = T.MapUtil.get(body, "files", List.class, new ArrayList());
|
||||
T.VerifyUtil.is(commitId).notEmpty(RCode.PARAM_CANNOT_EMPTY)
|
||||
.and(commitMessage).notEmpty(RCode.PARAM_CANNOT_EMPTY)
|
||||
.and(files).notEmpty(RCode.PARAM_CANNOT_EMPTY);
|
||||
|
||||
for (Map<String, String> m : files) {
|
||||
String path = T.MapUtil.getStr(m, "path");
|
||||
String content = T.MapUtil.getStr(m, "content");
|
||||
T.VerifyUtil.is(path).notEmpty(RCode.PARAM_CANNOT_EMPTY)
|
||||
.and(content).notEmpty(RCode.PARAM_CANNOT_EMPTY);
|
||||
}
|
||||
|
||||
applicationMergeService.resolveMrConflicts(mrId, body);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@PostMapping("/{workspaceId}/mr")
|
||||
public R newMr(@PathVariable("workspaceId") String workspaceId, @RequestBody ApplicationMergeEntity entity) {
|
||||
T.VerifyUtil.is(entity).notNull()
|
||||
.and(entity.getTitle()).notEmpty(RCode.PARAM_CANNOT_EMPTY)
|
||||
.and(entity.getTargetBranch()).notEmpty(RCode.PARAM_CANNOT_EMPTY)
|
||||
.and(entity.getTargetBranch()).notEmpty(RCode.PARAM_CANNOT_EMPTY);
|
||||
|
||||
// workspaceId
|
||||
entity.setWorkspaceId(workspaceId);
|
||||
|
||||
ApplicationMergeEntity record = applicationMergeService.newMr(entity);
|
||||
return R.ok().putData("record", record);
|
||||
}
|
||||
|
||||
@PutMapping("/{workspaceId}/mr/{mrId}")
|
||||
public synchronized R mergeMr(@PathVariable("mrId") String mrId, @RequestBody(required = false) Map<String, Object> body) {
|
||||
String action = T.MapUtil.getStr(body, "action");
|
||||
T.VerifyUtil.is(action).notEmpty(RCode.PARAM_CANNOT_EMPTY);
|
||||
|
||||
ApplicationMergeEntity record = applicationMergeService.mergeMr(mrId, action);
|
||||
if(T.BooleanUtil.and(
|
||||
T.ObjectUtil.equals("merge", action),
|
||||
T.ObjectUtil.notEqual(MergeRequestStatus.MERGED.toString(), record.getStatus())
|
||||
)){
|
||||
return R.error(RCode.GIT_MERGE_FAILED).putData("record", record);
|
||||
}
|
||||
return R.ok().putData("record", record);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
package net.geedge.asw.module.app.controller;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import net.geedge.asw.common.util.R;
|
||||
import net.geedge.asw.common.util.RCode;
|
||||
import net.geedge.asw.common.util.T;
|
||||
import net.geedge.asw.module.app.entity.ApplicationMergeEntity;
|
||||
import net.geedge.asw.module.app.service.IApplicationMergeService;
|
||||
import net.geedge.asw.module.app.service.impl.ApplicationMergeServiceImpl.MergeRequestStatus;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/v1/workspace")
|
||||
public class MergeRequestController {
|
||||
|
||||
@Autowired
|
||||
private IApplicationMergeService applicationMergeService;
|
||||
|
||||
@GetMapping("/{workspaceId}/mr")
|
||||
public R listMr(@PathVariable("workspaceId") String workspaceId, @RequestParam Map<String, Object> params) {
|
||||
// workspaceId
|
||||
params = T.MapUtil.defaultIfEmpty(params, new HashMap<>());
|
||||
params.put("workspaceId", workspaceId);
|
||||
|
||||
Page page = applicationMergeService.queryList(params);
|
||||
return R.ok(page);
|
||||
}
|
||||
|
||||
@GetMapping("/{workspaceId}/mr/{mrId}")
|
||||
public R infoMr(@PathVariable("mrId") String mrId) {
|
||||
ApplicationMergeEntity record = applicationMergeService.queryInfo(mrId);
|
||||
return R.ok().putData("record", record);
|
||||
}
|
||||
|
||||
@GetMapping("/{workspaceId}/mr/{mrId}/commits")
|
||||
public R listMrCommit(@PathVariable("mrId") String mrId) throws IOException {
|
||||
List<Map<Object, Object>> records = applicationMergeService.listMrCommit(mrId);
|
||||
return R.ok().putData("records", records);
|
||||
}
|
||||
|
||||
@GetMapping("/{workspaceId}/mr/{mrId}/diffs")
|
||||
public R mrDiff(@PathVariable("mrId") String mrId) {
|
||||
Map<Object, Object> record = applicationMergeService.mrCommitDiff(mrId);
|
||||
return R.ok().putData("record", record);
|
||||
}
|
||||
|
||||
@GetMapping("/{workspaceId}/mr/{mrId}/conflicts")
|
||||
public R getMrConflictList(@PathVariable("mrId") String mrId) throws IOException {
|
||||
Map<Object, Object> record = applicationMergeService.getMrConflictList(mrId);
|
||||
return R.ok().putData("record", record);
|
||||
}
|
||||
|
||||
@PostMapping("/{workspaceId}/mr/{mrId}/conflicts")
|
||||
public R resolveMrConflicts(@PathVariable("mrId") String mrId, @RequestBody Map<String, Object> body) throws IOException{
|
||||
String commitId = T.MapUtil.getStr(body, "commitId");
|
||||
String commitMessage = T.MapUtil.getStr(body, "commitMessage");
|
||||
List<Map<String, String>> files = T.MapUtil.get(body, "files", List.class, new ArrayList());
|
||||
T.VerifyUtil.is(commitId).notEmpty(RCode.PARAM_CANNOT_EMPTY)
|
||||
.and(commitMessage).notEmpty(RCode.PARAM_CANNOT_EMPTY)
|
||||
.and(files).notEmpty(RCode.PARAM_CANNOT_EMPTY);
|
||||
|
||||
for (Map<String, String> m : files) {
|
||||
String path = T.MapUtil.getStr(m, "path");
|
||||
String content = T.MapUtil.getStr(m, "content");
|
||||
T.VerifyUtil.is(path).notEmpty(RCode.PARAM_CANNOT_EMPTY)
|
||||
.and(content).notEmpty(RCode.PARAM_CANNOT_EMPTY);
|
||||
}
|
||||
|
||||
applicationMergeService.resolveMrConflicts(mrId, body);
|
||||
return R.ok();
|
||||
}
|
||||
|
||||
@PostMapping("/{workspaceId}/mr")
|
||||
public R newMr(@PathVariable("workspaceId") String workspaceId, @RequestBody ApplicationMergeEntity entity) throws IOException {
|
||||
T.VerifyUtil.is(entity).notNull()
|
||||
.and(entity.getTitle()).notEmpty(RCode.PARAM_CANNOT_EMPTY)
|
||||
.and(entity.getTargetBranch()).notEmpty(RCode.PARAM_CANNOT_EMPTY)
|
||||
.and(entity.getTargetBranch()).notEmpty(RCode.PARAM_CANNOT_EMPTY);
|
||||
|
||||
// workspaceId
|
||||
entity.setWorkspaceId(workspaceId);
|
||||
|
||||
ApplicationMergeEntity record = applicationMergeService.newMr(entity);
|
||||
return R.ok().putData("record", record);
|
||||
}
|
||||
|
||||
@PutMapping("/{workspaceId}/mr/{mrId}")
|
||||
public synchronized R mergeMr(@PathVariable("mrId") String mrId, @RequestBody(required = false) Map<String, Object> body) {
|
||||
String action = T.MapUtil.getStr(body, "action");
|
||||
T.VerifyUtil.is(action).notEmpty(RCode.PARAM_CANNOT_EMPTY);
|
||||
|
||||
ApplicationMergeEntity record = applicationMergeService.mergeMr(mrId, action);
|
||||
if(T.BooleanUtil.and(
|
||||
T.ObjectUtil.equals("merge", action),
|
||||
T.ObjectUtil.notEqual(MergeRequestStatus.MERGED.toString(), record.getStatus())
|
||||
)){
|
||||
return R.error(RCode.GIT_MERGE_FAILED).putData("record", record);
|
||||
}
|
||||
return R.ok().putData("record", record);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import net.geedge.asw.module.app.entity.ApplicationMergeEntity;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -13,15 +14,15 @@ public interface IApplicationMergeService extends IService<ApplicationMergeEntit
|
||||
|
||||
Page queryList(Map<String, Object> params);
|
||||
|
||||
ApplicationMergeEntity newMr(ApplicationMergeEntity entity);
|
||||
ApplicationMergeEntity newMr(ApplicationMergeEntity entity) throws IOException;
|
||||
|
||||
List<Map<Object, Object>> listMrCommit(String mrId);
|
||||
List<Map<Object, Object>> listMrCommit(String mrId) throws IOException;
|
||||
|
||||
Map<Object, Object> mrCommitDiff(String mrId);
|
||||
|
||||
Map<Object, Object> getMrConflictList(String mrId);
|
||||
Map<Object, Object> getMrConflictList(String mrId) throws IOException;
|
||||
|
||||
void resolveMrConflicts(String mrId, Map<String, Object> body);
|
||||
void resolveMrConflicts(String mrId, Map<String, Object> body) throws IOException;
|
||||
|
||||
ApplicationMergeEntity mergeMr(String mrId, String action);
|
||||
|
||||
|
||||
@@ -4,13 +4,28 @@ import cn.hutool.json.JSONObject;
|
||||
import net.geedge.asw.module.app.entity.ApplicationEntity;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public interface IApplicationService {
|
||||
|
||||
List<ApplicationEntity> queryList(String workspaceId, String branchName, String... names);
|
||||
Map<Object, Object> infoApplication(String workspaceId, String branch, String name);
|
||||
|
||||
List<ApplicationEntity> listApplication(String workspaceId, String branch, String... names);
|
||||
|
||||
List<Map<Object, Object>> listApplication(String workspaceId, String branch, String q);
|
||||
|
||||
void newApplication(String workspaceId, String branch, String name);
|
||||
|
||||
void deleteApplication(String workspaceId, String branch, String name);
|
||||
|
||||
void updateApplication(String workspaceId, String branch, String lastCommitId, String message, List<Map<String, String>> updateContent);
|
||||
|
||||
List<Map<Object, Object>> listApplicationCommit(String workspaceId, String branch, String name, String file);
|
||||
|
||||
Map<Object, Object> infoApplicationFileContent(String workspaceId, String branch, String name, String commitId, String file);
|
||||
|
||||
byte[] exportAppByFormat(List<ApplicationEntity> appList, String format);
|
||||
|
||||
List<ApplicationEntity> importAppByFormat(String workspaceId, String branchName, String format, List<JSONObject> dataList);
|
||||
List<ApplicationEntity> importAppByFormat(String workspaceId, String branch, String format, List<JSONObject> dataList);
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
package net.geedge.asw.module.app.service;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public interface IBranchService {
|
||||
|
||||
List<Map<Object, Object>> listBranch(String workspaceId, String search);
|
||||
|
||||
Map<Object, Object> infoBranch(String workspaceId, String branch);
|
||||
|
||||
Map<Object, Object> newBranch(String workspaceId, String name, String ref);
|
||||
|
||||
void deleteBranch(String workspaceId, String branch);
|
||||
|
||||
List<Map<Object, Object>> listBranchCommit(String workspaceId, String branch, String path);
|
||||
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
package net.geedge.asw.module.app.service;
|
||||
|
||||
import org.eclipse.jgit.api.Git;
|
||||
import org.eclipse.jgit.api.errors.ConcurrentRefUpdateException;
|
||||
import org.eclipse.jgit.dircache.DirCache;
|
||||
import org.eclipse.jgit.dircache.DirCacheEntry;
|
||||
import org.eclipse.jgit.lib.FileMode;
|
||||
import org.eclipse.jgit.lib.ObjectId;
|
||||
import org.eclipse.jgit.lib.Repository;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public interface IGitService {
|
||||
|
||||
Git getGitInstance(String workspaceId);
|
||||
|
||||
Repository initRepository(String workspaceId);
|
||||
|
||||
Map<Object, Object> infoCommit(String workspaceId, String commitId);
|
||||
|
||||
List<Map<Object, Object>> listBranch(String workspaceId, String search);
|
||||
|
||||
Map<Object, Object> infoBranch(String workspaceId, String branch);
|
||||
|
||||
Map<Object, Object> newBranch(String workspaceId, String branch, String ref);
|
||||
|
||||
void deleteBranch(String workspaceId, String branch);
|
||||
|
||||
boolean isBranchExists(String workspaceId, String branch);
|
||||
|
||||
List<Map<Object, Object>> listBranchCommit(String workspaceId, String branch, String path);
|
||||
|
||||
String getParentCommitId(String workspaceId, String branch, String commitId);
|
||||
|
||||
String getLatestCommitId(String workspaceId, String branch);
|
||||
|
||||
String getMergeBase(String workspaceId, String branchA, String branchB);
|
||||
|
||||
ObjectId insertBlobFileToDatabase(Repository repository, byte[] data) throws IOException;
|
||||
|
||||
DirCacheEntry buildDirCacheEntry(String path, FileMode mode, ObjectId objectId);
|
||||
|
||||
List<Map<Object, Object>> getDiffFileListInCommits(String workspaceId, String newCommitId, String oldCommitId);
|
||||
|
||||
String mergeBranch(String workspaceId, String sourceBranch, String targetBranch, String message, List<Map<String, String>> resolveConflictFileContent) throws RuntimeException;
|
||||
|
||||
List<Map<Object, Object>> listApplication(String workspaceId, String branch, String q);
|
||||
|
||||
Map<Object, Object> infoApplication(String workspaceId, String branch, String applicationName);
|
||||
|
||||
void newApplication(String workspaceId, String branch, String applicationName);
|
||||
|
||||
void deleteApplication(String workspaceId, String branch, String applicationName);
|
||||
|
||||
void updateApplication(String workspaceId, String branch, String lastCommitId, String message, List<Map<String, String>> updateContent);
|
||||
|
||||
List<Map<Object, Object>> listApplicationCommit(String workspaceId, String branch, String applicationName, String file);
|
||||
|
||||
Map<Object, Object> infoApplicationFileContent(String workspaceId, String branch, String applicationName, String commitId, String file);
|
||||
|
||||
List<Map<Object, Object>> listCommitRange(String workspaceId, String newCommitId, String oldCommitId);
|
||||
|
||||
List<String> getConflictFilePathInBranches(String workspaceId, String srcBranch, String tgtBranch);
|
||||
|
||||
List<Map<Object, Object>> getConflictFileInfoInBranches(String workspaceId, String srcBranch, String tgtBranch);
|
||||
|
||||
boolean commitIndex(Repository repo, String branch, DirCache index, ObjectId parentId1, ObjectId parentId2, String message) throws IOException, ConcurrentRefUpdateException;
|
||||
|
||||
}
|
||||
@@ -13,12 +13,20 @@ import net.geedge.asw.common.util.T;
|
||||
import net.geedge.asw.module.app.dao.ApplicationMergeDao;
|
||||
import net.geedge.asw.module.app.entity.ApplicationMergeEntity;
|
||||
import net.geedge.asw.module.app.service.IApplicationMergeService;
|
||||
import net.geedge.asw.module.app.service.IGitService;
|
||||
import net.geedge.asw.module.app.service.IBranchService;
|
||||
import net.geedge.asw.module.app.util.JGitUtils;
|
||||
import net.geedge.asw.module.sys.entity.SysUserEntity;
|
||||
import net.geedge.asw.module.sys.service.ISysUserService;
|
||||
import net.geedge.asw.module.workspace.service.IWorkspaceService;
|
||||
import org.eclipse.jgit.api.errors.GitAPIException;
|
||||
import org.eclipse.jgit.lib.ObjectId;
|
||||
import org.eclipse.jgit.lib.Repository;
|
||||
import org.eclipse.jgit.revwalk.RevCommit;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -29,10 +37,13 @@ public class ApplicationMergeServiceImpl extends ServiceImpl<ApplicationMergeDao
|
||||
private final static Log log = Log.get();
|
||||
|
||||
@Autowired
|
||||
private IGitService gitService;
|
||||
private ISysUserService userService;
|
||||
|
||||
@Autowired
|
||||
private ISysUserService userService;
|
||||
private IBranchService branchService;
|
||||
|
||||
@Autowired
|
||||
private IWorkspaceService workspaceService;
|
||||
|
||||
@Override
|
||||
public ApplicationMergeEntity queryInfo(String mrId) {
|
||||
@@ -53,7 +64,7 @@ public class ApplicationMergeServiceImpl extends ServiceImpl<ApplicationMergeDao
|
||||
}
|
||||
|
||||
@Override
|
||||
public ApplicationMergeEntity newMr(ApplicationMergeEntity entity) {
|
||||
public ApplicationMergeEntity newMr(ApplicationMergeEntity entity) throws IOException {
|
||||
entity.setCreateTimestamp(System.currentTimeMillis());
|
||||
entity.setCreateUserId(StpUtil.getLoginIdAsString());
|
||||
|
||||
@@ -62,10 +73,14 @@ public class ApplicationMergeServiceImpl extends ServiceImpl<ApplicationMergeDao
|
||||
|
||||
// start_commit_id
|
||||
String workspaceId = entity.getWorkspaceId();
|
||||
String sourceBranch = entity.getSourceBranch();
|
||||
String targetBranch = entity.getTargetBranch();
|
||||
String mergeBase = gitService.getMergeBase(workspaceId, sourceBranch, targetBranch);
|
||||
entity.setStartCommitId(mergeBase);
|
||||
File gitDir = workspaceService.getGitDir(workspaceId);
|
||||
try (Repository repository = JGitUtils.openRepository(gitDir)) {
|
||||
ObjectId branchAId = repository.resolve(entity.getSourceBranch());
|
||||
ObjectId branchBId = repository.resolve(entity.getTargetBranch());
|
||||
|
||||
RevCommit mergeBaseCommit = JGitUtils.getMergeBaseCommit(repository, branchAId, branchBId);
|
||||
entity.setStartCommitId(mergeBaseCommit.getName());
|
||||
}
|
||||
|
||||
// save
|
||||
this.save(entity);
|
||||
@@ -76,29 +91,36 @@ public class ApplicationMergeServiceImpl extends ServiceImpl<ApplicationMergeDao
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Map<Object, Object>> listMrCommit(String mrId) {
|
||||
public List<Map<Object, Object>> listMrCommit(String mrId) throws IOException {
|
||||
ApplicationMergeEntity entity = this.getById(mrId);
|
||||
T.VerifyUtil.is(entity).notEmpty(RCode.SYS_RECORD_NOT_FOUND);
|
||||
|
||||
String workspaceId = entity.getWorkspaceId();
|
||||
String oldCommitId = entity.getStartCommitId();
|
||||
String newCommitId = null;
|
||||
MergeRequestStatus mergeRequestStatus = MergeRequestStatus.getInstance(entity.getStatus());
|
||||
switch (mergeRequestStatus) {
|
||||
case OPEN: {
|
||||
newCommitId = gitService.getLatestCommitId(workspaceId, entity.getSourceBranch());
|
||||
break;
|
||||
}
|
||||
case CLOSED:
|
||||
case MERGED: {
|
||||
newCommitId = entity.getEndCommitId();
|
||||
break;
|
||||
}
|
||||
}
|
||||
File gitDir = workspaceService.getGitDir(workspaceId);
|
||||
|
||||
// newCommitId-oldCommitId 期间的提交信息
|
||||
List<Map<Object, Object>> commitRange = gitService.listCommitRange(workspaceId, newCommitId, oldCommitId);
|
||||
return commitRange;
|
||||
try (Repository repository = JGitUtils.openRepository(gitDir)) {
|
||||
String oldCommitId = entity.getStartCommitId();
|
||||
String newCommitId = null;
|
||||
MergeRequestStatus mergeRequestStatus = MergeRequestStatus.getInstance(entity.getStatus());
|
||||
switch (mergeRequestStatus) {
|
||||
case OPEN: {
|
||||
newCommitId = JGitUtils.getBranchLatestCommit(repository, entity.getSourceBranch()).getName();
|
||||
break;
|
||||
}
|
||||
case CLOSED:
|
||||
case MERGED: {
|
||||
newCommitId = entity.getEndCommitId();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// newCommitId-oldCommitId 期间的提交信息
|
||||
List<RevCommit> revCommits = JGitUtils.listCommitRange(repository, newCommitId, oldCommitId);
|
||||
|
||||
List<Map<Object, Object>> list = T.ListUtil.list(true);
|
||||
revCommits.forEach(revCommit -> list.add(JGitUtils.buildAswCommitInfo(revCommit)));
|
||||
return list;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -107,103 +129,115 @@ public class ApplicationMergeServiceImpl extends ServiceImpl<ApplicationMergeDao
|
||||
T.VerifyUtil.is(entity).notEmpty(RCode.SYS_RECORD_NOT_FOUND);
|
||||
|
||||
String workspaceId = entity.getWorkspaceId();
|
||||
String sourceBranch = entity.getSourceBranch();
|
||||
String targetBranch = entity.getTargetBranch();
|
||||
File gitDir = workspaceService.getGitDir(workspaceId);
|
||||
|
||||
// 获取 sourceBranch,targetBranch 合并冲突文件
|
||||
List<String> conflictFileList = T.ListUtil.list(true);
|
||||
try (Repository repository = JGitUtils.openRepository(gitDir)) {
|
||||
String sourceBranch = entity.getSourceBranch();
|
||||
String targetBranch = entity.getTargetBranch();
|
||||
|
||||
// src branch changed files
|
||||
String oldCommitId = entity.getStartCommitId();
|
||||
String newCommitId = null;
|
||||
MergeRequestStatus mergeRequestStatus = MergeRequestStatus.getInstance(entity.getStatus());
|
||||
switch (mergeRequestStatus) {
|
||||
case OPEN: {
|
||||
newCommitId = gitService.getLatestCommitId(workspaceId, sourceBranch);
|
||||
if (gitService.isBranchExists(workspaceId, targetBranch)) {
|
||||
// open 状态下,获取 sourceBranch,targetBranch 冲突文件
|
||||
conflictFileList = gitService.getConflictFilePathInBranches(workspaceId, sourceBranch, targetBranch);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CLOSED:
|
||||
case MERGED: {
|
||||
newCommitId = entity.getEndCommitId();
|
||||
break;
|
||||
}
|
||||
}
|
||||
// 获取 sourceBranch,targetBranch 合并冲突文件
|
||||
List<String> conflictFileList = T.ListUtil.list(true);
|
||||
|
||||
List<Map<Object, Object>> diffFileListInCommits = gitService.getDiffFileListInCommits(workspaceId, newCommitId, oldCommitId);
|
||||
List<String> finalConflictFileList = conflictFileList;
|
||||
diffFileListInCommits.parallelStream()
|
||||
.forEach(m -> {
|
||||
T.MapUtil.renameKey(m, "oldContent", "sourceContent");
|
||||
T.MapUtil.renameKey(m, "newContent", "targetContent");
|
||||
|
||||
T.MapUtil.renameKey(m, "oldPath", "sourcePath");
|
||||
T.MapUtil.renameKey(m, "newPath", "targetPath");
|
||||
|
||||
String sourcePath = T.MapUtil.getStr(m, "sourcePath");
|
||||
String targetPath = T.MapUtil.getStr(m, "targetPath");
|
||||
m.put("conflict", false);
|
||||
if (finalConflictFileList.contains(sourcePath) || finalConflictFileList.contains(targetPath)) {
|
||||
m.put("conflict", true);
|
||||
// src branch changed files
|
||||
String oldCommitId = entity.getStartCommitId();
|
||||
String newCommitId = null;
|
||||
MergeRequestStatus mergeRequestStatus = MergeRequestStatus.getInstance(entity.getStatus());
|
||||
switch (mergeRequestStatus) {
|
||||
case OPEN: {
|
||||
RevCommit branchLatestCommit = JGitUtils.getBranchLatestCommit(repository, sourceBranch);
|
||||
newCommitId = branchLatestCommit.getName();
|
||||
if (JGitUtils.isBranchExists(repository, targetBranch)) {
|
||||
// open 状态下,获取 sourceBranch,targetBranch 冲突文件
|
||||
conflictFileList = JGitUtils.getConflictFilePathInBranches(repository, sourceBranch, targetBranch);
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
case CLOSED:
|
||||
case MERGED: {
|
||||
newCommitId = entity.getEndCommitId();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Map<Object, Object> sourceCommit = gitService.infoCommit(workspaceId, oldCommitId);
|
||||
Map<Object, Object> targetCommit = gitService.infoCommit(workspaceId, newCommitId);
|
||||
List<Map<Object, Object>> diffFileListInCommits = JGitUtils.getDiffFileListInCommits(repository, newCommitId, oldCommitId);
|
||||
List<String> finalConflictFileList = conflictFileList;
|
||||
diffFileListInCommits.parallelStream()
|
||||
.forEach(m -> {
|
||||
T.MapUtil.renameKey(m, "oldContent", "sourceContent");
|
||||
T.MapUtil.renameKey(m, "newContent", "targetContent");
|
||||
|
||||
Map<Object, Object> m = T.MapUtil.builder()
|
||||
.put("sourceBranch", sourceBranch)
|
||||
.put("targetBranch", targetBranch)
|
||||
.put("sourceCommitId", oldCommitId)
|
||||
.put("targetCommitId", newCommitId)
|
||||
.put("sourceCommit", sourceCommit)
|
||||
.put("targetCommit", targetCommit)
|
||||
.put("files", diffFileListInCommits)
|
||||
.build();
|
||||
return m;
|
||||
T.MapUtil.renameKey(m, "oldPath", "sourcePath");
|
||||
T.MapUtil.renameKey(m, "newPath", "targetPath");
|
||||
|
||||
String sourcePath = T.MapUtil.getStr(m, "sourcePath");
|
||||
String targetPath = T.MapUtil.getStr(m, "targetPath");
|
||||
m.put("conflict", false);
|
||||
if (finalConflictFileList.contains(sourcePath) || finalConflictFileList.contains(targetPath)) {
|
||||
m.put("conflict", true);
|
||||
}
|
||||
});
|
||||
|
||||
RevCommit sourceCommit = JGitUtils.infoCommit(repository, oldCommitId);
|
||||
RevCommit targetCommit = JGitUtils.infoCommit(repository, newCommitId);
|
||||
|
||||
Map<Object, Object> m = T.MapUtil.builder()
|
||||
.put("sourceBranch", sourceBranch)
|
||||
.put("targetBranch", targetBranch)
|
||||
.put("sourceCommitId", oldCommitId)
|
||||
.put("targetCommitId", newCommitId)
|
||||
.put("sourceCommit", JGitUtils.buildAswCommitInfo(sourceCommit))
|
||||
.put("targetCommit", JGitUtils.buildAswCommitInfo(targetCommit))
|
||||
.put("files", diffFileListInCommits)
|
||||
.build();
|
||||
return m;
|
||||
} catch (IOException e) {
|
||||
log.error(e, "[mrCommitDiff] [error] [id: {}]", mrId);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Object, Object> getMrConflictList(String mrId) {
|
||||
public Map<Object, Object> getMrConflictList(String mrId) throws IOException {
|
||||
ApplicationMergeEntity entity = this.getById(mrId);
|
||||
T.VerifyUtil.is(entity).notEmpty(RCode.SYS_RECORD_NOT_FOUND);
|
||||
|
||||
String workspaceId = entity.getWorkspaceId();
|
||||
String sourceBranch = entity.getSourceBranch();
|
||||
String targetBranch = entity.getTargetBranch();
|
||||
File gitDir = workspaceService.getGitDir(workspaceId);
|
||||
|
||||
List<Map<Object, Object>> conflictFileInfoInBranches = gitService.getConflictFileInfoInBranches(workspaceId, sourceBranch, targetBranch);
|
||||
if (T.CollUtil.isNotEmpty(conflictFileInfoInBranches)) {
|
||||
// srcBranch->tgtBranch 有冲突,先从 tgtBranch merge 到 srcBranch,在 srcBranch 处理后再合并,参考 gitlab
|
||||
StringBuilder commitMessage = new StringBuilder();
|
||||
commitMessage.append("Merge branch '").append(targetBranch).append("' into '").append(sourceBranch).append("'\n\n");
|
||||
commitMessage.append("# Conflicts:\n");
|
||||
for (Map<Object, Object> map : conflictFileInfoInBranches) {
|
||||
String path = T.MapUtil.getStr(map, "path");
|
||||
commitMessage.append("# ").append(path).append("\n");
|
||||
try (Repository repository = JGitUtils.openRepository(gitDir)) {
|
||||
String sourceBranch = entity.getSourceBranch();
|
||||
String targetBranch = entity.getTargetBranch();
|
||||
|
||||
List<Map<Object, Object>> conflictFileInfoInBranches = JGitUtils.getConflictFileInfoInBranches(repository, sourceBranch, targetBranch);
|
||||
if (T.CollUtil.isNotEmpty(conflictFileInfoInBranches)) {
|
||||
// srcBranch->tgtBranch 有冲突,先从 tgtBranch merge 到 srcBranch,在 srcBranch 处理后再合并,参考 gitlab
|
||||
StringBuilder commitMessage = new StringBuilder();
|
||||
commitMessage.append("Merge branch '").append(targetBranch).append("' into '").append(sourceBranch).append("'\n\n");
|
||||
commitMessage.append("# Conflicts:\n");
|
||||
for (Map<Object, Object> map : conflictFileInfoInBranches) {
|
||||
String path = T.MapUtil.getStr(map, "path");
|
||||
commitMessage.append("# ").append(path).append("\n");
|
||||
}
|
||||
|
||||
String parentId = JGitUtils.getBranchLatestCommit(repository, sourceBranch).getName();
|
||||
Map<Object, Object> m = T.MapUtil.builder()
|
||||
.put("sourceBranch", sourceBranch)
|
||||
.put("targetBranch", targetBranch)
|
||||
.put("commitId", parentId)
|
||||
.put("commitMessage", commitMessage.toString())
|
||||
.put("files", conflictFileInfoInBranches)
|
||||
.build();
|
||||
return m;
|
||||
}
|
||||
|
||||
String parentId = gitService.getLatestCommitId(workspaceId, sourceBranch);
|
||||
Map<Object, Object> m = T.MapUtil.builder()
|
||||
return T.MapUtil.builder()
|
||||
.put("sourceBranch", sourceBranch)
|
||||
.put("targetBranch", targetBranch)
|
||||
.put("commitId", parentId)
|
||||
.put("commitMessage", commitMessage.toString())
|
||||
.put("commitId", null)
|
||||
.put("commitMessage", null)
|
||||
.put("files", conflictFileInfoInBranches)
|
||||
.build();
|
||||
return m;
|
||||
}
|
||||
|
||||
return T.MapUtil.builder()
|
||||
.put("sourceBranch", sourceBranch)
|
||||
.put("targetBranch", targetBranch)
|
||||
.put("commitId", null)
|
||||
.put("commitMessage", null)
|
||||
.put("files", conflictFileInfoInBranches)
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -213,20 +247,28 @@ public class ApplicationMergeServiceImpl extends ServiceImpl<ApplicationMergeDao
|
||||
* @param body
|
||||
*/
|
||||
@Override
|
||||
public void resolveMrConflicts(String mrId, Map<String, Object> body) {
|
||||
public void resolveMrConflicts(String mrId, Map<String, Object> body) throws IOException {
|
||||
ApplicationMergeEntity entity = this.getById(mrId);
|
||||
T.VerifyUtil.is(entity).notEmpty(RCode.SYS_RECORD_NOT_FOUND);
|
||||
|
||||
String workspaceId = entity.getWorkspaceId();
|
||||
String sourceBranch = entity.getSourceBranch();
|
||||
String targetBranch = entity.getTargetBranch();
|
||||
File gitDir = workspaceService.getGitDir(workspaceId);
|
||||
|
||||
String commitId = T.MapUtil.getStr(body, "commitId");
|
||||
String commitMessage = T.MapUtil.getStr(body, "commitMessage");
|
||||
List<Map<String, String>> files = T.MapUtil.get(body, "files", List.class, new ArrayList());
|
||||
try (Repository repository = JGitUtils.openRepository(gitDir)) {
|
||||
SysUserEntity loginUserEntity = userService.getById(StpUtil.getLoginIdAsString());
|
||||
String author = loginUserEntity.getName();
|
||||
|
||||
// 反过来合并
|
||||
gitService.mergeBranch(workspaceId, targetBranch, sourceBranch, commitMessage, files);
|
||||
String sourceBranch = entity.getSourceBranch();
|
||||
String targetBranch = entity.getTargetBranch();
|
||||
String commitMessage = T.MapUtil.getStr(body, "commitMessage");
|
||||
List<Map<String, String>> files = T.MapUtil.get(body, "files", List.class, new ArrayList());
|
||||
|
||||
// 反过来合并
|
||||
JGitUtils.mergeBranch(repository, targetBranch, sourceBranch, author, commitMessage, files);
|
||||
} catch (GitAPIException e) {
|
||||
log.error(e, "[resolveMrConflicts] [error] [id: {}]", mrId);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -241,75 +283,84 @@ public class ApplicationMergeServiceImpl extends ServiceImpl<ApplicationMergeDao
|
||||
ApplicationMergeEntity entity = this.getById(mrId);
|
||||
T.VerifyUtil.is(entity).notEmpty(RCode.SYS_RECORD_NOT_FOUND);
|
||||
|
||||
switch (action) {
|
||||
case "merge": {
|
||||
MergeRequestStatus mergeRequestStatus = MergeRequestStatus.getInstance(entity.getStatus());
|
||||
if (!mergeRequestStatus.canMerge()) {
|
||||
throw new ASWException(RCode.GIT_MERGE_NOT_SUPPORTED.setParam(mergeRequestStatus.toString()));
|
||||
}
|
||||
String workspaceId = entity.getWorkspaceId();
|
||||
File gitDir = workspaceService.getGitDir(workspaceId);
|
||||
|
||||
String srcBranch = entity.getSourceBranch();
|
||||
String tgtBranch = entity.getTargetBranch();
|
||||
|
||||
StringBuilder commitMessage = new StringBuilder();
|
||||
commitMessage.append("Merge branch '").append(srcBranch).append("' into '").append(tgtBranch).append("'\n\n");
|
||||
commitMessage.append(entity.getTitle());
|
||||
commitMessage.append("\n");
|
||||
|
||||
String workspaceId = entity.getWorkspaceId();
|
||||
|
||||
// 检查 tgtBranch 是否存在
|
||||
if (T.BooleanUtil.negate(gitService.isBranchExists(workspaceId, tgtBranch))) {
|
||||
throw new ASWException(RCode.GIT_MERGE_TARGET_BRANCH_NOT_EXIST.setParam(tgtBranch));
|
||||
}
|
||||
|
||||
// merge
|
||||
try {
|
||||
gitService.mergeBranch(workspaceId, srcBranch, tgtBranch, commitMessage.toString(), null);
|
||||
String latestCommitId = gitService.getLatestCommitId(workspaceId, srcBranch);
|
||||
entity.setEndCommitId(latestCommitId);
|
||||
entity.setStatus(MergeRequestStatus.MERGED.toString());
|
||||
} catch (Exception e) {
|
||||
log.error(e, "[mergeMr] [merge error] [workspaceId: {}] [srcBranch: {}] [tgtBranch: {}] [msg: {}]", workspaceId, srcBranch, tgtBranch, e.getMessage());
|
||||
throw new ASWException(RCode.GIT_MERGE_FAILED.setParam(e.getMessage()));
|
||||
}
|
||||
|
||||
// remove source branch
|
||||
if (1 == entity.getRemoveSourceBranch()) {
|
||||
try {
|
||||
log.info("[mergeMr] [remove source branch] [workspaceId: {}] [branch: {}]", workspaceId, srcBranch);
|
||||
gitService.deleteBranch(workspaceId, srcBranch);
|
||||
} catch (Exception e) {
|
||||
log.error(e, "[mergeMr] [remove source branch error] [workspaceId: {}] [branch: {}] [msg: {}]", workspaceId, srcBranch, e.getMessage());
|
||||
try (Repository repository = JGitUtils.openRepository(gitDir)) {
|
||||
switch (action) {
|
||||
case "merge": {
|
||||
MergeRequestStatus mergeRequestStatus = MergeRequestStatus.getInstance(entity.getStatus());
|
||||
if (!mergeRequestStatus.canMerge()) {
|
||||
throw new ASWException(RCode.GIT_MERGE_NOT_SUPPORTED.setParam(mergeRequestStatus.toString()));
|
||||
}
|
||||
|
||||
String srcBranch = entity.getSourceBranch();
|
||||
String tgtBranch = entity.getTargetBranch();
|
||||
|
||||
StringBuilder commitMessage = new StringBuilder();
|
||||
commitMessage.append("Merge branch '").append(srcBranch).append("' into '").append(tgtBranch).append("'\n\n");
|
||||
commitMessage.append(entity.getTitle());
|
||||
commitMessage.append("\n");
|
||||
|
||||
|
||||
// 检查 tgtBranch 是否存在
|
||||
if (T.BooleanUtil.negate(JGitUtils.isBranchExists(repository, tgtBranch))) {
|
||||
throw new ASWException(RCode.GIT_MERGE_TARGET_BRANCH_NOT_EXIST.setParam(tgtBranch));
|
||||
}
|
||||
|
||||
// merge
|
||||
try {
|
||||
SysUserEntity loginUserEntity = userService.getById(StpUtil.getLoginIdAsString());
|
||||
JGitUtils.mergeBranch(repository, srcBranch, tgtBranch, loginUserEntity.getName(), commitMessage.toString(), null);
|
||||
|
||||
String latestCommitId = JGitUtils.getBranchLatestCommit(repository, srcBranch).getName();
|
||||
entity.setEndCommitId(latestCommitId);
|
||||
entity.setStatus(MergeRequestStatus.MERGED.toString());
|
||||
} catch (Exception e) {
|
||||
log.error(e, "[mergeMr] [merge error] [workspaceId: {}] [srcBranch: {}] [tgtBranch: {}] [msg: {}]", workspaceId, srcBranch, tgtBranch, e.getMessage());
|
||||
throw new ASWException(RCode.GIT_MERGE_FAILED.setParam(e.getMessage()));
|
||||
}
|
||||
|
||||
// remove source branch
|
||||
if (1 == entity.getRemoveSourceBranch()) {
|
||||
try {
|
||||
log.info("[mergeMr] [remove source branch] [workspaceId: {}] [branch: {}]", workspaceId, srcBranch);
|
||||
branchService.deleteBranch(workspaceId, srcBranch);
|
||||
} catch (Exception e) {
|
||||
log.error(e, "[mergeMr] [remove source branch error] [workspaceId: {}] [branch: {}] [msg: {}]", workspaceId, srcBranch, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// update
|
||||
this.update(new LambdaUpdateWrapper<ApplicationMergeEntity>()
|
||||
.eq(ApplicationMergeEntity::getId, mrId)
|
||||
.set(ApplicationMergeEntity::getEndCommitId, entity.getEndCommitId())
|
||||
.set(ApplicationMergeEntity::getStatus, entity.getStatus())
|
||||
.set(ApplicationMergeEntity::getMessage, entity.getMessage())
|
||||
);
|
||||
return entity;
|
||||
}
|
||||
case "close": {
|
||||
String updateStatus = StrUtil.equals(MergeRequestStatus.OPEN.toString(), entity.getStatus()) ? MergeRequestStatus.CLOSED.toString() : entity.getStatus();
|
||||
entity.setStatus(updateStatus);
|
||||
|
||||
// update
|
||||
this.update(new LambdaUpdateWrapper<ApplicationMergeEntity>()
|
||||
.eq(ApplicationMergeEntity::getId, mrId)
|
||||
.set(ApplicationMergeEntity::getEndCommitId, entity.getEndCommitId())
|
||||
.set(ApplicationMergeEntity::getStatus, entity.getStatus())
|
||||
.set(ApplicationMergeEntity::getMessage, entity.getMessage())
|
||||
);
|
||||
return entity;
|
||||
// 关闭请求,保留当前 src branch last commit = end_commit_id
|
||||
String latestCommitId = JGitUtils.getBranchLatestCommit(repository, entity.getSourceBranch()).getName();
|
||||
this.update(new LambdaUpdateWrapper<ApplicationMergeEntity>()
|
||||
.eq(ApplicationMergeEntity::getId, mrId)
|
||||
.set(ApplicationMergeEntity::getStatus, updateStatus)
|
||||
.set(ApplicationMergeEntity::getEndCommitId, latestCommitId)
|
||||
);
|
||||
return entity;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
case "close": {
|
||||
String updateStatus = StrUtil.equals(MergeRequestStatus.OPEN.toString(), entity.getStatus()) ? MergeRequestStatus.CLOSED.toString() : entity.getStatus();
|
||||
entity.setStatus(updateStatus);
|
||||
|
||||
// 关闭请求,保留当前 src branch last commit = end_commit_id
|
||||
String latestCommitId = gitService.getLatestCommitId(entity.getWorkspaceId(), entity.getSourceBranch());
|
||||
this.update(new LambdaUpdateWrapper<ApplicationMergeEntity>()
|
||||
.eq(ApplicationMergeEntity::getId, mrId)
|
||||
.set(ApplicationMergeEntity::getStatus, updateStatus)
|
||||
.set(ApplicationMergeEntity::getEndCommitId, latestCommitId)
|
||||
);
|
||||
return entity;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
return entity;
|
||||
} catch (IOException e) {
|
||||
log.error(e, "[mergeMr] [error] [id: {}] [action: {}]", mrId, action);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return entity;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package net.geedge.asw.module.app.service.impl;
|
||||
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import cn.hutool.json.JSON;
|
||||
import cn.hutool.json.JSONConfig;
|
||||
import cn.hutool.json.JSONObject;
|
||||
@@ -9,108 +10,568 @@ import net.geedge.asw.common.util.RCode;
|
||||
import net.geedge.asw.common.util.T;
|
||||
import net.geedge.asw.module.app.entity.ApplicationEntity;
|
||||
import net.geedge.asw.module.app.service.IApplicationService;
|
||||
import net.geedge.asw.module.app.service.IGitService;
|
||||
import net.geedge.asw.module.app.service.ITSGApplicationService;
|
||||
import net.geedge.asw.module.app.util.JGitUtils;
|
||||
import net.geedge.asw.module.sys.entity.SysUserEntity;
|
||||
import net.geedge.asw.module.sys.service.ISysUserService;
|
||||
import net.geedge.asw.module.workspace.service.IWorkspaceService;
|
||||
import org.eclipse.jgit.api.Git;
|
||||
import org.eclipse.jgit.api.errors.ConcurrentRefUpdateException;
|
||||
import org.eclipse.jgit.api.errors.GitAPIException;
|
||||
import org.eclipse.jgit.diff.DiffEntry;
|
||||
import org.eclipse.jgit.diff.DiffFormatter;
|
||||
import org.eclipse.jgit.dircache.DirCache;
|
||||
import org.eclipse.jgit.dircache.DirCacheBuilder;
|
||||
import org.eclipse.jgit.dircache.DirCacheEntry;
|
||||
import org.eclipse.jgit.lib.FileMode;
|
||||
import org.eclipse.jgit.lib.ObjectId;
|
||||
import org.eclipse.jgit.lib.ObjectLoader;
|
||||
import org.eclipse.jgit.lib.Repository;
|
||||
import org.eclipse.jgit.lib.*;
|
||||
import org.eclipse.jgit.revwalk.RevCommit;
|
||||
import org.eclipse.jgit.revwalk.RevTree;
|
||||
import org.eclipse.jgit.revwalk.RevWalk;
|
||||
import org.eclipse.jgit.treewalk.CanonicalTreeParser;
|
||||
import org.eclipse.jgit.treewalk.TreeWalk;
|
||||
import org.eclipse.jgit.treewalk.filter.PathFilter;
|
||||
import org.eclipse.jgit.util.io.DisabledOutputStream;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.beans.factory.annotation.Value;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
public class ApplicationServiceImpl implements IApplicationService {
|
||||
|
||||
private static final Log log = Log.get();
|
||||
|
||||
@Value("${asw.application.template.meta.json}")
|
||||
private String metaJsonTemplate;
|
||||
|
||||
@Value("${asw.application.template.signature.json}")
|
||||
private String signatureJsonTemplate;
|
||||
|
||||
@Autowired
|
||||
private IGitService gitService;
|
||||
private ISysUserService userService;
|
||||
|
||||
@Autowired
|
||||
private IWorkspaceService workspaceService;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("tsg2402ApplicationService")
|
||||
private ITSGApplicationService tsg2402ApplicationService;
|
||||
|
||||
@Override
|
||||
public List<ApplicationEntity> queryList(String workspaceId, String branch, String... names) {
|
||||
List<ApplicationEntity> resultList = T.ListUtil.list(true);
|
||||
public Map<Object, Object> infoApplication(String workspaceId, String branch, String name) {
|
||||
Map<Object, Object> result = T.MapUtil.builder()
|
||||
.put("branch", branch)
|
||||
.build();
|
||||
|
||||
try (Git git = gitService.getGitInstance(workspaceId)) {
|
||||
Repository repository = git.getRepository();
|
||||
File gitDir = workspaceService.getGitDir(workspaceId);
|
||||
try (Repository repository = JGitUtils.openRepository(gitDir)) {
|
||||
ObjectId branchRef = repository.resolve(branch);
|
||||
result.put("commitId", branchRef.getName());
|
||||
|
||||
List<Map<Object, Object>> files = T.ListUtil.list(true);
|
||||
try (TreeWalk treeWalk = new TreeWalk(repository);
|
||||
RevWalk revWalk = new RevWalk(repository)) {
|
||||
|
||||
ObjectId branchRef = repository.resolve(branch);
|
||||
treeWalk.addTree(revWalk.parseTree(branchRef));
|
||||
treeWalk.setFilter(PathFilter.create("applications/"));
|
||||
treeWalk.setFilter(PathFilter.create("applications/" + name + "/"));
|
||||
treeWalk.setRecursive(true);
|
||||
|
||||
Map<String, String> signatureMapping = T.MapUtil.newHashMap();
|
||||
|
||||
Map<String, String> appFilePathMapping = T.MapUtil.newHashMap(true);
|
||||
while (treeWalk.next()) {
|
||||
String filePath = treeWalk.getPathString();
|
||||
String pathString = treeWalk.getPathString();
|
||||
Map<Object, Object> m = T.MapUtil.builder()
|
||||
.put("path", pathString)
|
||||
.build();
|
||||
|
||||
Map<Object, Object> fileContent = JGitUtils.getFileContent(repository, pathString, treeWalk.getObjectId(0));
|
||||
m.putAll(fileContent);
|
||||
files.add(m);
|
||||
|
||||
appFilePathMapping.put(pathString, pathString);
|
||||
}
|
||||
|
||||
Map<String, RevCommit> lastCommitMapping = this.getLastCommitIdDataByPath(repository, branch, appFilePathMapping);
|
||||
for (Map<Object, Object> m : files) {
|
||||
String path = T.MapUtil.getStr(m, "path");
|
||||
RevCommit revCommit = lastCommitMapping.get(path);
|
||||
m.put("lastCommitId", revCommit != null ? revCommit.getName() : null);
|
||||
}
|
||||
}
|
||||
result.put("files", files);
|
||||
} catch (IOException e) {
|
||||
log.error(e, "[infoApplication] [error] [workspaceId: {}] [branch: {}] [name: {}]", workspaceId, branch, name);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Map<Object, Object>> listApplication(String workspaceId, String branch, String q) {
|
||||
List<Map<Object, Object>> resultList = T.ListUtil.list(true);
|
||||
|
||||
File gitDir = workspaceService.getGitDir(workspaceId);
|
||||
try (Repository repository = JGitUtils.openRepository(gitDir);
|
||||
TreeWalk treeWalk = new TreeWalk(repository);
|
||||
RevWalk revWalk = new RevWalk(repository);) {
|
||||
|
||||
ObjectId branchRef = repository.resolve(branch);
|
||||
treeWalk.addTree(revWalk.parseTree(branchRef));
|
||||
treeWalk.setFilter(PathFilter.create("applications/"));
|
||||
treeWalk.setRecursive(true);
|
||||
|
||||
Map<String, String> appDirPathMapping = T.MapUtil.newHashMap(true);
|
||||
while (treeWalk.next()) {
|
||||
String filePath = treeWalk.getPathString();
|
||||
String fileName = treeWalk.getNameString();
|
||||
if (T.StrUtil.equals("meta.json", fileName)) {
|
||||
// application_name 从目录中获取
|
||||
String applicationName = T.PathUtil.getPathEle(Path.of(filePath), 1).toString();
|
||||
if (T.BooleanUtil.and(
|
||||
T.ObjectUtil.isNotEmpty(names),
|
||||
!Arrays.asList(names).contains(applicationName))) {
|
||||
// filter by name
|
||||
if (T.StrUtil.isNotEmpty(q) && !T.StrUtil.containsIgnoreCase(applicationName, q)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (treeWalk.getNameString()) {
|
||||
case "meta.json": {
|
||||
ObjectLoader loader = repository.open(treeWalk.getObjectId(0));
|
||||
String metaJsonStr = T.StrUtil.utf8Str(loader.getBytes());
|
||||
metaJsonStr = T.StrUtil.emptyToDefault(metaJsonStr, T.StrUtil.EMPTY_JSON);
|
||||
|
||||
ApplicationEntity application = T.JSONUtil.toBean(metaJsonStr, ApplicationEntity.class);
|
||||
application.setName(applicationName);
|
||||
resultList.add(application);
|
||||
break;
|
||||
}
|
||||
case "signature.json": {
|
||||
ObjectLoader loader = repository.open(treeWalk.getObjectId(0));
|
||||
signatureMapping.put(applicationName, T.StrUtil.utf8Str(loader.getBytes()));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
ObjectLoader loader = repository.open(treeWalk.getObjectId(0));
|
||||
String metaJsonStr = T.StrUtil.utf8Str(loader.getBytes());
|
||||
metaJsonStr = T.StrUtil.emptyToDefault(metaJsonStr, T.StrUtil.EMPTY_JSON);
|
||||
Map metaJsonMap = T.MapUtil.empty();
|
||||
try {
|
||||
metaJsonMap = T.JSONUtil.toBean(metaJsonStr, Map.class);
|
||||
} catch (Exception e) {
|
||||
log.error(e, "[listApplication] [meat.json format error] [application: {}]", applicationName);
|
||||
}
|
||||
}
|
||||
|
||||
for (ApplicationEntity entity : resultList) {
|
||||
String name = entity.getName();
|
||||
String signature = signatureMapping.getOrDefault(name, "");
|
||||
if (T.StrUtil.isNotEmpty(signature)) {
|
||||
JSONObject jsonObject = T.JSONUtil.parseObj(signature);
|
||||
entity.setSignature(jsonObject);
|
||||
}
|
||||
Map<Object, Object> m = T.MapUtil.newHashMap(true);
|
||||
m.putAll(metaJsonMap);
|
||||
m.put("name", applicationName);
|
||||
|
||||
String appDirPath = treeWalk.getPathString().replaceAll(fileName, "");
|
||||
appDirPathMapping.put(applicationName, appDirPath);
|
||||
|
||||
resultList.add(m);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
log.error(e, "[queryList] [error] [workspaceId: {}] [branch: {}]", workspaceId, branch);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
Map<String, RevCommit> lastCommitMapping = this.getLastCommitIdDataByPath(repository, branch, appDirPathMapping);
|
||||
|
||||
for (Map<Object, Object> map : resultList) {
|
||||
String applicationName = T.MapUtil.getStr(map, "name");
|
||||
RevCommit lastCommit = T.MapUtil.get(lastCommitMapping, applicationName, RevCommit.class);
|
||||
map.put("commit", JGitUtils.buildAswCommitInfo(lastCommit));
|
||||
}
|
||||
|
||||
// 按照提交日期倒叙
|
||||
resultList = resultList.stream().sorted(Comparator.comparing(map -> {
|
||||
Map commit = T.MapUtil.get((Map) map, "commit", Map.class, new HashMap(2));
|
||||
return (Long) T.MapUtil.getLong(commit, "createdAt", 0l);
|
||||
}).reversed()).collect(Collectors.toList());
|
||||
} catch (IOException e) {
|
||||
log.error(e, "[listApplication] [error] [workspaceId: {}] [branch: {}]", workspaceId, branch);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return resultList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ApplicationEntity> listApplication(String workspaceId, String branch, String... names) {
|
||||
List<ApplicationEntity> resultList = T.ListUtil.list(true);
|
||||
|
||||
File gitDir = workspaceService.getGitDir(workspaceId);
|
||||
try (Repository repository = JGitUtils.openRepository(gitDir);
|
||||
TreeWalk treeWalk = new TreeWalk(repository);
|
||||
RevWalk revWalk = new RevWalk(repository)) {
|
||||
|
||||
ObjectId branchRef = repository.resolve(branch);
|
||||
treeWalk.addTree(revWalk.parseTree(branchRef));
|
||||
treeWalk.setFilter(PathFilter.create("applications/"));
|
||||
treeWalk.setRecursive(true);
|
||||
|
||||
Map<String, String> signatureMapping = T.MapUtil.newHashMap();
|
||||
|
||||
while (treeWalk.next()) {
|
||||
String filePath = treeWalk.getPathString();
|
||||
String applicationName = T.PathUtil.getPathEle(Path.of(filePath), 1).toString();
|
||||
if (T.BooleanUtil.and(
|
||||
T.ObjectUtil.isNotEmpty(names),
|
||||
!Arrays.asList(names).contains(applicationName))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
switch (treeWalk.getNameString()) {
|
||||
case "meta.json": {
|
||||
ObjectLoader loader = repository.open(treeWalk.getObjectId(0));
|
||||
String metaJsonStr = T.StrUtil.utf8Str(loader.getBytes());
|
||||
metaJsonStr = T.StrUtil.emptyToDefault(metaJsonStr, T.StrUtil.EMPTY_JSON);
|
||||
|
||||
ApplicationEntity application = T.JSONUtil.toBean(metaJsonStr, ApplicationEntity.class);
|
||||
application.setName(applicationName);
|
||||
resultList.add(application);
|
||||
break;
|
||||
}
|
||||
case "signature.json": {
|
||||
ObjectLoader loader = repository.open(treeWalk.getObjectId(0));
|
||||
signatureMapping.put(applicationName, T.StrUtil.utf8Str(loader.getBytes()));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (ApplicationEntity entity : resultList) {
|
||||
String name = entity.getName();
|
||||
String signature = signatureMapping.getOrDefault(name, "");
|
||||
if (T.StrUtil.isNotEmpty(signature)) {
|
||||
JSONObject jsonObject = T.JSONUtil.parseObj(signature);
|
||||
entity.setSignature(jsonObject);
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
log.error(e, "[listApplication] [error] [workspaceId: {}] [branch: {}]", workspaceId, branch);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return resultList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void newApplication(String workspaceId, String branch, String name) {
|
||||
File gitDir = workspaceService.getGitDir(workspaceId);
|
||||
try (Repository repository = JGitUtils.openRepository(gitDir)) {
|
||||
Map<String, ObjectId> filePathAndBlobIdMap = T.MapUtil.newHashMap(true);
|
||||
for (String str : T.ListUtil.of("README.md", "meta.json", "signature.json")) {
|
||||
String savePath = T.StrUtil.concat(true, "applications/", name, "/", str);
|
||||
|
||||
String fileContent = T.StrUtil.EMPTY;
|
||||
if ("meta.json".equals(str)) {
|
||||
JSONObject jsonObject = T.JSONUtil.parseObj(this.metaJsonTemplate);
|
||||
jsonObject.set("id", T.StrUtil.uuid());
|
||||
jsonObject.set("name", name);
|
||||
jsonObject.set("longName", name);
|
||||
fileContent = T.JSONUtil.parse(jsonObject).toJSONString(2);
|
||||
}
|
||||
if ("signature.json".equals(str)) {
|
||||
fileContent = this.signatureJsonTemplate;
|
||||
}
|
||||
|
||||
ObjectId objectId = JGitUtils.insertBlobFileToDatabase(repository, fileContent.getBytes());
|
||||
filePathAndBlobIdMap.put(savePath, objectId);
|
||||
}
|
||||
|
||||
try (ObjectInserter inserter = repository.getObjectDatabase().newInserter();
|
||||
TreeWalk treeWalk = new TreeWalk(repository);
|
||||
RevWalk revWalk = new RevWalk(repository)) {
|
||||
|
||||
// branch tree
|
||||
ObjectId resolveId = repository.resolve(branch);
|
||||
if (null != resolveId) {
|
||||
treeWalk.addTree(revWalk.parseTree(resolveId));
|
||||
} else {
|
||||
treeWalk.addTree(new CanonicalTreeParser());
|
||||
}
|
||||
treeWalk.setRecursive(true);
|
||||
|
||||
DirCache newTree = DirCache.newInCore();
|
||||
DirCacheBuilder newTreeBuilder = newTree.builder();
|
||||
while (treeWalk.next()) {
|
||||
DirCacheEntry entry = JGitUtils.buildDirCacheEntry(treeWalk.getPathString(), treeWalk.getFileMode(0), treeWalk.getObjectId(0));
|
||||
newTreeBuilder.add(entry);
|
||||
}
|
||||
|
||||
// update new tree
|
||||
for (Map.Entry<String, ObjectId> entry : filePathAndBlobIdMap.entrySet()) {
|
||||
String filePath = entry.getKey();
|
||||
ObjectId blobId = entry.getValue();
|
||||
|
||||
// add file ref
|
||||
DirCacheEntry dirCacheEntry = JGitUtils.buildDirCacheEntry(filePath, FileMode.REGULAR_FILE, blobId);
|
||||
newTreeBuilder.add(dirCacheEntry);
|
||||
}
|
||||
|
||||
newTreeBuilder.finish();
|
||||
ObjectId newTreeId = newTree.writeTree(inserter);
|
||||
|
||||
String message = String.format("feat: add %s application", name);
|
||||
|
||||
SysUserEntity loginUserEntity = userService.getById(StpUtil.getLoginIdAsString());
|
||||
PersonIdent personIdent = JGitUtils.buildPersonIdent(loginUserEntity.getName());
|
||||
|
||||
// commit
|
||||
JGitUtils.createCommit(repository, branch, newTreeId, message, personIdent);
|
||||
}
|
||||
} catch (IOException | ConcurrentRefUpdateException e) {
|
||||
log.error(e, "[newApplication] [error] [workspaceId: {}] [branch: {}] [name: {}]", workspaceId, branch, name);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteApplication(String workspaceId, String branch, String name) {
|
||||
File gitDir = workspaceService.getGitDir(workspaceId);
|
||||
try (Repository repository = JGitUtils.openRepository(gitDir);
|
||||
ObjectInserter inserter = repository.getObjectDatabase().newInserter();
|
||||
TreeWalk treeWalk = new TreeWalk(repository);
|
||||
RevWalk revWalk = new RevWalk(repository);) {
|
||||
|
||||
ObjectId branchRef = repository.resolve(branch);
|
||||
treeWalk.addTree(revWalk.parseTree(branchRef));
|
||||
treeWalk.setRecursive(true);
|
||||
|
||||
DirCache newTree = DirCache.newInCore();
|
||||
DirCacheBuilder newTreeBuilder = newTree.builder();
|
||||
|
||||
String appFilePrefixStr = T.StrUtil.concat(true, "applications/", name, "/");
|
||||
while (treeWalk.next()) {
|
||||
String pathString = treeWalk.getPathString();
|
||||
if (!pathString.startsWith(appFilePrefixStr)) {
|
||||
DirCacheEntry entry = JGitUtils.buildDirCacheEntry(pathString, treeWalk.getFileMode(0), treeWalk.getObjectId(0));
|
||||
newTreeBuilder.add(entry);
|
||||
}
|
||||
}
|
||||
|
||||
newTreeBuilder.finish();
|
||||
ObjectId newTreeId = newTree.writeTree(inserter);
|
||||
|
||||
String message = String.format("refactor: remove %s application", name);
|
||||
|
||||
SysUserEntity loginUserEntity = userService.getById(StpUtil.getLoginIdAsString());
|
||||
PersonIdent personIdent = JGitUtils.buildPersonIdent(loginUserEntity.getName());
|
||||
|
||||
// commit
|
||||
JGitUtils.createCommit(repository, branch, newTreeId, message, personIdent);
|
||||
} catch (IOException | ConcurrentRefUpdateException e) {
|
||||
log.error(e, "[deleteApplication] [error] [workspaceId: {}] [branch: {}] [name: {}]", workspaceId, branch, name);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateApplication(String workspaceId, String branch, String lastCommitId, String message, List<Map<String, String>> updateContent) {
|
||||
File gitDir = workspaceService.getGitDir(workspaceId);
|
||||
try (Repository repository = JGitUtils.openRepository(gitDir);
|
||||
Git git = Git.open(repository.getDirectory());) {
|
||||
// 分支最新 commitId
|
||||
ObjectId branchRef = repository.resolve(branch);
|
||||
// 如果不相等,检查 param.lastCommitId --- branch.HEAD 期间是否更新了本次修改文件
|
||||
if (!T.StrUtil.equals(lastCommitId, branchRef.getName())) {
|
||||
List<String> updateFilePath = updateContent.stream()
|
||||
.filter(map -> {
|
||||
String action = T.MapUtil.getStr(map, "action");
|
||||
return T.StrUtil.equalsAny(action, "create", "update");
|
||||
})
|
||||
.map(map -> T.MapUtil.getStr(map, "path"))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
ObjectId currentCommitId = repository.resolve(lastCommitId);
|
||||
try (RevWalk walk = new RevWalk(repository)) {
|
||||
CanonicalTreeParser c1 = new CanonicalTreeParser();
|
||||
c1.reset(repository.newObjectReader(), walk.parseCommit(currentCommitId).getTree());
|
||||
|
||||
CanonicalTreeParser c2 = new CanonicalTreeParser();
|
||||
c2.reset(repository.newObjectReader(), walk.parseCommit(branchRef).getTree());
|
||||
|
||||
List<DiffEntry> diffs = git.diff()
|
||||
.setOldTree(c1)
|
||||
.setNewTree(c2)
|
||||
.call();
|
||||
List<String> affectFilePathList = diffs.stream()
|
||||
.filter(entry -> T.StrUtil.equalsAnyIgnoreCase(entry.getChangeType().name(), DiffEntry.ChangeType.MODIFY.name(), DiffEntry.ChangeType.ADD.name()))
|
||||
.map(DiffEntry::getNewPath)
|
||||
.collect(Collectors.toList());
|
||||
List<String> intersection = T.CollUtil.intersection(updateFilePath, affectFilePathList).stream().toList();
|
||||
if (T.CollUtil.isEmpty(intersection)) {
|
||||
// 在 param.lastCommitId 不是当前分支最新提交时,本次提交文件没有冲突,更新 commit=branch.HEAD
|
||||
lastCommitId = branchRef.getName();
|
||||
} else {
|
||||
throw new ASWException(RCode.GIT_COMMIT_CONFLICT_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
try (ObjectInserter inserter = repository.getObjectDatabase().newInserter();
|
||||
TreeWalk treeWalk = new TreeWalk(repository);
|
||||
RevWalk revWalk = new RevWalk(repository)) {
|
||||
|
||||
// branch tree
|
||||
treeWalk.addTree(revWalk.parseTree(branchRef));
|
||||
treeWalk.setRecursive(true);
|
||||
|
||||
DirCache newTree = DirCache.newInCore();
|
||||
DirCacheBuilder newTreeBuilder = newTree.builder();
|
||||
|
||||
List<String> updateFilePath = updateContent.stream().map(map -> T.MapUtil.getStr(map, "path")).collect(Collectors.toList());
|
||||
while (treeWalk.next()) {
|
||||
String pathString = treeWalk.getPathString();
|
||||
// 先删
|
||||
if (!updateFilePath.contains(pathString)) {
|
||||
DirCacheEntry entry = JGitUtils.buildDirCacheEntry(pathString, treeWalk.getFileMode(0), treeWalk.getObjectId(0));
|
||||
newTreeBuilder.add(entry);
|
||||
}
|
||||
}
|
||||
// 后增
|
||||
for (Map<String, String> map : updateContent) {
|
||||
String action = T.MapUtil.getStr(map, "action");
|
||||
if (T.StrUtil.equalsAnyIgnoreCase(action, "create", "update")) {
|
||||
String path = T.MapUtil.getStr(map, "path");
|
||||
DirCacheEntry dirCacheEntry = new DirCacheEntry(path);
|
||||
dirCacheEntry.setFileMode(FileMode.REGULAR_FILE);
|
||||
|
||||
String content = T.MapUtil.getStr(map, "content");
|
||||
String encoding = T.MapUtil.getStr(map, "encoding");
|
||||
if ("base64".equals(encoding)) {
|
||||
// binary
|
||||
byte[] data = Base64.getDecoder().decode(content);
|
||||
ObjectId objectId = JGitUtils.insertBlobFileToDatabase(repository, data);
|
||||
dirCacheEntry.setObjectId(objectId);
|
||||
} else {
|
||||
// text
|
||||
ObjectId objectId = JGitUtils.insertBlobFileToDatabase(repository, content.getBytes());
|
||||
dirCacheEntry.setObjectId(objectId);
|
||||
}
|
||||
newTreeBuilder.add(dirCacheEntry);
|
||||
}
|
||||
}
|
||||
|
||||
newTreeBuilder.finish();
|
||||
ObjectId newTreeId = newTree.writeTree(inserter);
|
||||
|
||||
SysUserEntity loginUserEntity = userService.getById(StpUtil.getLoginIdAsString());
|
||||
PersonIdent personIdent = JGitUtils.buildPersonIdent(loginUserEntity.getName());
|
||||
|
||||
// commit
|
||||
JGitUtils.createCommit(repository, branch, newTreeId, message, personIdent);
|
||||
}
|
||||
} catch (IOException | GitAPIException e) {
|
||||
log.error(e, "[updateApplication] [error] [workspaceId: {}] [branch: {}] [lastCommitId: {}]", workspaceId, branch, lastCommitId);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Map<Object, Object>> listApplicationCommit(String workspaceId, String branch, String name, String file) {
|
||||
List<Map<Object, Object>> resultList = T.ListUtil.list(true);
|
||||
|
||||
File gitDir = workspaceService.getGitDir(workspaceId);
|
||||
try (Repository repository = JGitUtils.openRepository(gitDir);
|
||||
Git git = Git.open(repository.getDirectory());) {
|
||||
|
||||
String filterPath = T.StrUtil.concat(true, "applications/", name);
|
||||
if (T.StrUtil.isNotEmpty(file)) {
|
||||
filterPath = T.StrUtil.concat(true, filterPath, "/", file);
|
||||
}
|
||||
|
||||
ObjectId branchRef = git.getRepository().resolve(branch);
|
||||
Iterable<RevCommit> iterable = git.log()
|
||||
.add(branchRef)
|
||||
.addPath(filterPath)
|
||||
.call();
|
||||
|
||||
for (RevCommit commit : iterable) {
|
||||
resultList.add(JGitUtils.buildAswCommitInfo(commit));
|
||||
}
|
||||
} catch (IOException | GitAPIException e) {
|
||||
log.error(e, "[listApplicationCommit] [error] [workspaceId: {}] [branch: {}] [name: {}]", workspaceId, branch, name);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return resultList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Object, Object> infoApplicationFileContent(String workspaceId, String branch, String name, String commitId, String file) {
|
||||
// applications/qq/meta.json
|
||||
String path = T.StrUtil.concat(true, "applications/", name, "/", file);
|
||||
|
||||
Map<Object, Object> result = T.MapUtil.builder()
|
||||
.put("path", path)
|
||||
.build();
|
||||
|
||||
File gitDir = workspaceService.getGitDir(workspaceId);
|
||||
try (Repository repository = JGitUtils.openRepository(gitDir);
|
||||
TreeWalk treeWalk = new TreeWalk(repository);
|
||||
RevWalk revWalk = new RevWalk(repository);
|
||||
) {
|
||||
RevCommit revCommit = revWalk.parseCommit(ObjectId.fromString(commitId));
|
||||
ObjectId treeId = revCommit.getTree().getId();
|
||||
|
||||
treeWalk.addTree(treeId);
|
||||
treeWalk.setRecursive(true);
|
||||
|
||||
while (treeWalk.next()) {
|
||||
if (T.StrUtil.equals(path, treeWalk.getPathString())) {
|
||||
Map<Object, Object> fileContent = JGitUtils.getFileContent(repository, treeWalk.getPathString(), treeWalk.getObjectId(0));
|
||||
result.putAll(fileContent);
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
log.error(e, "[infoApplicationFileContent] [error] [workspaceId: {}] [branch: {}] [name: {}]", workspaceId, branch, name);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 通过 path 获取 lastCommit
|
||||
*
|
||||
* @param repository
|
||||
* @param branch
|
||||
* @param pathMapping
|
||||
* @return
|
||||
*/
|
||||
public Map<String, RevCommit> getLastCommitIdDataByPath(Repository repository, String branch, Map<String, String> pathMapping) {
|
||||
Map<String, RevCommit> result = new HashMap<>();
|
||||
try (Git git = new Git(repository);
|
||||
DiffFormatter diffFormatter = new DiffFormatter(DisabledOutputStream.INSTANCE);
|
||||
) {
|
||||
diffFormatter.setRepository(repository);
|
||||
|
||||
// 指定分支获取 log
|
||||
Iterable<RevCommit> commits = git.log()
|
||||
.add(git.getRepository().resolve(branch))
|
||||
.call();
|
||||
for (RevCommit commit : commits) {
|
||||
// 获取上次提交,用以对比差异
|
||||
RevCommit parent = commit.getParentCount() > 0 ? commit.getParent(0) : null;
|
||||
if (parent == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// 计算当前提交与上次提交之间的差异
|
||||
List<DiffEntry> diffs = diffFormatter.scan(parent.getTree(), commit.getTree());
|
||||
for (DiffEntry diff : diffs) {
|
||||
String newPath = diff.getNewPath();
|
||||
String oldPath = diff.getOldPath();
|
||||
|
||||
// 检查是否匹配目标路径
|
||||
for (Map.Entry<String, String> entry : pathMapping.entrySet()) {
|
||||
String key = entry.getKey();
|
||||
String path = entry.getValue();
|
||||
if (T.BooleanUtil.and(
|
||||
(newPath.startsWith(path) || oldPath.startsWith(path)),
|
||||
!result.containsKey(key)
|
||||
)) {
|
||||
result.put(key, commit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 如果所有路径都找到对应的最后提交,提前结束循环
|
||||
if (result.size() == pathMapping.size()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (IOException | GitAPIException e) {
|
||||
log.error(e, "[getLastCommitIdDataByPath] [workspace: {}] [branch: {}]", repository.getDirectory().getPath(), branch);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public void saveOrUpdateBatch(String workspaceId, String branch, String commitMessage, List<ApplicationEntity> list) {
|
||||
try (Git git = gitService.getGitInstance(workspaceId);
|
||||
Repository repository = git.getRepository();
|
||||
File gitDir = workspaceService.getGitDir(workspaceId);
|
||||
try (Repository repository = JGitUtils.openRepository(gitDir);
|
||||
RevWalk revWalk = new RevWalk(repository)) {
|
||||
|
||||
ObjectId branchRef = repository.resolve(branch);
|
||||
@@ -186,7 +647,7 @@ public class ApplicationServiceImpl implements IApplicationService {
|
||||
DirCacheEntry dirCacheEntry = new DirCacheEntry(filePath);
|
||||
dirCacheEntry.setFileMode(FileMode.REGULAR_FILE);
|
||||
|
||||
ObjectId blobId = gitService.insertBlobFileToDatabase(repository, fileContent.getBytes());
|
||||
ObjectId blobId = JGitUtils.insertBlobFileToDatabase(repository, fileContent.getBytes());
|
||||
dirCacheEntry.setObjectId(blobId);
|
||||
newTreeBuilder.add(dirCacheEntry);
|
||||
}
|
||||
@@ -207,8 +668,8 @@ public class ApplicationServiceImpl implements IApplicationService {
|
||||
}
|
||||
|
||||
String fileContent = T.JSONUtil.parse(jsonObject).toJSONString(2);
|
||||
ObjectId objectId = gitService.insertBlobFileToDatabase(repository, fileContent.getBytes());
|
||||
DirCacheEntry dirCacheEntry = gitService.buildDirCacheEntry(T.StrUtil.concat(true, "applications/", entity.getName(), "/meta.json"), FileMode.REGULAR_FILE, objectId);
|
||||
ObjectId objectId = JGitUtils.insertBlobFileToDatabase(repository, fileContent.getBytes());
|
||||
DirCacheEntry dirCacheEntry = JGitUtils.buildDirCacheEntry(T.StrUtil.concat(true, "applications/", entity.getName(), "/meta.json"), FileMode.REGULAR_FILE, objectId);
|
||||
newTreeBuilder.add(dirCacheEntry);
|
||||
|
||||
// signature.json
|
||||
@@ -216,14 +677,18 @@ public class ApplicationServiceImpl implements IApplicationService {
|
||||
JSONObject jsonObject2 = T.JSONUtil.parseObj(jsonStr);
|
||||
|
||||
String fileContent2 = T.JSONUtil.parse(jsonObject2).toJSONString(2);
|
||||
ObjectId objectId2 = gitService.insertBlobFileToDatabase(repository, fileContent2.getBytes());
|
||||
DirCacheEntry dirCacheEntry2 = gitService.buildDirCacheEntry(T.StrUtil.concat(true, "applications/", entity.getName(), "/signature.json"), FileMode.REGULAR_FILE, objectId2);
|
||||
ObjectId objectId2 = JGitUtils.insertBlobFileToDatabase(repository, fileContent2.getBytes());
|
||||
DirCacheEntry dirCacheEntry2 = JGitUtils.buildDirCacheEntry(T.StrUtil.concat(true, "applications/", entity.getName(), "/signature.json"), FileMode.REGULAR_FILE, objectId2);
|
||||
newTreeBuilder.add(dirCacheEntry2);
|
||||
}
|
||||
newTreeBuilder.finish();
|
||||
|
||||
RevCommit commitId = revWalk.parseCommit(branchRef);
|
||||
boolean success = gitService.commitIndex(repository, branch, newTree, commitId, null, commitMessage);
|
||||
|
||||
SysUserEntity loginUserEntity = userService.getById(StpUtil.getLoginIdAsString());
|
||||
PersonIdent personIdent = JGitUtils.buildPersonIdent(loginUserEntity.getName());
|
||||
|
||||
boolean success = JGitUtils.commitIndex(repository, branch, newTree, commitId, null, commitMessage, personIdent);
|
||||
log.info("[saveOrUpdateBatch] [workspaceId: {}] [branch: {}] [commitId: {}] [success: {}]", workspaceId, branch, commitId, success);
|
||||
}
|
||||
} catch (IOException | ConcurrentRefUpdateException e) {
|
||||
@@ -252,7 +717,7 @@ public class ApplicationServiceImpl implements IApplicationService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ApplicationEntity> importAppByFormat(String workspaceId, String branchName, String format, List<JSONObject> dataList) {
|
||||
public List<ApplicationEntity> importAppByFormat(String workspaceId, String branch, String format, List<JSONObject> dataList) {
|
||||
try {
|
||||
switch (format) {
|
||||
case "tsg2402": {
|
||||
@@ -260,7 +725,7 @@ public class ApplicationServiceImpl implements IApplicationService {
|
||||
|
||||
// commit
|
||||
String commitMessage = "feat: import application data from TSG system (version 2402)";
|
||||
this.saveOrUpdateBatch(workspaceId, branchName, commitMessage, records);
|
||||
this.saveOrUpdateBatch(workspaceId, branch, commitMessage, records);
|
||||
return records;
|
||||
}
|
||||
default:
|
||||
|
||||
@@ -0,0 +1,156 @@
|
||||
package net.geedge.asw.module.app.service.impl;
|
||||
|
||||
import cn.hutool.log.Log;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import net.geedge.asw.common.util.ASWException;
|
||||
import net.geedge.asw.common.util.RCode;
|
||||
import net.geedge.asw.common.util.T;
|
||||
import net.geedge.asw.module.app.entity.ApplicationMergeEntity;
|
||||
import net.geedge.asw.module.app.service.IBranchService;
|
||||
import net.geedge.asw.module.app.service.IApplicationMergeService;
|
||||
import net.geedge.asw.module.app.service.impl.ApplicationMergeServiceImpl.MergeRequestStatus;
|
||||
import net.geedge.asw.module.app.util.JGitUtils;
|
||||
import net.geedge.asw.module.workspace.service.IWorkspaceService;
|
||||
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.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@Service
|
||||
public class BranchServiceImpl implements IBranchService {
|
||||
|
||||
private final static Log log = Log.get();
|
||||
|
||||
@Autowired
|
||||
private IWorkspaceService workspaceService;
|
||||
|
||||
@Autowired
|
||||
private IApplicationMergeService applicationMergeService;
|
||||
|
||||
@Override
|
||||
public List<Map<Object, Object>> listBranch(String workspaceId, String search) {
|
||||
List<Map<Object, Object>> resultList = T.ListUtil.list(true);
|
||||
|
||||
File gitDir = workspaceService.getGitDir(workspaceId);
|
||||
try (Repository repository = JGitUtils.openRepository(gitDir);
|
||||
Git git = Git.open(repository.getDirectory())) {
|
||||
String fullBranch = repository.getFullBranch();
|
||||
|
||||
String defaultBranch = "main";
|
||||
if (fullBranch != null && fullBranch.startsWith(JGitUtils.LOCAL_BRANCH_PREFIX)) {
|
||||
defaultBranch = fullBranch.substring(JGitUtils.LOCAL_BRANCH_PREFIX.length());
|
||||
}
|
||||
|
||||
// 默认行为,进查询本地分支
|
||||
List<Ref> call = git.branchList().call();
|
||||
RevWalk revCommits = new RevWalk(repository);
|
||||
|
||||
for (Ref ref : call) {
|
||||
String branchName = ref.getName();
|
||||
// 返回时去掉前缀
|
||||
branchName = branchName.replaceAll(JGitUtils.LOCAL_BRANCH_PREFIX, "");
|
||||
if (T.StrUtil.isNotEmpty(search)) {
|
||||
if (!T.StrUtil.contains(branchName, search)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
Map<Object, Object> m = T.MapUtil.builder()
|
||||
.put("name", branchName)
|
||||
.put("default", T.StrUtil.equals(defaultBranch, branchName))
|
||||
.build();
|
||||
|
||||
RevCommit commit = revCommits.parseCommit(ref.getObjectId());
|
||||
m.put("commit", JGitUtils.buildAswCommitInfo(commit));
|
||||
|
||||
resultList.add(m);
|
||||
}
|
||||
revCommits.close();
|
||||
revCommits.dispose();
|
||||
} catch (GitAPIException | IOException e) {
|
||||
log.error(e, "[listBranch] [error] [workspaceId: {}]", workspaceId);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return resultList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Object, Object> infoBranch(String workspaceId, String branchName) {
|
||||
List<Map<Object, Object>> listBranch = this.listBranch(workspaceId, branchName);
|
||||
// 分支不存在
|
||||
if (T.CollUtil.isEmpty(listBranch)) {
|
||||
throw new ASWException(RCode.SYS_RECORD_NOT_FOUND);
|
||||
}
|
||||
return T.CollUtil.getFirst(listBranch);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<Object, Object> newBranch(String workspaceId, String name, String ref) {
|
||||
File gitDir = workspaceService.getGitDir(workspaceId);
|
||||
try (Repository repository = JGitUtils.openRepository(gitDir);
|
||||
Git git = Git.open(repository.getDirectory())) {
|
||||
|
||||
git.branchCreate()
|
||||
.setName(name)
|
||||
.setStartPoint(ref)
|
||||
.call();
|
||||
|
||||
return this.infoBranch(workspaceId, name);
|
||||
} catch (GitAPIException | IOException e) {
|
||||
log.error(e, "[newBranch] [error] [workspaceId: {}] [branch: {}] [ref: {}]", workspaceId, name, ref);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleteBranch(String workspaceId, String branchName) {
|
||||
log.info("[deleteBranch] [begin] [workspaceId: {}] [branch: {}]", workspaceId, branchName);
|
||||
|
||||
File gitDir = workspaceService.getGitDir(workspaceId);
|
||||
try (Repository repository = JGitUtils.openRepository(gitDir);
|
||||
Git git = Git.open(repository.getDirectory())) {
|
||||
|
||||
git.branchDelete()
|
||||
.setBranchNames(branchName)
|
||||
.setForce(true)
|
||||
.call();
|
||||
|
||||
// OPEN 状态,mr 源分支被删除,mr 记录直接删掉
|
||||
applicationMergeService.remove(new LambdaQueryWrapper<ApplicationMergeEntity>()
|
||||
.eq(ApplicationMergeEntity::getWorkspaceId, workspaceId)
|
||||
.eq(ApplicationMergeEntity::getSourceBranch, branchName)
|
||||
.eq(ApplicationMergeEntity::getStatus, MergeRequestStatus.OPEN.toString())
|
||||
);
|
||||
} catch (GitAPIException | IOException e) {
|
||||
log.error(e, "[deleteBranch] [error] [workspaceId: {}] [branchName: {}]", workspaceId, branchName);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Map<Object, Object>> listBranchCommit(String workspaceId, String branch, String path) {
|
||||
List<Map<Object, Object>> resultList = T.ListUtil.list(true);
|
||||
|
||||
File gitDir = workspaceService.getGitDir(workspaceId);
|
||||
try (Repository repository = JGitUtils.openRepository(gitDir)) {
|
||||
|
||||
List<RevCommit> branchCommitList = JGitUtils.getBranchCommitList(repository, branch, path);
|
||||
branchCommitList.forEach(revCommit -> resultList.add(JGitUtils.buildAswCommitInfo(revCommit)));
|
||||
|
||||
} catch (GitAPIException | IOException e) {
|
||||
log.error(e, "[listBranchCommit] [error] [workspaceId: {}] [branch: {}] [path: {}]", workspaceId, branch, path);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return resultList;
|
||||
}
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
820
src/main/java/net/geedge/asw/module/app/util/JGitUtils.java
Normal file
820
src/main/java/net/geedge/asw/module/app/util/JGitUtils.java
Normal file
@@ -0,0 +1,820 @@
|
||||
package net.geedge.asw.module.app.util;
|
||||
|
||||
import cn.hutool.log.Log;
|
||||
import net.geedge.asw.common.util.ASWException;
|
||||
import net.geedge.asw.common.util.RCode;
|
||||
import net.geedge.asw.common.util.T;
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
import org.eclipse.jgit.api.*;
|
||||
import org.eclipse.jgit.api.errors.ConcurrentRefUpdateException;
|
||||
import org.eclipse.jgit.api.errors.GitAPIException;
|
||||
import org.eclipse.jgit.api.errors.JGitInternalException;
|
||||
import org.eclipse.jgit.diff.*;
|
||||
import org.eclipse.jgit.dircache.DirCache;
|
||||
import org.eclipse.jgit.dircache.DirCacheBuilder;
|
||||
import org.eclipse.jgit.dircache.DirCacheEntry;
|
||||
import org.eclipse.jgit.internal.JGitText;
|
||||
import org.eclipse.jgit.lib.*;
|
||||
import org.eclipse.jgit.merge.MergeFormatter;
|
||||
import org.eclipse.jgit.merge.MergeStrategy;
|
||||
import org.eclipse.jgit.merge.RecursiveMerger;
|
||||
import org.eclipse.jgit.merge.ThreeWayMerger;
|
||||
import org.eclipse.jgit.revwalk.RevCommit;
|
||||
import org.eclipse.jgit.revwalk.RevWalk;
|
||||
import org.eclipse.jgit.revwalk.filter.RevFilter;
|
||||
import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
|
||||
import org.eclipse.jgit.transport.PushResult;
|
||||
import org.eclipse.jgit.transport.RemoteRefUpdate;
|
||||
import org.eclipse.jgit.treewalk.CanonicalTreeParser;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Component
|
||||
public class JGitUtils {
|
||||
|
||||
private final static Log log = Log.get();
|
||||
/**
|
||||
* 本地分支引用前缀
|
||||
*/
|
||||
public static final String LOCAL_BRANCH_PREFIX = "refs/heads/";
|
||||
|
||||
/**
|
||||
* 默认分支
|
||||
*/
|
||||
public static final String DEFAULT_BRANCH = "main";
|
||||
|
||||
private static String textExtensions;
|
||||
|
||||
@Autowired
|
||||
public JGitUtils(Environment environment) {
|
||||
textExtensions = environment.getProperty("file.extensions.text", "txt,csv,md,html,xml,json,log,bat,py,sh,ini,conf,yaml,yml,properties,toml,java,c,cpp,js,php,ts,go,rb,rtf,tex,rss,xhtml,sql");
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回 git repository
|
||||
*
|
||||
* @param gitDir
|
||||
* @return
|
||||
* @throws IOException
|
||||
*/
|
||||
public static Repository openRepository(File gitDir) throws IOException {
|
||||
FileRepositoryBuilder builder = new FileRepositoryBuilder();
|
||||
Repository repository = builder.setGitDir(gitDir)
|
||||
.readEnvironment()
|
||||
.findGitDir()
|
||||
.build();
|
||||
return repository;
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化仓库
|
||||
*
|
||||
* @param repoDir
|
||||
* @param author
|
||||
*/
|
||||
public static void initRepository(File repoDir, String author) {
|
||||
try (
|
||||
Git git = Git.init()
|
||||
.setBare(true)
|
||||
.setDirectory(repoDir)
|
||||
.setInitialBranch(DEFAULT_BRANCH)
|
||||
.call();
|
||||
Repository repository = git.getRepository();
|
||||
ObjectInserter inserter = repository.getObjectDatabase().newInserter();
|
||||
) {
|
||||
DirCache dirCache = DirCache.newInCore();
|
||||
DirCacheBuilder builder = dirCache.builder();
|
||||
|
||||
ObjectId objectId = JGitUtils.insertBlobFileToDatabase(repository, "".getBytes());
|
||||
DirCacheEntry entry = JGitUtils.buildDirCacheEntry("README.md", FileMode.REGULAR_FILE, objectId);
|
||||
builder.add(entry);
|
||||
builder.finish();
|
||||
|
||||
// commit
|
||||
String message = "Initial commit";
|
||||
PersonIdent personIdent = new PersonIdent(author, "asw@geedgenetworks.com");
|
||||
|
||||
JGitUtils.createCommit(repository, DEFAULT_BRANCH, dirCache.writeTree(inserter), message, personIdent);
|
||||
} catch (GitAPIException | IOException e) {
|
||||
log.error(e, "[initRepository] [git init error]");
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 返回分支是否存在
|
||||
*
|
||||
* @param repository
|
||||
* @param branch
|
||||
* @return
|
||||
* @throws IOException
|
||||
*/
|
||||
public static boolean isBranchExists(Repository repository, String branch) throws IOException {
|
||||
Ref ref = repository.findRef(T.StrUtil.concat(true, LOCAL_BRANCH_PREFIX, branch));
|
||||
return null != ref;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取提交对象
|
||||
*
|
||||
* @param repository
|
||||
* @param commitId
|
||||
* @return
|
||||
* @throws IOException
|
||||
*/
|
||||
public static RevCommit infoCommit(Repository repository, String commitId) throws IOException {
|
||||
try (RevWalk revCommits = new RevWalk(repository);) {
|
||||
RevCommit commit = revCommits.parseCommit(ObjectId.fromString(commitId));
|
||||
return commit;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 返回分支最新提交
|
||||
*
|
||||
* @param repository
|
||||
* @param branch
|
||||
* @return
|
||||
*/
|
||||
public static RevCommit getBranchLatestCommit(Repository repository, String branch) throws IOException {
|
||||
RevWalk revWalk = new RevWalk(repository);
|
||||
RevCommit commit = revWalk.parseCommit(repository.resolve(branch));
|
||||
return commit;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取分支提交记录
|
||||
*
|
||||
* @param repository
|
||||
* @param branch
|
||||
* @param path
|
||||
* @return
|
||||
* @throws GitAPIException
|
||||
* @throws IOException
|
||||
*/
|
||||
public static List<RevCommit> getBranchCommitList(Repository repository, String branch, String path) throws GitAPIException, IOException {
|
||||
List<RevCommit> resultList = T.ListUtil.list(true);
|
||||
Git git = Git.open(repository.getDirectory());
|
||||
ObjectId branchRef = git.getRepository().resolve(branch);
|
||||
LogCommand command = git.log().add(branchRef);
|
||||
if (T.StrUtil.isNotEmpty(path)) {
|
||||
command.addPath(path);
|
||||
}
|
||||
|
||||
Iterable<RevCommit> iterable = command.call();
|
||||
for (RevCommit commit : iterable) {
|
||||
resultList.add(commit);
|
||||
}
|
||||
return resultList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取父提交
|
||||
*
|
||||
* @param repository
|
||||
* @param branch
|
||||
* @param commitId
|
||||
* @return
|
||||
* @throws IOException
|
||||
*/
|
||||
public static RevCommit getParentCommit(Repository repository, String branch, String commitId) throws IOException {
|
||||
try (RevWalk revWalk = new RevWalk(repository)) {
|
||||
Ref branchRef = repository.findRef(branch);
|
||||
revWalk.markStart(revWalk.parseCommit(branchRef.getObjectId()));
|
||||
|
||||
RevCommit parentCommit = null;
|
||||
Iterator<RevCommit> iterator = revWalk.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
RevCommit currentCommit = iterator.next();
|
||||
if (currentCommit.getId().getName().equals(commitId)) {
|
||||
if (currentCommit.getParentCount() > 0) {
|
||||
parentCommit = currentCommit.getParent(0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (null == parentCommit) {
|
||||
throw new ASWException(RCode.GIT_PARENT_COMMITID_NOT_FOUND);
|
||||
}
|
||||
return parentCommit;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the merge base of two commits or null if there is no common ancestry.
|
||||
* 返回两个提交的合并基础,如果没有共同祖先,则返回 null。
|
||||
*
|
||||
* @param repository
|
||||
* @param commitIdA
|
||||
* @param commitIdB
|
||||
* @return the commit id of the merge base or null if there is no common base
|
||||
*/
|
||||
public static RevCommit getMergeBaseCommit(Repository repository, ObjectId commitIdA, ObjectId commitIdB) {
|
||||
try (RevWalk rw = new RevWalk(repository)) {
|
||||
RevCommit a = rw.lookupCommit(commitIdA);
|
||||
RevCommit b = rw.lookupCommit(commitIdB);
|
||||
|
||||
rw.setRevFilter(RevFilter.MERGE_BASE);
|
||||
rw.markStart(a);
|
||||
rw.markStart(b);
|
||||
RevCommit mergeBase = rw.next();
|
||||
if (mergeBase == null) {
|
||||
return null;
|
||||
}
|
||||
return mergeBase;
|
||||
} catch (Exception e) {
|
||||
log.error(e, "Failed to determine merge base");
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* commit range
|
||||
* 沿着 parent(0) 的主路径提交列表,忽略所有分支路径的提交
|
||||
*
|
||||
* @param repository
|
||||
* @param newCommitId
|
||||
* @param oldCommitId
|
||||
* @return
|
||||
* @throws IOException
|
||||
*/
|
||||
public static List<RevCommit> listCommitRange(Repository repository, String newCommitId, String oldCommitId) throws IOException {
|
||||
log.info("[listCommitRange] [begin] [repository: {}] [newCommitId: {}] [oldCommitId: {}]", repository, newCommitId, oldCommitId);
|
||||
List<RevCommit> commitList = T.ListUtil.list(true);
|
||||
|
||||
try (RevWalk revWalk = new RevWalk(repository)) {
|
||||
RevCommit revCommit = revWalk.parseCommit(repository.resolve(newCommitId));
|
||||
|
||||
Set<ObjectId> visitedCommits = new HashSet<>();
|
||||
while (revCommit != null && !visitedCommits.contains(revCommit.getId())) {
|
||||
if (oldCommitId != null && revCommit.getId().getName().equals(oldCommitId)) {
|
||||
break;
|
||||
}
|
||||
|
||||
commitList.add(revCommit);
|
||||
visitedCommits.add(revCommit.getId());
|
||||
|
||||
// 沿着 parent(0) 前进
|
||||
if (revCommit.getParentCount() > 0) {
|
||||
revCommit = revWalk.parseCommit(revCommit.getParent(0));
|
||||
} else {
|
||||
revCommit = null;
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
log.info("[listCommitRange] [finshed] [repository: {}] [commits size: {}]", repository, commitList.size());
|
||||
}
|
||||
return commitList;
|
||||
}
|
||||
|
||||
/**
|
||||
* 构建 DirCacheEntry
|
||||
*
|
||||
* @param path
|
||||
* @param mode
|
||||
* @param objectId
|
||||
* @return
|
||||
*/
|
||||
public static DirCacheEntry buildDirCacheEntry(String path, FileMode mode, ObjectId objectId) {
|
||||
DirCacheEntry dirCacheEntry = new DirCacheEntry(path);
|
||||
dirCacheEntry.setFileMode(mode);
|
||||
dirCacheEntry.setObjectId(objectId);
|
||||
return dirCacheEntry;
|
||||
}
|
||||
|
||||
public static PersonIdent buildPersonIdent(String name) {
|
||||
return buildPersonIdent(name, "asw@geedgenetworks.com");
|
||||
}
|
||||
|
||||
public static PersonIdent buildPersonIdent(String name, String email) {
|
||||
return new PersonIdent(name, email);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将 file object 添加到 objectDatabases 并返回 ObjectId
|
||||
*
|
||||
* @param repository
|
||||
* @param data
|
||||
* @return
|
||||
* @throws IOException
|
||||
*/
|
||||
public static ObjectId insertBlobFileToDatabase(Repository repository, byte[] data) throws IOException {
|
||||
try (ObjectInserter inserter = repository.getObjectDatabase().newInserter()) {
|
||||
ObjectId blobId = inserter.insert(Constants.OBJ_BLOB, data);
|
||||
inserter.flush();
|
||||
return blobId;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* commit
|
||||
*
|
||||
* @param repository
|
||||
* @param branch
|
||||
* @param treeId
|
||||
* @param message
|
||||
* @param personIdent
|
||||
* @throws IOException
|
||||
* @throws ConcurrentRefUpdateException
|
||||
*/
|
||||
public static void createCommit(Repository repository, String branch, ObjectId treeId, String message, PersonIdent personIdent) throws IOException, ConcurrentRefUpdateException {
|
||||
try (ObjectInserter inserter = repository.getObjectDatabase().newInserter();
|
||||
RevWalk revWalk = new RevWalk(repository);) {
|
||||
|
||||
CommitBuilder builder = new CommitBuilder();
|
||||
builder.setTreeId(treeId);
|
||||
builder.setMessage(message);
|
||||
|
||||
ObjectId branchRef = repository.resolve(branch);
|
||||
if (null != branchRef) {
|
||||
RevCommit parentId = revWalk.parseCommit(branchRef);
|
||||
builder.setParentId(parentId);
|
||||
}
|
||||
|
||||
builder.setAuthor(personIdent);
|
||||
builder.setCommitter(personIdent);
|
||||
|
||||
// 插入新的提交对象
|
||||
ObjectId commitId = inserter.insert(builder);
|
||||
inserter.flush();
|
||||
|
||||
// 更新 branch 指向新的提交
|
||||
RefUpdate ru = null;
|
||||
RefUpdate.Result rc = null;
|
||||
if (null != branchRef) {
|
||||
ru = repository.updateRef(T.StrUtil.concat(true, LOCAL_BRANCH_PREFIX, branch));
|
||||
ru.setNewObjectId(commitId);
|
||||
rc = ru.update();
|
||||
} else {
|
||||
ru = repository.updateRef(Constants.HEAD);
|
||||
ru.setNewObjectId(commitId);
|
||||
rc = ru.update();
|
||||
}
|
||||
switch (rc) {
|
||||
case NEW:
|
||||
case FORCED:
|
||||
case FAST_FORWARD:
|
||||
break;
|
||||
case REJECTED:
|
||||
case LOCK_FAILURE:
|
||||
throw new ConcurrentRefUpdateException(JGitText.get().couldNotLockHEAD, ru.getRef(), rc);
|
||||
default:
|
||||
throw new JGitInternalException(MessageFormat.format(
|
||||
JGitText.get().updatingRefFailed, branch, commitId.toString(),
|
||||
rc));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* commit index
|
||||
*
|
||||
* @param repository
|
||||
* @param branch
|
||||
* @param index
|
||||
* @param parentId1
|
||||
* @param parentId2
|
||||
* @param message
|
||||
* @param personIdent
|
||||
* @return
|
||||
* @throws IOException
|
||||
* @throws ConcurrentRefUpdateException
|
||||
*/
|
||||
public static boolean commitIndex(Repository repository, String branch, DirCache index, ObjectId parentId1, ObjectId parentId2, String message, PersonIdent personIdent) throws IOException, ConcurrentRefUpdateException {
|
||||
boolean success = false;
|
||||
try (ObjectInserter odi = repository.newObjectInserter()) {
|
||||
|
||||
// new index
|
||||
ObjectId indexTreeId = index.writeTree(odi);
|
||||
|
||||
// PersonIdent
|
||||
CommitBuilder commit = new CommitBuilder();
|
||||
commit.setAuthor(personIdent);
|
||||
commit.setCommitter(personIdent);
|
||||
|
||||
if (null != parentId1 && null == parentId2) {
|
||||
commit.setParentId(parentId1);
|
||||
}
|
||||
if (null != parentId1 && null != parentId2) {
|
||||
commit.setParentIds(parentId1, parentId2);
|
||||
}
|
||||
|
||||
commit.setTreeId(indexTreeId);
|
||||
commit.setMessage(message);
|
||||
|
||||
|
||||
// insert the commit into the repository
|
||||
ObjectId commitId = odi.insert(commit);
|
||||
odi.flush();
|
||||
|
||||
RefUpdate ru = repository.updateRef(T.StrUtil.concat(true, JGitUtils.LOCAL_BRANCH_PREFIX, branch));
|
||||
ru.setNewObjectId(commitId);
|
||||
RefUpdate.Result rc = ru.update();
|
||||
switch (rc) {
|
||||
case NEW:
|
||||
case FORCED:
|
||||
case FAST_FORWARD:
|
||||
success = true;
|
||||
break;
|
||||
case REJECTED:
|
||||
case LOCK_FAILURE:
|
||||
throw new ConcurrentRefUpdateException(JGitText.get().couldNotLockHEAD, ru.getRef(), rc);
|
||||
default:
|
||||
throw new JGitInternalException(MessageFormat.format(
|
||||
JGitText.get().updatingRefFailed, branch, commitId.toString(),
|
||||
rc));
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取 commitIdA -> commitIdB 文件差异
|
||||
*
|
||||
* @param repository
|
||||
* @param newCommitId
|
||||
* @param oldCommitId
|
||||
* @return
|
||||
* @throws IOException
|
||||
*/
|
||||
public static List<Map<Object, Object>> getDiffFileListInCommits(Repository repository, String newCommitId, String oldCommitId) throws IOException {
|
||||
log.info("[getDiffFileListInCommits] [begin] [repository: {}] [newCommitId: {}] [oldCommitId: {}]", repository, newCommitId, oldCommitId);
|
||||
try (RevWalk revWalk = new RevWalk(repository);
|
||||
DiffFormatter diffFormatter = new DiffFormatter(null);
|
||||
) {
|
||||
|
||||
RevCommit oldCommit = revWalk.parseCommit(repository.resolve(oldCommitId));
|
||||
RevCommit newCommit = revWalk.parseCommit(repository.resolve(newCommitId));
|
||||
|
||||
// oldTree
|
||||
CanonicalTreeParser oldTree = new CanonicalTreeParser();
|
||||
oldTree.reset(repository.newObjectReader(), oldCommit.getTree());
|
||||
// newTree
|
||||
CanonicalTreeParser newTree = new CanonicalTreeParser();
|
||||
newTree.reset(repository.newObjectReader(), newCommit.getTree());
|
||||
|
||||
// diff
|
||||
List<Map<Object, Object>> files = T.ListUtil.list(true);
|
||||
|
||||
diffFormatter.setRepository(repository);
|
||||
diffFormatter.setDiffComparator(RawTextComparator.DEFAULT);
|
||||
diffFormatter.setDetectRenames(true);
|
||||
|
||||
List<DiffEntry> diffs = diffFormatter.scan(oldTree, newTree);
|
||||
for (DiffEntry diff : diffs) {
|
||||
int addedLines = 0;
|
||||
int deletedLines = 0;
|
||||
EditList edits = diffFormatter.toFileHeader(diff).toEditList();
|
||||
for (Edit edit : edits) {
|
||||
switch (edit.getType()) {
|
||||
case INSERT:
|
||||
addedLines += edit.getLengthB();
|
||||
break;
|
||||
case DELETE:
|
||||
deletedLines += edit.getLengthA();
|
||||
break;
|
||||
case REPLACE:
|
||||
addedLines += edit.getLengthB();
|
||||
deletedLines += edit.getLengthA();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
String oldPath = diff.getOldPath(), newPath = diff.getNewPath(), encoding = null, oldContent = null, newContent = null;
|
||||
switch (diff.getChangeType()) {
|
||||
case COPY:
|
||||
case ADD: {
|
||||
Map<Object, Object> fileContent = getFileContent(repository, newPath, diff.getNewId().toObjectId());
|
||||
encoding = T.MapUtil.getStr(fileContent, "encoding", "");
|
||||
newContent = T.MapUtil.getStr(fileContent, "content", "");
|
||||
break;
|
||||
}
|
||||
case DELETE: {
|
||||
Map<Object, Object> fileContent = getFileContent(repository, oldPath, diff.getOldId().toObjectId());
|
||||
encoding = T.MapUtil.getStr(fileContent, "encoding", "");
|
||||
oldContent = T.MapUtil.getStr(fileContent, "content", "");
|
||||
break;
|
||||
}
|
||||
case MODIFY: {
|
||||
Map<Object, Object> fileContent = getFileContent(repository, oldPath, diff.getOldId().toObjectId());
|
||||
oldContent = T.MapUtil.getStr(fileContent, "content", "");
|
||||
|
||||
Map<Object, Object> fileContent1 = getFileContent(repository, newPath, diff.getNewId().toObjectId());
|
||||
encoding = T.MapUtil.getStr(fileContent1, "encoding", "");
|
||||
newContent = T.MapUtil.getStr(fileContent1, "content", "");
|
||||
break;
|
||||
}
|
||||
case RENAME: {
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
files.add(
|
||||
T.MapUtil.builder()
|
||||
.put("oldPath", oldPath)
|
||||
.put("newPath", newPath)
|
||||
.put("addedLines", addedLines)
|
||||
.put("removedLines", deletedLines)
|
||||
.put("encoding", encoding)
|
||||
.put("oldContent", oldContent)
|
||||
.put("newContent", newContent)
|
||||
.put("action", diff.getChangeType().name().toLowerCase())
|
||||
.build()
|
||||
);
|
||||
}
|
||||
return files;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 获取 sourceBranch,targetBranch 冲突文件路径
|
||||
*
|
||||
* @param repository
|
||||
* @param srcBranch
|
||||
* @param tgtBranch
|
||||
* @return
|
||||
* @throws IOException
|
||||
*/
|
||||
public static List<String> getConflictFilePathInBranches(Repository repository, String srcBranch, String tgtBranch) throws IOException {
|
||||
log.info("[getConflictFileListInBranches] [begin] [repository: {}] [srcBranch: {}] [tgtBranch: {}]", repository, srcBranch, tgtBranch);
|
||||
try (RevWalk revWalk = new RevWalk(repository)) {
|
||||
|
||||
RevCommit commitA = revWalk.parseCommit(repository.resolve(srcBranch));
|
||||
RevCommit commitB = revWalk.parseCommit(repository.resolve(tgtBranch));
|
||||
|
||||
// Find the merge base
|
||||
RevCommit mergeBaseCommit = JGitUtils.getMergeBaseCommit(repository, commitA, commitB);
|
||||
String mergeBaseId = mergeBaseCommit.getName();
|
||||
log.info("[getConflictFileListInBranches] [mergeBase: {}]", mergeBaseId);
|
||||
|
||||
RevCommit mergeBase = revWalk.parseCommit(repository.resolve(mergeBaseId));
|
||||
|
||||
ThreeWayMerger threeWayMerger = (ThreeWayMerger) MergeStrategy.RECURSIVE.newMerger(repository, true);
|
||||
threeWayMerger.setBase(mergeBase);
|
||||
|
||||
boolean isOk = threeWayMerger.merge(commitA, commitB);
|
||||
log.info("[getConflictFileListInBranches] [merge result] [isOk: {}]", isOk);
|
||||
if (!isOk) {
|
||||
List<String> unmergedPaths = ((RecursiveMerger) threeWayMerger).getUnmergedPaths();
|
||||
return unmergedPaths;
|
||||
}
|
||||
return T.ListUtil.empty();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取 sourceBranch,targetBranch 冲突文件详情
|
||||
*
|
||||
* @param repository
|
||||
* @param srcBranch
|
||||
* @param tgtBranch
|
||||
* @return
|
||||
* @throws IOException
|
||||
*/
|
||||
public static List<Map<Object, Object>> getConflictFileInfoInBranches(Repository repository, String srcBranch, String tgtBranch) throws IOException {
|
||||
log.info("[getConflictFileInfoInBranches] [begin] [repository: {}] [srcBranch: {}] [tgtBranch: {}]", repository, srcBranch, tgtBranch);
|
||||
try (RevWalk revWalk = new RevWalk(repository);) {
|
||||
|
||||
RevCommit commitA = revWalk.parseCommit(repository.resolve(srcBranch));
|
||||
RevCommit commitB = revWalk.parseCommit(repository.resolve(tgtBranch));
|
||||
|
||||
// Find the merge base
|
||||
String mergeBaseId = getMergeBaseCommit(repository, commitA, commitB).getName();
|
||||
log.info("[getConflictFileInfoInBranches] [mergeBase: {}]", mergeBaseId);
|
||||
|
||||
RevCommit mergeBase = revWalk.parseCommit(repository.resolve(mergeBaseId));
|
||||
|
||||
ThreeWayMerger threeWayMerger = (ThreeWayMerger) MergeStrategy.RECURSIVE.newMerger(repository, true);
|
||||
threeWayMerger.setBase(mergeBase);
|
||||
|
||||
boolean isOk = threeWayMerger.merge(commitA, commitB);
|
||||
log.info("[getConflictFileInfoInBranches] [merge result] [isOk: {}]", isOk);
|
||||
|
||||
if (!isOk) {
|
||||
List<Map<Object, Object>> files = T.ListUtil.list(true);
|
||||
|
||||
Map<String, org.eclipse.jgit.merge.MergeResult<? extends Sequence>> mergeResults = ((RecursiveMerger) threeWayMerger).getMergeResults();
|
||||
for (Map.Entry<String, org.eclipse.jgit.merge.MergeResult<? extends Sequence>> entry : mergeResults.entrySet()) {
|
||||
String unmergedPath = entry.getKey();
|
||||
// 暂不支持处理二进制文件冲突
|
||||
if (isBinary(T.FileNameUtil.getName(unmergedPath))) {
|
||||
throw new ASWException(RCode.GIT_BINARY_CONFLICT_ERROR);
|
||||
}
|
||||
|
||||
org.eclipse.jgit.merge.MergeResult<? extends Sequence> mergeResult = entry.getValue();
|
||||
try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) {
|
||||
MergeFormatter formatter = new MergeFormatter();
|
||||
|
||||
String oursName = unmergedPath;
|
||||
String theirsName = unmergedPath;
|
||||
formatter.formatMerge(outputStream, mergeResult, mergeBaseId, oursName, theirsName, StandardCharsets.UTF_8);
|
||||
files.add(
|
||||
T.MapUtil.builder()
|
||||
.put("path", unmergedPath)
|
||||
.put("content", outputStream.toString(StandardCharsets.UTF_8.name()))
|
||||
.put("conflict", true)
|
||||
.build()
|
||||
);
|
||||
}
|
||||
}
|
||||
return files;
|
||||
}
|
||||
return T.ListUtil.empty();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 分支合并
|
||||
*
|
||||
* @param centralRepository
|
||||
* @param srcBranch
|
||||
* @param tgtBranch
|
||||
* @param author
|
||||
* @param message
|
||||
* @param resolveConflictFileContent
|
||||
* @throws RuntimeException
|
||||
* @throws GitAPIException
|
||||
* @throws IOException
|
||||
*/
|
||||
public static void mergeBranch(Repository centralRepository, String srcBranch, String tgtBranch, String author, String message, List<Map<String, String>> resolveConflictFileContent) throws RuntimeException, GitAPIException, IOException {
|
||||
log.info("[mergeBranch] [begin] [repository: {}] [srcBranch: {}] [tgtBranch: {}]", centralRepository, srcBranch, tgtBranch);
|
||||
// prepare a new folder for the cloned repository
|
||||
File localPath = T.FileUtil.file(net.geedge.asw.common.util.Constants.TEMP_PATH, T.StrUtil.uuid());
|
||||
T.FileUtil.del(localPath);
|
||||
T.FileUtil.mkdir(localPath);
|
||||
|
||||
// bare repository
|
||||
File repoDir = centralRepository.getDirectory();
|
||||
|
||||
// clone
|
||||
try (Git git = Git.cloneRepository()
|
||||
.setBare(false)
|
||||
.setURI(repoDir.getAbsolutePath())
|
||||
.setDirectory(localPath)
|
||||
.setCredentialsProvider(null)
|
||||
.call();
|
||||
Repository repository = git.getRepository();) {
|
||||
StoredConfig config = repository.getConfig();
|
||||
config.setString("user", null, "name", author);
|
||||
config.setString("user", null, "email", "asw@geedgenetworks.com");
|
||||
config.save();
|
||||
|
||||
// git fetch
|
||||
git.fetch().call();
|
||||
|
||||
// checout
|
||||
git.checkout()
|
||||
.setCreateBranch(T.StrUtil.equals(DEFAULT_BRANCH, tgtBranch) ? false : true)
|
||||
.setName(tgtBranch)
|
||||
.setUpstreamMode(CreateBranchCommand.SetupUpstreamMode.TRACK)
|
||||
.setStartPoint("origin/" + tgtBranch)
|
||||
.call();
|
||||
|
||||
// merge
|
||||
MergeResult mergeResult = git.merge()
|
||||
.setCommit(true)
|
||||
.setMessage(message)
|
||||
.setStrategy(MergeStrategy.RECURSIVE)
|
||||
.setFastForward(MergeCommand.FastForwardMode.NO_FF)
|
||||
.include(repository.findRef("origin/" + srcBranch))
|
||||
.call();
|
||||
|
||||
MergeResult.MergeStatus mergeStatus = mergeResult.getMergeStatus();
|
||||
log.info("[mergeBranch] [merge status: {}]", mergeStatus);
|
||||
if (!mergeStatus.isSuccessful()) {
|
||||
// 解决冲突
|
||||
if (mergeStatus == MergeResult.MergeStatus.CONFLICTING && T.CollUtil.isNotEmpty(resolveConflictFileContent)) {
|
||||
Map<String, int[][]> conflicts = mergeResult.getConflicts();
|
||||
for (Map.Entry<String, int[][]> entry : conflicts.entrySet()) {
|
||||
String conflictFilePath = entry.getKey();
|
||||
Map<String, String> map = resolveConflictFileContent.stream()
|
||||
.filter(m -> T.StrUtil.equals(conflictFilePath, T.MapUtil.getStr(m, "path")))
|
||||
.findFirst()
|
||||
.orElse(null);
|
||||
if (null != map) {
|
||||
Path filePath = Paths.get(localPath.getAbsolutePath(), conflictFilePath);
|
||||
Files.write(filePath, T.MapUtil.getStr(map, "content").getBytes(StandardCharsets.UTF_8));
|
||||
git.add().addFilepattern(conflictFilePath).call();
|
||||
}
|
||||
}
|
||||
git.commit().setMessage(message).call();
|
||||
} else {
|
||||
// 其他类型的合并错误,抛出异常
|
||||
String errorMessage = String.format("Merge failed: %s, Conflicts: %s", mergeStatus, mergeResult.getConflicts());
|
||||
throw new RuntimeException(errorMessage);
|
||||
}
|
||||
}
|
||||
|
||||
// push
|
||||
Iterable<PushResult> pushResultIterable = git.push()
|
||||
.setRemote("origin")
|
||||
.add(tgtBranch)
|
||||
.call();
|
||||
for (PushResult pushResult : pushResultIterable) {
|
||||
for (RemoteRefUpdate update : pushResult.getRemoteUpdates()) {
|
||||
if (update.getStatus() != RemoteRefUpdate.Status.OK && update.getStatus() != RemoteRefUpdate.Status.UP_TO_DATE) {
|
||||
log.error("[mergeBranch] [push error] [remote: {}] [status: {}]", update.getRemoteName(), update.getStatus());
|
||||
String errorMessage = "Push failed: " + update.getStatus();
|
||||
throw new RuntimeException(errorMessage);
|
||||
}
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
T.FileUtil.del(localPath);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* build asw commit info
|
||||
*
|
||||
* @param commit
|
||||
* @return
|
||||
*/
|
||||
public static Map<Object, Object> buildAswCommitInfo(RevCommit commit) {
|
||||
if (null == commit) {
|
||||
return T.MapUtil.newHashMap();
|
||||
}
|
||||
|
||||
Map<Object, Object> m = new LinkedHashMap<>();
|
||||
m.put("id", commit.getName());
|
||||
m.put("shortId", T.StrUtil.subPre(commit.getName(), 8));
|
||||
m.put("createdAt", TimeUnit.SECONDS.toMillis(commit.getCommitTime()));
|
||||
|
||||
m.put("title", commit.getShortMessage());
|
||||
m.put("message", commit.getFullMessage());
|
||||
|
||||
List<String> parentIds = Arrays.stream(commit.getParents()).map(RevCommit::getName).collect(Collectors.toList());
|
||||
m.put("parentIds", parentIds);
|
||||
|
||||
PersonIdent authorIdent = commit.getAuthorIdent();
|
||||
m.put("authorName", authorIdent.getName());
|
||||
m.put("authorEmail", authorIdent.getEmailAddress());
|
||||
m.put("authoredDate", authorIdent.getWhen().getTime());
|
||||
|
||||
PersonIdent committerIdent = commit.getCommitterIdent();
|
||||
m.put("committerName", committerIdent.getName());
|
||||
m.put("committerEmail", committerIdent.getEmailAddress());
|
||||
m.put("committedDate", committerIdent.getWhen().getTime());
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* is binary file
|
||||
*
|
||||
* @param filename
|
||||
* @return
|
||||
*/
|
||||
public static boolean isBinary(String filename) {
|
||||
String extension = FilenameUtils.getExtension(filename);
|
||||
List<String> split = T.StrUtil.split(textExtensions, ",");
|
||||
return !split.contains(extension.toLowerCase());
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据 path,objectId 读取文件内容
|
||||
* 响应 Map,key=encoding,content
|
||||
*
|
||||
* @param repository
|
||||
* @param path
|
||||
* @param objectId
|
||||
* @return
|
||||
* @throws IOException
|
||||
*/
|
||||
public static Map<Object, Object> getFileContent(Repository repository, String path, ObjectId objectId) throws IOException {
|
||||
String encoding = null, content = null;
|
||||
|
||||
ObjectLoader loader = repository.open(objectId);
|
||||
if (isBinary(T.FileNameUtil.getName(path))) {
|
||||
encoding = "base64";
|
||||
content = Base64.getEncoder().encodeToString(loader.getBytes());
|
||||
} else {
|
||||
content = T.StrUtil.utf8Str(loader.getBytes());
|
||||
}
|
||||
return T.MapUtil.builder()
|
||||
.put("encoding", encoding)
|
||||
.put("content", content)
|
||||
.build();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -5,9 +5,10 @@ import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableId;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
import net.geedge.asw.module.sys.entity.SysRoleEntity;
|
||||
import net.geedge.asw.common.util.T;
|
||||
import net.geedge.asw.module.sys.entity.SysUserEntity;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
@@ -36,4 +37,8 @@ public class WorkspaceEntity {
|
||||
@TableField(exist = false)
|
||||
private List<WorkspaceMemberEntity> members;
|
||||
|
||||
public File buildGitPath() {
|
||||
return T.FileUtil.file(T.WebPathUtil.getRootPath(), "workspace", this.getId());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4,6 +4,7 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import net.geedge.asw.module.workspace.entity.WorkspaceEntity;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Map;
|
||||
|
||||
public interface IWorkspaceService extends IService<WorkspaceEntity>{
|
||||
@@ -15,4 +16,7 @@ public interface IWorkspaceService extends IService<WorkspaceEntity>{
|
||||
WorkspaceEntity updateWorkspace(WorkspaceEntity workspace);
|
||||
|
||||
void deleteWorkspace(String ids);
|
||||
|
||||
File getGitDir(String workspaceId);
|
||||
|
||||
}
|
||||
@@ -14,10 +14,12 @@ import net.geedge.asw.common.util.ASWException;
|
||||
import net.geedge.asw.common.util.Constants;
|
||||
import net.geedge.asw.common.util.RCode;
|
||||
import net.geedge.asw.common.util.T;
|
||||
import net.geedge.asw.module.app.util.JGitUtils;
|
||||
import net.geedge.asw.module.feign.client.DashboardClient;
|
||||
import net.geedge.asw.module.feign.client.KibanaClient;
|
||||
import net.geedge.asw.module.sys.entity.SysUserEntity;
|
||||
import net.geedge.asw.module.sys.service.ISysConfigService;
|
||||
import net.geedge.asw.module.app.service.IGitService;
|
||||
import net.geedge.asw.module.sys.service.ISysUserService;
|
||||
import net.geedge.asw.module.workspace.dao.WorkspaceDao;
|
||||
import net.geedge.asw.module.workspace.entity.WorkspaceEntity;
|
||||
import net.geedge.asw.module.workspace.entity.WorkspaceMemberEntity;
|
||||
@@ -37,9 +39,6 @@ public class WorkspaceServiceImpl extends ServiceImpl<WorkspaceDao, WorkspaceEnt
|
||||
|
||||
private final static Log log = Log.get();
|
||||
|
||||
@Autowired
|
||||
private IGitService gitService;
|
||||
|
||||
@Autowired
|
||||
private IWorkspaceService workspaceService;
|
||||
|
||||
@@ -55,6 +54,9 @@ public class WorkspaceServiceImpl extends ServiceImpl<WorkspaceDao, WorkspaceEnt
|
||||
@Autowired
|
||||
private ISysConfigService sysConfigService;
|
||||
|
||||
@Autowired
|
||||
private ISysUserService userService;
|
||||
|
||||
@Override
|
||||
public Page queryList(Map<String, Object> params) {
|
||||
Page page = new Query(WorkspaceEntity.class).getPage(params);
|
||||
@@ -96,8 +98,8 @@ public class WorkspaceServiceImpl extends ServiceImpl<WorkspaceDao, WorkspaceEnt
|
||||
}
|
||||
|
||||
// init repository
|
||||
gitService.initRepository(workspace.getId());
|
||||
|
||||
SysUserEntity loginUserEntity = userService.getById(StpUtil.getLoginIdAsString());
|
||||
JGitUtils.initRepository(workspace.buildGitPath(), loginUserEntity.getName());
|
||||
return workspace;
|
||||
}
|
||||
|
||||
@@ -235,6 +237,24 @@ public class WorkspaceServiceImpl extends ServiceImpl<WorkspaceDao, WorkspaceEnt
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* get repository path
|
||||
* path= {webRootPath}/workspace/{workspace.id}
|
||||
*/
|
||||
@Override
|
||||
public File getGitDir(String workspaceId) {
|
||||
WorkspaceEntity workspace = workspaceService.getById(workspaceId);
|
||||
File gitDir = workspace.buildGitPath();
|
||||
|
||||
// 目录不存在,初始化裸仓库
|
||||
if (!gitDir.exists()) {
|
||||
log.info("[getGitDir] [dir not exist] [init new repository] [path: {}]", gitDir);
|
||||
SysUserEntity loginUserEntity = userService.getById(StpUtil.getLoginIdAsString());
|
||||
JGitUtils.initRepository(gitDir, loginUserEntity.getName());
|
||||
}
|
||||
return gitDir;
|
||||
}
|
||||
|
||||
private void validateWorkspaceInfo(WorkspaceEntity workspace, boolean isUpdate) {
|
||||
|
||||
if (!T.StrUtil.equalsAnyIgnoreCase(workspace.getVisibility(), "private", "public")) {
|
||||
|
||||
Reference in New Issue
Block a user