fix: 处理 mr 过程中分支被删除的情况

This commit is contained in:
shizhendong
2024-11-15 15:34:26 +08:00
parent f322ce25ff
commit 7f7d0347ce
7 changed files with 45 additions and 156 deletions

View File

@@ -66,6 +66,7 @@ public enum RCode {
GIT_PARENT_COMMITID_NOT_FOUND(203003, "Parent commitId not found"),
GIT_BINARY_CONFLICT_ERROR(203004, "Binary file conflict found; resolve conflicts in binary files manually"),
GIT_MERGE_NOT_SUPPORTED(203005, "Cannot merge in the {0} state"),
GIT_MERGE_TARGET_BRANCH_NOT_EXIST(203006, "The target branch {0} does not exist."),
// Runner

View File

@@ -1,15 +0,0 @@
package net.geedge.asw.module.app.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import net.geedge.asw.module.app.entity.ApplicationEntity;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
import java.util.Map;
@Mapper
public interface ApplicationDao extends BaseMapper<ApplicationEntity>{
List<ApplicationEntity> queryList(Page page, Map<String, Object> params);
}

View File

@@ -28,6 +28,8 @@ public interface IGitService {
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);

View File

@@ -120,8 +120,10 @@ public class ApplicationMergeServiceImpl extends ServiceImpl<ApplicationMergeDao
switch (mergeRequestStatus) {
case OPEN: {
newCommitId = gitService.getLatestCommitId(workspaceId, sourceBranch);
// open 状态下,获取 sourceBranch,targetBranch 冲突文件
conflictFileList = gitService.getConflictFilePathInBranches(workspaceId, sourceBranch, targetBranch);
if (gitService.isBranchExists(workspaceId, targetBranch)) {
// open 状态下,获取 sourceBranch,targetBranch 冲突文件
conflictFileList = gitService.getConflictFilePathInBranches(workspaceId, sourceBranch, targetBranch);
}
break;
}
case CLOSED:
@@ -231,7 +233,7 @@ public class ApplicationMergeServiceImpl extends ServiceImpl<ApplicationMergeDao
* merge operation
*
* @param mrId
* @param action merge|close
* @param action merge|close
* @return
*/
@Override
@@ -252,6 +254,11 @@ public class ApplicationMergeServiceImpl extends ServiceImpl<ApplicationMergeDao
String message = entity.getTitle();
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, message, null);
@@ -259,17 +266,17 @@ public class ApplicationMergeServiceImpl extends ServiceImpl<ApplicationMergeDao
entity.setEndCommitId(latestCommitId);
entity.setStatus(MergeRequestStatus.MERGED.toString());
} catch (Exception e) {
log.error(e, "[newMr] [merge error] [workspaceId: {}] [srcBranch: {}] [tgtBranch: {}] [msg: {}]", workspaceId, srcBranch, tgtBranch, e.getMessage());
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("[newMr] [remove source branch] [workspaceId: {}] [branch: {}]", workspaceId, srcBranch);
log.info("[mergeMr] [remove source branch] [workspaceId: {}] [branch: {}]", workspaceId, srcBranch);
gitService.deleteBranch(workspaceId, srcBranch);
} catch (Exception e) {
log.error(e, "[newMr] [remove source branch error] [workspaceId: {}] [branch: {}] [msg: {}]", workspaceId, srcBranch, e.getMessage());
log.error(e, "[mergeMr] [remove source branch error] [workspaceId: {}] [branch: {}] [msg: {}]", workspaceId, srcBranch, e.getMessage());
}
}
@@ -308,6 +315,7 @@ public class ApplicationMergeServiceImpl extends ServiceImpl<ApplicationMergeDao
public String toString() {
return "open";
}
public boolean canMerge() {
return true;
}
@@ -317,6 +325,7 @@ public class ApplicationMergeServiceImpl extends ServiceImpl<ApplicationMergeDao
public String toString() {
return "merged";
}
public boolean canMerge() {
return false;
}
@@ -326,6 +335,7 @@ public class ApplicationMergeServiceImpl extends ServiceImpl<ApplicationMergeDao
public String toString() {
return "closed";
}
public boolean canMerge() {
return false;
}

View File

