Skip to content

Adds files.getInfo / files.get_info methods to retrieve information about directory/files #724

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

Open
wants to merge 15 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/proud-ants-flash.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
'@e2b/python-sdk': patch
'e2b': patch
---

added getInfo/get_info method for file information
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ generate-js:
cd spec/envd && buf generate --template buf-js.gen.yaml

generate-python:
if [ ! -f "/go/bin/protoc-gen-connect-python" ]; then \
if [ ! -f "$(GOPATH)/bin/protoc-gen-connect-python" ]; then \
$(MAKE) -C packages/connect-python build; \
fi
cd packages/python-sdk && make generate-api
Expand Down
109 changes: 109 additions & 0 deletions apps/web/src/app/(docs)/docs/filesystem/info/page.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
# Get information about a file or directory

You can get information about a file or directory using the `files.getInfo()` / `files.get_info()` methods. Information such as file name, type, and path is returned.

### Getting information about a file

<CodeGroup>
```js
import { Sandbox } from '@e2b/code-interpreter'

const sandbox = await Sandbox.create()

// Create a new file
await sandbox.files.write('test_file.txt', 'Hello, world!')

// Get information about the file
const info = await sandbox.files.getInfo('test_file.txt')

console.log(info)
// {
// name: 'test_file.txt',
// type: 'file',
// path: '/home/user/test_file.txt',
// size: 13,
// mode: 0o644,
// permissions: '-rw-r--r--',
// owner: 'user',
// group: 'user',
// modifiedTime: '2025-05-26T12:00:00.000Z'
// }
```
```python
from e2b_code_interpreter import Sandbox

sandbox = Sandbox()

# Create a new file
sandbox.files.write('test_file', 'Hello, world!')

# Get information about the file
info = sandbox.files.get_info('test_file')

print(info)
# EntryInfo(
# name='test_file.txt',
# type=<FileType.FILE: 'file'>,
# path='/home/user/test_file.txt',
# size=13,
# mode=0o644,
# permissions='-rw-r--r--',
# owner='user',
# group='user',
# modified_time='2025-05-26T12:00:00.000Z'
# )
```
</CodeGroup>

### Getting information about a directory

<CodeGroup>
```js
import { Sandbox } from '@e2b/code-interpreter'

const sandbox = await Sandbox.create()

// Create a new directory
await sandbox.files.makeDir('test_dir')

// Get information about the directory
const info = await sandbox.files.getInfo('test_dir')

console.log(info)
// {
// name: 'test_dir',
// type: 'dir',
// path: '/home/user/test_dir',
// size: 0,
// mode: 0o755,
// permissions: 'drwxr-xr-x',
// owner: 'user',
// group: 'user',
// modifiedTime: '2025-05-26T12:00:00.000Z'
// }
```
```python
from e2b_code_interpreter import Sandbox

sandbox = Sandbox()

# Create a new directory
sandbox.files.make_dir('test_dir')

# Get information about the directory
info = sandbox.files.get_info('test_dir')

print(info)
# EntryInfo(
# name='test_dir',
# type=<FileType.DIR: 'dir'>,
# path='/home/user/test_dir',
# size=0,
# mode=0o755,
# permissions='drwxr-xr-x',
# owner='user',
# group='user',
# modified_time='2025-05-26T12:00:00.000Z'
# )
```
</CodeGroup>
12 changes: 11 additions & 1 deletion apps/web/src/components/Navigation/routes.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,10 @@
import { Braces, CheckCircle, Home, KeyRound, MessagesSquare } from 'lucide-react'
import {
Braces,
CheckCircle,
Home,
KeyRound,
MessagesSquare,
} from 'lucide-react'
import sdkRefRoutesJson from './sdkRefRoutes.json'

enum Tag {
Expand Down Expand Up @@ -353,6 +359,10 @@ export const docRoutes: NavGroup[] = [
title: 'Read & write',
href: '/docs/filesystem/read-write',
},
{
title: 'Get info about a file or directory',
href: '/docs/filesystem/info',
},
{
title: 'Watch directory for changes',
href: '/docs/filesystem/watch',
Expand Down
36 changes: 34 additions & 2 deletions packages/js-sdk/src/envd/filesystem/filesystem_pb.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
// @generated by protoc-gen-es v2.2.2 with parameter "target=ts"
// @generated by protoc-gen-es v2.4.0 with parameter "target=ts"
// @generated from file filesystem/filesystem.proto (package filesystem, syntax proto3)
/* eslint-disable */

import type { GenEnum, GenFile, GenMessage, GenService } from "@bufbuild/protobuf/codegenv1";
import { enumDesc, fileDesc, messageDesc, serviceDesc } from "@bufbuild/protobuf/codegenv1";
import type { Timestamp } from "@bufbuild/protobuf/wkt";
import { file_google_protobuf_timestamp } from "@bufbuild/protobuf/wkt";
import type { Message } from "@bufbuild/protobuf";

/**
* Describes the file filesystem/filesystem.proto.
*/
export const file_filesystem_filesystem: GenFile = /*@__PURE__*/
fileDesc("ChtmaWxlc3lzdGVtL2ZpbGVzeXN0ZW0ucHJvdG8SCmZpbGVzeXN0ZW0iMgoLTW92ZVJlcXVlc3QSDgoGc291cmNlGAEgASgJEhMKC2Rlc3RpbmF0aW9uGAIgASgJIjQKDE1vdmVSZXNwb25zZRIkCgVlbnRyeRgBIAEoCzIVLmZpbGVzeXN0ZW0uRW50cnlJbmZvIh4KDk1ha2VEaXJSZXF1ZXN0EgwKBHBhdGgYASABKAkiNwoPTWFrZURpclJlc3BvbnNlEiQKBWVudHJ5GAEgASgLMhUuZmlsZXN5c3RlbS5FbnRyeUluZm8iHQoNUmVtb3ZlUmVxdWVzdBIMCgRwYXRoGAEgASgJIhAKDlJlbW92ZVJlc3BvbnNlIhsKC1N0YXRSZXF1ZXN0EgwKBHBhdGgYASABKAkiNAoMU3RhdFJlc3BvbnNlEiQKBWVudHJ5GAEgASgLMhUuZmlsZXN5c3RlbS5FbnRyeUluZm8iSwoJRW50cnlJbmZvEgwKBG5hbWUYASABKAkSIgoEdHlwZRgCIAEoDjIULmZpbGVzeXN0ZW0uRmlsZVR5cGUSDAoEcGF0aBgDIAEoCSItCg5MaXN0RGlyUmVxdWVzdBIMCgRwYXRoGAEgASgJEg0KBWRlcHRoGAIgASgNIjkKD0xpc3REaXJSZXNwb25zZRImCgdlbnRyaWVzGAEgAygLMhUuZmlsZXN5c3RlbS5FbnRyeUluZm8iMgoPV2F0Y2hEaXJSZXF1ZXN0EgwKBHBhdGgYASABKAkSEQoJcmVjdXJzaXZlGAIgASgIIkQKD0ZpbGVzeXN0ZW1FdmVudBIMCgRuYW1lGAEgASgJEiMKBHR5cGUYAiABKA4yFS5maWxlc3lzdGVtLkV2ZW50VHlwZSLgAQoQV2F0Y2hEaXJSZXNwb25zZRI4CgVzdGFydBgBIAEoCzInLmZpbGVzeXN0ZW0uV2F0Y2hEaXJSZXNwb25zZS5TdGFydEV2ZW50SAASMQoKZmlsZXN5c3RlbRgCIAEoCzIbLmZpbGVzeXN0ZW0uRmlsZXN5c3RlbUV2ZW50SAASOwoJa2VlcGFsaXZlGAMgASgLMiYuZmlsZXN5c3RlbS5XYXRjaERpclJlc3BvbnNlLktlZXBBbGl2ZUgAGgwKClN0YXJ0RXZlbnQaCwoJS2VlcEFsaXZlQgcKBWV2ZW50IjcKFENyZWF0ZVdhdGNoZXJSZXF1ZXN0EgwKBHBhdGgYASABKAkSEQoJcmVjdXJzaXZlGAIgASgIIisKFUNyZWF0ZVdhdGNoZXJSZXNwb25zZRISCgp3YXRjaGVyX2lkGAEgASgJIi0KF0dldFdhdGNoZXJFdmVudHNSZXF1ZXN0EhIKCndhdGNoZXJfaWQYASABKAkiRwoYR2V0V2F0Y2hlckV2ZW50c1Jlc3BvbnNlEisKBmV2ZW50cxgBIAMoCzIbLmZpbGVzeXN0ZW0uRmlsZXN5c3RlbUV2ZW50IioKFFJlbW92ZVdhdGNoZXJSZXF1ZXN0EhIKCndhdGNoZXJfaWQYASABKAkiFwoVUmVtb3ZlV2F0Y2hlclJlc3BvbnNlKlIKCEZpbGVUeXBlEhkKFUZJTEVfVFlQRV9VTlNQRUNJRklFRBAAEhIKDkZJTEVfVFlQRV9GSUxFEAESFwoTRklMRV9UWVBFX0RJUkVDVE9SWRACKpgBCglFdmVudFR5cGUSGgoWRVZFTlRfVFlQRV9VTlNQRUNJRklFRBAAEhUKEUVWRU5UX1RZUEVfQ1JFQVRFEAESFAoQRVZFTlRfVFlQRV9XUklURRACEhUKEUVWRU5UX1RZUEVfUkVNT1ZFEAMSFQoRRVZFTlRfVFlQRV9SRU5BTUUQBBIUChBFVkVOVF9UWVBFX0NITU9EEAUynwUKCkZpbGVzeXN0ZW0SOQoEU3RhdBIXLmZpbGVzeXN0ZW0uU3RhdFJlcXVlc3QaGC5maWxlc3lzdGVtLlN0YXRSZXNwb25zZRJCCgdNYWtlRGlyEhouZmlsZXN5c3RlbS5NYWtlRGlyUmVxdWVzdBobLmZpbGVzeXN0ZW0uTWFrZURpclJlc3BvbnNlEjkKBE1vdmUSFy5maWxlc3lzdGVtLk1vdmVSZXF1ZXN0GhguZmlsZXN5c3RlbS5Nb3ZlUmVzcG9uc2USQgoHTGlzdERpchIaLmZpbGVzeXN0ZW0uTGlzdERpclJlcXVlc3QaGy5maWxlc3lzdGVtLkxpc3REaXJSZXNwb25zZRI/CgZSZW1vdmUSGS5maWxlc3lzdGVtLlJlbW92ZVJlcXVlc3QaGi5maWxlc3lzdGVtLlJlbW92ZVJlc3BvbnNlEkcKCFdhdGNoRGlyEhsuZmlsZXN5c3RlbS5XYXRjaERpclJlcXVlc3QaHC5maWxlc3lzdGVtLldhdGNoRGlyUmVzcG9uc2UwARJUCg1DcmVhdGVXYXRjaGVyEiAuZmlsZXN5c3RlbS5DcmVhdGVXYXRjaGVyUmVxdWVzdBohLmZpbGVzeXN0ZW0uQ3JlYXRlV2F0Y2hlclJlc3BvbnNlEl0KEEdldFdhdGNoZXJFdmVudHMSIy5maWxlc3lzdGVtLkdldFdhdGNoZXJFdmVudHNSZXF1ZXN0GiQuZmlsZXN5c3RlbS5HZXRXYXRjaGVyRXZlbnRzUmVzcG9uc2USVAoNUmVtb3ZlV2F0Y2hlchIgLmZpbGVzeXN0ZW0uUmVtb3ZlV2F0Y2hlclJlcXVlc3QaIS5maWxlc3lzdGVtLlJlbW92ZVdhdGNoZXJSZXNwb25zZUJpCg5jb20uZmlsZXN5c3RlbUIPRmlsZXN5c3RlbVByb3RvUAGiAgNGWFiqAgpGaWxlc3lzdGVtygIKRmlsZXN5c3RlbeICFkZpbGVzeXN0ZW1cR1BCTWV0YWRhdGHqAgpGaWxlc3lzdGVtYgZwcm90bzM");
fileDesc("ChtmaWxlc3lzdGVtL2ZpbGVzeXN0ZW0ucHJvdG8SCmZpbGVzeXN0ZW0iMgoLTW92ZVJlcXVlc3QSDgoGc291cmNlGAEgASgJEhMKC2Rlc3RpbmF0aW9uGAIgASgJIjQKDE1vdmVSZXNwb25zZRIkCgVlbnRyeRgBIAEoCzIVLmZpbGVzeXN0ZW0uRW50cnlJbmZvIh4KDk1ha2VEaXJSZXF1ZXN0EgwKBHBhdGgYASABKAkiNwoPTWFrZURpclJlc3BvbnNlEiQKBWVudHJ5GAEgASgLMhUuZmlsZXN5c3RlbS5FbnRyeUluZm8iHQoNUmVtb3ZlUmVxdWVzdBIMCgRwYXRoGAEgASgJIhAKDlJlbW92ZVJlc3BvbnNlIhsKC1N0YXRSZXF1ZXN0EgwKBHBhdGgYASABKAkiNAoMU3RhdFJlc3BvbnNlEiQKBWVudHJ5GAEgASgLMhUuZmlsZXN5c3RlbS5FbnRyeUluZm8izQEKCUVudHJ5SW5mbxIMCgRuYW1lGAEgASgJEiIKBHR5cGUYAiABKA4yFC5maWxlc3lzdGVtLkZpbGVUeXBlEgwKBHBhdGgYAyABKAkSDAoEc2l6ZRgEIAEoAxIMCgRtb2RlGAUgASgNEhMKC3Blcm1pc3Npb25zGAYgASgJEg0KBW93bmVyGAcgASgJEg0KBWdyb3VwGAggASgJEjEKDW1vZGlmaWVkX3RpbWUYCSABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wIi0KDkxpc3REaXJSZXF1ZXN0EgwKBHBhdGgYASABKAkSDQoFZGVwdGgYAiABKA0iOQoPTGlzdERpclJlc3BvbnNlEiYKB2VudHJpZXMYASADKAsyFS5maWxlc3lzdGVtLkVudHJ5SW5mbyIyCg9XYXRjaERpclJlcXVlc3QSDAoEcGF0aBgBIAEoCRIRCglyZWN1cnNpdmUYAiABKAgiRAoPRmlsZXN5c3RlbUV2ZW50EgwKBG5hbWUYASABKAkSIwoEdHlwZRgCIAEoDjIVLmZpbGVzeXN0ZW0uRXZlbnRUeXBlIuABChBXYXRjaERpclJlc3BvbnNlEjgKBXN0YXJ0GAEgASgLMicuZmlsZXN5c3RlbS5XYXRjaERpclJlc3BvbnNlLlN0YXJ0RXZlbnRIABIxCgpmaWxlc3lzdGVtGAIgASgLMhsuZmlsZXN5c3RlbS5GaWxlc3lzdGVtRXZlbnRIABI7CglrZWVwYWxpdmUYAyABKAsyJi5maWxlc3lzdGVtLldhdGNoRGlyUmVzcG9uc2UuS2VlcEFsaXZlSAAaDAoKU3RhcnRFdmVudBoLCglLZWVwQWxpdmVCBwoFZXZlbnQiNwoUQ3JlYXRlV2F0Y2hlclJlcXVlc3QSDAoEcGF0aBgBIAEoCRIRCglyZWN1cnNpdmUYAiABKAgiKwoVQ3JlYXRlV2F0Y2hlclJlc3BvbnNlEhIKCndhdGNoZXJfaWQYASABKAkiLQoXR2V0V2F0Y2hlckV2ZW50c1JlcXVlc3QSEgoKd2F0Y2hlcl9pZBgBIAEoCSJHChhHZXRXYXRjaGVyRXZlbnRzUmVzcG9uc2USKwoGZXZlbnRzGAEgAygLMhsuZmlsZXN5c3RlbS5GaWxlc3lzdGVtRXZlbnQiKgoUUmVtb3ZlV2F0Y2hlclJlcXVlc3QSEgoKd2F0Y2hlcl9pZBgBIAEoCSIXChVSZW1vdmVXYXRjaGVyUmVzcG9uc2UqUgoIRmlsZVR5cGUSGQoVRklMRV9UWVBFX1VOU1BFQ0lGSUVEEAASEgoORklMRV9UWVBFX0ZJTEUQARIXChNGSUxFX1RZUEVfRElSRUNUT1JZEAIqmAEKCUV2ZW50VHlwZRIaChZFVkVOVF9UWVBFX1VOU1BFQ0lGSUVEEAASFQoRRVZFTlRfVFlQRV9DUkVBVEUQARIUChBFVkVOVF9UWVBFX1dSSVRFEAISFQoRRVZFTlRfVFlQRV9SRU1PVkUQAxIVChFFVkVOVF9UWVBFX1JFTkFNRRAEEhQKEEVWRU5UX1RZUEVfQ0hNT0QQBTKfBQoKRmlsZXN5c3RlbRI5CgRTdGF0EhcuZmlsZXN5c3RlbS5TdGF0UmVxdWVzdBoYLmZpbGVzeXN0ZW0uU3RhdFJlc3BvbnNlEkIKB01ha2VEaXISGi5maWxlc3lzdGVtLk1ha2VEaXJSZXF1ZXN0GhsuZmlsZXN5c3RlbS5NYWtlRGlyUmVzcG9uc2USOQoETW92ZRIXLmZpbGVzeXN0ZW0uTW92ZVJlcXVlc3QaGC5maWxlc3lzdGVtLk1vdmVSZXNwb25zZRJCCgdMaXN0RGlyEhouZmlsZXN5c3RlbS5MaXN0RGlyUmVxdWVzdBobLmZpbGVzeXN0ZW0uTGlzdERpclJlc3BvbnNlEj8KBlJlbW92ZRIZLmZpbGVzeXN0ZW0uUmVtb3ZlUmVxdWVzdBoaLmZpbGVzeXN0ZW0uUmVtb3ZlUmVzcG9uc2USRwoIV2F0Y2hEaXISGy5maWxlc3lzdGVtLldhdGNoRGlyUmVxdWVzdBocLmZpbGVzeXN0ZW0uV2F0Y2hEaXJSZXNwb25zZTABElQKDUNyZWF0ZVdhdGNoZXISIC5maWxlc3lzdGVtLkNyZWF0ZVdhdGNoZXJSZXF1ZXN0GiEuZmlsZXN5c3RlbS5DcmVhdGVXYXRjaGVyUmVzcG9uc2USXQoQR2V0V2F0Y2hlckV2ZW50cxIjLmZpbGVzeXN0ZW0uR2V0V2F0Y2hlckV2ZW50c1JlcXVlc3QaJC5maWxlc3lzdGVtLkdldFdhdGNoZXJFdmVudHNSZXNwb25zZRJUCg1SZW1vdmVXYXRjaGVyEiAuZmlsZXN5c3RlbS5SZW1vdmVXYXRjaGVyUmVxdWVzdBohLmZpbGVzeXN0ZW0uUmVtb3ZlV2F0Y2hlclJlc3BvbnNlQmkKDmNvbS5maWxlc3lzdGVtQg9GaWxlc3lzdGVtUHJvdG9QAaICA0ZYWKoCCkZpbGVzeXN0ZW3KAgpGaWxlc3lzdGVt4gIWRmlsZXN5c3RlbVxHUEJNZXRhZGF0YeoCCkZpbGVzeXN0ZW1iBnByb3RvMw", [file_google_protobuf_timestamp]);

/**
* @generated from message filesystem.MoveRequest
Expand Down Expand Up @@ -167,6 +169,36 @@ export type EntryInfo = Message<"filesystem.EntryInfo"> & {
* @generated from field: string path = 3;
*/
path: string;

/**
* @generated from field: int64 size = 4;
*/
size: bigint;

/**
* @generated from field: uint32 mode = 5;
*/
mode: number;

/**
* @generated from field: string permissions = 6;
*/
permissions: string;

/**
* @generated from field: string owner = 7;
*/
owner: string;

/**
* @generated from field: string group = 8;
*/
group: string;

/**
* @generated from field: google.protobuf.Timestamp modified_time = 9;
*/
modifiedTime?: Timestamp;
};

/**
Expand Down
2 changes: 1 addition & 1 deletion packages/js-sdk/src/envd/process/process_pb.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// @generated by protoc-gen-es v2.2.2 with parameter "target=ts"
// @generated by protoc-gen-es v2.4.0 with parameter "target=ts"
// @generated from file process/process.proto (package process, syntax proto3)
/* eslint-disable */

Expand Down
95 changes: 93 additions & 2 deletions packages/js-sdk/src/sandbox/filesystem/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import { FilesystemEvent, WatchHandle } from './watchHandle'
import { compareVersions } from 'compare-versions'
import { InvalidArgumentError, TemplateError } from '../../errors'
import { ENVD_VERSION_RECURSIVE_WATCH } from '../../envd/versions'
import type { Timestamp } from '@bufbuild/protobuf/wkt'

/**
* Sandbox filesystem object information.
Expand All @@ -47,6 +48,38 @@ export interface EntryInfo {
path: string
}

export interface EntryInfoExtended extends EntryInfo {
/**
* Size of the filesystem object in bytes.
*/
size: number

/**
* File mode and permission bits.
*/
mode: number

/**
* String representation of file permissions (e.g. 'rwxr-xr-x').
*/
permissions: string

/**
* Owner of the filesystem object.
*/
owner: string

/**
* Group owner of the filesystem object.
*/
group: string

/**
* Last modification time of the filesystem object.
*/
modifiedTime?: Date
}

/**
* Sandbox filesystem object type.
*/
Expand Down Expand Up @@ -75,6 +108,15 @@ function mapFileType(fileType: FsFileType) {
}
}

function mapModifiedTime(modifiedTime: Timestamp | undefined) {
if (!modifiedTime) return undefined

return new Date(
Number(modifiedTime.seconds) * 1000 +
Math.floor(modifiedTime.nanos / 1_000_000)
)
}

/**
* Options for the sandbox filesystem operations.
*/
Expand Down Expand Up @@ -346,7 +388,10 @@ export class Filesystem {
*
* @returns list of entries in the sandbox filesystem directory.
*/
async list(path: string, opts?: FilesystemListOpts): Promise<EntryInfo[]> {
async list(
path: string,
opts?: FilesystemListOpts
): Promise<EntryInfoExtended[]> {
if (typeof opts?.depth === 'number' && opts.depth < 1) {
throw new InvalidArgumentError('depth should be at least one')
}
Expand All @@ -363,7 +408,7 @@ export class Filesystem {
}
)

const entries: EntryInfo[] = []
const entries: EntryInfoExtended[] = []

for (const e of res.entries) {
const type = mapFileType(e.type)
Expand All @@ -373,6 +418,12 @@ export class Filesystem {
name: e.name,
type,
path: e.path,
size: Number(e.size),
mode: e.mode,
permissions: e.permissions,
owner: e.owner,
group: e.group,
modifiedTime: mapModifiedTime(e.modifiedTime),
})
}
}
Expand Down Expand Up @@ -504,6 +555,46 @@ export class Filesystem {
}
}

/**
* Get information about a file or directory.
*
* @param path path to a file or directory.
* @param opts connection options.
*
* @returns information about the file or directory like name, type, and path.
*/
async getInfo(
path: string,
opts?: FilesystemRequestOpts
): Promise<EntryInfoExtended> {
try {
const res = await this.rpc.stat(
{ path },
{ headers: authenticationHeader(opts?.user) }
)

if (!res.entry) {
throw new Error(
'Expected to receive information about the file or directory'
)
}

return {
name: res.entry.name,
type: mapFileType(res.entry.type),
path: res.entry.path,
size: Number(res.entry.size),
mode: res.entry.mode,
permissions: res.entry.permissions,
owner: res.entry.owner,
group: res.entry.group,
modifiedTime: mapModifiedTime(res.entry.modifiedTime),
}
} catch (err) {
throw handleRpcError(err)
}
}

/**
* Start watching a directory for filesystem events.
*
Expand Down
Loading
Loading