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; package net.geedge.asw.module.app.service;
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.errors.ConcurrentRefUpdateException; import org.eclipse.jgit.api.errors.ConcurrentRefUpdateException;
import org.eclipse.jgit.dircache.DirCache; import org.eclipse.jgit.dircache.DirCache;
import org.eclipse.jgit.lib.ObjectId; import org.eclipse.jgit.lib.ObjectId;
@@ -11,6 +12,8 @@ import java.util.Map;
public interface IGitService { public interface IGitService {
Git getGitInstance(String workspaceId);
Repository initRepository(String workspaceId); Repository initRepository(String workspaceId);
Map<Object, Object> infoCommit(String workspaceId, String commitId); Map<Object, Object> infoCommit(String workspaceId, String commitId);
@@ -29,9 +32,11 @@ public interface IGitService {
String getLatestCommitId(String workspaceId, String branch); 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); 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); 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); 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; 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"); String commitMessage = T.MapUtil.getStr(body, "commitMessage");
List<Map<String, String>> files = T.MapUtil.get(body, "files", List.class, new ArrayList()); 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 // merge
try { try {
String commitId = gitService.mergeBranch(workspaceId, srcBranch, tgtBranch, message); String commitId = gitService.mergeBranch(workspaceId, srcBranch, tgtBranch, message, null);
entity.setCommitId(commitId); entity.setCommitId(commitId);
entity.setStatus(MergeRequestStatus.MERGED.toString()); entity.setStatus(MergeRequestStatus.MERGED.toString());
} catch (Exception e) { } catch (Exception e) {

View File

@@ -46,7 +46,9 @@ import java.io.ByteArrayOutputStream;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.MessageFormat; import java.text.MessageFormat;
import java.util.*; import java.util.*;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
@@ -107,6 +109,7 @@ public class GitServiceImpl implements IGitService {
/** /**
* get git instance * get git instance
*/ */
@Override
public Git getGitInstance(String workspaceId) { public Git getGitInstance(String workspaceId) {
File repoDir = this.getRepoDirPath(workspaceId); File repoDir = this.getRepoDirPath(workspaceId);
try { try {
@@ -436,7 +439,7 @@ public class GitServiceImpl implements IGitService {
} }
@Override @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); log.info("[mergeBranch] [begin] [workspaceId: {}] [srcBranch: {}] [tgtBranch: {}]", workspaceId, srcBranch, tgtBranch);
// prepare a new folder for the cloned repository // prepare a new folder for the cloned repository
File localPath = T.FileUtil.file(net.geedge.asw.common.util.Constants.TEMP_PATH, T.StrUtil.uuid()); 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(); .call();
MergeResult.MergeStatus mergeStatus = mergeResult.getMergeStatus(); MergeResult.MergeStatus mergeStatus = mergeResult.getMergeStatus();
if (mergeStatus.isSuccessful()) { log.info("[mergeBranch] [merge status: {}]", mergeStatus);
log.info("[mergeBranch] [merge success]"); if (!mergeStatus.isSuccessful()) {
// 解决冲突
// push if (mergeStatus == MergeResult.MergeStatus.CONFLICTING && T.CollUtil.isNotEmpty(resolveConflictFileContent)) {
Iterable<PushResult> pushResultIterable = git.push() Map<String, int[][]> conflicts = mergeResult.getConflicts();
.setRemote("origin") for (Map.Entry<String, int[][]> entry : conflicts.entrySet()) {
.add(tgtBranch) String conflictFilePath = entry.getKey();
.call(); Map<String, String> map = resolveConflictFileContent.stream()
for (PushResult pushResult : pushResultIterable) { .filter(m -> T.StrUtil.equals(conflictFilePath, T.MapUtil.getStr(m, "path")))
for (RemoteRefUpdate update : pushResult.getRemoteUpdates()) { .findFirst()
if (update.getStatus() != RemoteRefUpdate.Status.OK && update.getStatus() != RemoteRefUpdate.Status.UP_TO_DATE) { .orElse(null);
log.error("[mergeBranch] [push error] [remote: {}] [status: {}]", update.getRemoteName(), update.getStatus()); if (null != map) {
String errorMessage = "Push failed: " + update.getStatus(); Path filePath = Paths.get(localPath.getAbsolutePath(), conflictFilePath);
throw new RuntimeException(errorMessage); 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) { } catch (Exception e) {
log.error(e, "[mergeBranch] [error] [workspaceId: {}]", workspaceId); log.error(e, "[mergeBranch] [error] [workspaceId: {}]", workspaceId);
throw new RuntimeException(e.getMessage()); throw new RuntimeException(e.getMessage());
@@ -1072,7 +1097,8 @@ public class GitServiceImpl implements IGitService {
* @return * @return
* @throws IOException * @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()) { try (ObjectInserter inserter = repository.getObjectDatabase().newInserter()) {
ObjectId blobId = inserter.insert(Constants.OBJ_BLOB, data); ObjectId blobId = inserter.insert(Constants.OBJ_BLOB, data);
inserter.flush(); inserter.flush();
@@ -1201,58 +1227,58 @@ public class GitServiceImpl implements IGitService {
* @param commitMessage * @param commitMessage
* @param files * @param files
*/ */
@Override // @Override
public void resolveMrConflicts(String workspaceId, String srcBranch, String tgtBranch, String commitId, String commitMessage, List<Map<String, String>> files) { // public void resolveMrConflicts(String workspaceId, String srcBranch, String tgtBranch, String commitId, String commitMessage, List<Map<String, String>> files) {
try (Git git = this.getGitInstance(workspaceId); // try (Git git = this.getGitInstance(workspaceId);
Repository repository = git.getRepository(); // Repository repository = git.getRepository();
TreeWalk treeWalk = new TreeWalk(repository); // TreeWalk treeWalk = new TreeWalk(repository);
RevWalk revWalk = new RevWalk(repository)) { // RevWalk revWalk = new RevWalk(repository)) {
//
ObjectId srcBranchLatestCommitId = repository.resolve(srcBranch); // ObjectId srcBranchLatestCommitId = repository.resolve(srcBranch);
//
// branch tree // // branch tree
treeWalk.addTree(revWalk.parseTree(srcBranchLatestCommitId)); // treeWalk.addTree(revWalk.parseTree(srcBranchLatestCommitId));
treeWalk.setRecursive(true); // treeWalk.setRecursive(true);
//
DirCache newTree = DirCache.newInCore(); // DirCache newTree = DirCache.newInCore();
DirCacheBuilder newTreeBuilder = newTree.builder(); // DirCacheBuilder newTreeBuilder = newTree.builder();
//
List<String> updateFilePath = files.stream().map(map -> T.MapUtil.getStr(map, "path")).collect(Collectors.toList()); // List<String> updateFilePath = files.stream().map(map -> T.MapUtil.getStr(map, "path")).collect(Collectors.toList());
while (treeWalk.next()) { // while (treeWalk.next()) {
String pathString = treeWalk.getPathString(); // String pathString = treeWalk.getPathString();
// 先删 // // 先删
if (!updateFilePath.contains(pathString)) { // if (!updateFilePath.contains(pathString)) {
DirCacheEntry entry = new DirCacheEntry(pathString); // DirCacheEntry entry = new DirCacheEntry(pathString);
entry.setFileMode(treeWalk.getFileMode(0)); // entry.setFileMode(treeWalk.getFileMode(0));
entry.setObjectId(treeWalk.getObjectId(0)); // entry.setObjectId(treeWalk.getObjectId(0));
newTreeBuilder.add(entry); // newTreeBuilder.add(entry);
} // }
} // }
// 后增 // // 后增
for (Map<String, String> map : files) { // for (Map<String, String> map : files) {
String path = T.MapUtil.getStr(map, "path"); // String path = T.MapUtil.getStr(map, "path");
DirCacheEntry dirCacheEntry = new DirCacheEntry(path); // DirCacheEntry dirCacheEntry = new DirCacheEntry(path);
dirCacheEntry.setFileMode(FileMode.REGULAR_FILE); // dirCacheEntry.setFileMode(FileMode.REGULAR_FILE);
//
String content = T.MapUtil.getStr(map, "content"); // String content = T.MapUtil.getStr(map, "content");
ObjectId objectId = this.insertBlobFileToDatabase(repository, content.getBytes()); // ObjectId objectId = this.insertBlobFileToDatabase(repository, content.getBytes());
dirCacheEntry.setObjectId(objectId); // dirCacheEntry.setObjectId(objectId);
newTreeBuilder.add(dirCacheEntry); // newTreeBuilder.add(dirCacheEntry);
} // }
newTreeBuilder.finish(); // newTreeBuilder.finish();
//
// merge commit // // merge commit
ObjectId parentId1 = ObjectId.fromString(commitId); // ObjectId parentId1 = ObjectId.fromString(commitId);
RevCommit revCommit = revWalk.parseCommit(repository.resolve(tgtBranch)); // RevCommit revCommit = revWalk.parseCommit(repository.resolve(tgtBranch));
ObjectId parentId2 = revCommit.getId(); // ObjectId parentId2 = revCommit.getId();
//
boolean success = this.commitIndex(repository, srcBranch, newTree, parentId1, parentId2, commitMessage); // boolean success = this.commitIndex(repository, srcBranch, newTree, parentId1, parentId2, commitMessage);
log.info("[resolveMrConflicts] [workspaceId: {}] [srcBranch: {}] [tgtBranch: {}] [commitId: {}] [success: {}]", workspaceId, srcBranch, tgtBranch, commitId, success); // log.info("[resolveMrConflicts] [workspaceId: {}] [srcBranch: {}] [tgtBranch: {}] [commitId: {}] [success: {}]", workspaceId, srcBranch, tgtBranch, commitId, success);
} catch (IOException | ConcurrentRefUpdateException e) { // } catch (IOException | ConcurrentRefUpdateException e) {
log.error(e, "[resolveMrConflicts] [error] [workspaceId: {}] [srcBranch: {}] [tgtBranch: {}] [commitId: {}]", workspaceId, srcBranch, tgtBranch, commitId); // log.error(e, "[resolveMrConflicts] [error] [workspaceId: {}] [srcBranch: {}] [tgtBranch: {}] [commitId: {}]", workspaceId, srcBranch, tgtBranch, commitId);
throw new RuntimeException(e); // throw new RuntimeException(e);
} // }
} // }
/** /**
* commit * commit
@@ -1326,6 +1352,7 @@ public class GitServiceImpl implements IGitService {
* @throws IOException * @throws IOException
* @throws ConcurrentRefUpdateException * @throws ConcurrentRefUpdateException
*/ */
@Override
public boolean commitIndex(Repository repo, String branch, DirCache index, ObjectId parentId1, ObjectId parentId2, String message) throws IOException, ConcurrentRefUpdateException { public boolean commitIndex(Repository repo, String branch, DirCache index, ObjectId parentId1, ObjectId parentId2, String message) throws IOException, ConcurrentRefUpdateException {
boolean success = false; boolean success = false;
try (ObjectInserter odi = repo.newObjectInserter()) { try (ObjectInserter odi = repo.newObjectInserter()) {