feat(项目设置): 存储库文件pull功能开发

This commit is contained in:
song-tianyang 2023-11-07 16:36:23 +08:00 committed by 建国
parent 72f1d1abd1
commit c461e3cf55
11 changed files with 162 additions and 37 deletions

View File

@ -444,6 +444,7 @@ file.log.previous=之前
file.log.upload=上传
file.log.repository.add=添加了存储库文件
file.log.re-upload=重新上传
file.log.pull=拉取了文件
file.name.cannot.be.empty=文件名称不能为空
#file management over

View File

@ -480,6 +480,7 @@ file.log.previous=behind
file.log.upload=upload
file.log.repository.add=Add repository file
file.log.re-upload=re-upload
file.log.pull=Pull file
file.name.cannot.be.empty=File name cannot be empty
#file management over

View File

@ -479,6 +479,7 @@ file.log.previous=之前
file.log.upload=上传
file.log.repository.add=添加了存储库文件
file.log.re-upload=重新上传
file.log.pull=拉取了文件
file.name.cannot.be.empty=文件名称不能为空
#file management over
# template

View File

@ -480,6 +480,7 @@ file.log.previous=之前
file.log.upload=上傳
file.log.repository.add=添加了存儲庫文件
file.log.re-upload=重新上傳
file.log.pull=拉取了文件
file.name.cannot.be.empty=文件名稱不能為空
#file management over

View File

