Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Project manager API for basic file system operations #9245

Merged
merged 12 commits into from
Mar 8, 2024
151 changes: 151 additions & 0 deletions docs/language-server/protocol-project-manager.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,14 @@ transport formats, please look [here](./protocol-architecture.md).
- [`ProgressUnit`](#progressunit)
- [`EngineVersion`](#engineversion)
- [`RunningState`](#runningstate)
- [`FileSystemEntry`](#filesystementry)
- [`Attributes`](#attributes)
- [`UTCDateTime`](#utcdatetime)
- [File System Management Operations](#file-system-management-operations)
- [List Directories](#list-directories)
- [Create Directory](#create-directory)
- [Delete Directory](#delete-directory)
- [Move File Or Directory](#move-file-or-directory)
- [Project Management Operations](#project-management-operations)
- [`project/open`](#projectopen)
- [`project/close`](#projectclose)
Expand Down Expand Up @@ -187,6 +195,149 @@ interface RunningStatus {
}
```

### `FileSystemEntry`

A directory entry in the fileystem operations.

#### Format

```typescript
type FileSystemEntry = FileEntry | DirectoryEntry | ProjectEntry;

interface FileEntry {
path: string;
attributes: Attributes;
}

interface DirectoryEntry {
path: string;
attributes: Attributes;
}

interface ProjectEntry {
path: string;
attributes: Attributes;
metadata: ProjectMetadata;
}
```

### `Attributes`

Basic attributes of a filesystem entry.

#### Format

```typescript
interface Attributes {
creationTime: UTCDateTime;
lastAccessTime: UTCDateTime;
lastModifiedTime: UTCDateTime;
byteSize: number;
}
```

### `UTCDateTime`

Time in UTC time zone represented as ISO-8601 string.

#### Format

```typescript
type UTCDateTime = string;
```

## File System Management Operations

The project-manager binary provides Cli interface to do basic filesystem
operations.

### List Directories

List directory returning information about filesystem entries together with the
project metadata if the listed directory contains a project.

#### Parameters

```typescript
project-manager --filesystem-list {path}
```

#### Result

```typescript
{
entries: FileSystemEntry[];
}
```

#### Errors

- [`ProjectDataStoreError`](#projectdatastoreerror) to signal problems with
underlying data store.

### Create Directory

Create directory with the specified path.

#### Parameters

```typescript
project-manager --filesystem-create-directory {path}
```

### Result

```typescript
null;
```

#### Errors

- [`ProjectDataStoreError`](#projectdatastoreerror) to signal problems with
underlying data store.

### Delete Directory

Deletes directory with the specified path.

#### Parameters

```typescript
project-manager --filesystem-delete-directory {path}
```

### Result

```typescript
null;
```

#### Errors

- [`ProjectDataStoreError`](#projectdatastoreerror) to signal problems with
underlying data store.

### Move File Or Directory

Moves file or directory from target path to the destination path.

#### Parameters

```typescript
project-manager --filesystem-move-from {path} --filesystem-move-to {path}
```

### Result

```typescript
null;
```

#### Errors

- [`ProjectDataStoreError`](#projectdatastoreerror) to signal problems with
underlying data store.

## Project Management Operations

The primary responsibility of the project managers is to allow users to manage
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@ object Cli {
val PROJECTS_DIRECTORY = "projects-directory"
val PROJECT_LIST = "project-list"

val FILESYSTEM_LIST = "filesystem-list"
val FILESYSTEM_CREATE_DIRECTORY = "filesystem-create-directory"
val FILESYSTEM_DELETE_DIRECTORY = "filesystem-delete-directory"
val FILESYSTEM_MOVE_FROM = "filesystem-move-from"
val FILESYSTEM_MOVE_TO = "filesystem-move-to"

object option {

val help: cli.Option = cli.Option
Expand Down Expand Up @@ -82,6 +88,46 @@ object Cli {
.longOpt(PROJECT_LIST)
.desc("List user projects.")
.build()

val filesystemList: cli.Option = cli.Option.builder
.hasArg(true)
.numberOfArgs(1)
.argName("path")
.longOpt(FILESYSTEM_LIST)
.desc("List directory.")
.build()

val filesystemCreateDirectory: cli.Option = cli.Option.builder
.hasArg(true)
.numberOfArgs(1)
.argName("path")
.longOpt(FILESYSTEM_CREATE_DIRECTORY)
.desc("Create directory.")
.build()

val filesystemDeleteDirectory: cli.Option = cli.Option.builder
.hasArg(true)
.numberOfArgs(1)
.argName("path")
.longOpt(FILESYSTEM_DELETE_DIRECTORY)
.desc("Delete directory.")
.build()

val filesystemMoveFrom: cli.Option = cli.Option.builder
.hasArg(true)
.numberOfArgs(1)
.argName("path")
.longOpt(FILESYSTEM_MOVE_FROM)
.desc("Move directory. Target.")
.build()

val filesystemMoveTo: cli.Option = cli.Option.builder
.hasArg(true)
.numberOfArgs(1)
.argName("path")
.longOpt(FILESYSTEM_MOVE_TO)
.desc("Move directory. Destination.")
.build()
}

val options: cli.Options =
Expand All @@ -95,6 +141,11 @@ object Cli {
.addOption(option.profilingTime)
.addOption(option.projectsDirectory)
.addOption(option.projectList)
.addOption(option.filesystemList)
.addOption(option.filesystemCreateDirectory)
.addOption(option.filesystemDeleteDirectory)
.addOption(option.filesystemMoveFrom)
.addOption(option.filesystemMoveTo)

/** Parse the command line options. */
def parse(args: Array[String]): Either[String, cli.CommandLine] = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,12 @@ import org.enso.projectmanager.boot.Globals.{
FailureExitCode,
SuccessExitCode
}
import org.enso.projectmanager.boot.command.filesystem.{
FileSystemCreateDirectoryCommand,
FileSystemDeleteDirectoryCommand,
FileSystemListCommand,
FileSystemMoveDirectoryCommand
}
import org.enso.projectmanager.boot.command.{CommandHandler, ProjectListCommand}
import org.enso.projectmanager.boot.configuration.{
MainProcessConfig,
Expand Down Expand Up @@ -209,6 +215,39 @@ 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_LIST)) {
val directory = Paths.get(options.getOptionValue(Cli.FILESYSTEM_LIST))
val fileSystemListCommand =
FileSystemListCommand[ZIO[ZAny, +*, +*]](config, directory.toFile)
commandHandler.printJson(fileSystemListCommand.run)
} else if (options.hasOption(Cli.FILESYSTEM_CREATE_DIRECTORY)) {
val directory =
Paths.get(options.getOptionValue(Cli.FILESYSTEM_CREATE_DIRECTORY))
val fileSystemCreateDirectoryCommand =
FileSystemCreateDirectoryCommand[ZIO[ZAny, +*, +*]](
config,
directory.toFile
)
commandHandler.printJson(fileSystemCreateDirectoryCommand.run)
} else if (options.hasOption(Cli.FILESYSTEM_DELETE_DIRECTORY)) {
val directory =
Paths.get(options.getOptionValue(Cli.FILESYSTEM_DELETE_DIRECTORY))
val fileSystemDeleteDirectoryCommand =
FileSystemDeleteDirectoryCommand[ZIO[ZAny, +*, +*]](
config,
directory.toFile
)
commandHandler.printJson(fileSystemDeleteDirectoryCommand.run)
} else if (options.hasOption(Cli.FILESYSTEM_MOVE_FROM)) {
val from = Paths.get(options.getOptionValue(Cli.FILESYSTEM_MOVE_FROM))
val to = Paths.get(options.getOptionValue(Cli.FILESYSTEM_MOVE_TO))
val fileSystemMoveDirectoryCommand =
FileSystemMoveDirectoryCommand[ZIO[ZAny, +*, +*]](
config,
from.toFile,
to.toFile
)
commandHandler.printJson(fileSystemMoveDirectoryCommand.run)
} else if (options.hasOption(Cli.PROJECT_LIST)) {
val projectsPathOpt =
Option(options.getOptionValue(Cli.PROJECTS_DIRECTORY))
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package org.enso.projectmanager.boot.command.filesystem

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.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.FileSystemCreateDirectory
import org.enso.projectmanager.service.filesystem.{
FileSystemService,
FileSystemServiceApi,
FileSystemServiceFailure
}

import java.io.File

final class FileSystemCreateDirectoryCommand[F[+_, +_]: CovariantFlatMap](
service: FileSystemServiceApi[F],
path: File
) {

def run: F[FileSystemServiceFailure, FileSystemCreateDirectory.Result] =
service.createDirectory(path).map(_ => FileSystemCreateDirectory.Result)
}

object FileSystemCreateDirectoryCommand {

def apply[F[+_, +_]: Applicative: CovariantFlatMap: ErrorChannel: Sync](
config: ProjectManagerConfig,
path: File
): FileSystemCreateDirectoryCommand[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 FileSystemCreateDirectoryCommand[F](service, path)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
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.FileSystemDeleteDirectory
import org.enso.projectmanager.service.filesystem.{
FileSystemService,
FileSystemServiceApi,
FileSystemServiceFailure
}

import java.io.File

final class FileSystemDeleteDirectoryCommand[F[+_, +_]: CovariantFlatMap](
service: FileSystemServiceApi[F],
path: File
) {

def run: F[FileSystemServiceFailure, FileSystemDeleteDirectory.Result] =
service.deleteDirectory(path).map(_ => FileSystemDeleteDirectory.Result)
}

object FileSystemDeleteDirectoryCommand {

def apply[F[+_, +_]: Applicative: CovariantFlatMap: ErrorChannel: Sync](
config: ProjectManagerConfig,
path: File
): FileSystemDeleteDirectoryCommand[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 FileSystemDeleteDirectoryCommand[F](service, path)
}
}
Loading
Loading