diff --git a/app/server/appsmith-git/src/main/java/com/appsmith/git/files/FileUtilsCEImpl.java b/app/server/appsmith-git/src/main/java/com/appsmith/git/files/FileUtilsCEImpl.java index 2aa964d5c4..112ecac824 100644 --- a/app/server/appsmith-git/src/main/java/com/appsmith/git/files/FileUtilsCEImpl.java +++ b/app/server/appsmith-git/src/main/java/com/appsmith/git/files/FileUtilsCEImpl.java @@ -251,7 +251,7 @@ public class FileUtilsCEImpl implements FileInterface { @Override public Mono saveArtifactToGitRepo( - Path baseRepoSuffix, GitResourceMap gitResourceMap, String branchName, boolean keepWorkingDirChanges) + Path baseRepoSuffix, GitResourceMap gitResourceMapFromDB, String branchName, boolean keepWorkingDirChanges) throws GitAPIException, IOException { // Repo path will be: @@ -261,14 +261,18 @@ public class FileUtilsCEImpl implements FileInterface { .resetToLastCommit(baseRepoSuffix, branchName, keepWorkingDirChanges) .flatMap(isSwitched -> { Path baseRepo = Paths.get(gitServiceConfig.getGitRootPath()).resolve(baseRepoSuffix); + Mono gitResourceMapFromFSMono = constructGitResourceMapFromGitRepo( + baseRepoSuffix, branchName) + .name("constructGitResourceMapFromGitRepo"); - try { - updateEntitiesInRepo(gitResourceMap, baseRepo); - } catch (IOException e) { - return Mono.error(e); - } - - return Mono.just(baseRepo); + return gitResourceMapFromFSMono.flatMap(gitResourceMapFromFS -> { + try { + updateEntitiesInRepo(gitResourceMapFromDB, baseRepo, gitResourceMapFromFS); + } catch (IOException e) { + return Mono.error(e); + } + return Mono.just(baseRepo); + }); }) .subscribeOn(scheduler); } @@ -327,19 +331,28 @@ public class FileUtilsCEImpl implements FileInterface { } } - protected Set updateEntitiesInRepo(GitResourceMap gitResourceMap, Path baseRepo) throws IOException { - ModifiedResources modifiedResources = gitResourceMap.getModifiedResources(); - Map resourceMap = gitResourceMap.getGitResourceMap(); + protected Set updateEntitiesInRepo( + GitResourceMap gitResourceMapFromDB, Path baseRepo, GitResourceMap gitResourceMapFromFS) + throws IOException { + Map resourceMapFromDB = gitResourceMapFromDB.getGitResourceMap(); - Set filesInRepo = getExistingFilesInRepo(baseRepo); - - Set updatedFilesToBeSerialized = resourceMap.keySet().parallelStream() + Set filesInRepo = new HashSet<>(); + Set updatedFiles = new HashSet<>(); + Set filesInDB = resourceMapFromDB.keySet().parallelStream() .map(gitResourceIdentity -> gitResourceIdentity.getFilePath()) .collect(Collectors.toSet()); + Map filesInFS = gitResourceMapFromFS.getGitResourceMap().entrySet().parallelStream() + .map(entry -> { + filesInRepo.add(entry.getKey().getFilePath()); + return entry; + }) + .collect(Collectors.toMap(entry -> entry.getKey().getFilePath(), entry -> entry.getValue())); + // Remove all files that need to be serialized from the existing files list, as well as the README file // What we are left with are all the files to be deleted - filesInRepo.removeAll(updatedFilesToBeSerialized); + + filesInRepo.removeAll(filesInDB); filesInRepo.remove(README_FILE_NAME); // Delete all the files because they are no longer needed @@ -357,20 +370,19 @@ public class FileUtilsCEImpl implements FileInterface { // Now go through the resource map and based on resource type, check if the resource is modified before // serialization - // Or simply choose the mechanism for serialization - Map modifiedResourcesTypes = getModifiedResourcesTypes(); - return resourceMap.entrySet().parallelStream() + resourceMapFromDB.entrySet().parallelStream() .map(entry -> { GitResourceIdentity key = entry.getKey(); boolean resourceUpdated = true; - if (modifiedResourcesTypes.containsKey(key.getResourceType()) && modifiedResources != null) { - GitResourceType comparisonType = modifiedResourcesTypes.get(key.getResourceType()); - + try { resourceUpdated = - modifiedResources.isResourceUpdatedNew(comparisonType, key.getResourceIdentifier()); + fileOperations.hasFileChanged(entry.getValue(), filesInFS.get(key.getFilePath())); + } catch (IOException e) { + log.error("Error while checking if file has changed", e); } if (resourceUpdated) { + log.info("Resource updated: {}", key.getFilePath()); String filePath = key.getFilePath(); saveResourceCommon(entry.getValue(), baseRepo.resolve(filePath)); @@ -380,6 +392,7 @@ public class FileUtilsCEImpl implements FileInterface { }) .filter(Objects::nonNull) .collect(Collectors.toSet()); + return updatedFiles; } protected Set updateEntitiesInRepo(ApplicationGitReference applicationGitReference, Path baseRepo) { diff --git a/app/server/appsmith-git/src/main/java/com/appsmith/git/files/operations/FileOperationsCEv2Impl.java b/app/server/appsmith-git/src/main/java/com/appsmith/git/files/operations/FileOperationsCEv2Impl.java index abc686507d..8e4dadb8e0 100644 --- a/app/server/appsmith-git/src/main/java/com/appsmith/git/files/operations/FileOperationsCEv2Impl.java +++ b/app/server/appsmith-git/src/main/java/com/appsmith/git/files/operations/FileOperationsCEv2Impl.java @@ -113,6 +113,28 @@ public class FileOperationsCEv2Impl implements FileOperationsCE { } } + public boolean hasFileChanged(Object sourceEntity, Object fsSourceEntity) throws IOException { + if (fsSourceEntity == null) { + return true; + } + + boolean hasChanged = true; + if (sourceEntity instanceof String s) { + hasChanged = !s.equals(fsSourceEntity.toString()); + } else if (sourceEntity instanceof JSONObject json) { + JsonNode sourceNode = objectMapper.readTree(json.toString()); + String contentToWrite = objectWriter.writeValueAsString(sourceNode); + String fsContent = objectWriter.writeValueAsString(fsSourceEntity); + hasChanged = !contentToWrite.equals(fsContent); + } else { + String contentToWrite = objectWriter.writeValueAsString(sourceEntity); + String fsContent = objectWriter.writeValueAsString(fsSourceEntity); + hasChanged = !contentToWrite.equals(fsContent); + } + + return hasChanged; + } + /** * This method will be used to read and dehydrate the json file present from the local git repo * diff --git a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/git/operations/FileOperationsCE.java b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/git/operations/FileOperationsCE.java index 33556855e2..205cfe5533 100644 --- a/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/git/operations/FileOperationsCE.java +++ b/app/server/appsmith-interfaces/src/main/java/com/appsmith/external/git/operations/FileOperationsCE.java @@ -18,6 +18,8 @@ public interface FileOperationsCE { boolean writeToFile(Object sourceEntity, Path path) throws IOException; + boolean hasFileChanged(Object sourceEntity, Object fsSourceEntity) throws IOException; + void scanAndDeleteFileForDeletedResources(Set validResources, Path resourceDirectory); void scanAndDeleteDirectoryForDeletedResources(Set validResources, Path resourceDirectory); diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/CommonGitFileUtilsCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/CommonGitFileUtilsCE.java index 3d52dd1239..712ae25e94 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/CommonGitFileUtilsCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/helpers/ce/CommonGitFileUtilsCE.java @@ -178,7 +178,7 @@ public class CommonGitFileUtilsCE { Path baseRepoSuffix, ArtifactExchangeJson artifactExchangeJson, String branchName) { // this should come from the specific files - GitResourceMap gitResourceMap = createGitResourceMap(artifactExchangeJson); + GitResourceMap gitResourceMapFromDB = createGitResourceMap(artifactExchangeJson); Mono keepWorkingDirChangesMono = featureFlagService.check(FeatureFlagEnum.release_git_reset_optimization_enabled); @@ -186,7 +186,7 @@ public class CommonGitFileUtilsCE { return keepWorkingDirChangesMono.flatMap(keepWorkingDirChanges -> { try { return fileUtils - .saveArtifactToGitRepo(baseRepoSuffix, gitResourceMap, branchName, keepWorkingDirChanges) + .saveArtifactToGitRepo(baseRepoSuffix, gitResourceMapFromDB, branchName, keepWorkingDirChanges) .subscribeOn(Schedulers.boundedElastic()); } catch (IOException | GitAPIException exception) { return Mono.error(exception);