@ -68,7 +68,14 @@ public class FileRepositoryController {
@PostMapping("/add-file")
@Operation(summary = "项目管理-文件管理-存储库-添加文件")
@RequiresPermissions(PermissionConstants.PROJECT_FILE_MANAGEMENT_READ_ADD)
public String upload(@Validated @RequestBody RepositoryFileAddRequest request) throws Exception {
public String addFile(@Validated @RequestBody RepositoryFileAddRequest request) throws Exception {
return fileRepositoryService.addFile(request, SessionUtils.getUserId());
}
@GetMapping("/pull-file/{id}")
@Operation(summary = "项目管理-文件管理-存储库-更新文件")
@RequiresPermissions(PermissionConstants.PROJECT_FILE_MANAGEMENT_READ_ADD)
public String pullFile(@PathVariable String id) throws Exception {
return fileMetadataService.pullFile(id, SessionUtils.getUserId());
}
}

View File

@ -65,7 +65,6 @@ public class FileMetadataLogService {
.build().getLogDTO();
operationLogService.add(dto);
}
public void saveUpdateLog(FileMetadata module, String projectId, String operator) {
Project project = projectMapper.selectByPrimaryKey(projectId);
LogDTO dto = LogDTOBuilder.builder()
@ -162,4 +161,21 @@ public class FileMetadataLogService {
.build().getLogDTO();
operationLogService.add(dto);
}
public void saveFilePullLog(FileMetadata module, String operator) {
Project project = projectMapper.selectByPrimaryKey(module.getProjectId());
LogDTO dto = LogDTOBuilder.builder()
.projectId(module.getProjectId())
.organizationId(project.getOrganizationId())
.type(OperationLogType.UPDATE.name())
.module(logModule)
.method(HttpMethodConstants.GET.name())
.path("/project/file/repository/pull-file")
.sourceId(module.getId())
.content(Translator.get("file.log.pull") + " " + module.getName())
.originalValue(JSON.toJSONBytes(module))
.createUser(operator)
.build().getLogDTO();
operationLogService.add(dto);
}
}

View File

@ -22,8 +22,10 @@ import io.metersphere.sdk.util.JSON;
import io.metersphere.sdk.util.LogUtils;
import io.metersphere.sdk.util.TempFileUtils;
import io.metersphere.sdk.util.Translator;
import io.metersphere.system.dto.sdk.RemoteFileAttachInfo;
import io.metersphere.system.file.FileRequest;
import io.metersphere.system.uid.IDGenerator;
import io.metersphere.system.utils.GitRepositoryUtil;
import io.metersphere.system.utils.PageUtils;
import io.metersphere.system.utils.Pager;
import jakarta.annotation.Resource;
@ -333,33 +335,17 @@ public class FileMetadataService {
if (oldFile == null) {
throw new MSException(Translator.get("old.file.not.exist"));
}
oldFile.setLatest(false);
fileMetadataMapper.updateByPrimaryKeySelective(oldFile);
//删除旧的预览文件
TempFileUtils.deleteTmpFile(oldFile.getId());
long operationTime = System.currentTimeMillis();
FileMetadata fileMetadata = new FileMetadata();
fileMetadata.setId(IDGenerator.nextStr());
fileMetadata.setStorage(oldFile.getStorage());
fileMetadata.setProjectId(oldFile.getProjectId());
fileMetadata.setModuleId(oldFile.getModuleId());
fileMetadata.setName(oldFile.getName());
fileMetadata.setType(oldFile.getType());
fileMetadata.setCreateTime(operationTime);
fileMetadata.setCreateUser(oldFile.getCreateUser());
fileMetadata.setUpdateTime(operationTime);
fileMetadata.setUpdateUser(operator);
if (!StringUtils.equals(oldFile.getStorage(), StorageType.MINIO.name())) {
//非minio类型文件不允许重新上传
throw new MSException(Translator.get("file.not.exist"));
}
this.setFileVersionIsOld(oldFile, operator);
FileMetadata fileMetadata = this.genNewVersion(oldFile, operator);
fileMetadata.setSize(uploadFile.getSize());
fileMetadata.setRefId(oldFile.getRefId());
fileMetadata.setEnable(oldFile.getEnable());
fileMetadata.setLatest(true);
fileMetadataMapper.insert(fileMetadata);
//记录日志
fileMetadataLogService.saveReUploadLog(fileMetadata, operator);
// 上传文件
String filePath = this.uploadFile(fileMetadata, uploadFile);
FileMetadata updateFileMetadata = new FileMetadata();
@ -454,4 +440,69 @@ public class FileMetadataService {
fileMetadataLogService.saveFileMoveLog(logList, request.getProjectId(), operator);
}
}
private void setFileVersionIsOld(FileMetadata oldFile, String operator) {
//删除旧的预览文件
TempFileUtils.deleteTmpFile(oldFile.getId());
//更新文件版本分支
FileMetadata updateModel = new FileMetadata();
updateModel.setId(oldFile.getId());
updateModel.setLatest(false);
updateModel.setUpdateTime(System.currentTimeMillis());
updateModel.setUpdateUser(operator);
fileMetadataMapper.updateByPrimaryKeySelective(updateModel);
}
private FileMetadata genNewVersion(FileMetadata oldFile, String operator) {
long operationTime = System.currentTimeMillis();
FileMetadata fileMetadata = new FileMetadata();
fileMetadata.setId(IDGenerator.nextStr());
fileMetadata.setStorage(oldFile.getStorage());
fileMetadata.setProjectId(oldFile.getProjectId());
fileMetadata.setModuleId(oldFile.getModuleId());
fileMetadata.setName(oldFile.getName());
fileMetadata.setType(oldFile.getType());
fileMetadata.setCreateTime(operationTime);
fileMetadata.setCreateUser(oldFile.getCreateUser());
fileMetadata.setUpdateTime(operationTime);
fileMetadata.setPath(oldFile.getPath());
fileMetadata.setUpdateUser(operator);
fileMetadata.setRefId(oldFile.getRefId());
fileMetadata.setEnable(oldFile.getEnable());
fileMetadata.setLatest(true);
return fileMetadata;
}
public String pullFile(String fileId, String operator) {
FileMetadata oldFile = fileMetadataMapper.selectByPrimaryKey(fileId);
String returnFileId = fileId;
if (StringUtils.equals(oldFile.getStorage(), StorageType.GIT.name())) {
FileMetadataRepository metadataRepository = fileMetadataRepositoryMapper.selectByPrimaryKey(fileId);
FileModuleRepository moduleRepository = fileModuleRepositoryMapper.selectByPrimaryKey(oldFile.getModuleId());
if (metadataRepository != null && moduleRepository != null) {
GitRepositoryUtil repositoryUtils = new GitRepositoryUtil(moduleRepository.getUrl(), moduleRepository.getUserName(), moduleRepository.getToken());
RemoteFileAttachInfo gitFileAttachInfo = repositoryUtils.selectLastCommitIdByBranch(metadataRepository.getBranch(), oldFile.getPath());
if (!StringUtils.equals(gitFileAttachInfo.getCommitId(), metadataRepository.getCommitId())) {
this.setFileVersionIsOld(oldFile, operator);
FileMetadata fileMetadata = this.genNewVersion(oldFile, operator);
fileMetadata.setSize(gitFileAttachInfo.getSize());
fileMetadataMapper.insert(fileMetadata);
returnFileId = fileMetadata.getId();
FileMetadataRepository fileMetadataRepository = new FileMetadataRepository();
fileMetadataRepository.setFileMetadataId(returnFileId);
fileMetadataRepository.setBranch(gitFileAttachInfo.getBranch());
fileMetadataRepository.setCommitId(gitFileAttachInfo.getCommitId());
fileMetadataRepository.setCommitMessage(gitFileAttachInfo.getCommitMessage());
fileMetadataRepositoryMapper.insert(fileMetadataRepository);
//记录日志
fileMetadataLogService.saveFilePullLog(fileMetadata, operator);
}
}
}
return returnFileId;
}
}

