diff --git a/src/main/java/net/geedge/asw/module/app/controller/ApplicationController.java b/src/main/java/net/geedge/asw/module/app/controller/ApplicationController.java index 55c488a..68bc260 100644 --- a/src/main/java/net/geedge/asw/module/app/controller/ApplicationController.java +++ b/src/main/java/net/geedge/asw/module/app/controller/ApplicationController.java @@ -15,6 +15,7 @@ import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import java.io.IOException; +import java.nio.charset.StandardCharsets; import java.util.Collection; import java.util.List; import java.util.Map; @@ -57,6 +58,19 @@ public class ApplicationController { return R.ok(); } + @PostMapping("/{workspaceId}/branch/{branchName}/application/{applicationName}/rename") + public R renameApplication(@PathVariable("workspaceId") String workspaceId, + @PathVariable("branchName") String branchName, + @PathVariable("applicationName") String applicationName, + @RequestBody Map body) { + String newName = T.MapUtil.getStr(body, "name"); + T.VerifyUtil.is(newName).notEmpty(RCode.PARAM_CANNOT_EMPTY); + + // url decode + applicationName = T.URLUtil.decode(applicationName, StandardCharsets.UTF_8); + applicationService.renameApplication(workspaceId, branchName, applicationName, newName); + return R.ok(); + } @PostMapping("/{workspaceId}/branch/{branchName}/application/commit") public synchronized R updateApplication(@PathVariable("workspaceId") String workspaceId, diff --git a/src/main/java/net/geedge/asw/module/app/service/IApplicationService.java b/src/main/java/net/geedge/asw/module/app/service/IApplicationService.java index ea1bbd9..f9b07ad 100644 --- a/src/main/java/net/geedge/asw/module/app/service/IApplicationService.java +++ b/src/main/java/net/geedge/asw/module/app/service/IApplicationService.java @@ -16,6 +16,8 @@ public interface IApplicationService { void newApplication(String workspaceId, String branch, String name); + void renameApplication(String workspaceId, String branch, String oldName, String newName); + void deleteApplication(String workspaceId, String branch, String name); void updateApplication(String workspaceId, String branch, String lastCommitId, String message, List> updateContent); diff --git a/src/main/java/net/geedge/asw/module/app/service/impl/ApplicationServiceImpl.java b/src/main/java/net/geedge/asw/module/app/service/impl/ApplicationServiceImpl.java index 082425b..587b96a 100644 --- a/src/main/java/net/geedge/asw/module/app/service/impl/ApplicationServiceImpl.java +++ b/src/main/java/net/geedge/asw/module/app/service/impl/ApplicationServiceImpl.java @@ -244,23 +244,21 @@ public class ApplicationServiceImpl implements IApplicationService { File gitDir = workspaceService.getGitDir(workspaceId); try (Repository repository = JGitUtils.openRepository(gitDir)) { Map 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); - + for (String filename : T.ListUtil.of("README.md", "meta.json", "signature.json")) { String fileContent = T.StrUtil.EMPTY; - if ("meta.json".equals(str)) { + if ("meta.json".equals(filename)) { 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)) { + if ("signature.json".equals(filename)) { fileContent = this.signatureJsonTemplate; } ObjectId objectId = JGitUtils.insertBlobFileToDatabase(repository, fileContent.getBytes()); - filePathAndBlobIdMap.put(savePath, objectId); + filePathAndBlobIdMap.put(JGitUtils.buildFilePath(name, filename), objectId); } try (ObjectInserter inserter = repository.getObjectDatabase().newInserter(); @@ -310,6 +308,79 @@ public class ApplicationServiceImpl implements IApplicationService { } } + @Override + public void renameApplication(String workspaceId, String branch, String oldName, String newName) { + log.info("[applicationName] [begin] [workspaceId: {}] [branch: {}] [oldName: {}] [newName: {}]", workspaceId, branch, oldName, newName); + if (T.StrUtil.equals(oldName, newName)) { + log.warn("[renameApplication] [newName has not changed]"); + return; + } + 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.setRecursive(true); + + DirCache newTree = DirCache.newInCore(); + DirCacheBuilder newTreeBuilder = newTree.builder(); + + boolean isCommit = false; + String prefix = JGitUtils.buildFilePrefix(oldName); + while (treeWalk.next()) { + String pathString = treeWalk.getPathString(); + // rename file + if (pathString.startsWith(prefix)) { + isCommit = true; + + String filename = treeWalk.getNameString(); + String savePath = JGitUtils.buildFilePath(newName, filename); + if (T.StrUtil.equals("meta.json", filename)) { + // 更新 meta.json name,longName 的值 + ObjectLoader loader = repository.open(treeWalk.getObjectId(0)); + String metaJsonStr = T.StrUtil.utf8Str(loader.getBytes()); + JSONObject jsonObject = T.JSONUtil.parseObj(metaJsonStr); + jsonObject.set("name", newName); + jsonObject.set("longName", newName); + String content = T.JSONUtil.parse(jsonObject).toJSONString(2); + + ObjectId blobId = JGitUtils.insertBlobFileToDatabase(repository, content.getBytes()); + DirCacheEntry dirCacheEntry = JGitUtils.buildDirCacheEntry(savePath, treeWalk.getFileMode(0), blobId); + newTreeBuilder.add(dirCacheEntry); + } else { + DirCacheEntry dirCacheEntry = JGitUtils.buildDirCacheEntry(savePath, treeWalk.getFileMode(0), treeWalk.getObjectId(0)); + newTreeBuilder.add(dirCacheEntry); + } + } else { + // other file + DirCacheEntry entry = JGitUtils.buildDirCacheEntry(pathString, treeWalk.getFileMode(0), treeWalk.getObjectId(0)); + newTreeBuilder.add(entry); + } + } + newTreeBuilder.finish(); + + if (isCommit) { + try (ObjectInserter inserter = repository.getObjectDatabase().newInserter()) { + + ObjectId newTreeId = newTree.writeTree(inserter); + String message = String.format("chore: rename application %s to %s", oldName, newName); + + SysUserEntity loginUserEntity = userService.getById(StpUtil.getLoginIdAsString()); + PersonIdent personIdent = JGitUtils.buildPersonIdent(loginUserEntity.getName()); + + JGitUtils.createCommit(repository, branch, newTreeId, message, personIdent); + } + } else { + log.warn("[renameApplication] [old application not found] [name: {}]", oldName); + } + } catch (IOException | ConcurrentRefUpdateException e) { + log.error(e, "[renameApplication] [error] [workspaceId: {}] [branch: {}] [oldName: {}] [newName: {}]", workspaceId, branch, oldName, newName); + throw new RuntimeException(e); + } + } + @Override public void deleteApplication(String workspaceId, String branch, String name) { File gitDir = workspaceService.getGitDir(workspaceId); @@ -325,7 +396,7 @@ public class ApplicationServiceImpl implements IApplicationService { DirCache newTree = DirCache.newInCore(); DirCacheBuilder newTreeBuilder = newTree.builder(); - String appFilePrefixStr = T.StrUtil.concat(true, "applications/", name, "/"); + String appFilePrefixStr = JGitUtils.buildFilePrefix(name); while (treeWalk.next()) { String pathString = treeWalk.getPathString(); if (!pathString.startsWith(appFilePrefixStr)) { @@ -483,7 +554,7 @@ public class ApplicationServiceImpl implements IApplicationService { @Override public Map infoApplicationFileContent(String workspaceId, String branch, String name, String commitId, String file) { // applications/qq/meta.json - String path = T.StrUtil.concat(true, "applications/", name, "/", file); + String path = JGitUtils.buildFilePath(name, file); Map result = T.MapUtil.builder() .put("path", path) @@ -607,8 +678,8 @@ public class ApplicationServiceImpl implements IApplicationService { // 修改文件路径信息 List updateFilePath = T.ListUtil.list(true); updateAppList.parallelStream().forEach(entity -> { - updateFilePath.add(T.StrUtil.concat(true, "applications/", entity.getName(), "/meta.json")); - updateFilePath.add(T.StrUtil.concat(true, "applications/", entity.getName(), "/signature.json")); + updateFilePath.add(JGitUtils.buildFilePath(entity.getName(), "meta.json")); + updateFilePath.add(JGitUtils.buildFilePath(entity.getName(), "signature.json")); }); // build tree @@ -643,7 +714,7 @@ public class ApplicationServiceImpl implements IApplicationService { fileContent = T.JSONUtil.parse(tempJSONObject).toJSONString(2); } // save - String filePath = T.StrUtil.concat(true, "applications/", entity.getName(), "/", fileName); + String filePath = JGitUtils.buildFilePath(entity.getName(), fileName); DirCacheEntry dirCacheEntry = new DirCacheEntry(filePath); dirCacheEntry.setFileMode(FileMode.REGULAR_FILE); @@ -669,7 +740,7 @@ public class ApplicationServiceImpl implements IApplicationService { String fileContent = T.JSONUtil.parse(jsonObject).toJSONString(2); ObjectId objectId = JGitUtils.insertBlobFileToDatabase(repository, fileContent.getBytes()); - DirCacheEntry dirCacheEntry = JGitUtils.buildDirCacheEntry(T.StrUtil.concat(true, "applications/", entity.getName(), "/meta.json"), FileMode.REGULAR_FILE, objectId); + DirCacheEntry dirCacheEntry = JGitUtils.buildDirCacheEntry(JGitUtils.buildFilePath(entity.getName(), "meta.json"), FileMode.REGULAR_FILE, objectId); newTreeBuilder.add(dirCacheEntry); // signature.json @@ -678,7 +749,7 @@ public class ApplicationServiceImpl implements IApplicationService { String fileContent2 = T.JSONUtil.parse(jsonObject2).toJSONString(2); ObjectId objectId2 = JGitUtils.insertBlobFileToDatabase(repository, fileContent2.getBytes()); - DirCacheEntry dirCacheEntry2 = JGitUtils.buildDirCacheEntry(T.StrUtil.concat(true, "applications/", entity.getName(), "/signature.json"), FileMode.REGULAR_FILE, objectId2); + DirCacheEntry dirCacheEntry2 = JGitUtils.buildDirCacheEntry(JGitUtils.buildFilePath(entity.getName(), "signature.json"), FileMode.REGULAR_FILE, objectId2); newTreeBuilder.add(dirCacheEntry2); } newTreeBuilder.finish(); diff --git a/src/main/java/net/geedge/asw/module/app/util/JGitUtils.java b/src/main/java/net/geedge/asw/module/app/util/JGitUtils.java index d23675b..9cee524 100644 --- a/src/main/java/net/geedge/asw/module/app/util/JGitUtils.java +++ b/src/main/java/net/geedge/asw/module/app/util/JGitUtils.java @@ -302,6 +302,27 @@ public class JGitUtils { return commitList; } + /** + * 文件前缀 + * + * @param applicationName + * @return + */ + public static String buildFilePrefix(String applicationName) { + return T.StrUtil.concat(true, "applications/", applicationName, "/"); + } + + /** + * git file save path + * + * @param applicationName + * @param fileName + * @return + */ + public static String buildFilePath(String applicationName, String fileName) { + return T.StrUtil.concat(true, buildFilePrefix(applicationName), fileName); + } + /** * 构建 DirCacheEntry * @@ -543,6 +564,14 @@ public class JGitUtils { break; } case RENAME: { + if (0 != addedLines | 0 != deletedLines) { + Map fileContent = getFileContent(repository, oldPath, diff.getOldId().toObjectId()); + oldContent = T.MapUtil.getStr(fileContent, "content", ""); + + Map fileContent1 = getFileContent(repository, newPath, diff.getNewId().toObjectId()); + encoding = T.MapUtil.getStr(fileContent1, "encoding", ""); + newContent = T.MapUtil.getStr(fileContent1, "content", ""); + } break; } default: