diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/git/GitRedisUtils.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/git/GitRedisUtils.java index 6c27759f3ea..e0d61cdc192 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/git/GitRedisUtils.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/git/GitRedisUtils.java @@ -69,7 +69,7 @@ public Mono releaseFileLock(String defaultApplicationId) { * @return : Boolean for whether the lock is acquired */ // TODO @Manish add artifactType reference in incoming prs. - public Mono acquireGitLock(String baseArtifactId, String commandName, boolean isLockRequired) { + public Mono acquireGitLock(String baseArtifactId, String commandName, Boolean isLockRequired) { if (!Boolean.TRUE.equals(isLockRequired)) { return Mono.just(Boolean.TRUE); } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/git/central/CentralGitServiceCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/git/central/CentralGitServiceCE.java index 576a7fb99cd..4254b5d4dd2 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/git/central/CentralGitServiceCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/git/central/CentralGitServiceCE.java @@ -31,4 +31,6 @@ Mono fetchRemoteChanges( ArtifactType artifactType, GitType gitType, RefType refType); + + Mono discardChanges(String branchedArtifactId, ArtifactType artifactType, GitType gitType); } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/git/central/CentralGitServiceCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/git/central/CentralGitServiceCEImpl.java index 7a15b41f63c..55e1692b816 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/git/central/CentralGitServiceCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/git/central/CentralGitServiceCEImpl.java @@ -1112,4 +1112,84 @@ private Mono updateArtifactWithGitMetadataGivenPermission( .getArtifactHelper(artifact.getArtifactType()) .saveArtifact(artifact); } + + /** + * Resets the artifact to last commit, all uncommitted changes are lost in the process. + * @param branchedArtifactId : id of the branchedArtifact + * @param artifactType type of the artifact + * @param gitType what is the intended implementation type + * @return : a publisher of an artifact. + */ + @Override + public Mono discardChanges( + String branchedArtifactId, ArtifactType artifactType, GitType gitType) { + + if (!hasText(branchedArtifactId)) { + return Mono.error(new AppsmithException(AppsmithError.INVALID_PARAMETER, FieldName.ARTIFACT_ID)); + } + + GitArtifactHelper gitArtifactHelper = gitArtifactHelperResolver.getArtifactHelper(artifactType); + AclPermission artifactEditPermission = gitArtifactHelper.getArtifactEditPermission(); + + Mono branchedArtifactMonoCached = + gitArtifactHelper.getArtifactById(branchedArtifactId, artifactEditPermission); + + Mono recreatedArtifactFromLastCommit; + + // Rehydrate the artifact from local file system + recreatedArtifactFromLastCommit = branchedArtifactMonoCached + .flatMap(branchedArtifact -> { + GitArtifactMetadata branchedGitData = branchedArtifact.getGitArtifactMetadata(); + if (branchedGitData == null || !hasText(branchedGitData.getDefaultArtifactId())) { + return Mono.error( + new AppsmithException(AppsmithError.INVALID_GIT_CONFIGURATION, GIT_CONFIG_ERROR)); + } + + return Mono.just(branchedArtifact) + .doFinally(signalType -> gitRedisUtils.acquireGitLock( + branchedGitData.getDefaultArtifactId(), + GitConstants.GitCommandConstants.DISCARD, + TRUE)); + }) + .flatMap(branchedArtifact -> { + GitArtifactMetadata branchedGitData = branchedArtifact.getGitArtifactMetadata(); + ArtifactJsonTransformationDTO jsonTransformationDTO = new ArtifactJsonTransformationDTO(); + // Because this operation is only valid for branches + jsonTransformationDTO.setArtifactType(artifactType); + jsonTransformationDTO.setRefType(RefType.BRANCH); + jsonTransformationDTO.setWorkspaceId(branchedArtifact.getWorkspaceId()); + jsonTransformationDTO.setBaseArtifactId(branchedGitData.getDefaultArtifactId()); + jsonTransformationDTO.setRefName(branchedGitData.getRefName()); + jsonTransformationDTO.setRepoName(branchedGitData.getRepoName()); + + GitHandlingService gitHandlingService = gitHandlingServiceResolver.getGitHandlingService(gitType); + + return gitHandlingService + .recreateArtifactJsonFromLastCommit(jsonTransformationDTO) + .onErrorResume(throwable -> { + log.error("Git recreate ArtifactJsonFailed : {}", throwable.getMessage()); + return Mono.error( + new AppsmithException( + AppsmithError.GIT_ACTION_FAILED, + "discard changes", + "Please create a new branch and resolve conflicts in the remote repository before proceeding.")); + }) + .flatMap(artifactExchangeJson -> importService.importArtifactInWorkspaceFromGit( + branchedArtifact.getWorkspaceId(), + branchedArtifact.getId(), + artifactExchangeJson, + branchedGitData.getBranchName())) + // Update the last deployed status after the rebase + .flatMap(importedArtifact -> gitArtifactHelper.publishArtifact(importedArtifact, true)); + }) + .flatMap(branchedArtifact -> gitAnalyticsUtils + .addAnalyticsForGitOperation(AnalyticsEvents.GIT_DISCARD_CHANGES, branchedArtifact, null) + .doFinally(signalType -> gitRedisUtils.releaseFileLock( + branchedArtifact.getGitArtifactMetadata().getDefaultArtifactId(), TRUE))) + .name(GitSpan.OPS_DISCARD_CHANGES) + .tap(Micrometer.observation(observationRegistry)); + + return Mono.create(sink -> + recreatedArtifactFromLastCommit.subscribe(sink::success, sink::error, null, sink.currentContext())); + } } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/git/central/GitHandlingServiceCE.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/git/central/GitHandlingServiceCE.java index 5b9551ffa67..de387a9e75e 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/git/central/GitHandlingServiceCE.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/git/central/GitHandlingServiceCE.java @@ -58,4 +58,7 @@ Mono> commitArtifact( Artifact branchedArtifact, CommitDTO commitDTO, ArtifactJsonTransformationDTO jsonTransformationDTO); Mono fetchRemoteChanges(ArtifactJsonTransformationDTO jsonTransformationDTO, GitAuth gitAuth); + + Mono recreateArtifactJsonFromLastCommit( + ArtifactJsonTransformationDTO jsonTransformationDTO); } diff --git a/app/server/appsmith-server/src/main/java/com/appsmith/server/git/fs/GitFSServiceCEImpl.java b/app/server/appsmith-server/src/main/java/com/appsmith/server/git/fs/GitFSServiceCEImpl.java index e84ecd9f7a4..27dc09fde45 100644 --- a/app/server/appsmith-server/src/main/java/com/appsmith/server/git/fs/GitFSServiceCEImpl.java +++ b/app/server/appsmith-server/src/main/java/com/appsmith/server/git/fs/GitFSServiceCEImpl.java @@ -598,4 +598,23 @@ public Mono fetchRemoteChanges(ArtifactJsonTransformationDTO jsonTransfo return checkoutBranchMono.then(Mono.defer(() -> fetchRemoteMono)); } + + @Override + public Mono recreateArtifactJsonFromLastCommit( + ArtifactJsonTransformationDTO jsonTransformationDTO) { + + String workspaceId = jsonTransformationDTO.getWorkspaceId(); + String baseArtifactId = jsonTransformationDTO.getBaseArtifactId(); + String repoName = jsonTransformationDTO.getRepoName(); + String refName = jsonTransformationDTO.getRefName(); + + ArtifactType artifactType = jsonTransformationDTO.getArtifactType(); + GitArtifactHelper gitArtifactHelper = gitArtifactHelperResolver.getArtifactHelper(artifactType); + Path repoSuffix = gitArtifactHelper.getRepoSuffixPath(workspaceId, baseArtifactId, repoName); + + return fsGitHandler.rebaseBranch(repoSuffix, refName).flatMap(rebaseStatus -> { + return commonGitFileUtils.reconstructArtifactExchangeJsonFromGitRepoWithAnalytics( + workspaceId, baseArtifactId, repoName, refName, artifactType); + }); + } }