View File

@ -556,7 +556,7 @@ public class FileManagementControllerTests extends BaseTest {
FileUploadRequest fileUploadRequest = new FileUploadRequest();
fileUploadRequest.setProjectId(project.getId());
//重新上传并修改文件版本
//构建参数
FileReUploadRequest fileReUploadRequest = new FileReUploadRequest();
fileReUploadRequest.setFileId(reUploadFileId);
String filePath = Objects.requireNonNull(this.getClass().getClassLoader().getResource("file/file_re-upload.JPG")).getPath();
@ -565,6 +565,17 @@ public class FileManagementControllerTests extends BaseTest {
paramMap.add("file", file);
paramMap.add("request", JSON.toJSONString(fileReUploadRequest));
//测试非minio文件不能重新上传
FileMetadata updateModel = new FileMetadata();
updateModel.setId(reUploadFileId);
updateModel.setStorage(StorageType.GIT.name());
fileMetadataMapper.updateByPrimaryKeySelective(updateModel);
this.requestMultipart(FileManagementRequestUtils.URL_FILE_RE_UPLOAD, paramMap).andExpect(status().is5xxServerError());
//测试完了改回去
updateModel.setStorage(StorageType.MINIO.name());
fileMetadataMapper.updateByPrimaryKeySelective(updateModel);
//重新上传并修改文件版本
MvcResult mvcResult = this.requestMultipartWithOkAndReturn(FileManagementRequestUtils.URL_FILE_RE_UPLOAD, paramMap);
String reUploadId = JSON.parseObject(mvcResult.getResponse().getContentAsString(StandardCharsets.UTF_8), ResultHolder.class).getData().toString();
checkLog(reUploadId, OperationLogType.UPDATE, FileManagementRequestUtils.URL_FILE_RE_UPLOAD);

View File

@ -362,7 +362,7 @@ public class FileRepositoryControllerTest extends BaseTest {
request.setModuleId(repositoryId);
MvcResult result = this.requestPostWithOkAndReturn(FileManagementRequestUtils.URL_FILE_REPOSITORY_FILE_ADD, request);
String fileId = JSON.parseObject(result.getResponse().getContentAsString(), ResultHolder.class).getData().toString();
this.checkFileRepositoryFile(fileId, request);
this.checkRepositoryFile(fileId, request);
this.checkLog(fileId, OperationLogType.ADD, FileManagementRequestUtils.URL_FILE_REPOSITORY_FILE_ADD);
fileList.add(fileId);
//测试其他分支的多层目录的文件
@ -374,7 +374,7 @@ public class FileRepositoryControllerTest extends BaseTest {
request.setModuleId(repositoryId);
result = this.requestPostWithOkAndReturn(FileManagementRequestUtils.URL_FILE_REPOSITORY_FILE_ADD, request);
fileId = JSON.parseObject(result.getResponse().getContentAsString(), ResultHolder.class).getData().toString();
this.checkFileRepositoryFile(fileId, request);
this.checkRepositoryFile(fileId, request);
fileList.add(fileId);
//测试隐藏文件
String folderFilePath2 = "test-folder/.keep";
@ -384,7 +384,7 @@ public class FileRepositoryControllerTest extends BaseTest {
request.setModuleId(repositoryId);
result = this.requestPostWithOkAndReturn(FileManagementRequestUtils.URL_FILE_REPOSITORY_FILE_ADD, request);
fileId = JSON.parseObject(result.getResponse().getContentAsString(), ResultHolder.class).getData().toString();
this.checkFileRepositoryFile(fileId, request);
this.checkRepositoryFile(fileId, request);
fileList.add(fileId);
//测试添加jar包并且启用
request = new RepositoryFileAddRequest();
@ -394,7 +394,7 @@ public class FileRepositoryControllerTest extends BaseTest {
request.setModuleId(repositoryId);
result = this.requestPostWithOkAndReturn(FileManagementRequestUtils.URL_FILE_REPOSITORY_FILE_ADD, request);
fileId = JSON.parseObject(result.getResponse().getContentAsString(), ResultHolder.class).getData().toString();
this.checkFileRepositoryFile(fileId, request);
this.checkRepositoryFile(fileId, request);
fileList.add(fileId);
//获取图片信息
request = new RepositoryFileAddRequest();
@ -403,7 +403,7 @@ public class FileRepositoryControllerTest extends BaseTest {
request.setModuleId(repositoryId);
result = this.requestPostWithOkAndReturn(FileManagementRequestUtils.URL_FILE_REPOSITORY_FILE_ADD, request);
fileId = JSON.parseObject(result.getResponse().getContentAsString(), ResultHolder.class).getData().toString();
this.checkFileRepositoryFile(fileId, request);
this.checkRepositoryFile(fileId, request);
this.picFileId = fileId;
fileList.add(fileId);
{
@ -481,8 +481,29 @@ public class FileRepositoryControllerTest extends BaseTest {
Assertions.assertTrue(compressedResult.getResponse().getContentAsByteArray().length > 0);
}
@Test
@Order(12)
public void repositoryPullFileTest() throws Exception {
if (StringUtils.isEmpty(picFileId)) {
this.repositoryAddFileTest();
}
MvcResult mvcResult = this.requestGetWithOkAndReturn(String.format(FileManagementRequestUtils.URL_FILE_REPOSITORY_FILE_PULL, picFileId));
String fileId = JSON.parseObject(mvcResult.getResponse().getContentAsString(), ResultHolder.class).getData().toString();
//此时没有更新记录应当相等
Assertions.assertEquals(fileId, picFileId);
private void checkFileRepositoryFile(String fileId, RepositoryFileAddRequest request) {
//手动更改过去的commit id 达到pull更新的效果
FileMetadataRepository updateRepository = new FileMetadataRepository();
updateRepository.setFileMetadataId(picFileId);
updateRepository.setCommitId(IDGenerator.nextStr());
fileMetadataRepositoryMapper.updateByPrimaryKeySelective(updateRepository);
mvcResult = this.requestGetWithOkAndReturn(String.format(FileManagementRequestUtils.URL_FILE_REPOSITORY_FILE_PULL, picFileId));
fileId = JSON.parseObject(mvcResult.getResponse().getContentAsString(), ResultHolder.class).getData().toString();
this.checkRepositoryFile(picFileId, fileId);
}
private void checkRepositoryFile(String fileId, RepositoryFileAddRequest request) {
FileMetadataRepository repository = fileMetadataRepositoryMapper.selectByPrimaryKey(fileId);
Assertions.assertEquals(repository.getBranch(), request.getBranch());
Assertions.assertNotNull(repository.getCommitId());
@ -492,6 +513,24 @@ public class FileRepositoryControllerTest extends BaseTest {
Assertions.assertEquals(fileMetadata.getStorage(), StorageType.GIT.name());
}
private void checkRepositoryFile(String fileId, String newFileId) {
FileMetadata oldMetadata = fileMetadataMapper.selectByPrimaryKey(fileId);
FileMetadataRepository oldRepository = fileMetadataRepositoryMapper.selectByPrimaryKey(fileId);
FileMetadata newMetadata = fileMetadataMapper.selectByPrimaryKey(newFileId);
FileMetadataRepository newRepository = fileMetadataRepositoryMapper.selectByPrimaryKey(newFileId);
Assertions.assertNotEquals(fileId, newFileId);
Assertions.assertEquals(oldMetadata.getName(), newMetadata.getName());
Assertions.assertEquals(oldMetadata.getPath(), newMetadata.getPath());
Assertions.assertEquals(oldMetadata.getStorage(), newMetadata.getStorage());
Assertions.assertEquals(oldMetadata.getModuleId(), newMetadata.getModuleId());
Assertions.assertEquals(oldMetadata.getType(), newMetadata.getType());
Assertions.assertEquals(oldMetadata.getRefId(), newMetadata.getRefId());
Assertions.assertEquals(oldRepository.getBranch(), newRepository.getBranch());
Assertions.assertNotEquals(oldRepository.getFileMetadataId(), newRepository.getFileMetadataId());
}
protected MvcResult downloadFile(String url, Object... uriVariables) throws Exception {
return mockMvc.perform(getRequestBuilder(url, uriVariables))
.andExpect(content().contentType(MediaType.APPLICATION_OCTET_STREAM_VALUE))

View File

@ -54,8 +54,7 @@ public class FileManagementRequestUtils {
public static final String URL_FILE_REPOSITORY_CREATE = "/project/file/repository/add-repository";
//修改存储库
public static final String URL_FILE_REPOSITORY_UPDATE = "/project/file/repository/update-repository";
//添加文件
public static final String URL_FILE_REPOSITORY_FILE_ADD = "/project/file/repository/add-file";
public static final String URL_FILE_REPOSITORY_FILE_PULL = "/project/file/repository/pull-file/%s";
}

View File

@ -83,7 +83,6 @@ public class GitRepositoryUtil {
}
public RemoteFileAttachInfo selectLastCommitIdByBranch(String branch, String filePath) {
RemoteFileAttachInfo attachInfo;
InMemoryRepository repo = null;
TreeWalk treeWalk = null;
try {
@ -105,8 +104,7 @@ public class GitRepositoryUtil {
if (StringUtils.isEmpty(fileLastCommitId)) {
fileLastCommitId = lastCommitId.getName();
}
attachInfo = new RemoteFileAttachInfo(repositoryUrl, userName, token, branch, fileLastCommitId, filePath, commit.getFullMessage(), loader.getSize());
return attachInfo;
return new RemoteFileAttachInfo(repositoryUrl, userName, token, branch, fileLastCommitId, filePath, commit.getFullMessage(), loader.getSize());
}
}
} catch (Exception e) {
@ -117,7 +115,7 @@ public class GitRepositoryUtil {
}
this.closeConnection(repo);
}
return null;
return new RemoteFileAttachInfo();
}
private String getFileLastCommitId(ObjectId objectId, String filePath) throws Exception {