Skip to content

Commit

Permalink
feat: move project to trash
Browse files Browse the repository at this point in the history
  • Loading branch information
4e6 committed Jul 3, 2024
1 parent f8f0c08 commit 0e580d6
Show file tree
Hide file tree
Showing 16 changed files with 184 additions and 51 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import org.enso.projectmanager.boot.configuration.{
}
import org.enso.projectmanager.control.core.{Applicative, CovariantFlatMap}
import org.enso.projectmanager.control.effect.{Async, ErrorChannel, Exec, Sync}
import org.enso.projectmanager.infrastructure.desktop.DesktopTrash
import org.enso.projectmanager.infrastructure.file.BlockingFileSystem
import org.enso.projectmanager.infrastructure.http.ProjectsEndpoint
import org.enso.projectmanager.infrastructure.languageserver.{
Expand Down Expand Up @@ -68,8 +69,16 @@ class MainModule[

lazy val projectValidator = new ProjectNameValidator[F]()

lazy val trash = new DesktopTrash[F]

lazy val projectRepositoryFactory =
new ProjectFileRepositoryFactory[F](config.storage, clock, fileSystem, gen)
new ProjectFileRepositoryFactory[F](
config.storage,
clock,
fileSystem,
gen,
trash
)

val distributionConfiguration = DefaultDistributionConfiguration
val loggingService = Logging.GlobalLoggingService
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import org.enso.projectmanager.control.core.syntax._
import org.enso.projectmanager.control.effect.syntax._
import org.enso.projectmanager.control.core.{Applicative, CovariantFlatMap}
import org.enso.projectmanager.control.effect.{ErrorChannel, Sync}
import org.enso.projectmanager.infrastructure.desktop.DesktopTrash
import org.enso.projectmanager.infrastructure.file.BlockingFileSystem
import org.enso.projectmanager.infrastructure.random.SystemGenerator
import org.enso.projectmanager.infrastructure.repository.{
Expand Down Expand Up @@ -47,13 +48,16 @@ object ProjectListCommand {
val clock = new RealClock[F]
val fileSystem = new BlockingFileSystem[F](config.timeout.ioTimeout)
val gen = new SystemGenerator[F]
val trash = new DesktopTrash[F]

val projectRepositoryFactory = new ProjectFileRepositoryFactory[F](
config.storage,
clock,
fileSystem,
gen
)
val projectRepositoryFactory =
new ProjectFileRepositoryFactory[F](
config.storage,
clock,
fileSystem,
gen,
trash
)
val projectRepository =
projectRepositoryFactory.getProjectRepository(projectsPath)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import org.enso.projectmanager.boot.configuration.ProjectManagerConfig
import org.enso.projectmanager.control.core.{Applicative, CovariantFlatMap}
import org.enso.projectmanager.control.core.syntax._
import org.enso.projectmanager.control.effect.{ErrorChannel, Sync}
import org.enso.projectmanager.infrastructure.desktop.DesktopTrash
import org.enso.projectmanager.infrastructure.file.BlockingFileSystem
import org.enso.projectmanager.infrastructure.random.SystemGenerator
import org.enso.projectmanager.infrastructure.repository.ProjectFileRepositoryFactory
Expand Down Expand Up @@ -35,12 +36,16 @@ object FileSystemCreateDirectoryCommand {
val clock = new RealClock[F]
val fileSystem = new BlockingFileSystem[F](config.timeout.ioTimeout)
val gen = new SystemGenerator[F]
val projectRepositoryFactory = new ProjectFileRepositoryFactory[F](
config.storage,
clock,
fileSystem,
gen
)
val trash = new DesktopTrash[F]

val projectRepositoryFactory =
new ProjectFileRepositoryFactory[F](
config.storage,
clock,
fileSystem,
gen,
trash
)

val service = new FileSystemService[F](fileSystem, projectRepositoryFactory)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import org.enso.projectmanager.boot.configuration.ProjectManagerConfig
import org.enso.projectmanager.control.core.syntax._
import org.enso.projectmanager.control.core.{Applicative, CovariantFlatMap}
import org.enso.projectmanager.control.effect.{ErrorChannel, Sync}
import org.enso.projectmanager.infrastructure.desktop.DesktopTrash
import org.enso.projectmanager.infrastructure.file.BlockingFileSystem
import org.enso.projectmanager.infrastructure.random.SystemGenerator
import org.enso.projectmanager.infrastructure.repository.ProjectFileRepositoryFactory
Expand Down Expand Up @@ -35,12 +36,16 @@ object FileSystemDeleteCommand {
val clock = new RealClock[F]
val fileSystem = new BlockingFileSystem[F](config.timeout.ioTimeout)
val gen = new SystemGenerator[F]
val projectRepositoryFactory = new ProjectFileRepositoryFactory[F](
config.storage,
clock,
fileSystem,
gen
)
val trash = new DesktopTrash[F]

val projectRepositoryFactory =
new ProjectFileRepositoryFactory[F](
config.storage,
clock,
fileSystem,
gen,
trash
)

val service = new FileSystemService[F](fileSystem, projectRepositoryFactory)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import org.enso.projectmanager.boot.configuration.ProjectManagerConfig
import org.enso.projectmanager.control.core.syntax._
import org.enso.projectmanager.control.core.{Applicative, CovariantFlatMap}
import org.enso.projectmanager.control.effect.{ErrorChannel, Sync}
import org.enso.projectmanager.infrastructure.desktop.DesktopTrash
import org.enso.projectmanager.infrastructure.file.BlockingFileSystem
import org.enso.projectmanager.infrastructure.random.SystemGenerator
import org.enso.projectmanager.infrastructure.repository.ProjectFileRepositoryFactory
Expand Down Expand Up @@ -38,12 +39,16 @@ object FileSystemListCommand {
val clock = new RealClock[F]
val fileSystem = new BlockingFileSystem[F](config.timeout.ioTimeout)
val gen = new SystemGenerator[F]
val projectRepositoryFactory = new ProjectFileRepositoryFactory[F](
config.storage,
clock,
fileSystem,
gen
)
val trash = new DesktopTrash[F]

val projectRepositoryFactory =
new ProjectFileRepositoryFactory[F](
config.storage,
clock,
fileSystem,
gen,
trash
)

val service = new FileSystemService[F](fileSystem, projectRepositoryFactory)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import org.enso.projectmanager.boot.configuration.ProjectManagerConfig
import org.enso.projectmanager.control.core.syntax._
import org.enso.projectmanager.control.core.{Applicative, CovariantFlatMap}
import org.enso.projectmanager.control.effect.{ErrorChannel, Sync}
import org.enso.projectmanager.infrastructure.desktop.DesktopTrash
import org.enso.projectmanager.infrastructure.file.BlockingFileSystem
import org.enso.projectmanager.infrastructure.random.SystemGenerator
import org.enso.projectmanager.infrastructure.repository.ProjectFileRepositoryFactory
Expand Down Expand Up @@ -37,12 +38,16 @@ object FileSystemMoveDirectoryCommand {
val clock = new RealClock[F]
val fileSystem = new BlockingFileSystem[F](config.timeout.ioTimeout)
val gen = new SystemGenerator[F]
val projectRepositoryFactory = new ProjectFileRepositoryFactory[F](
config.storage,
clock,
fileSystem,
gen
)
val trash = new DesktopTrash[F]

val projectRepositoryFactory =
new ProjectFileRepositoryFactory[F](
config.storage,
clock,
fileSystem,
gen,
trash
)

val service = new FileSystemService[F](fileSystem, projectRepositoryFactory)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import org.enso.projectmanager.boot.configuration.ProjectManagerConfig
import org.enso.projectmanager.control.core.syntax._
import org.enso.projectmanager.control.core.{Applicative, CovariantFlatMap}
import org.enso.projectmanager.control.effect.{ErrorChannel, Sync}
import org.enso.projectmanager.infrastructure.desktop.DesktopTrash
import org.enso.projectmanager.infrastructure.file.BlockingFileSystem
import org.enso.projectmanager.infrastructure.random.SystemGenerator
import org.enso.projectmanager.infrastructure.repository.ProjectFileRepositoryFactory
Expand Down Expand Up @@ -36,12 +37,16 @@ object FileSystemWritePathCommand {
val clock = new RealClock[F]
val fileSystem = new BlockingFileSystem[F](config.timeout.ioTimeout)
val gen = new SystemGenerator[F]
val projectRepositoryFactory = new ProjectFileRepositoryFactory[F](
config.storage,
clock,
fileSystem,
gen
)
val trash = new DesktopTrash[F]

val projectRepositoryFactory =
new ProjectFileRepositoryFactory[F](
config.storage,
clock,
fileSystem,
gen,
trash
)

val service = new FileSystemService[F](fileSystem, projectRepositoryFactory)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package org.enso.projectmanager.infrastructure.desktop

import org.enso.desktopenvironment.{Platform, Trash}
import org.enso.projectmanager.control.effect.Sync

import java.io.File

class DesktopTrash[F[+_, +_]: Sync](trash: Trash = Platform.getTrash)
extends TrashCan[F] {

/** @inheritdoc */
override def moveToTrash(path: File): F[Nothing, Boolean] =
Sync[F].effect(trash.moveToTrash(path.toPath))
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package org.enso.projectmanager.infrastructure.desktop

import java.io.File

/** An abstraction form the trash can.
*
* @tparam F a monadic context
*/
trait TrashCan[F[+_, +_]] {

/** Moves the provided path to the trash bin.
*
* @return `true` if the operation was successful
*/
def moveToTrash(path: File): F[Nothing, Boolean]
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import org.enso.projectmanager.control.core.{
import org.enso.projectmanager.control.core.syntax._
import org.enso.projectmanager.control.effect.syntax._
import org.enso.projectmanager.control.effect.{ErrorChannel, Sync}
import org.enso.projectmanager.infrastructure.desktop.TrashCan
import org.enso.projectmanager.infrastructure.file.FileSystem
import org.enso.projectmanager.infrastructure.file.FileSystemFailure.{
FileNotFound,
Expand All @@ -35,6 +36,7 @@ import org.enso.projectmanager.model.{Project, ProjectMetadata}
* @param clock a clock
* @param fileSystem a file system abstraction
* @param gen a random generator
* @param trash a trash can
*/
class ProjectFileRepository[
F[+_, +_]: Sync: ErrorChannel: CovariantFlatMap: Applicative
Expand All @@ -43,7 +45,8 @@ class ProjectFileRepository[
metadataStorageConfig: MetadataStorageConfig,
clock: Clock[F],
fileSystem: FileSystem[F],
gen: Generator[F]
gen: Generator[F],
trash: TrashCan[F]
) extends ProjectRepository[F] {

/** @inheritdoc */
Expand Down Expand Up @@ -224,6 +227,19 @@ class ProjectFileRepository[
}
}

/** @inheritdoc */
override def moveToTrash(
projectId: UUID
): F[ProjectRepositoryFailure, Boolean] = {
findById(projectId)
.flatMap {
case Some(project) =>
trash.moveToTrash(project.path)
case None =>
ErrorChannel[F].fail(ProjectNotFoundInIndex)
}
}

/** @inheritdoc */
override def moveProject(
projectId: UUID,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package org.enso.projectmanager.infrastructure.repository
import org.enso.projectmanager.boot.configuration.StorageConfig
import org.enso.projectmanager.control.core.{Applicative, CovariantFlatMap}
import org.enso.projectmanager.control.effect.{ErrorChannel, Sync}
import org.enso.projectmanager.infrastructure.desktop.TrashCan
import org.enso.projectmanager.infrastructure.file.FileSystem
import org.enso.projectmanager.infrastructure.random.Generator
import org.enso.projectmanager.infrastructure.time.Clock
Expand All @@ -14,7 +15,8 @@ class ProjectFileRepositoryFactory[
storageConfig: StorageConfig,
clock: Clock[F],
fileSystem: FileSystem[F],
gen: Generator[F]
gen: Generator[F],
trash: TrashCan[F]
) extends ProjectRepositoryFactory[F] {

/** @inheritdoc */
Expand All @@ -28,7 +30,8 @@ class ProjectFileRepositoryFactory[
storageConfig.metadata,
clock,
fileSystem,
gen
gen,
trash
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,13 @@ trait ProjectRepository[F[+_, +_]] {
*/
def delete(projectId: UUID): F[ProjectRepositoryFailure, Unit]

/** Move the provided project to the trash bin.
*
* @param projectId the project id trash
* @return `true` if the operation was successful
*/
def moveToTrash(projectId: UUID): F[ProjectRepositoryFailure, Boolean]

/** Renames a project.
*
* @param projectId the project id to rename
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,14 +144,26 @@ class ProjectService[
override def deleteUserProject(
projectId: UUID,
projectsDirectory: Option[File]
): F[ProjectServiceFailure, Unit] =
log.debug("Deleting project [{}].", projectId) *>
ensureProjectIsNotRunning(projectId) *>
projectRepositoryFactory
.getProjectRepository(projectsDirectory)
.delete(projectId)
.mapError(toServiceFailure) *>
log.info("Project deleted [{}].", projectId)
): F[ProjectServiceFailure, Unit] = {
val projectRepository =
projectRepositoryFactory.getProjectRepository(projectsDirectory)
val moveProjectToTrash =
projectRepository.moveToTrash(projectId).mapError(toServiceFailure)
val deleteProject =
projectRepository.delete(projectId).mapError(toServiceFailure)

for {
_ <- log.debug("Preparing to delete the project [{}].", projectId)
_ <- ensureProjectIsNotRunning(projectId)
_ <- CovariantFlatMap[F].ifM(moveProjectToTrash)(
ifTrue = log.info("Project moved to trash [{}].", projectId),
ifFalse =
log.info("Failed to trash the project. Deleting [{}].", projectId) *>
deleteProject *>
log.info("Project deleted [{}]", projectId)
)
} yield ()
}

private def ensureProjectIsNotRunning(
projectId: UUID
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,11 @@ import org.enso.projectmanager.service.versionmanagement.{
RuntimeVersionManagerFactory
}
import org.enso.projectmanager.service.{ProjectCreationService, ProjectService}
import org.enso.projectmanager.test.{ObservableGenerator, ProgrammableClock}
import org.enso.projectmanager.test.{
ObservableGenerator,
ProgrammableClock,
Shredder
}
import org.enso.runtimeversionmanager.CurrentVersion
import org.enso.runtimeversionmanager.components.GraalVMVersion
import org.enso.runtimeversionmanager.test.FakeReleases
Expand Down Expand Up @@ -102,6 +106,8 @@ class BaseServerSpec extends JsonRpcServerTestKit with BeforeAndAfterAll {

lazy val gen = new ObservableGenerator[ZAny]()

lazy val trash = new Shredder[ZAny]

val testProjectsRoot = Files.createTempDirectory(null).toFile
sys.addShutdownHook(FileUtils.deleteQuietly(testProjectsRoot))

Expand Down Expand Up @@ -141,7 +147,8 @@ class BaseServerSpec extends JsonRpcServerTestKit with BeforeAndAfterAll {
testStorageConfig,
testClock,
fileSystem,
gen
gen,
trash
)

lazy val projectNameValidator = new ProjectNameValidator[ZIO[ZAny, *, *]]()
Expand Down
Loading

0 comments on commit 0e580d6

Please sign in to comment.