fix: mr 解决冲突接口 改为: clone,ckeckout,merge,add,commit,push 操作流程

This commit is contained in:
shizhendong
2024-11-12 18:11:30 +08:00
parent e6c075f653
commit 304895a81b
3 changed files with 109 additions and 78 deletions

View File

@@ -1,5 +1,6 @@
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.lib.ObjectId;
@@ -11,6 +12,8 @@ import java.util.Map;
public interface IGitService {
Git getGitInstance(String workspaceId);
Repository initRepository(String workspaceId);
Map<Object, Object> infoCommit(String workspaceId, String commitId);
@@ -29,9 +32,11 @@ public interface IGitService {
String getLatestCommitId(String workspaceId, String branch);
ObjectId insertBlobFileToDatabase(Repository repository, byte[] data) throws IOException;
List<Map<Object, Object>> getDiffFileListInCommits(String workspaceId, String newCommitId, String oldCommitId);
String mergeBranch(String workspaceId, String sourceBranch, String targetBranch, String message) throws RuntimeException;
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);
@@ -53,8 +58,6 @@ public interface IGitService {
List<Map<Object, Object>> getConflictFileInfoInBranches(String workspaceId, String srcBranch, String tgtBranch);
void resolveMrConflicts(String workspaceId, String srcBranch, String tgtBranch, String commitId, String commitMessage, List<Map<String, String>> files);
boolean commitIndex(Repository repo, String branch, DirCache index, ObjectId parentId1, ObjectId parentId2, String message) throws IOException, ConcurrentRefUpdateException;
}

View File

@@ -211,7 +211,8 @@ public class ApplicationMergeServiceImpl extends ServiceImpl<ApplicationMergeDao
String commitMessage = T.MapUtil.getStr(body, "commitMessage");
List<Map<String, String>> files = T.MapUtil.get(body, "files", List.class, new ArrayList());
gitService.resolveMrConflicts(workspaceId, sourceBranch, targetBranch, commitId, commitMessage, files);
// 反过来合并
gitService.mergeBranch(workspaceId, targetBranch, sourceBranch, commitMessage, files);
}
/**
@@ -241,7 +242,7 @@ public class ApplicationMergeServiceImpl extends ServiceImpl<ApplicationMergeDao
// merge
try {
String commitId = gitService.mergeBranch(workspaceId, srcBranch, tgtBranch, message);
String commitId = gitService.mergeBranch(workspaceId, srcBranch, tgtBranch, message, null);
entity.setCommitId(commitId);
entity.setStatus(MergeRequestStatus.MERGED.toString());
} catch (Exception e) {

View File

@@ -46,7 +46,9 @@ 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.ExecutorService;
@@ -107,6 +109,7 @@ public class GitServiceImpl implements IGitService {
/**
* get git instance
*/
@Override
public Git getGitInstance(String workspaceId) {
File repoDir = this.getRepoDirPath(workspaceId);
try {
@@ -436,7 +439,7 @@ public class GitServiceImpl implements IGitService {
}
@Override
public String mergeBranch(String workspaceId, String srcBranch, String tgtBranch, String message) throws RuntimeException {
public String mergeBranch(String workspaceId, String srcBranch, String tgtBranch, String message, List<Map<String, String>> resolveConflictFileContent) throws RuntimeException {
log.info("[mergeBranch] [begin] [workspaceId: {}] [srcBranch: {}] [tgtBranch: {}]", workspaceId, 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());
@@ -475,29 +478,51 @@ public class GitServiceImpl implements IGitService {
.call();
MergeResult.MergeStatus mergeStatus = mergeResult.getMergeStatus();
if (mergeStatus.isSuccessful()) {
log.info("[mergeBranch] [merge success]");
// 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);
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);
}
return mergeResult.getNewHead().getName();
} else {
log.error("[mergeBranch] [merge failed] [mergeStatus: {}] [conflict: {}]", mergeStatus, T.JSONUtil.toJsonStr(mergeResult.getConflicts()));
String errorMessage = String.format("Merge failed: %s, Conflicts: %s", mergeStatus, T.JSONUtil.toJsonStr(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);
}
}
}
if (null != mergeResult.getNewHead()) {
return mergeResult.getNewHead().getName();
}
// 解决冲突合并的情况下无法从 mergeResult 中获取提交信息,查询最新提交信息返回
return this.getLatestCommitId(workspaceId, srcBranch);
} catch (Exception e) {
log.error(e, "[mergeBranch] [error] [workspaceId: {}]", workspaceId);
throw new RuntimeException(e.getMessage());
@@ -1072,7 +1097,8 @@ public class GitServiceImpl implements IGitService {
* @return
* @throws IOException
*/
private ObjectId insertBlobFileToDatabase(Repository repository, byte[] data) throws IOException {
@Override
public ObjectId insertBlobFileToDatabase(Repository repository, byte[] data) throws IOException {
try (ObjectInserter inserter = repository.getObjectDatabase().newInserter()) {
ObjectId blobId = inserter.insert(Constants.OBJ_BLOB, data);
inserter.flush();
@@ -1201,58 +1227,58 @@ public class GitServiceImpl implements IGitService {
* @param commitMessage
* @param files
*/
@Override
public void resolveMrConflicts(String workspaceId, String srcBranch, String tgtBranch, String commitId, String commitMessage, List<Map<String, String>> files) {
try (Git git = this.getGitInstance(workspaceId);
Repository repository = git.getRepository();
TreeWalk treeWalk = new TreeWalk(repository);
RevWalk revWalk = new RevWalk(repository)) {
ObjectId srcBranchLatestCommitId = repository.resolve(srcBranch);
// branch tree
treeWalk.addTree(revWalk.parseTree(srcBranchLatestCommitId));
treeWalk.setRecursive(true);
DirCache newTree = DirCache.newInCore();
DirCacheBuilder newTreeBuilder = newTree.builder();
List<String> updateFilePath = files.stream().map(map -> T.MapUtil.getStr(map, "path")).collect(Collectors.toList());
while (treeWalk.next()) {
String pathString = treeWalk.getPathString();
// 先删
if (!updateFilePath.contains(pathString)) {
DirCacheEntry entry = new DirCacheEntry(pathString);
entry.setFileMode(treeWalk.getFileMode(0));
entry.setObjectId(treeWalk.getObjectId(0));
newTreeBuilder.add(entry);
}
}
// 后增
for (Map<String, String> map : files) {
String path = T.MapUtil.getStr(map, "path");
DirCacheEntry dirCacheEntry = new DirCacheEntry(path);
dirCacheEntry.setFileMode(FileMode.REGULAR_FILE);
String content = T.MapUtil.getStr(map, "content");
ObjectId objectId = this.insertBlobFileToDatabase(repository, content.getBytes());
dirCacheEntry.setObjectId(objectId);
newTreeBuilder.add(dirCacheEntry);
}
newTreeBuilder.finish();
// merge commit
ObjectId parentId1 = ObjectId.fromString(commitId);
RevCommit revCommit = revWalk.parseCommit(repository.resolve(tgtBranch));
ObjectId parentId2 = revCommit.getId();
boolean success = this.commitIndex(repository, srcBranch, newTree, parentId1, parentId2, commitMessage);
log.info("[resolveMrConflicts] [workspaceId: {}] [srcBranch: {}] [tgtBranch: {}] [commitId: {}] [success: {}]", workspaceId, srcBranch, tgtBranch, commitId, success);
} catch (IOException | ConcurrentRefUpdateException e) {
log.error(e, "[resolveMrConflicts] [error] [workspaceId: {}] [srcBranch: {}] [tgtBranch: {}] [commitId: {}]", workspaceId, srcBranch, tgtBranch, commitId);
throw new RuntimeException(e);
}
}
// @Override
// public void resolveMrConflicts(String workspaceId, String srcBranch, String tgtBranch, String commitId, String commitMessage, List<Map<String, String>> files) {
// try (Git git = this.getGitInstance(workspaceId);
// Repository repository = git.getRepository();
// TreeWalk treeWalk = new TreeWalk(repository);
// RevWalk revWalk = new RevWalk(repository)) {
//
// ObjectId srcBranchLatestCommitId = repository.resolve(srcBranch);
//
// // branch tree
// treeWalk.addTree(revWalk.parseTree(srcBranchLatestCommitId));
// treeWalk.setRecursive(true);
//
// DirCache newTree = DirCache.newInCore();
// DirCacheBuilder newTreeBuilder = newTree.builder();
//
// List<String> updateFilePath = files.stream().map(map -> T.MapUtil.getStr(map, "path")).collect(Collectors.toList());
// while (treeWalk.next()) {
// String pathString = treeWalk.getPathString();
// // 先删
// if (!updateFilePath.contains(pathString)) {
// DirCacheEntry entry = new DirCacheEntry(pathString);
// entry.setFileMode(treeWalk.getFileMode(0));
// entry.setObjectId(treeWalk.getObjectId(0));
// newTreeBuilder.add(entry);
// }
// }
// // 后增
// for (Map<String, String> map : files) {
// String path = T.MapUtil.getStr(map, "path");
// DirCacheEntry dirCacheEntry = new DirCacheEntry(path);
// dirCacheEntry.setFileMode(FileMode.REGULAR_FILE);
//
// String content = T.MapUtil.getStr(map, "content");
// ObjectId objectId = this.insertBlobFileToDatabase(repository, content.getBytes());
// dirCacheEntry.setObjectId(objectId);
// newTreeBuilder.add(dirCacheEntry);
// }
// newTreeBuilder.finish();
//
// // merge commit
// ObjectId parentId1 = ObjectId.fromString(commitId);
// RevCommit revCommit = revWalk.parseCommit(repository.resolve(tgtBranch));
// ObjectId parentId2 = revCommit.getId();
//
// boolean success = this.commitIndex(repository, srcBranch, newTree, parentId1, parentId2, commitMessage);
// log.info("[resolveMrConflicts] [workspaceId: {}] [srcBranch: {}] [tgtBranch: {}] [commitId: {}] [success: {}]", workspaceId, srcBranch, tgtBranch, commitId, success);
// } catch (IOException | ConcurrentRefUpdateException e) {
// log.error(e, "[resolveMrConflicts] [error] [workspaceId: {}] [srcBranch: {}] [tgtBranch: {}] [commitId: {}]", workspaceId, srcBranch, tgtBranch, commitId);
// throw new RuntimeException(e);
// }
// }
/**
* commit
@@ -1326,6 +1352,7 @@ public class GitServiceImpl implements IGitService {
* @throws IOException
* @throws ConcurrentRefUpdateException
*/
@Override
public boolean commitIndex(Repository repo, String branch, DirCache index, ObjectId parentId1, ObjectId parentId2, String message) throws IOException, ConcurrentRefUpdateException {
boolean success = false;
try (ObjectInserter odi = repo.newObjectInserter()) {