mirror of
https://github.com/enso-org/enso.git
synced 2024-11-22 03:32:23 +03:00
Auto create the root folder if not present. (#10444)
Adds `filesystem-exists` to Project Manager CLI.
If the root folder isn't present will add it at start up.
(cherry picked from commit 891f176e9c
)
This commit is contained in:
parent
e7bc0717ee
commit
468e60e39a
@ -124,58 +124,67 @@ export default class LocalBackend extends Backend {
|
||||
): Promise<backend.AnyAsset[]> {
|
||||
const parentIdRaw = query.parentId == null ? null : extractTypeAndId(query.parentId).id
|
||||
const parentId = query.parentId ?? newDirectoryId(this.projectManager.rootDirectory)
|
||||
const entries = await this.projectManager.listDirectory(parentIdRaw)
|
||||
return entries
|
||||
.map(entry => {
|
||||
switch (entry.type) {
|
||||
case projectManager.FileSystemEntryType.DirectoryEntry: {
|
||||
return {
|
||||
type: backend.AssetType.directory,
|
||||
id: newDirectoryId(entry.path),
|
||||
modifiedAt: entry.attributes.lastModifiedTime,
|
||||
parentId,
|
||||
title: fileInfo.fileName(entry.path),
|
||||
permissions: [],
|
||||
projectState: null,
|
||||
labels: [],
|
||||
description: null,
|
||||
} satisfies backend.DirectoryAsset
|
||||
// Check if Root Directory Exists
|
||||
if (
|
||||
parentIdRaw == null &&
|
||||
!(await this.projectManager.exists(this.projectManager.rootDirectory))
|
||||
) {
|
||||
await this.projectManager.createDirectory(this.projectManager.rootDirectory)
|
||||
return []
|
||||
} else {
|
||||
const entries = await this.projectManager.listDirectory(parentIdRaw)
|
||||
return entries
|
||||
.map(entry => {
|
||||
switch (entry.type) {
|
||||
case projectManager.FileSystemEntryType.DirectoryEntry: {
|
||||
return {
|
||||
type: backend.AssetType.directory,
|
||||
id: newDirectoryId(entry.path),
|
||||
modifiedAt: entry.attributes.lastModifiedTime,
|
||||
parentId,
|
||||
title: fileInfo.fileName(entry.path),
|
||||
permissions: [],
|
||||
projectState: null,
|
||||
labels: [],
|
||||
description: null,
|
||||
} satisfies backend.DirectoryAsset
|
||||
}
|
||||
case projectManager.FileSystemEntryType.ProjectEntry: {
|
||||
return {
|
||||
type: backend.AssetType.project,
|
||||
id: newProjectId(entry.metadata.id),
|
||||
title: entry.metadata.name,
|
||||
modifiedAt: entry.metadata.lastOpened ?? entry.metadata.created,
|
||||
parentId,
|
||||
permissions: [],
|
||||
projectState: {
|
||||
type:
|
||||
this.projectManager.projects.get(entry.metadata.id)?.state ??
|
||||
backend.ProjectState.closed,
|
||||
volumeId: '',
|
||||
path: entry.path,
|
||||
},
|
||||
labels: [],
|
||||
description: null,
|
||||
} satisfies backend.ProjectAsset
|
||||
}
|
||||
case projectManager.FileSystemEntryType.FileEntry: {
|
||||
return {
|
||||
type: backend.AssetType.file,
|
||||
id: newFileId(entry.path),
|
||||
title: fileInfo.fileName(entry.path),
|
||||
modifiedAt: entry.attributes.lastModifiedTime,
|
||||
parentId,
|
||||
permissions: [],
|
||||
projectState: null,
|
||||
labels: [],
|
||||
description: null,
|
||||
} satisfies backend.FileAsset
|
||||
}
|
||||
}
|
||||
case projectManager.FileSystemEntryType.ProjectEntry: {
|
||||
return {
|
||||
type: backend.AssetType.project,
|
||||
id: newProjectId(entry.metadata.id),
|
||||
title: entry.metadata.name,
|
||||
modifiedAt: entry.metadata.lastOpened ?? entry.metadata.created,
|
||||
parentId,
|
||||
permissions: [],
|
||||
projectState: {
|
||||
type:
|
||||
this.projectManager.projects.get(entry.metadata.id)?.state ??
|
||||
backend.ProjectState.closed,
|
||||
volumeId: '',
|
||||
path: entry.path,
|
||||
},
|
||||
labels: [],
|
||||
description: null,
|
||||
} satisfies backend.ProjectAsset
|
||||
}
|
||||
case projectManager.FileSystemEntryType.FileEntry: {
|
||||
return {
|
||||
type: backend.AssetType.file,
|
||||
id: newFileId(entry.path),
|
||||
title: fileInfo.fileName(entry.path),
|
||||
modifiedAt: entry.attributes.lastModifiedTime,
|
||||
parentId,
|
||||
permissions: [],
|
||||
projectState: null,
|
||||
labels: [],
|
||||
description: null,
|
||||
} satisfies backend.FileAsset
|
||||
}
|
||||
}
|
||||
})
|
||||
.sort(backend.compareAssets)
|
||||
})
|
||||
.sort(backend.compareAssets)
|
||||
}
|
||||
}
|
||||
|
||||
/** Return a list of projects belonging to the current user.
|
||||
|
@ -415,6 +415,20 @@ export default class ProjectManager {
|
||||
return await this.sendRequest<VersionList>('engine/list-available', {})
|
||||
}
|
||||
|
||||
/** Checks if a file or directory exists. */
|
||||
async exists(parentId: Path | null) {
|
||||
/** The type of the response body of this endpoint. */
|
||||
interface ResponseBody {
|
||||
readonly exists: boolean
|
||||
}
|
||||
const response = await this.runStandaloneCommand<ResponseBody>(
|
||||
null,
|
||||
'filesystem-exists',
|
||||
parentId ?? this.rootDirectory
|
||||
)
|
||||
return response.exists
|
||||
}
|
||||
|
||||
/** List directories, projects and files in the given folder. */
|
||||
async listDirectory(parentId: Path | null) {
|
||||
/** The type of the response body of this endpoint. */
|
||||
|
@ -214,6 +214,17 @@ export default function projectManagerShimMiddleware(
|
||||
})
|
||||
try {
|
||||
switch (cliArguments[0]) {
|
||||
case '--filesystem-exists': {
|
||||
const directoryPath = cliArguments[1]
|
||||
if (directoryPath != null) {
|
||||
const exists = await fs
|
||||
.access(directoryPath)
|
||||
.then(() => true)
|
||||
.catch(() => false)
|
||||
result = toJSONRPCResult({ exists })
|
||||
}
|
||||
break
|
||||
}
|
||||
case '--filesystem-list': {
|
||||
const directoryPath = cliArguments[1]
|
||||
if (directoryPath != null) {
|
||||
|
@ -17,6 +17,7 @@ object Cli {
|
||||
val PROJECTS_DIRECTORY = "projects-directory"
|
||||
val PROJECT_LIST = "project-list"
|
||||
|
||||
val FILESYSTEM_EXISTS = "filesystem-exists"
|
||||
val FILESYSTEM_LIST = "filesystem-list"
|
||||
val FILESYSTEM_CREATE_DIRECTORY = "filesystem-create-directory"
|
||||
val FILESYSTEM_DELETE = "filesystem-delete"
|
||||
@ -90,6 +91,14 @@ object Cli {
|
||||
.desc("List user projects.")
|
||||
.build()
|
||||
|
||||
val filesystemExists: cli.Option = cli.Option.builder
|
||||
.hasArg(true)
|
||||
.numberOfArgs(1)
|
||||
.argName("path")
|
||||
.longOpt(FILESYSTEM_EXISTS)
|
||||
.desc("Check if a file or directory exists.")
|
||||
.build()
|
||||
|
||||
val filesystemList: cli.Option = cli.Option.builder
|
||||
.hasArg(true)
|
||||
.numberOfArgs(1)
|
||||
@ -150,6 +159,7 @@ object Cli {
|
||||
.addOption(option.profilingTime)
|
||||
.addOption(option.projectsDirectory)
|
||||
.addOption(option.projectList)
|
||||
.addOption(option.filesystemExists)
|
||||
.addOption(option.filesystemList)
|
||||
.addOption(option.filesystemCreateDirectory)
|
||||
.addOption(option.filesystemDelete)
|
||||
|
@ -12,6 +12,7 @@ import org.enso.projectmanager.boot.Globals.{
|
||||
import org.enso.projectmanager.boot.command.filesystem.{
|
||||
FileSystemCreateDirectoryCommand,
|
||||
FileSystemDeleteCommand,
|
||||
FileSystemExistsCommand,
|
||||
FileSystemListCommand,
|
||||
FileSystemMoveDirectoryCommand,
|
||||
FileSystemWritePathCommand
|
||||
@ -218,6 +219,11 @@ object ProjectManager extends ZIOAppDefault with LazyLogging {
|
||||
ZIO.succeed(SuccessExitCode)
|
||||
} else if (options.hasOption(Cli.VERSION_OPTION)) {
|
||||
displayVersion(options.hasOption(Cli.JSON_OPTION))
|
||||
} else if (options.hasOption(Cli.FILESYSTEM_EXISTS)) {
|
||||
val path = Paths.get(options.getOptionValue(Cli.FILESYSTEM_EXISTS))
|
||||
val fileSystemExistsCommand =
|
||||
FileSystemExistsCommand[ZIO[ZAny, +*, +*]](config, path.toFile)
|
||||
commandHandler.printJson(fileSystemExistsCommand.run)
|
||||
} else if (options.hasOption(Cli.FILESYSTEM_LIST)) {
|
||||
val directory = Paths.get(options.getOptionValue(Cli.FILESYSTEM_LIST))
|
||||
val fileSystemListCommand =
|
||||
|
@ -0,0 +1,51 @@
|
||||
package org.enso.projectmanager.boot.command.filesystem
|
||||
|
||||
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.file.BlockingFileSystem
|
||||
import org.enso.projectmanager.infrastructure.random.SystemGenerator
|
||||
import org.enso.projectmanager.infrastructure.repository.ProjectFileRepositoryFactory
|
||||
import org.enso.projectmanager.infrastructure.time.RealClock
|
||||
import org.enso.projectmanager.protocol.FileSystemManagementApi.FileSystemExists
|
||||
import org.enso.projectmanager.service.filesystem.{
|
||||
FileSystemService,
|
||||
FileSystemServiceApi,
|
||||
FileSystemServiceFailure
|
||||
}
|
||||
|
||||
import java.io.File
|
||||
|
||||
final class FileSystemExistsCommand[
|
||||
F[+_, +_]: CovariantFlatMap
|
||||
](service: FileSystemServiceApi[F], path: File) {
|
||||
|
||||
def run: F[FileSystemServiceFailure, FileSystemExists.Result] =
|
||||
service
|
||||
.exists(path)
|
||||
.map(FileSystemExists.Result)
|
||||
}
|
||||
|
||||
object FileSystemExistsCommand {
|
||||
|
||||
def apply[F[+_, +_]: Applicative: CovariantFlatMap: ErrorChannel: Sync](
|
||||
config: ProjectManagerConfig,
|
||||
path: File
|
||||
): FileSystemExistsCommand[F] = {
|
||||
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 service = new FileSystemService[F](fileSystem, projectRepositoryFactory)
|
||||
|
||||
new FileSystemExistsCommand[F](service, path)
|
||||
}
|
||||
|
||||
}
|
@ -24,6 +24,23 @@ object FileSystemManagementApi {
|
||||
}
|
||||
}
|
||||
|
||||
case object FileSystemExists extends Method("filesystem/exists") {
|
||||
|
||||
case class Params(path: File)
|
||||
|
||||
case class Result(exists: Boolean)
|
||||
|
||||
implicit val hasParams: HasParams.Aux[this.type, FileSystemExists.Params] =
|
||||
new HasParams[this.type] {
|
||||
type Params = FileSystemExists.Params
|
||||
}
|
||||
|
||||
implicit val hasResult: HasResult.Aux[this.type, FileSystemExists.Result] =
|
||||
new HasResult[this.type] {
|
||||
type Result = FileSystemExists.Result
|
||||
}
|
||||
}
|
||||
|
||||
case object FileSystemCreateDirectory
|
||||
extends Method("filesystem/createDirectory") {
|
||||
|
||||
|
@ -38,6 +38,7 @@ object JsonRpc {
|
||||
.registerRequest(ConfigDelete)
|
||||
.registerRequest(LoggingServiceGetEndpoint)
|
||||
.registerRequest(FileSystemList)
|
||||
.registerRequest(FileSystemExists)
|
||||
.registerRequest(FileSystemCreateDirectory)
|
||||
.registerRequest(FileSystemDeleteDirectory)
|
||||
.registerRequest(FileSystemMoveDirectory)
|
||||
|
@ -21,6 +21,14 @@ class FileSystemService[F[+_, +_]: Applicative: CovariantFlatMap: ErrorChannel](
|
||||
projectRepositoryFactory: ProjectRepositoryFactory[F]
|
||||
) extends FileSystemServiceApi[F] {
|
||||
|
||||
/** @inheritdoc */
|
||||
override def exists(path: File): F[FileSystemServiceFailure, Boolean] =
|
||||
fileSystem
|
||||
.exists(path)
|
||||
.mapError(_ =>
|
||||
FileSystemServiceFailure.FileSystem("Failed to check if path exists")
|
||||
)
|
||||
|
||||
/** @inheritdoc */
|
||||
override def list(
|
||||
path: File
|
||||
|
@ -4,6 +4,13 @@ import java.io.{File, InputStream}
|
||||
|
||||
trait FileSystemServiceApi[F[+_, +_]] {
|
||||
|
||||
/** Checks if the file or directory exists.
|
||||
*
|
||||
* @param path the file or directory to check
|
||||
* @return true if the file or directory exists, false otherwise
|
||||
*/
|
||||
def exists(path: File): F[FileSystemServiceFailure, Boolean]
|
||||
|
||||
/** List file system entries in the provided directory
|
||||
*
|
||||
* @param path the directory to list
|
||||
|
@ -204,5 +204,29 @@ class FileSystemServiceSpec
|
||||
FileUtils.deleteQuietly(filePath)
|
||||
}
|
||||
|
||||
"check existence of a path" in {
|
||||
implicit val client: WsTestClient = new WsTestClient(address)
|
||||
|
||||
val testDir = testStorageConfig.userProjectsPath
|
||||
|
||||
val projectName = "New_Project_1"
|
||||
createProject(projectName)
|
||||
|
||||
val testFile = new File(testDir, "foo.txt")
|
||||
val dummyFile = new File(testDir, "foo.exe")
|
||||
|
||||
Files.createFile(testFile.toPath)
|
||||
|
||||
val result1 = fileSystemService
|
||||
.exists(testFile)
|
||||
.unsafeRunSync()
|
||||
result1.value should be(true)
|
||||
|
||||
val result2 = fileSystemService
|
||||
.exists(dummyFile)
|
||||
.unsafeRunSync()
|
||||
result2.value should be(false)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user