@fnndsc/brasa 0.56.1 → 0.56.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/buildinfo.json +1 -1
- package/dist/builtins/berth/berth.d.ts +90 -3
- package/dist/builtins/berth/berth.js +129 -76
- package/dist/builtins/berth/berth.js.map +1 -1
- package/dist/builtins/berth/berthClose.d.ts +25 -6
- package/dist/builtins/berth/berthClose.js +8 -64
- package/dist/builtins/berth/berthClose.js.map +1 -1
- package/dist/builtins/berth/berthCube.d.ts +3 -2
- package/dist/builtins/berth/berthCube.js +9 -16
- package/dist/builtins/berth/berthCube.js.map +1 -1
- package/dist/builtins/berth/berthProcesses.js +33 -3
- package/dist/builtins/berth/berthProcesses.js.map +1 -1
- package/dist/builtins/debug.d.ts +24 -3
- package/dist/builtins/debug.js +66 -13
- package/dist/builtins/debug.js.map +1 -1
- package/dist/builtins/fs/acl.args.d.ts +5 -38
- package/dist/builtins/fs/acl.args.js +6 -72
- package/dist/builtins/fs/acl.args.js.map +1 -1
- package/dist/builtins/fs/acl.d.ts +100 -10
- package/dist/builtins/fs/acl.js +222 -68
- package/dist/builtins/fs/acl.js.map +1 -1
- package/dist/builtins/fs/cat.args.d.ts +14 -15
- package/dist/builtins/fs/cat.args.js +13 -40
- package/dist/builtins/fs/cat.args.js.map +1 -1
- package/dist/builtins/fs/cat.d.ts +40 -3
- package/dist/builtins/fs/cat.js +92 -13
- package/dist/builtins/fs/cat.js.map +1 -1
- package/dist/builtins/fs/cd.d.ts +24 -6
- package/dist/builtins/fs/cd.js +71 -18
- package/dist/builtins/fs/cd.js.map +1 -1
- package/dist/builtins/fs/configWrite.d.ts +24 -8
- package/dist/builtins/fs/configWrite.js +77 -36
- package/dist/builtins/fs/configWrite.js.map +1 -1
- package/dist/builtins/fs/cp.d.ts +39 -4
- package/dist/builtins/fs/cp.js +122 -56
- package/dist/builtins/fs/cp.js.map +1 -1
- package/dist/builtins/fs/download.d.ts +31 -4
- package/dist/builtins/fs/download.js +75 -38
- package/dist/builtins/fs/download.js.map +1 -1
- package/dist/builtins/fs/du.d.ts +59 -33
- package/dist/builtins/fs/du.js +111 -79
- package/dist/builtins/fs/du.js.map +1 -1
- package/dist/builtins/fs/edit.d.ts +19 -4
- package/dist/builtins/fs/edit.js +77 -16
- package/dist/builtins/fs/edit.js.map +1 -1
- package/dist/builtins/fs/find.d.ts +25 -0
- package/dist/builtins/fs/find.js +76 -5
- package/dist/builtins/fs/find.js.map +1 -1
- package/dist/builtins/fs/ls.d.ts +69 -4
- package/dist/builtins/fs/ls.js +84 -45
- package/dist/builtins/fs/ls.js.map +1 -1
- package/dist/builtins/fs/mkdir.d.ts +28 -18
- package/dist/builtins/fs/mkdir.js +95 -66
- package/dist/builtins/fs/mkdir.js.map +1 -1
- package/dist/builtins/fs/mv.d.ts +34 -4
- package/dist/builtins/fs/mv.js +129 -64
- package/dist/builtins/fs/mv.js.map +1 -1
- package/dist/builtins/fs/pull.args.d.ts +56 -17
- package/dist/builtins/fs/pull.args.js +16 -66
- package/dist/builtins/fs/pull.args.js.map +1 -1
- package/dist/builtins/fs/pull.d.ts +62 -0
- package/dist/builtins/fs/pull.js +123 -31
- package/dist/builtins/fs/pull.js.map +1 -1
- package/dist/builtins/fs/pwd.d.ts +19 -5
- package/dist/builtins/fs/pwd.js +62 -8
- package/dist/builtins/fs/pwd.js.map +1 -1
- package/dist/builtins/fs/rm.d.ts +58 -21
- package/dist/builtins/fs/rm.js +99 -82
- package/dist/builtins/fs/rm.js.map +1 -1
- package/dist/builtins/fs/rmdir.d.ts +29 -11
- package/dist/builtins/fs/rmdir.js +87 -36
- package/dist/builtins/fs/rmdir.js.map +1 -1
- package/dist/builtins/fs/touch.d.ts +44 -9
- package/dist/builtins/fs/touch.js +91 -27
- package/dist/builtins/fs/touch.js.map +1 -1
- package/dist/builtins/fs/tree.d.ts +36 -9
- package/dist/builtins/fs/tree.js +126 -36
- package/dist/builtins/fs/tree.js.map +1 -1
- package/dist/builtins/fs/upload.d.ts +22 -3
- package/dist/builtins/fs/upload.js +82 -14
- package/dist/builtins/fs/upload.js.map +1 -1
- package/dist/builtins/fs/xattr.args.d.ts +12 -33
- package/dist/builtins/fs/xattr.args.js +17 -95
- package/dist/builtins/fs/xattr.args.js.map +1 -1
- package/dist/builtins/fs/xattr.d.ts +98 -8
- package/dist/builtins/fs/xattr.js +163 -24
- package/dist/builtins/fs/xattr.js.map +1 -1
- package/dist/builtins/games/bytes.d.ts +201 -5
- package/dist/builtins/games/bytes.js +255 -54
- package/dist/builtins/games/bytes.js.map +1 -1
- package/dist/builtins/games/chimes.d.ts +180 -3
- package/dist/builtins/games/chimes.js +203 -26
- package/dist/builtins/games/chimes.js.map +1 -1
- package/dist/builtins/games/chrislab.d.ts +101 -3
- package/dist/builtins/games/chrislab.js +117 -17
- package/dist/builtins/games/chrislab.js.map +1 -1
- package/dist/builtins/games/cowsay.d.ts +93 -2
- package/dist/builtins/games/cowsay.js +90 -31
- package/dist/builtins/games/cowsay.js.map +1 -1
- package/dist/builtins/games/figlet.d.ts +70 -2
- package/dist/builtins/games/figlet.js +83 -6
- package/dist/builtins/games/figlet.js.map +1 -1
- package/dist/builtins/games/lab.d.ts +104 -5
- package/dist/builtins/games/lab.js +144 -6
- package/dist/builtins/games/lab.js.map +1 -1
- package/dist/builtins/games/lolcat.d.ts +61 -1
- package/dist/builtins/games/lolcat.js +59 -24
- package/dist/builtins/games/lolcat.js.map +1 -1
- package/dist/builtins/games/morse.d.ts +36 -1
- package/dist/builtins/games/morse.js +50 -2
- package/dist/builtins/games/morse.js.map +1 -1
- package/dist/builtins/games/numbers.d.ts +241 -5
- package/dist/builtins/games/numbers.js +298 -23
- package/dist/builtins/games/numbers.js.map +1 -1
- package/dist/builtins/games/play.d.ts +96 -6
- package/dist/builtins/games/play.js +137 -6
- package/dist/builtins/games/play.js.map +1 -1
- package/dist/builtins/games/qr.d.ts +40 -1
- package/dist/builtins/games/qr.js +51 -2
- package/dist/builtins/games/qr.js.map +1 -1
- package/dist/builtins/games/show.d.ts +131 -6
- package/dist/builtins/games/show.js +208 -20
- package/dist/builtins/games/show.js.map +1 -1
- package/dist/builtins/games/sky.d.ts +178 -4
- package/dist/builtins/games/sky.js +228 -12
- package/dist/builtins/games/sky.js.map +1 -1
- package/dist/builtins/games/text.d.ts +258 -7
- package/dist/builtins/games/text.js +310 -29
- package/dist/builtins/games/text.js.map +1 -1
- package/dist/builtins/games/trek.d.ts +67 -3
- package/dist/builtins/games/trek.js +63 -10
- package/dist/builtins/games/trek.js.map +1 -1
- package/dist/builtins/games/wtf.d.ts +58 -1
- package/dist/builtins/games/wtf.js +67 -6
- package/dist/builtins/games/wtf.js.map +1 -1
- package/dist/builtins/help.d.ts +41 -3
- package/dist/builtins/help.js +92 -796
- package/dist/builtins/help.js.map +1 -1
- package/dist/builtins/net/connect.d.ts +36 -3
- package/dist/builtins/net/connect.js +84 -26
- package/dist/builtins/net/connect.js.map +1 -1
- package/dist/builtins/net/cubepath.d.ts +49 -5
- package/dist/builtins/net/cubepath.js +69 -27
- package/dist/builtins/net/cubepath.js.map +1 -1
- package/dist/builtins/net/logout.d.ts +13 -4
- package/dist/builtins/net/logout.js +49 -3
- package/dist/builtins/net/logout.js.map +1 -1
- package/dist/builtins/net/netstat.d.ts +29 -4
- package/dist/builtins/net/netstat.js +64 -23
- package/dist/builtins/net/netstat.js.map +1 -1
- package/dist/builtins/net/pacs.d.ts +169 -15
- package/dist/builtins/net/pacs.js +92 -33
- package/dist/builtins/net/pacs.js.map +1 -1
- package/dist/builtins/net/query.args.d.ts +95 -0
- package/dist/builtins/net/query.args.js +26 -0
- package/dist/builtins/net/query.args.js.map +1 -0
- package/dist/builtins/net/query.d.ts +98 -5
- package/dist/builtins/net/query.js +89 -83
- package/dist/builtins/net/query.js.map +1 -1
- package/dist/builtins/net/status.d.ts +5 -3
- package/dist/builtins/net/status.js +5 -12
- package/dist/builtins/net/status.js.map +1 -1
- package/dist/builtins/parametersofplugin.d.ts +82 -3
- package/dist/builtins/parametersofplugin.js +79 -23
- package/dist/builtins/parametersofplugin.js.map +1 -1
- package/dist/builtins/proc.d.ts +210 -3
- package/dist/builtins/proc.js +210 -119
- package/dist/builtins/proc.js.map +1 -1
- package/dist/builtins/res/compute.d.ts +67 -3
- package/dist/builtins/res/compute.js +121 -35
- package/dist/builtins/res/compute.js.map +1 -1
- package/dist/builtins/res/dicom.d.ts +55 -7
- package/dist/builtins/res/dicom.js +86 -52
- package/dist/builtins/res/dicom.js.map +1 -1
- package/dist/builtins/res/expect.d.ts +52 -3
- package/dist/builtins/res/expect.js +92 -29
- package/dist/builtins/res/expect.js.map +1 -1
- package/dist/builtins/res/feed.d.ts +475 -3
- package/dist/builtins/res/feed.js +253 -158
- package/dist/builtins/res/feed.js.map +1 -1
- package/dist/builtins/res/files.d.ts +517 -3
- package/dist/builtins/res/files.js +124 -44
- package/dist/builtins/res/files.js.map +1 -1
- package/dist/builtins/res/gather.d.ts +113 -3
- package/dist/builtins/res/gather.js +153 -44
- package/dist/builtins/res/gather.js.map +1 -1
- package/dist/builtins/res/gather.process.d.ts +27 -19
- package/dist/builtins/res/gather.process.js +29 -59
- package/dist/builtins/res/gather.process.js.map +1 -1
- package/dist/builtins/res/group.d.ts +284 -3
- package/dist/builtins/res/group.js +147 -76
- package/dist/builtins/res/group.js.map +1 -1
- package/dist/builtins/res/image.d.ts +30 -2
- package/dist/builtins/res/image.js +62 -10
- package/dist/builtins/res/image.js.map +1 -1
- package/dist/builtins/res/play.d.ts +71 -9
- package/dist/builtins/res/play.js +124 -82
- package/dist/builtins/res/play.js.map +1 -1
- package/dist/builtins/res/plugininstance.d.ts +307 -2
- package/dist/builtins/res/plugininstance.js +122 -50
- package/dist/builtins/res/plugininstance.js.map +1 -1
- package/dist/builtins/res/pluginmeta.d.ts +244 -2
- package/dist/builtins/res/pluginmeta.js +98 -40
- package/dist/builtins/res/pluginmeta.js.map +1 -1
- package/dist/builtins/res/record.d.ts +37 -3
- package/dist/builtins/res/record.js +127 -57
- package/dist/builtins/res/record.js.map +1 -1
- package/dist/builtins/res/resourceList.d.ts +136 -0
- package/dist/builtins/res/resourceList.js +51 -0
- package/dist/builtins/res/resourceList.js.map +1 -0
- package/dist/builtins/res/tag.d.ts +244 -3
- package/dist/builtins/res/tag.js +97 -41
- package/dist/builtins/res/tag.js.map +1 -1
- package/dist/builtins/res/user.d.ts +122 -3
- package/dist/builtins/res/user.js +83 -21
- package/dist/builtins/res/user.js.map +1 -1
- package/dist/builtins/res/workflow.d.ts +244 -2
- package/dist/builtins/res/workflow.js +97 -40
- package/dist/builtins/res/workflow.js.map +1 -1
- package/dist/builtins/store.d.ts +85 -3
- package/dist/builtins/store.js +135 -68
- package/dist/builtins/store.js.map +1 -1
- package/dist/builtins/sys/apropos.d.ts +80 -5
- package/dist/builtins/sys/apropos.js +121 -15
- package/dist/builtins/sys/apropos.js.map +1 -1
- package/dist/builtins/sys/cal.d.ts +44 -5
- package/dist/builtins/sys/cal.js +57 -10
- package/dist/builtins/sys/cal.js.map +1 -1
- package/dist/builtins/sys/command.d.ts +20 -0
- package/dist/builtins/sys/command.js +31 -0
- package/dist/builtins/sys/command.js.map +1 -1
- package/dist/builtins/sys/context.d.ts +13 -3
- package/dist/builtins/sys/context.js +51 -4
- package/dist/builtins/sys/context.js.map +1 -1
- package/dist/builtins/sys/date.d.ts +56 -5
- package/dist/builtins/sys/date.js +63 -9
- package/dist/builtins/sys/date.js.map +1 -1
- package/dist/builtins/sys/echo.d.ts +63 -2
- package/dist/builtins/sys/echo.js +87 -8
- package/dist/builtins/sys/echo.js.map +1 -1
- package/dist/builtins/sys/fortune.d.ts +27 -2
- package/dist/builtins/sys/fortune.js +44 -2
- package/dist/builtins/sys/fortune.js.map +1 -1
- package/dist/builtins/sys/grep.d.ts +245 -11
- package/dist/builtins/sys/grep.js +418 -131
- package/dist/builtins/sys/grep.js.map +1 -1
- package/dist/builtins/sys/joblets.d.ts +66 -7
- package/dist/builtins/sys/joblets.js +101 -14
- package/dist/builtins/sys/joblets.js.map +1 -1
- package/dist/builtins/sys/motd.d.ts +37 -3
- package/dist/builtins/sys/motd.js +49 -8
- package/dist/builtins/sys/motd.js.map +1 -1
- package/dist/builtins/sys/notes.d.ts +75 -3
- package/dist/builtins/sys/notes.js +90 -29
- package/dist/builtins/sys/notes.js.map +1 -1
- package/dist/builtins/sys/physicalmode.d.ts +24 -3
- package/dist/builtins/sys/physicalmode.js +68 -14
- package/dist/builtins/sys/physicalmode.js.map +1 -1
- package/dist/builtins/sys/tasks.d.ts +74 -5
- package/dist/builtins/sys/tasks.js +102 -14
- package/dist/builtins/sys/tasks.js.map +1 -1
- package/dist/builtins/sys/textFilters.d.ts +673 -41
- package/dist/builtins/sys/textFilters.js +719 -264
- package/dist/builtins/sys/textFilters.js.map +1 -1
- package/dist/builtins/sys/timing.d.ts +24 -3
- package/dist/builtins/sys/timing.js +67 -14
- package/dist/builtins/sys/timing.js.map +1 -1
- package/dist/builtins/sys/variables.d.ts +70 -4
- package/dist/builtins/sys/variables.js +103 -31
- package/dist/builtins/sys/variables.js.map +1 -1
- package/dist/builtins/sys/version.d.ts +27 -2
- package/dist/builtins/sys/version.js +48 -3
- package/dist/builtins/sys/version.js.map +1 -1
- package/dist/builtins/sys/weather.d.ts +92 -15
- package/dist/builtins/sys/weather.js +71 -45
- package/dist/builtins/sys/weather.js.map +1 -1
- package/dist/builtins/sys/whoami.d.ts +38 -18
- package/dist/builtins/sys/whoami.js +112 -8
- package/dist/builtins/sys/whoami.js.map +1 -1
- package/dist/builtins/utils.d.ts +1 -38
- package/dist/builtins/utils.js +1 -87
- package/dist/builtins/utils.js.map +1 -1
- package/dist/chris/backend.js +2 -0
- package/dist/chris/backend.js.map +1 -1
- package/dist/chris/chrisCommands.js +62 -159
- package/dist/chris/chrisCommands.js.map +1 -1
- package/dist/chris/commandFallback.d.ts +12 -0
- package/dist/chris/commandFallback.js +47 -0
- package/dist/chris/commandFallback.js.map +1 -1
- package/dist/chris/files.js +24 -85
- package/dist/chris/files.js.map +1 -1
- package/dist/chris/filesystem.js +7 -5
- package/dist/chris/filesystem.js.map +1 -1
- package/dist/chris/help.js +0 -1082
- package/dist/chris/help.js.map +1 -1
- package/dist/chris/kinds.d.ts +30 -0
- package/dist/chris/kinds.js +154 -0
- package/dist/chris/kinds.js.map +1 -0
- package/dist/chris/mounts.d.ts +4 -4
- package/dist/chris/mounts.js +9 -16
- package/dist/chris/mounts.js.map +1 -1
- package/dist/chris/navigation.d.ts +2 -3
- package/dist/chris/navigation.js +6 -20
- package/dist/chris/navigation.js.map +1 -1
- package/dist/chris/pacsResources.d.ts +259 -0
- package/dist/chris/pacsResources.js +168 -0
- package/dist/chris/pacsResources.js.map +1 -0
- package/dist/chris/promptContext.d.ts +6 -0
- package/dist/chris/promptContext.js +3 -1
- package/dist/chris/promptContext.js.map +1 -1
- package/dist/core/argumentKinds.d.ts +107 -0
- package/dist/core/argumentKinds.js +223 -0
- package/dist/core/argumentKinds.js.map +1 -0
- package/dist/core/backend.d.ts +4 -1
- package/dist/core/backend.js.map +1 -1
- package/dist/core/commandDeclaration.d.ts +453 -0
- package/dist/core/commandDeclaration.js +52 -0
- package/dist/core/commandDeclaration.js.map +1 -0
- package/dist/core/commandParse.d.ts +64 -0
- package/dist/core/commandParse.js +468 -0
- package/dist/core/commandParse.js.map +1 -0
- package/dist/core/commandRegistry.d.ts +37 -0
- package/dist/core/commandRegistry.js +100 -3
- package/dist/core/commandRegistry.js.map +1 -1
- package/dist/core/commandSchema.d.ts +32 -0
- package/dist/core/commandSchema.js +117 -0
- package/dist/core/commandSchema.js.map +1 -0
- package/dist/core/commandUsage.d.ts +62 -0
- package/dist/core/commandUsage.js +247 -0
- package/dist/core/commandUsage.js.map +1 -0
- package/dist/core/coreCommands.js +66 -214
- package/dist/core/coreCommands.js.map +1 -1
- package/dist/core/dispatch.js +15 -8
- package/dist/core/dispatch.js.map +1 -1
- package/dist/core/paths.d.ts +51 -0
- package/dist/core/paths.js +86 -2
- package/dist/core/paths.js.map +1 -1
- package/dist/core/preprocess.d.ts +10 -9
- package/dist/core/preprocess.js +10 -20
- package/dist/core/preprocess.js.map +1 -1
- package/dist/core/warmupFailures.d.ts +34 -2
- package/dist/core/warmupFailures.js +43 -2
- package/dist/core/warmupFailures.js.map +1 -1
- package/dist/lib/completer/cfsPaths.d.ts +14 -0
- package/dist/lib/completer/cfsPaths.js +91 -0
- package/dist/lib/completer/cfsPaths.js.map +1 -0
- package/dist/lib/completer/declared.d.ts +15 -0
- package/dist/lib/completer/declared.js +189 -0
- package/dist/lib/completer/declared.js.map +1 -0
- package/dist/lib/completer/index.js +33 -79
- package/dist/lib/completer/index.js.map +1 -1
- package/dist/lib/parser.d.ts +5 -8
- package/dist/lib/parser.js +2 -11
- package/dist/lib/parser.js.map +1 -1
- package/dist/lib/vfs/vfs.d.ts +2 -1
- package/dist/lib/vfs/vfs.js +9 -6
- package/dist/lib/vfs/vfs.js.map +1 -1
- package/dist/lib/wildcard.js +2 -3
- package/dist/lib/wildcard.js.map +1 -1
- package/dist/notes.json +1 -1
- package/package.json +6 -5
|
@@ -1,15 +1,37 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @file
|
|
3
|
-
*
|
|
2
|
+
* @file `touch`: makes files in ChRIS's filesystem (CFS), empty or with text.
|
|
3
|
+
*
|
|
4
|
+
* Declared in one record (`touchCommand`): files, which glob, and the text
|
|
5
|
+
* to write, given inline (`--withContents`) or from a file on this machine
|
|
6
|
+
* (`--withContentsFromFile`). A path through a link is written where the
|
|
7
|
+
* link points.
|
|
8
|
+
*
|
|
9
|
+
* Key components:
|
|
10
|
+
* - touchCommand: the declaration.
|
|
11
|
+
* - builtin_touch: the declaration run over words already split.
|
|
12
|
+
* - touch_run: the typed core behind both, and the typed API.
|
|
13
|
+
*
|
|
14
|
+
* Typical usage:
|
|
15
|
+
* ```ts
|
|
16
|
+
* await builtin_touch(['--withContents', 'Hello!', 'greeting.txt']);
|
|
17
|
+
* await touch_run({ paths: ['greeting.txt'], contents: 'Hello!' });
|
|
18
|
+
* ```
|
|
19
|
+
*
|
|
20
|
+
* Dependencies: the session's filesystem and listing cache, the store-path
|
|
21
|
+
* resolver, and this machine's disk (for `--withContentsFromFile`).
|
|
22
|
+
*
|
|
23
|
+
* @module
|
|
4
24
|
*/
|
|
5
25
|
import chalk from 'chalk';
|
|
6
26
|
import fs from 'fs';
|
|
7
27
|
import path from 'path';
|
|
8
|
-
import {
|
|
28
|
+
import { path_resolve, storePath_resolve } from '../utils.js';
|
|
9
29
|
import { listingCache_get, vfsDispatcher_get } from '../../core/filesystem.js';
|
|
10
30
|
import { pathEntry_find, entry_isFolder } from './entries.js';
|
|
11
31
|
import { errno_words, touch_render, vfs_fail } from '@fnndsc/fond';
|
|
12
32
|
import { envelope_ok, envelope_error } from '@fnndsc/menu';
|
|
33
|
+
import { command_declare } from '../../core/commandDeclaration.js';
|
|
34
|
+
import { declaredCommand_run } from '../../core/commandParse.js';
|
|
13
35
|
/**
|
|
14
36
|
* Reads the local file whose text a touch writes.
|
|
15
37
|
*
|
|
@@ -53,6 +75,64 @@ async function file_touch(dispatcher, targetPath, content) {
|
|
|
53
75
|
const written = await dispatcher.write(targetPath, content ?? '');
|
|
54
76
|
return written.ok || written.errno !== 'EISDIR' ? written : vfs_fail('EISDIR', `Is a directory: a folder already holds ${targetPath}`);
|
|
55
77
|
}
|
|
78
|
+
/**
|
|
79
|
+
* Forgets the listing of the folder that holds a touched file, by the
|
|
80
|
+
* session's path and by the store's.
|
|
81
|
+
*
|
|
82
|
+
* @param shown - The file as the session names it.
|
|
83
|
+
* @param targetPath - The file in the store.
|
|
84
|
+
*/
|
|
85
|
+
function parentListings_forget(shown, targetPath) {
|
|
86
|
+
for (const at of new Set([shown, targetPath]))
|
|
87
|
+
listingCache_get().cache_invalidate?.(path.posix.dirname(at));
|
|
88
|
+
}
|
|
89
|
+
/** What a `touch` line may hold. */
|
|
90
|
+
const TOUCH_GRAMMAR = {
|
|
91
|
+
operands: [
|
|
92
|
+
{ name: 'paths', kind: 'cfsPath', repeat: true, glob: true, summary: 'The files to make; with text, only the first takes it' },
|
|
93
|
+
],
|
|
94
|
+
options: {
|
|
95
|
+
withContents: { long: 'withContents', summary: 'Create the file with this text inline', value: { name: 'string', kind: 'word' } },
|
|
96
|
+
withContentsFromFile: { long: 'withContentsFromFile', summary: 'Create the file with the text of a file on this machine', value: { name: 'file', kind: 'hostPath' } },
|
|
97
|
+
},
|
|
98
|
+
};
|
|
99
|
+
/**
|
|
100
|
+
* `touch [--withContents <string>] [--withContentsFromFile <file>] <file…>`: the declaration.
|
|
101
|
+
*
|
|
102
|
+
* @example
|
|
103
|
+
* ```ts
|
|
104
|
+
* commands_register({ declarations: [touchCommand] });
|
|
105
|
+
* ```
|
|
106
|
+
*/
|
|
107
|
+
export const touchCommand = command_declare({
|
|
108
|
+
name: 'touch',
|
|
109
|
+
grammar: TOUCH_GRAMMAR,
|
|
110
|
+
help: {
|
|
111
|
+
summary: 'Create empty files or files with content',
|
|
112
|
+
description: "Makes each file in ChRIS's filesystem: a file already there is left as it is, a missing one is made empty. With --withContents or --withContentsFromFile the first file is written whole with that text. A path through a link is written where the link points. touch makes no folders (mkdir -p does).",
|
|
113
|
+
category: 'Files',
|
|
114
|
+
posix: { group: 'Files', differs: 'makes a CFS file; --withContents writes text into it' },
|
|
115
|
+
examples: [
|
|
116
|
+
'touch file.txt # Create empty file',
|
|
117
|
+
'touch --withContents "Hello!" greeting.txt # Create file with string',
|
|
118
|
+
'touch --withContentsFromFile template.json config.json # Create from local file',
|
|
119
|
+
],
|
|
120
|
+
},
|
|
121
|
+
handler: async (args) => touch_run({
|
|
122
|
+
paths: args.operands.paths,
|
|
123
|
+
contents: args.options.withContents,
|
|
124
|
+
contentsFromFile: args.options.withContentsFromFile,
|
|
125
|
+
}),
|
|
126
|
+
});
|
|
127
|
+
/**
|
|
128
|
+
* `touch` over words already split: the declaration's parse and handler.
|
|
129
|
+
*
|
|
130
|
+
* @param args - The words after `touch`.
|
|
131
|
+
* @returns The envelope from {@link touch_run}, or the refusal of a bad line.
|
|
132
|
+
*/
|
|
133
|
+
export async function builtin_touch(args) {
|
|
134
|
+
return declaredCommand_run(touchCommand, args);
|
|
135
|
+
}
|
|
56
136
|
/**
|
|
57
137
|
* Creates empty files or updates timestamps: the shared typed core behind
|
|
58
138
|
* the parsed builtin and the typed API.
|
|
@@ -77,24 +157,25 @@ export async function touch_run(runOptions) {
|
|
|
77
157
|
}
|
|
78
158
|
const wrote = content !== undefined;
|
|
79
159
|
// Only the first path takes content.
|
|
80
|
-
const filesToTouch = wrote ?
|
|
160
|
+
const filesToTouch = wrote ? pathArgs.slice(0, 1) : pathArgs;
|
|
81
161
|
let rendered = '';
|
|
82
162
|
let renderedErr = '';
|
|
83
163
|
const outcomes = [];
|
|
84
164
|
const dispatcher = vfsDispatcher_get();
|
|
85
165
|
for (const pathArg of filesToTouch) {
|
|
86
166
|
try {
|
|
87
|
-
const
|
|
167
|
+
const shown = await path_resolve(pathArg);
|
|
168
|
+
const targetPath = await storePath_resolve(pathArg);
|
|
88
169
|
const done = await file_touch(dispatcher, targetPath, content);
|
|
89
170
|
if (done.ok) {
|
|
90
|
-
rendered += `${touch_render(
|
|
91
|
-
outcomes.push({ path:
|
|
92
|
-
|
|
171
|
+
rendered += `${touch_render(shown, true, wrote)}\n`;
|
|
172
|
+
outcomes.push({ path: shown, created: true });
|
|
173
|
+
parentListings_forget(shown, targetPath);
|
|
93
174
|
}
|
|
94
175
|
else {
|
|
95
|
-
renderedErr += `${chalk.red(`Failed to create file: ${
|
|
176
|
+
renderedErr += `${chalk.red(`Failed to create file: ${shown}`)}\n`;
|
|
96
177
|
renderedErr += `${chalk.gray(` ${done.reason ?? errno_words(done.errno)}`)}\n`;
|
|
97
|
-
outcomes.push({ path:
|
|
178
|
+
outcomes.push({ path: shown, created: false });
|
|
98
179
|
}
|
|
99
180
|
}
|
|
100
181
|
catch (e) {
|
|
@@ -112,21 +193,4 @@ export async function touch_run(runOptions) {
|
|
|
112
193
|
}
|
|
113
194
|
return envelope_ok(rendered, model);
|
|
114
195
|
}
|
|
115
|
-
/**
|
|
116
|
-
* Creates files from parsed command-line arguments.
|
|
117
|
-
*
|
|
118
|
-
* @param args - Command line arguments (paths and --withContents flags).
|
|
119
|
-
* @returns The envelope from {@link touch_run}.
|
|
120
|
-
*/
|
|
121
|
-
export async function builtin_touch(args) {
|
|
122
|
-
const parsed = commandArgs_process(args);
|
|
123
|
-
const refusal = optionsUnknown_refusal('touch', parsed, ['withContents', 'withContentsFromFile']);
|
|
124
|
-
if (refusal !== null)
|
|
125
|
-
return envelope_error('', undefined, `${chalk.red(refusal)}\n`);
|
|
126
|
-
return touch_run({
|
|
127
|
-
paths: parsed._,
|
|
128
|
-
contents: parsed['withContents'] !== undefined ? String(parsed['withContents']) : undefined,
|
|
129
|
-
contentsFromFile: parsed['withContentsFromFile'] !== undefined ? String(parsed['withContentsFromFile']) : undefined,
|
|
130
|
-
});
|
|
131
|
-
}
|
|
132
196
|
//# sourceMappingURL=touch.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"touch.js","sourceRoot":"","sources":["../../../src/builtins/fs/touch.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"touch.js","sourceRoot":"","sources":["../../../src/builtins/fs/touch.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,16 +1,43 @@
|
|
|
1
1
|
import { CommandEnvelope } from '@fnndsc/menu';
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
4
|
-
* Uses chili's scan_do machinery for recursive filesystem traversal.
|
|
5
|
-
*
|
|
6
|
-
* @param args - Command line arguments (optional path and flags).
|
|
7
|
-
* @returns A Promise that resolves when the tree is displayed.
|
|
3
|
+
* `tree [--follow] [--path] [--dirs] [--dirpath] [path]`: the declaration.
|
|
8
4
|
*
|
|
9
5
|
* @example
|
|
6
|
+
* ```ts
|
|
7
|
+
* commands_register({ declarations: [treeCommand] }, 'backend');
|
|
10
8
|
* ```
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
9
|
+
*/
|
|
10
|
+
export declare const treeCommand: import("../../core/commandDeclaration.js").CommandDeclaration<{
|
|
11
|
+
readonly operands: readonly [{
|
|
12
|
+
readonly name: "path";
|
|
13
|
+
readonly kind: "cfsPath";
|
|
14
|
+
readonly optional: true;
|
|
15
|
+
readonly glob: true;
|
|
16
|
+
readonly summary: "The folder to draw; the working directory when none is given";
|
|
17
|
+
}];
|
|
18
|
+
readonly options: {
|
|
19
|
+
readonly follow: {
|
|
20
|
+
readonly long: "follow";
|
|
21
|
+
readonly summary: "Follow symbolic links when traversing";
|
|
22
|
+
};
|
|
23
|
+
readonly listPaths: {
|
|
24
|
+
readonly long: "path";
|
|
25
|
+
readonly summary: "Emit one full path per entry (grep-friendly, no tree art)";
|
|
26
|
+
};
|
|
27
|
+
readonly dirs: {
|
|
28
|
+
readonly long: "dirs";
|
|
29
|
+
readonly summary: "Show directories only";
|
|
30
|
+
};
|
|
31
|
+
readonly dirpath: {
|
|
32
|
+
readonly long: "dirpath";
|
|
33
|
+
readonly summary: "Emit one full directory path per line";
|
|
34
|
+
};
|
|
35
|
+
};
|
|
36
|
+
}>;
|
|
37
|
+
/**
|
|
38
|
+
* `tree` over words already split: the declaration's parse and handler.
|
|
39
|
+
*
|
|
40
|
+
* @param args - The words after `tree`.
|
|
41
|
+
* @returns The tree, or the refusal of a bad line.
|
|
15
42
|
*/
|
|
16
43
|
export declare function builtin_tree(args: string[]): Promise<CommandEnvelope>;
|
package/dist/builtins/fs/tree.js
CHANGED
|
@@ -1,9 +1,27 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @file
|
|
3
|
-
*
|
|
2
|
+
* @file `tree`: a folder of ChRIS's filesystem (CFS) drawn as a tree, or
|
|
3
|
+
* listed one path per line.
|
|
4
|
+
*
|
|
5
|
+
* Declared in one record (`treeCommand`): one path, and its switches.
|
|
6
|
+
*
|
|
7
|
+
* Key components:
|
|
8
|
+
* - treeCommand: the declaration.
|
|
9
|
+
* - builtin_tree: the declaration run over words already split.
|
|
10
|
+
*
|
|
11
|
+
* Typical usage:
|
|
12
|
+
* ```ts
|
|
13
|
+
* await builtin_tree(['--dirs', '~/feeds']);
|
|
14
|
+
* ```
|
|
15
|
+
*
|
|
16
|
+
* Dependencies: chili's scan for the walk; the listing for whether a path
|
|
17
|
+
* is there.
|
|
18
|
+
*
|
|
19
|
+
* @module
|
|
4
20
|
*/
|
|
5
21
|
import chalk from 'chalk';
|
|
6
|
-
import {
|
|
22
|
+
import { path_resolve, storePath_resolve, error_stripDebugPrefix } from '../utils.js';
|
|
23
|
+
import { command_declare } from '../../core/commandDeclaration.js';
|
|
24
|
+
import { declaredCommand_run } from '../../core/commandParse.js';
|
|
7
25
|
import { vfs } from '../../lib/vfs/vfs.js';
|
|
8
26
|
import { session } from '../../session/index.js';
|
|
9
27
|
import { spinner } from '../../lib/spinner.js';
|
|
@@ -12,55 +30,92 @@ import { bytes_format } from '@fnndsc/chili/commands/fs/upload.js';
|
|
|
12
30
|
import { errorStack } from '@fnndsc/fond';
|
|
13
31
|
import { envelope_ok, envelope_error } from '@fnndsc/menu';
|
|
14
32
|
import { exitCode_set } from '../../core/handlerRun.js';
|
|
15
|
-
/** The options tree reads; any other is refused by name. */
|
|
16
|
-
const TREE_OPTIONS = ['follow', 'path', 'dirs', 'dirpath'];
|
|
17
33
|
/**
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
|
|
22
|
-
|
|
34
|
+
* What a `tree` line may hold. An option it does not have is refused, not
|
|
35
|
+
* skipped: `tree -L 1 x` once scanned a folder named `1`, and
|
|
36
|
+
* `tree --bogus x` the whole home.
|
|
37
|
+
*/
|
|
38
|
+
const TREE_GRAMMAR = {
|
|
39
|
+
operands: [
|
|
40
|
+
{ name: 'path', kind: 'cfsPath', optional: true, glob: true, summary: 'The folder to draw; the working directory when none is given' },
|
|
41
|
+
],
|
|
42
|
+
options: {
|
|
43
|
+
follow: { long: 'follow', summary: 'Follow symbolic links when traversing' },
|
|
44
|
+
listPaths: { long: 'path', summary: 'Emit one full path per entry (grep-friendly, no tree art)' },
|
|
45
|
+
dirs: { long: 'dirs', summary: 'Show directories only' },
|
|
46
|
+
dirpath: { long: 'dirpath', summary: 'Emit one full directory path per line' },
|
|
47
|
+
},
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* `tree [--follow] [--path] [--dirs] [--dirpath] [path]`: the declaration.
|
|
23
51
|
*
|
|
24
52
|
* @example
|
|
25
|
-
* ```
|
|
26
|
-
*
|
|
27
|
-
* tree /home/user/data # Tree of specific path
|
|
28
|
-
* tree --follow # Follow symbolic links
|
|
53
|
+
* ```ts
|
|
54
|
+
* commands_register({ declarations: [treeCommand] }, 'backend');
|
|
29
55
|
* ```
|
|
30
56
|
*/
|
|
57
|
+
export const treeCommand = command_declare({
|
|
58
|
+
name: 'tree',
|
|
59
|
+
grammar: TREE_GRAMMAR,
|
|
60
|
+
help: {
|
|
61
|
+
summary: 'Display directory tree structure',
|
|
62
|
+
description: "Draws a folder of ChRIS's filesystem and everything under it as a tree, with the total size and the number of items; or, with --path or --dirpath, lists one full path per line. The working directory when no path is given.",
|
|
63
|
+
category: 'Navigation',
|
|
64
|
+
posix: { group: 'Files', differs: 'a CFS tree' },
|
|
65
|
+
examples: [
|
|
66
|
+
'tree # Tree of current directory',
|
|
67
|
+
'tree /home/user/data # Tree of specific path',
|
|
68
|
+
'tree --follow # Follow symbolic links',
|
|
69
|
+
'tree --path # One path per line, no decoration',
|
|
70
|
+
'tree --dirs # Directory hierarchy only',
|
|
71
|
+
'tree --dirpath # One directory path per line',
|
|
72
|
+
],
|
|
73
|
+
},
|
|
74
|
+
holds: [],
|
|
75
|
+
handler: tree_run,
|
|
76
|
+
});
|
|
77
|
+
/**
|
|
78
|
+
* `tree` over words already split: the declaration's parse and handler.
|
|
79
|
+
*
|
|
80
|
+
* @param args - The words after `tree`.
|
|
81
|
+
* @returns The tree, or the refusal of a bad line.
|
|
82
|
+
*/
|
|
31
83
|
export async function builtin_tree(args) {
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
const
|
|
43
|
-
const dirpathMode =
|
|
44
|
-
const pathMode =
|
|
45
|
-
const dirsOnly =
|
|
46
|
-
//
|
|
84
|
+
return declaredCommand_run(treeCommand, args);
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Displays a directory tree of the ChRIS filesystem.
|
|
88
|
+
* Uses chili's scan_do machinery for recursive filesystem traversal.
|
|
89
|
+
*
|
|
90
|
+
* @param args - The line, parsed.
|
|
91
|
+
* @returns The tree and its summary, or why it could not be drawn.
|
|
92
|
+
*/
|
|
93
|
+
async function tree_run(args) {
|
|
94
|
+
const pathArg = args.operands.path;
|
|
95
|
+
const dirpathMode = args.options.dirpath;
|
|
96
|
+
const pathMode = args.options.listPaths || dirpathMode;
|
|
97
|
+
const dirsOnly = args.options.dirs || dirpathMode;
|
|
98
|
+
// Read where the store keeps it (a run's data path, a link on the line),
|
|
99
|
+
// and shown as it was asked: the tree's root is the path as typed.
|
|
47
100
|
let targetPath;
|
|
48
|
-
|
|
49
|
-
|
|
101
|
+
let logicalRoot;
|
|
102
|
+
if (pathArg !== undefined) {
|
|
103
|
+
logicalRoot = await path_resolve(pathArg);
|
|
104
|
+
targetPath = await storePath_resolve(pathArg);
|
|
50
105
|
// A path that is not there is said to be not there, as tree says it,
|
|
51
106
|
// rather than scanned into an empty tree.
|
|
52
107
|
const entry = await vfs.data_get(targetPath, { directory: true });
|
|
53
108
|
if (!entry.ok) {
|
|
54
109
|
errorStack.stack_pop();
|
|
55
110
|
exitCode_set(1);
|
|
56
|
-
return envelope_error('', undefined, `${chalk.red(`tree: ${
|
|
111
|
+
return envelope_error('', undefined, `${chalk.red(`tree: ${pathArg}: No such file or directory`)}\n`);
|
|
57
112
|
}
|
|
58
113
|
}
|
|
59
114
|
// Build scan options
|
|
60
115
|
const scanOptions = {
|
|
61
116
|
silent: true,
|
|
62
117
|
tree: false, // We'll format it ourselves
|
|
63
|
-
follow:
|
|
118
|
+
follow: args.options.follow,
|
|
64
119
|
dirsOnly,
|
|
65
120
|
// A named folder is scanned where it stands: the shared directory stays put.
|
|
66
121
|
...(targetPath ? { folder: targetPath } : {}),
|
|
@@ -78,14 +133,18 @@ export async function builtin_tree(args) {
|
|
|
78
133
|
spinner.stop();
|
|
79
134
|
let rendered = '';
|
|
80
135
|
if (pathMode) {
|
|
81
|
-
// --path: emit one full
|
|
136
|
+
// --path: emit one full path per entry — grep-friendly, under the path asked
|
|
82
137
|
for (const item of scanResult.fileInfo) {
|
|
83
|
-
rendered += `${item.chrisPath}\n`;
|
|
138
|
+
rendered += `${shownPath_derive(item.chrisPath, targetPath, logicalRoot)}\n`;
|
|
84
139
|
}
|
|
85
140
|
}
|
|
86
141
|
else if (scanResult.fileInfo.length === 0) {
|
|
87
142
|
// An empty folder is its own tree: its name, and nothing under it.
|
|
88
|
-
rendered += `${
|
|
143
|
+
rendered += `${pathArg ?? originalFolder}\n`;
|
|
144
|
+
}
|
|
145
|
+
else if (targetPath !== undefined && pathArg !== undefined) {
|
|
146
|
+
// The tree hangs from the path as typed, its entries below it.
|
|
147
|
+
rendered += `${treeUnder_render(scanResult.fileInfo, targetPath, pathArg)}\n`;
|
|
89
148
|
}
|
|
90
149
|
else {
|
|
91
150
|
// Default: ASCII tree
|
|
@@ -96,4 +155,35 @@ export async function builtin_tree(args) {
|
|
|
96
155
|
rendered += `${chalk.gray(`${scanResult.fileInfo.length} items`)}\n`;
|
|
97
156
|
return envelope_ok(rendered);
|
|
98
157
|
}
|
|
158
|
+
/**
|
|
159
|
+
* A scanned path as the person asked for it: under the logical root in
|
|
160
|
+
* place of the store folder it was read from.
|
|
161
|
+
*
|
|
162
|
+
* @param chrisPath - The path the scan gave (a store path).
|
|
163
|
+
* @param storeRoot - The store folder scanned, when one was named.
|
|
164
|
+
* @param logicalRoot - The same folder as the session names it.
|
|
165
|
+
* @returns The path to show.
|
|
166
|
+
*/
|
|
167
|
+
function shownPath_derive(chrisPath, storeRoot, logicalRoot) {
|
|
168
|
+
if (storeRoot === undefined || logicalRoot === undefined)
|
|
169
|
+
return chrisPath;
|
|
170
|
+
if (chrisPath === storeRoot)
|
|
171
|
+
return logicalRoot;
|
|
172
|
+
return chrisPath.startsWith(`${storeRoot}/`) ? `${logicalRoot}${chrisPath.slice(storeRoot.length)}` : chrisPath;
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Draws a scanned folder's tree hanging from the path as typed: its entries
|
|
176
|
+
* relative to the store folder they were read from.
|
|
177
|
+
*
|
|
178
|
+
* @param files - What the scan found.
|
|
179
|
+
* @param storeRoot - The store folder scanned.
|
|
180
|
+
* @param shown - The root's label: the path as typed.
|
|
181
|
+
* @returns The tree.
|
|
182
|
+
*/
|
|
183
|
+
function treeUnder_render(files, storeRoot, shown) {
|
|
184
|
+
const under = files.map((file) => (file.chrisPath.startsWith(`${storeRoot}/`) ? { ...file, chrisPath: file.chrisPath.slice(storeRoot.length + 1) } : file));
|
|
185
|
+
// archy draws the root's own label first: an empty line, which the path takes.
|
|
186
|
+
const lines = archyTree_create(under).split('\n');
|
|
187
|
+
return [shown, ...lines.slice(1)].join('\n').replace(/\n+$/, '');
|
|
188
|
+
}
|
|
99
189
|
//# sourceMappingURL=tree.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tree.js","sourceRoot":"","sources":["../../../src/builtins/fs/tree.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"tree.js","sourceRoot":"","sources":["../../../src/builtins/fs/tree.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,8 +1,27 @@
|
|
|
1
1
|
import { type CommandEnvelope } from '@fnndsc/menu';
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
3
|
+
* `upload <source> <destination>`: the declaration.
|
|
4
4
|
*
|
|
5
|
-
* @
|
|
6
|
-
*
|
|
5
|
+
* @example
|
|
6
|
+
* ```ts
|
|
7
|
+
* commands_register({ declarations: [uploadCommand] }, 'backend');
|
|
8
|
+
* ```
|
|
9
|
+
*/
|
|
10
|
+
export declare const uploadCommand: import("../../core/commandDeclaration.js").CommandDeclaration<{
|
|
11
|
+
readonly operands: readonly [{
|
|
12
|
+
readonly name: "source";
|
|
13
|
+
readonly kind: "hostPath";
|
|
14
|
+
readonly summary: "What to upload from this machine's disk: a file, a folder, or a wildcard chili matches there";
|
|
15
|
+
}, {
|
|
16
|
+
readonly name: "destination";
|
|
17
|
+
readonly kind: "cfsPath";
|
|
18
|
+
readonly summary: "The ChRIS folder it goes into";
|
|
19
|
+
}];
|
|
20
|
+
}>;
|
|
21
|
+
/**
|
|
22
|
+
* `upload` over words already split: the declaration's parse and handler.
|
|
23
|
+
*
|
|
24
|
+
* @param args - The words after `upload`.
|
|
25
|
+
* @returns The upload summary, or the refusal of a bad line.
|
|
7
26
|
*/
|
|
8
27
|
export declare function builtin_upload(args: string[]): Promise<CommandEnvelope>;
|
|
@@ -1,18 +1,41 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @file
|
|
3
|
-
*
|
|
2
|
+
* @file `upload`: files, folders or the matches of a wildcard on this
|
|
3
|
+
* machine's disk, into ChRIS, with progress.
|
|
4
|
+
*
|
|
5
|
+
* The destination is where the store keeps it (`storePath_resolve`): an
|
|
6
|
+
* upload into a link lands in the folder the link points at.
|
|
7
|
+
*
|
|
8
|
+
* Declared in one record (`uploadCommand`): a host path operand, then one
|
|
9
|
+
* CFS path. The host path is never globbed by the line: chili matches a
|
|
10
|
+
* wildcard in it against the engine's disk.
|
|
11
|
+
*
|
|
12
|
+
* Key components:
|
|
13
|
+
* - uploadCommand: the declaration.
|
|
14
|
+
* - builtin_upload: the declaration run over words already split.
|
|
15
|
+
*
|
|
16
|
+
* Typical usage:
|
|
17
|
+
* ```ts
|
|
18
|
+
* await builtin_upload(['~/data/file.csv', '/home/user/uploads/']);
|
|
19
|
+
* ```
|
|
20
|
+
*
|
|
21
|
+
* Dependencies: chili's transfer, cumin's listing cache, the session's surface.
|
|
22
|
+
*
|
|
23
|
+
* @module
|
|
4
24
|
*/
|
|
5
25
|
import chalk from 'chalk';
|
|
6
|
-
import { path_resolve } from '../utils.js';
|
|
26
|
+
import { path_resolve, storePath_resolve } from '../utils.js';
|
|
7
27
|
import { files_uploadWithProgress as chefs_upload_cmd, bytes_format } from '@fnndsc/chili/commands/fs/upload.js';
|
|
8
28
|
import { listCache_get } from '@fnndsc/cumin';
|
|
9
29
|
import { sink_get } from '../../core/sink.js';
|
|
10
|
-
import { shellArguments_pathnameExpansion } from '../../lib/parser.js';
|
|
11
30
|
import { surface_get } from '../../core/surface.js';
|
|
12
31
|
import { repl_confirm } from '../../core/question.js';
|
|
32
|
+
import { command_declare } from '../../core/commandDeclaration.js';
|
|
33
|
+
import { declaredCommand_run } from '../../core/commandParse.js';
|
|
13
34
|
import { errorStack } from '@fnndsc/fond';
|
|
14
35
|
import { envelope_ok, envelope_error } from '@fnndsc/menu';
|
|
15
36
|
import { exitCode_set } from '../../core/handlerRun.js';
|
|
37
|
+
/** The characters that make a host path a pattern chili matches against the disk. */
|
|
38
|
+
const HOST_WILDCARD = /[*?[]/;
|
|
16
39
|
/**
|
|
17
40
|
* Asks the issuing surface to confirm replacement of an existing CFS target.
|
|
18
41
|
*
|
|
@@ -27,18 +50,54 @@ async function uploadConfirmation_request(message) {
|
|
|
27
50
|
throw new Error('Operation cancelled by user.');
|
|
28
51
|
}
|
|
29
52
|
}
|
|
53
|
+
/** What an `upload` line may hold: one place on this machine, then one ChRIS path. */
|
|
54
|
+
const UPLOAD_GRAMMAR = {
|
|
55
|
+
operands: [
|
|
56
|
+
{ name: 'source', kind: 'hostPath', summary: "What to upload from this machine's disk: a file, a folder, or a wildcard chili matches there" },
|
|
57
|
+
{ name: 'destination', kind: 'cfsPath', summary: 'The ChRIS folder it goes into' },
|
|
58
|
+
],
|
|
59
|
+
};
|
|
60
|
+
/**
|
|
61
|
+
* `upload <source> <destination>`: the declaration.
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* ```ts
|
|
65
|
+
* commands_register({ declarations: [uploadCommand] }, 'backend');
|
|
66
|
+
* ```
|
|
67
|
+
*/
|
|
68
|
+
export const uploadCommand = command_declare({
|
|
69
|
+
name: 'upload',
|
|
70
|
+
grammar: UPLOAD_GRAMMAR,
|
|
71
|
+
help: {
|
|
72
|
+
summary: 'Upload local files, directories, or glob matches to ChRIS',
|
|
73
|
+
description: 'Upload local files, directories, or glob matches to ChRIS with progress tracking. A progress bar shows the file count and percentage complete, the estimated time remaining (ETA) and the data transferred; summary statistics follow the upload.',
|
|
74
|
+
category: 'Files',
|
|
75
|
+
examples: [
|
|
76
|
+
'upload ~/data/file.csv /home/user/uploads/',
|
|
77
|
+
'upload ~/Pictures/earthandmoon* .',
|
|
78
|
+
'upload ./results/ ~/data/',
|
|
79
|
+
'upload ~/experiment/data /home/user/projects/',
|
|
80
|
+
],
|
|
81
|
+
},
|
|
82
|
+
handler: async (args) => upload_run(args.operands.source, args.operands.destination),
|
|
83
|
+
});
|
|
84
|
+
/**
|
|
85
|
+
* `upload` over words already split: the declaration's parse and handler.
|
|
86
|
+
*
|
|
87
|
+
* @param args - The words after `upload`.
|
|
88
|
+
* @returns The upload summary, or the refusal of a bad line.
|
|
89
|
+
*/
|
|
90
|
+
export async function builtin_upload(args) {
|
|
91
|
+
return declaredCommand_run(uploadCommand, args);
|
|
92
|
+
}
|
|
30
93
|
/**
|
|
31
94
|
* Uploads a local file or directory to ChRIS.
|
|
32
95
|
*
|
|
33
|
-
* @param
|
|
96
|
+
* @param localPath - The host path, as typed: a wildcard in it is matched on the engine's disk.
|
|
97
|
+
* @param remotePath - The ChRIS destination, as typed.
|
|
34
98
|
* @returns An envelope carrying the upload summary.
|
|
35
99
|
*/
|
|
36
|
-
|
|
37
|
-
if (args.length < 2) {
|
|
38
|
-
return envelope_ok(`${chalk.red('Usage: upload <local_path> <remote_path>')}\n`);
|
|
39
|
-
}
|
|
40
|
-
const localPath = args[0];
|
|
41
|
-
const remotePath = args[1];
|
|
100
|
+
async function upload_run(localPath, remotePath) {
|
|
42
101
|
// The local path is read by the ENGINE: under a daemon that is the daemon
|
|
43
102
|
// host's disk, which belongs to nobody attending the session unless the
|
|
44
103
|
// operator declared it theirs (--host-control=files). Without that, refuse
|
|
@@ -47,8 +106,11 @@ export async function builtin_upload(args) {
|
|
|
47
106
|
exitCode_set(1);
|
|
48
107
|
return envelope_error('', undefined, `${chalk.red("upload: calypso's host disk is nobody's; start calypso with --host-control=files, or upload from a surface that can supply the bytes.")}\n`);
|
|
49
108
|
}
|
|
50
|
-
|
|
51
|
-
|
|
109
|
+
// chili reads an exact path first and matches a pattern only when nothing
|
|
110
|
+
// stands at it.
|
|
111
|
+
const localGlob = HOST_WILDCARD.test(localPath);
|
|
112
|
+
// Where the store keeps the destination: a link's target, not the link.
|
|
113
|
+
const targetRemote = await storePath_resolve(remotePath);
|
|
52
114
|
try {
|
|
53
115
|
const summary = await chefs_upload_cmd(localPath, targetRemote, {
|
|
54
116
|
expandLocalGlob: localGlob,
|
|
@@ -85,8 +147,14 @@ export async function builtin_upload(args) {
|
|
|
85
147
|
if (summary.transferredCount > 0) {
|
|
86
148
|
const listCache = listCache_get();
|
|
87
149
|
listCache.cache_invalidateTree(summary.actualTargetPath);
|
|
88
|
-
//
|
|
150
|
+
// The destination's own listing, by both its names: where the store
|
|
151
|
+
// keeps it, and the path it was reached by.
|
|
89
152
|
listCache.cache_invalidate(targetRemote);
|
|
153
|
+
listCache.cache_invalidate(await path_resolve(remotePath));
|
|
154
|
+
}
|
|
155
|
+
if (summary.failedCount > 0) {
|
|
156
|
+
exitCode_set(1);
|
|
157
|
+
return envelope_error(rendered, undefined, '');
|
|
90
158
|
}
|
|
91
159
|
return envelope_ok(rendered);
|
|
92
160
|
}
|