@@ -3,10 +3,14 @@ package net.geedge.asw.module.app.service.impl;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.json.JSONObject;
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.IApplicationMergeService;
import net.geedge.asw.module.app.service.IGitService;
import net.geedge.asw.module.app.service.impl.ApplicationMergeServiceImpl.MergeRequestStatus;
import net.geedge.asw.module.sys.entity.SysUserEntity;
import net.geedge.asw.module.sys.service.ISysUserService;
import net.geedge.asw.module.workspace.entity.WorkspaceEntity;
@@ -37,7 +41,6 @@ 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;
@@ -50,7 +53,6 @@ import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.MessageFormat;
import java.util.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
@@ -80,8 +82,7 @@ public class GitServiceImpl implements IGitService {
private IWorkspaceService workspaceService;
@Autowired
@Qualifier("virtualThreadExecutor")
private ExecutorService virtualThreadExecutor;
private IApplicationMergeService applicationMergeService;
/**
* is binary file
@@ -257,17 +258,36 @@ public class GitServiceImpl implements IGitService {
@Override
public void deleteBranch(String workspaceId, String branchName) {
log.info("[deleteBranch] [begin] [workspaceId: {}] [branch: {}]", workspaceId, branchName);
try (Git git = this.getGitInstance(workspaceId)) {
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 e) {
log.error(e, "[deleteBranch] [error] [workspaceId: {}] [branchName: {}]", workspaceId, branchName);
throw new ASWException(RCode.ERROR);
}
}
@Override
public boolean isBranchExists(String workspaceId, String branch) {
try (Git git = this.getGitInstance(workspaceId)) {
Ref ref = git.getRepository().findRef(T.StrUtil.concat(true, LOCAL_BRANCH_PREFIX, branch));
return null != ref;
} catch (IOException e) {
log.error(e, "[isBranchExists] [workspaceId: {}] [branch: {}]", workspaceId, branch);
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);
@@ -1228,70 +1248,6 @@ public class GitServiceImpl implements IGitService {
return result;
}
/**
* 解决冲突提交到 srcBranch
* 提交指定 srcBranchtgtBranch 最新 commitId,像 merge commit 一样
*
* @param workspaceId
* @param srcBranch
* @param tgtBranch
* @param commitId
* @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);
// }
// }
/**
* commit
*

View File

@@ -1,67 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="net.geedge.asw.module.app.dao.ApplicationDao">
<resultMap id="appResult" type="net.geedge.asw.module.app.entity.ApplicationEntity">
<result property="id" column="id"/>
<result property="name" column="name"/>
<result property="tags" column="tags"/>
<result property="packageName" column="package_name"/>
<result property="website" column="website"/>
<result property="provider" column="provider"/>
<result property="status" column="status"/>
<result property="properties" column="properties" typeHandler="com.baomidou.mybatisplus.extension.handlers.JacksonTypeHandler"/>
<result property="description" column="description"/>
<result property="createTimestamp" column="create_timestamp"/>
<result property="updateTimestamp" column="update_timestamp"/>
<result property="createUserId" column="create_user_id"/>
<result property="updateUserId" column="update_user_id"/>
<result property="workspaceId" column="workspace_id"/>
<result property="opVersion" column="op_version"/>
<association property="createUser" columnPrefix="cu_" javaType="net.geedge.asw.module.sys.entity.SysUserEntity">
<id property="id" column="id"/>
<result property="name" column="name"/>
<result property="userName" column="user_name"/>
</association>
<association property="updateUser" columnPrefix="uu_" javaType="net.geedge.asw.module.sys.entity.SysUserEntity">
<id property="id" column="id"/>
<result property="name" column="name"/>
<result property="userName" column="user_name"/>
</association>
</resultMap>
<select id="queryList" resultMap="appResult">
SELECT
app.*,
cu.id as cu_id,
cu.name as cu_name,
cu.user_name as cu_user_name,
uu.id as uu_id,
uu.name as uu_name,
uu.user_name as uu_user_name
FROM
application app
left join sys_user cu on app.create_user_id = cu.id
left join sys_user uu on app.update_user_id = uu.id
<where>
<if test="params.ids != null and params.ids != ''">
app.id in
<foreach item="id" collection="params.ids.split(',')" separator="," open="(" close=")">
#{id}
</foreach>
</if>
<if test="params.q != null and params.q != ''">
AND ( locate(#{params.q}, app.name) OR locate(#{params.q}, app.description) )
</if>
<if test="params.workspaceId != null and params.workspaceId != ''">
AND app.workspace_id = #{params.workspaceId}
</if>
</where>
<if test="params.orderBy == null or params.orderBy == ''">
ORDER BY app.id
</if>
</select>
</mapper>

View File

@@ -155,5 +155,7 @@ INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_
INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (247, '203004', 'GIT_BINARY_CONFLICT_ERROR', '发现二进制文件冲突;手动解决二进制文件中的冲突', 'zh', '', 'admin', 1724030366000);
INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (248, '203005', 'GIT_MERGE_NOT_SUPPORTED', 'Cannot merge in the {0} state', 'en', '', 'admin', 1724030366000);
INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (249, '203005', 'GIT_MERGE_NOT_SUPPORTED', '无法在{0}状态下合并', 'zh', '', 'admin', 1724030366000);
INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (250, '203006', 'GIT_MERGE_TARGET_BRANCH_NOT_EXIST', 'The target branch {0} does not exist.', 'en', '', 'admin', 1724030366000);
INSERT INTO `sys_i18n`(`id`, `name`, `code`, `value`, `lang`, `remark`, `update_user_id`, `update_timestamp`) VALUES (251, '203006', 'GIT_MERGE_TARGET_BRANCH_NOT_EXIST', '目标分支 {0} 不存在', 'zh', '', 'admin', 1724030366000);
SET FOREIGN_KEY_CHECKS = 1;