diff --git a/Cargo.toml b/Cargo.toml index 857c964314..835aab42fa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -108,6 +108,7 @@ shellexpand = "3.1.0" spdx = "0.10" spfs = { path = "crates/spfs" } spfs-cli-common = { path = "crates/spfs-cli/common" } +spfs-cli-main = { path = "crates/spfs-cli/main" } spfs-encoding = { path = "crates/spfs-encoding" } spfs-vfs = { path = "crates/spfs-vfs" } spk-build = { path = "crates/spk-build" } diff --git a/crates/spfs-cli/cmd-docs/Cargo.toml b/crates/spfs-cli/cmd-docs/Cargo.toml new file mode 100644 index 0000000000..3e564fb091 --- /dev/null +++ b/crates/spfs-cli/cmd-docs/Cargo.toml @@ -0,0 +1,30 @@ +[package] +authors = { workspace = true } +edition = { workspace = true } +name = "spfs-cli-docs" +version = { workspace = true } +license-file = { workspace = true } +homepage = { workspace = true } +repository = { workspace = true } +readme = { workspace = true } +description = { workspace = true } + +[lints] +workspace = true + +[[bin]] +name = "spfs-docs" +path = "src/cmd_docs.rs" + +[features] +sentry = ["spfs-cli-common/sentry"] + +[dependencies] +clap = { workspace = true } +clap-markdown = "0.1.5" +miette = { workspace = true, features = ["fancy"] } +spfs = { workspace = true } +spfs-cli-common = { workspace = true } +spfs-cli-main = { workspace = true } +tokio = { workspace = true, features = ["rt", "rt-multi-thread"] } +tracing = { workspace = true } diff --git a/crates/spfs-cli/cmd-docs/src/cmd_docs.rs b/crates/spfs-cli/cmd-docs/src/cmd_docs.rs new file mode 100644 index 0000000000..d4a7248065 --- /dev/null +++ b/crates/spfs-cli/cmd-docs/src/cmd_docs.rs @@ -0,0 +1,35 @@ +// Copyright (c) Contributors to the SPK project. +// SPDX-License-Identifier: Apache-2.0 +// https://github.com/spkenv/spk + +use std::fs; + +use clap::Parser; +use miette::Result; +use spfs_cli_common as cli; + +cli::main!(CmdDocs); + +use spfs_cli_main::cmd_spfs::Opt; + +/// Write Markdown documentation for all SPFS subcommands to docs folder. +#[derive(Debug, Parser)] +#[clap(name = "spfs-docs")] +pub struct CmdDocs { + #[clap(flatten)] + pub logging: cli::Logging, +} + +impl CmdDocs { + pub async fn run(&mut self, _config: &spfs::Config) -> Result { + let mut markdown = clap_markdown::help_markdown::(); + markdown.insert(0, '\n'); + markdown.insert_str(0, "---\n"); + markdown.insert_str(0, "chapter: true\n"); + markdown.insert_str(0, "title: SPFS CLI\n"); + markdown.insert_str(0, "---\n"); + // This path is relative to the current shell directory. + fs::write("docs/spfs/cli/markdown.md", markdown).expect("Unable to write file"); + Ok(0) + } +} diff --git a/crates/spfs-cli/main/Cargo.toml b/crates/spfs-cli/main/Cargo.toml index 32dbe3409d..b9f666b1e7 100644 --- a/crates/spfs-cli/main/Cargo.toml +++ b/crates/spfs-cli/main/Cargo.toml @@ -17,6 +17,10 @@ workspace = true name = "spfs" path = "src/bin.rs" +[lib] +name = "spfs_cli_main" +path = "src/lib.rs" + [features] fuse = ["spfs/fuse-backend"] sentry = ["spfs-cli-common/sentry"] diff --git a/crates/spfs-cli/main/src/bin.rs b/crates/spfs-cli/main/src/bin.rs index a1c39291e4..30ecad3286 100644 --- a/crates/spfs-cli/main/src/bin.rs +++ b/crates/spfs-cli/main/src/bin.rs @@ -2,179 +2,8 @@ // SPDX-License-Identifier: Apache-2.0 // https://github.com/spkenv/spk -use clap::{Parser, Subcommand}; -use miette::Result; -use spfs::{Error, OsErrorExt}; - -mod cmd_check; -mod cmd_commit; -mod cmd_config; -mod cmd_diff; -mod cmd_edit; -mod cmd_info; -mod cmd_init; -mod cmd_layers; -mod cmd_log; -mod cmd_ls; -mod cmd_ls_tags; -mod cmd_migrate; -mod cmd_platforms; -mod cmd_pull; -mod cmd_push; -mod cmd_read; -mod cmd_reset; -mod cmd_run; -mod cmd_runtime; -mod cmd_runtime_info; -mod cmd_runtime_list; -mod cmd_runtime_prune; -mod cmd_runtime_remove; -mod cmd_search; -#[cfg(feature = "server")] -mod cmd_server; -mod cmd_shell; -mod cmd_tag; -mod cmd_tags; -mod cmd_untag; -mod cmd_version; -mod cmd_write; - +use clap::Parser; use spfs_cli_common as cli; -use spfs_cli_common::CommandName; +use spfs_cli_main::cmd_spfs::Opt; cli::main!(Opt); - -/// Filesystem isolation, capture and distribution. -#[derive(Debug, Parser)] -#[clap( - about, - after_help = "EXTERNAL SUBCOMMANDS:\ - \n render render the contents of an environment or layer\ - \n monitor watch a runtime and clean it up when complete\ - " -)] -pub struct Opt { - #[clap(flatten)] - pub logging: cli::Logging, - #[clap(subcommand)] - pub cmd: Command, -} - -#[derive(strum::AsRefStr, Debug, Subcommand)] -#[strum(serialize_all = "lowercase")] -#[clap(trailing_var_arg = true, dont_delimit_trailing_values = true)] -pub enum Command { - Version(cmd_version::CmdVersion), - Init(cmd_init::CmdInit), - Edit(cmd_edit::CmdEdit), - Commit(cmd_commit::CmdCommit), - Config(cmd_config::CmdConfig), - Reset(cmd_reset::CmdReset), - Run(cmd_run::CmdRun), - Tag(cmd_tag::CmdTag), - Untag(cmd_untag::CmdUntag), - Shell(cmd_shell::CmdShell), - Runtime(cmd_runtime::CmdRuntime), - Layers(cmd_layers::CmdLayers), - Platforms(cmd_platforms::CmdPlatforms), - Tags(cmd_tags::CmdTags), - Info(cmd_info::CmdInfo), - Pull(cmd_pull::CmdPull), - Push(cmd_push::CmdPush), - Log(cmd_log::CmdLog), - Search(cmd_search::CmdSearch), - Diff(cmd_diff::CmdDiff), - LsTags(cmd_ls_tags::CmdLsTags), - Ls(cmd_ls::CmdLs), - Migrate(cmd_migrate::CmdMigrate), - Check(cmd_check::CmdCheck), - Read(cmd_read::CmdRead), - Write(cmd_write::CmdWrite), - - #[cfg(feature = "server")] - Server(cmd_server::CmdServer), - - #[clap(external_subcommand)] - External(Vec), -} - -impl CommandName for Opt { - fn command_name(&self) -> &str { - self.cmd.as_ref() - } -} - -impl Opt { - async fn run(&mut self, config: &spfs::Config) -> Result { - match &mut self.cmd { - Command::Version(cmd) => cmd.run().await, - Command::Edit(cmd) => cmd.run(config).await, - Command::Init(cmd) => cmd.run(config).await, - Command::Commit(cmd) => cmd.run(config).await, - Command::Config(cmd) => cmd.run(config).await, - Command::Reset(cmd) => cmd.run(config).await, - Command::Tag(cmd) => cmd.run(config).await, - Command::Untag(cmd) => cmd.run(config).await, - Command::Runtime(cmd) => cmd.run(config).await, - Command::Layers(cmd) => cmd.run(config).await, - Command::Platforms(cmd) => cmd.run(config).await, - Command::Tags(cmd) => cmd.run(config).await, - Command::Info(cmd) => cmd.run(config).await, - Command::Log(cmd) => cmd.run(config).await, - Command::Search(cmd) => cmd.run(config).await, - Command::Diff(cmd) => cmd.run(config).await, - Command::LsTags(cmd) => cmd.run(config).await, - Command::Ls(cmd) => cmd.run(config).await, - Command::Migrate(cmd) => cmd.run(config).await, - Command::Check(cmd) => cmd.run(config).await, - Command::Read(cmd) => cmd.run(config).await, - Command::Write(cmd) => cmd.run(config).await, - Command::Run(cmd) => cmd.run(config).await, - Command::Shell(cmd) => cmd.run(config).await, - Command::Pull(cmd) => cmd.run(config).await, - Command::Push(cmd) => cmd.run(config).await, - #[cfg(feature = "server")] - Command::Server(cmd) => cmd.run(config).await, - Command::External(args) => run_external_subcommand(args.clone()).await, - } - } -} - -async fn run_external_subcommand(args: Vec) -> Result { - { - let mut args = args.into_iter(); - let command = match args.next() { - None => { - tracing::error!("Invalid subcommand, cannot be empty"); - return Ok(1); - } - Some(c) => c, - }; - - // either in the PATH or next to the current binary - let cmd_path = match spfs::which_spfs(&command) { - Some(cmd) => cmd, - None => { - let mut p = std::env::current_exe() - .map_err(|err| Error::process_spawn_error("current_exe()", err, None))?; - p.set_file_name(&command); - p - } - }; - - let cmd = spfs::bootstrap::Command { - executable: cmd_path.into(), - args: args.map(Into::into).collect(), - vars: Vec::new(), - }; - - match cmd.exec() { - Ok(o) => match o {}, - Err(err) if err.is_os_not_found() => { - tracing::error!("{command} not found in PATH, was it properly installed?") - } - Err(err) => tracing::error!("subcommand failed: {err:?}"), - } - Ok(1) - } -} diff --git a/crates/spfs-cli/main/src/cmd_spfs.rs b/crates/spfs-cli/main/src/cmd_spfs.rs new file mode 100644 index 0000000000..772452da99 --- /dev/null +++ b/crates/spfs-cli/main/src/cmd_spfs.rs @@ -0,0 +1,168 @@ +use clap::{Parser, Subcommand}; +use spfs::{Error, OsErrorExt}; +use spfs_cli_common as cli; +use spfs_cli_common::CommandName; + +use crate::{ + cmd_check, + cmd_commit, + cmd_config, + cmd_diff, + cmd_edit, + cmd_info, + cmd_init, + cmd_layers, + cmd_log, + cmd_ls, + cmd_ls_tags, + cmd_migrate, + cmd_platforms, + cmd_pull, + cmd_push, + cmd_read, + cmd_reset, + cmd_run, + cmd_runtime, + cmd_search, + cmd_shell, + cmd_tag, + cmd_tags, + cmd_untag, + cmd_version, + cmd_write, +}; + +/// Filesystem isolation, capture and distribution. +#[derive(Debug, Parser)] +#[clap( + about, + after_help = "EXTERNAL SUBCOMMANDS:\ + \n render render the contents of an environment or layer\ + \n monitor watch a runtime and clean it up when complete\ + " +)] +pub struct Opt { + #[clap(flatten)] + pub logging: cli::Logging, + #[clap(subcommand)] + pub cmd: Command, +} + +#[derive(strum::AsRefStr, Debug, Subcommand)] +#[strum(serialize_all = "lowercase")] +#[clap(trailing_var_arg = true, dont_delimit_trailing_values = true)] +pub enum Command { + Version(cmd_version::CmdVersion), + Init(cmd_init::CmdInit), + Edit(cmd_edit::CmdEdit), + Commit(cmd_commit::CmdCommit), + Config(cmd_config::CmdConfig), + Reset(cmd_reset::CmdReset), + Run(cmd_run::CmdRun), + Tag(cmd_tag::CmdTag), + Untag(cmd_untag::CmdUntag), + Shell(cmd_shell::CmdShell), + Runtime(cmd_runtime::CmdRuntime), + Layers(cmd_layers::CmdLayers), + Platforms(cmd_platforms::CmdPlatforms), + Tags(cmd_tags::CmdTags), + Info(cmd_info::CmdInfo), + Pull(cmd_pull::CmdPull), + Push(cmd_push::CmdPush), + Log(cmd_log::CmdLog), + Search(cmd_search::CmdSearch), + Diff(cmd_diff::CmdDiff), + LsTags(cmd_ls_tags::CmdLsTags), + Ls(cmd_ls::CmdLs), + Migrate(cmd_migrate::CmdMigrate), + Check(cmd_check::CmdCheck), + Read(cmd_read::CmdRead), + Write(cmd_write::CmdWrite), + + #[cfg(feature = "server")] + Server(crate::cmd_server::CmdServer), + + #[clap(external_subcommand)] + External(Vec), +} + +impl CommandName for Opt { + fn command_name(&self) -> &str { + self.cmd.as_ref() + } +} + +impl Opt { + pub async fn run(&mut self, config: &spfs::Config) -> miette::Result { + match &mut self.cmd { + Command::Version(cmd) => cmd.run().await, + Command::Edit(cmd) => cmd.run(config).await, + Command::Init(cmd) => cmd.run(config).await, + Command::Commit(cmd) => cmd.run(config).await, + Command::Config(cmd) => cmd.run(config).await, + Command::Reset(cmd) => cmd.run(config).await, + Command::Tag(cmd) => cmd.run(config).await, + Command::Untag(cmd) => cmd.run(config).await, + Command::Runtime(cmd) => cmd.run(config).await, + Command::Layers(cmd) => cmd.run(config).await, + Command::Platforms(cmd) => cmd.run(config).await, + Command::Tags(cmd) => cmd.run(config).await, + Command::Info(cmd) => cmd.run(config).await, + Command::Log(cmd) => cmd.run(config).await, + Command::Search(cmd) => cmd.run(config).await, + Command::Diff(cmd) => cmd.run(config).await, + Command::LsTags(cmd) => cmd.run(config).await, + Command::Ls(cmd) => cmd.run(config).await, + Command::Migrate(cmd) => cmd.run(config).await, + Command::Check(cmd) => cmd.run(config).await, + Command::Read(cmd) => cmd.run(config).await, + Command::Write(cmd) => cmd.run(config).await, + Command::Run(cmd) => cmd.run(config).await, + Command::Shell(cmd) => cmd.run(config).await, + Command::Pull(cmd) => cmd.run(config).await, + Command::Push(cmd) => cmd.run(config).await, + #[cfg(feature = "server")] + Command::Server(cmd) => cmd.run(config).await, + Command::External(args) => run_external_subcommand(args.clone()).await, + } + } +} + +async fn run_external_subcommand(args: Vec) -> miette::Result { + { + let mut args = args.into_iter(); + let command = match args.next() { + None => { + tracing::error!("Invalid subcommand, cannot be empty"); + return Ok(1); + } + Some(c) => c, + }; + + // either in the PATH or next to the current binary + let cmd_path = match spfs::which_spfs(&command) { + Some(cmd) => cmd, + None => { + let mut p = std::env::current_exe() + .map_err(|err| Error::process_spawn_error("current_exe()", err, None))?; + p.set_file_name(&command); + p + } + }; + + let cmd = spfs::bootstrap::Command { + executable: cmd_path.into(), + args: args.map(Into::into).collect(), + vars: Vec::new(), + }; + + match cmd.exec() { + Ok(o) => match o {}, + Err(err) if err.is_os_not_found() => { + tracing::error!("{command} not found in PATH, was it properly installed?") + } + Err(err) => tracing::error!("subcommand failed: {err:?}"), + } + Ok(1) + } +} diff --git a/crates/spfs-cli/main/src/lib.rs b/crates/spfs-cli/main/src/lib.rs new file mode 100644 index 0000000000..79b0c2be36 --- /dev/null +++ b/crates/spfs-cli/main/src/lib.rs @@ -0,0 +1,37 @@ +// Copyright (c) Contributors to the SPK project. +// SPDX-License-Identifier: Apache-2.0 +// https://github.com/spkenv/spk + +mod cmd_check; +mod cmd_commit; +mod cmd_config; +mod cmd_diff; +mod cmd_edit; +mod cmd_info; +mod cmd_init; +mod cmd_layers; +mod cmd_log; +mod cmd_ls; +mod cmd_ls_tags; +mod cmd_migrate; +mod cmd_platforms; +mod cmd_pull; +mod cmd_push; +mod cmd_read; +mod cmd_reset; +mod cmd_run; +mod cmd_runtime; +mod cmd_runtime_info; +mod cmd_runtime_list; +mod cmd_runtime_prune; +mod cmd_runtime_remove; +mod cmd_search; +#[cfg(feature = "server")] +mod cmd_server; +mod cmd_shell; +pub mod cmd_spfs; +mod cmd_tag; +mod cmd_tags; +mod cmd_untag; +mod cmd_version; +mod cmd_write; diff --git a/docs/spfs/cli/markdown.md b/docs/spfs/cli/markdown.md new file mode 100644 index 0000000000..6e6114b2e9 --- /dev/null +++ b/docs/spfs/cli/markdown.md @@ -0,0 +1,795 @@ +--- +title: SPFS CLI +chapter: true +--- + +# Command-Line Help for `spfs-cli-main` + +This document contains the help content for the `spfs-cli-main` command-line program. + +**Command Overview:** + +* [`spfs-cli-main`↴](#spfs-cli-main) +* [`spfs-cli-main version`↴](#spfs-cli-main-version) +* [`spfs-cli-main init`↴](#spfs-cli-main-init) +* [`spfs-cli-main init repo`↴](#spfs-cli-main-init-repo) +* [`spfs-cli-main edit`↴](#spfs-cli-main-edit) +* [`spfs-cli-main commit`↴](#spfs-cli-main-commit) +* [`spfs-cli-main config`↴](#spfs-cli-main-config) +* [`spfs-cli-main reset`↴](#spfs-cli-main-reset) +* [`spfs-cli-main run`↴](#spfs-cli-main-run) +* [`spfs-cli-main tag`↴](#spfs-cli-main-tag) +* [`spfs-cli-main untag`↴](#spfs-cli-main-untag) +* [`spfs-cli-main shell`↴](#spfs-cli-main-shell) +* [`spfs-cli-main runtime`↴](#spfs-cli-main-runtime) +* [`spfs-cli-main runtime info`↴](#spfs-cli-main-runtime-info) +* [`spfs-cli-main runtime list`↴](#spfs-cli-main-runtime-list) +* [`spfs-cli-main runtime prune`↴](#spfs-cli-main-runtime-prune) +* [`spfs-cli-main runtime remove`↴](#spfs-cli-main-runtime-remove) +* [`spfs-cli-main layers`↴](#spfs-cli-main-layers) +* [`spfs-cli-main platforms`↴](#spfs-cli-main-platforms) +* [`spfs-cli-main tags`↴](#spfs-cli-main-tags) +* [`spfs-cli-main info`↴](#spfs-cli-main-info) +* [`spfs-cli-main pull`↴](#spfs-cli-main-pull) +* [`spfs-cli-main push`↴](#spfs-cli-main-push) +* [`spfs-cli-main log`↴](#spfs-cli-main-log) +* [`spfs-cli-main search`↴](#spfs-cli-main-search) +* [`spfs-cli-main diff`↴](#spfs-cli-main-diff) +* [`spfs-cli-main ls-tags`↴](#spfs-cli-main-ls-tags) +* [`spfs-cli-main ls`↴](#spfs-cli-main-ls) +* [`spfs-cli-main migrate`↴](#spfs-cli-main-migrate) +* [`spfs-cli-main check`↴](#spfs-cli-main-check) +* [`spfs-cli-main read`↴](#spfs-cli-main-read) +* [`spfs-cli-main write`↴](#spfs-cli-main-write) + +## `spfs-cli-main` + +SPK is a Package Manager for high-velocity software environments, built on SPFS. SPFS is a system for filesystem isolation, capture, and distribution. + +**Usage:** `spfs-cli-main [OPTIONS] ` + +EXTERNAL SUBCOMMANDS: + render render the contents of an environment or layer + monitor watch a runtime and clean it up when complete + +###### **Subcommands:** + +* `version` — Print the version of spfs +* `init` — Create an empty filesystem repository +* `edit` — Make the current runtime editable +* `commit` — Commit the current runtime state or a directory to storage +* `config` — Output the current configuration of spfs +* `reset` — Reset changes, or rebuild the entire spfs directory +* `run` — Run a program in a configured spfs environment +* `tag` — Tag an object +* `untag` — Remove tag versions or entire tag streams +* `shell` — Enter a subshell in a configured spfs environment +* `runtime` — View and manage spfs runtime information +* `layers` — List all layers in an spfs repository +* `platforms` — List all platforms in an spfs repository +* `tags` — List all tags in an spfs repository +* `info` — Display information about the current environment, or specific items +* `pull` — Pull one or more objects to the local repository +* `push` — Push one or more objects to a remote repository +* `log` — Log the history of a given tag over time +* `search` — Search for available tags by substring +* `diff` — Compare two spfs file system states +* `ls-tags` — List tags by their path +* `ls` — List the contents of a committed directory +* `migrate` — Migrate the data from and older repository format to the latest one +* `check` — Check a repositories internal integrity +* `read` — Output the contents of a blob to stdout +* `write` — Store an arbitrary blob of data in spfs + +###### **Options:** + +* `-v`, `--verbose` — Make output more verbose, can be specified more than once +* `--log-file ` — Additionally log output to the provided file +* `--timestamp` — Enables timestamp in logging (always enabled in file log) + + + +## `spfs-cli-main version` + +Print the version of spfs + +**Usage:** `spfs-cli-main version` + + + +## `spfs-cli-main init` + +Create an empty filesystem repository + +**Usage:** `spfs-cli-main init ` + +###### **Subcommands:** + +* `repo` — Initialize an empty filesystem repository + + + +## `spfs-cli-main init repo` + +Initialize an empty filesystem repository + +Does nothing when run on an existing repository + +**Usage:** `spfs-cli-main init repo ` + +###### **Arguments:** + +* `` — The root of the new repository + + + +## `spfs-cli-main edit` + +Make the current runtime editable + +**Usage:** `spfs-cli-main edit [OPTIONS]` + +###### **Options:** + +* `--off` — Disable edit mode instead +* `--keep-runtime` — Change a runtime into a durable runtime, will also make the runtime editable + + + +## `spfs-cli-main commit` + +Commit the current runtime state or a directory to storage + +**Usage:** `spfs-cli-main commit [OPTIONS] [KIND]` + +###### **Arguments:** + +* `` — The desired object type to create, skip this when giving --path or --ref + + Possible values: `layer`, `platform` + + +###### **Options:** + +* `-r`, `--remote ` — Commit files directly into a remote repository + + The default is to commit to the local repository. This flag is only valid with the --path argument. +* `-t`, `--tag ` — A human-readable tag for the generated object + + Can be provided more than once. +* `--path ` — Commit this directory instead of the current spfs changes +* `--ref ` — Combine existing items into a platform, use a '+' to join multiple +* `--hash-while-committing` — Hash the files while committing, rather than before. + + This option can improve commit times when a large number of the files are both large, and don't already exist in the repository. It may degrade commit times when committing directly to a slow or remote repository. When given, all files are written to the repository even if the payload exists, rather than hashing the file first to determine if it needs to be transferred. +* `--max-concurrent-blobs ` — The total number of blobs that can be committed concurrently + + Default value: `1000` +* `--max-concurrent-branches ` — The total number of branches that can be processed concurrently at each level of the rendered file tree. + + The number of active trees being processed can grow exponentially by this exponent for each additional level of depth in the rendered file tree. In general, this number should be kept low. + + Default value: `5` + + + +## `spfs-cli-main config` + +Output the current configuration of spfs + +**Usage:** `spfs-cli-main config` + + + +## `spfs-cli-main reset` + +Reset changes, or rebuild the entire spfs directory + +**Usage:** `spfs-cli-main reset [OPTIONS] [PATHS]...` + +###### **Arguments:** + +* `` — Glob patterns in the spfs dir of files to reset, defaults to everything + +###### **Options:** + +* `--sync` — Sync the latest information for each tag even if it already exists +* `--check` — Traverse and check the entire graph, filling in any missing data + + When a repository is in good health, this should not be necessary, but if some subset of the data has been deleted or lost, this option may help recover it. +* `--resync` — Forcefully sync all associated graph data even if it already exists + + When a repository is in good health, this should not be necessary, but if some subset of the data has been deleted, lost, or corrupted this option may help recover it. +* `--max-concurrent-manifests ` — The total number of manifests that can be synced concurrently + + Default value: `100` +* `--max-concurrent-payloads ` — The total number of file payloads that can be synced concurrently + + Default value: `100` +* `--progress ` — Options for showing progress + + Possible values: + - `bars`: + Show progress bars (default) + - `none`: + Do not show any progress + +* `-e`, `--edit` — Mount the resulting runtime in edit mode + + Default to true if REF is empty or not given +* `-r`, `--ref ` — The tag or id to rebuild the runtime with. + + Uses current runtime stack if not given. Use '-' or an empty string to request an empty environment. Only valid if no paths are given + + + +## `spfs-cli-main run` + +Run a program in a configured spfs environment + +**Usage:** `spfs-cli-main run [OPTIONS] <--rerun |REFERENCE> [-- ...]` + +###### **Arguments:** + +* `` — The tag or id of the desired runtime + + Use '-' to or an empty string to request an empty environment +* `` — The command to run in the environment and its arguments + + In order to ensure that flags are passed as-is, '--' must be place before specifying the command and any flags that should be given to that command: e.g. `spfs run -- command --flag-for-command` + +###### **Options:** + +* `--sync` — Sync the latest information for each tag even if it already exists +* `--check` — Traverse and check the entire graph, filling in any missing data + + When a repository is in good health, this should not be necessary, but if some subset of the data has been deleted or lost, this option may help recover it. +* `--resync` — Forcefully sync all associated graph data even if it already exists + + When a repository is in good health, this should not be necessary, but if some subset of the data has been deleted, lost, or corrupted this option may help recover it. +* `--max-concurrent-manifests ` — The total number of manifests that can be synced concurrently + + Default value: `100` +* `--max-concurrent-payloads ` — The total number of file payloads that can be synced concurrently + + Default value: `100` +* `--progress ` — Options for showing progress + + Possible values: + - `bars`: + Show progress bars (default) + - `none`: + Do not show any progress + +* `-v`, `--verbose` — Make output more verbose, can be specified more than once +* `--log-file ` — Additionally log output to the provided file +* `--timestamp` — Enables timestamp in logging (always enabled in file log) +* `-e`, `--edit` — Mount the spfs filesystem in edit mode (default if REF is empty or not given) +* `--no-edit` — Mount the spfs filesystem in read-only mode (default if REF is non-empty) +* `--force` — Requires --rerun. Force reset the process fields of the runtime before it is run again +* `-k`, `--keep-runtime` — Use to keep the runtime around rather than deleting it when the process exits. This is best used with '--name NAME' to make rerunning the runtime easier at a later time +* `--runtime-name ` — Provide a name for this runtime to make it easier to identify +* `--rerun ` — Name of an existing durable runtime to reuse for this run +* `--annotation ` — Adds annotation key-value string data to the new runtime. + + This allows external processes to store arbitrary data in the runtimes they create. This is most useful with durable runtimes. The data can be retrieved by running `spfs runtime info` or `spfs info` and using the `--get ` or `--get-all` options + + Annotation data is specified as key-value string pairs separated by either an equals sign or colon (--annotation name=value --annotation other:value). Multiple pairs of annotation data can also be specified at once in yaml or json format (--annotation '{name: value, other: value}'). + + Annotation data can also be given in a json or yaml file, by using the `--annotation-file ` argument. If given, `--annotation` arguments will supersede anything given in annotation files. + + If the same key is used more than once, the last key-value pair will override the earlier values for the same key. +* `--annotation-file ` — Specify annotation key-value data from a json or yaml file (see --annotation) + + + +## `spfs-cli-main tag` + +Tag an object + +**Usage:** `spfs-cli-main tag [OPTIONS] ...` + +###### **Arguments:** + +* `` — The reference or id of the item to tag +* `` — The tag(s) to point to the the given target + +###### **Options:** + +* `-r`, `--remote ` — Create tags in a remote repository instead of the local one + + + +## `spfs-cli-main untag` + +Remove tag versions or entire tag streams + +**Usage:** `spfs-cli-main untag [OPTIONS] ` + +###### **Arguments:** + +* `` — The tag to remove + + Unless --all or --latest is provided, this must have an explicit version number (eg: path/name~0) + +###### **Options:** + +* `-r`, `--remote ` — Remove tags in a remote repository instead of the local one +* `--latest` — Only remove the latest version of this tag +* `-a`, `--all` — Remove all versions of this tag, deleting it completely + + + +## `spfs-cli-main shell` + +Enter a subshell in a configured spfs environment + +**Usage:** `spfs-cli-main shell [OPTIONS] <--rerun |REF>` + +###### **Arguments:** + +* `` — The tag or id of the desired runtime + + Use '-' or an empty string to request an empty environment + +###### **Options:** + +* `--sync` — Sync the latest information for each tag even if it already exists +* `--check` — Traverse and check the entire graph, filling in any missing data + + When a repository is in good health, this should not be necessary, but if some subset of the data has been deleted or lost, this option may help recover it. +* `--resync` — Forcefully sync all associated graph data even if it already exists + + When a repository is in good health, this should not be necessary, but if some subset of the data has been deleted, lost, or corrupted this option may help recover it. +* `--max-concurrent-manifests ` — The total number of manifests that can be synced concurrently + + Default value: `100` +* `--max-concurrent-payloads ` — The total number of file payloads that can be synced concurrently + + Default value: `100` +* `--progress ` — Options for showing progress + + Possible values: + - `bars`: + Show progress bars (default) + - `none`: + Do not show any progress + +* `-v`, `--verbose` — Make output more verbose, can be specified more than once +* `--log-file ` — Additionally log output to the provided file +* `--timestamp` — Enables timestamp in logging (always enabled in file log) +* `-e`, `--edit` — Mount the spfs filesystem in edit mode (true if REF is empty or not given) +* `--no-edit` — Mount the spfs filesystem in read-only mode (default if REF is non-empty) +* `--rerun ` — Name of a previously run durable runtime to reuse for this run +* `--force` — Requires --rerun. Force reset the process fields of the runtime before it is run again +* `--runtime-name ` — Provide a name for this runtime to make it easier to identify +* `-k`, `--keep-runtime` — Use to keep the runtime around rather than deleting it when the process exits. This is best used with '--name NAME' to make rerunning the runtime easier at a later time +* `--annotation ` — Adds annotation key-value string data to the new runtime. + + This allows external processes to store arbitrary data in the runtimes they create. This is most useful with durable runtimes. The data can be retrieved by running `spfs runtime info` or `spfs info` and using the `--get ` or `--get-all` options + + Annotation data is specified as key-value string pairs separated by either an equals sign or colon (--annotation name=value --annotation other:value). Multiple pairs of annotation data can also be specified at once in yaml or json format (--annotation '{name: value, other: value}'). + + Annotation data can also be given in a json or yaml file, by using the `--annotation-file ` argument. If given, `--annotation` arguments will supersede anything given in annotation files. + + If the same key is used more than once, the last key-value pair will override the earlier values for the same key. +* `--annotation-file ` — Specify annotation key-value data from a json or yaml file (see --annotation) + + + +## `spfs-cli-main runtime` + +View and manage spfs runtime information + +**Usage:** `spfs-cli-main runtime ` + +**Command Alias:** `rt` + +###### **Subcommands:** + +* `info` — Show the complete state of a runtime +* `list` — List runtime information from the repository +* `prune` — Find and remove runtimes from the repository based on a pruning strategy +* `remove` — Remove runtimes from the repository + + + +## `spfs-cli-main runtime info` + +Show the complete state of a runtime + +**Usage:** `spfs-cli-main runtime info [OPTIONS] ` + +###### **Arguments:** + +* `` — The name/id of the runtime to remove + +###### **Options:** + +* `-r`, `--remote ` — Load a runtime in a remote or alternate repository +* `--get ` — Output the data value for the given annotation key(s) from the active runtime. Each value is printed on its own line without its key +* `--get-all` — Output all the annotation keys and values from the active runtime as a yaml dictionary + + + +## `spfs-cli-main runtime list` + +List runtime information from the repository + +**Usage:** `spfs-cli-main runtime list [OPTIONS]` + +**Command Alias:** `ls` + +###### **Options:** + +* `-r`, `--remote ` — List runtimes in a remote or alternate repository +* `-q`, `--quiet` — Only print the name of each runtime, no additional data + + + +## `spfs-cli-main runtime prune` + +Find and remove runtimes from the repository based on a pruning strategy + +**Usage:** `spfs-cli-main runtime prune [OPTIONS]` + +###### **Options:** + +* `-r`, `--remote ` — Prune a runtime in a remote or alternate repository +* `--ignore-user` — Remove the runtime even if it's owned by someone else +* `--ignore-host` — Remove the runtime even if it appears to be from a different host + + Implies --ignore-monitor +* `--ignore-monitor` — Do not try and terminate the monitor process, just remove runtime data +* `--from-before-boot` — Remove runtimes started before last reboot + + + +## `spfs-cli-main runtime remove` + +Remove runtimes from the repository + +**Usage:** `spfs-cli-main runtime remove [OPTIONS] [NAME]...` + +**Command Alias:** `rm` + +###### **Arguments:** + +* `` — The name/id of the runtime to remove + +###### **Options:** + +* `-r`, `--remote ` — Remove a runtime in a remote or alternate repository +* `-f`, `--force` — Remove the runtime from the repository forcefully + + Even if the monitor cannot be stopped or killed the data will be removed from the repository. +* `--ignore-user` — Remove the runtime even if it's owned by someone else +* `--ignore-host` — Remove the runtime even if it appears to be from a different host + + Implies --ignore-monitor +* `--ignore-monitor` — Do not try and terminate the monitor process, just remove runtime data +* `--remove-durable` — Allow durable runtimes to be removed, normally they will not be removed + + + +## `spfs-cli-main layers` + +List all layers in an spfs repository + +**Usage:** `spfs-cli-main layers [OPTIONS]` + +###### **Options:** + +* `-r`, `--remote ` — Show layers from remote repository instead of the local one +* `--short` — Show the shortened form of each reported layer digest +* `--tags` — Also find and report any tags that point to each layer, implies --short + + + +## `spfs-cli-main platforms` + +List all platforms in an spfs repository + +**Usage:** `spfs-cli-main platforms [OPTIONS]` + +###### **Options:** + +* `-r`, `--remote ` — Show layers from remote repository instead of the local one +* `--short` — Show the shortened form of each reported layer digest +* `--tags` — Also find and report any tags that point to each platform, implies --short + + + +## `spfs-cli-main tags` + +List all tags in an spfs repository + +**Usage:** `spfs-cli-main tags [OPTIONS]` + +###### **Options:** + +* `-r`, `--remote ` — Show layers from remote repository instead of the local one +* `--target` — Also show the target digest of each tag +* `--short` — Show the shortened form of each reported digest, implies --target + + + +## `spfs-cli-main info` + +Display information about the current environment, or specific items + +**Usage:** `spfs-cli-main info [OPTIONS] [REF]...` + +###### **Arguments:** + +* `` — Tag, id, or /spfs/file/path to show information about + +###### **Options:** + +* `-v`, `--verbose` — Make output more verbose, can be specified more than once +* `--log-file ` — Additionally log output to the provided file +* `--timestamp` — Enables timestamp in logging (always enabled in file log) +* `--get ` — Output the data value for the given annotation key(s) from the active runtime. Each value is printed on its own line without its key +* `--get-all` — Output all the annotation keys and values from the active runtime as a yaml dictionary +* `-H`, `--human-readable` — Lists file sizes in human readable format +* `-r`, `--remote ` — Operate on a remote repository instead of the local one + + This is really only helpful if you are providing a specific ref to look up. +* `--tags` — Also find and report any tags that point to any identified digest (implies '--short') +* `--short` — Use shortened digests in the output (nicer, but slower) +* `--follow` — Follow and show child objects, depth-first + + + +## `spfs-cli-main pull` + +Pull one or more objects to the local repository + +**Usage:** `spfs-cli-main pull [OPTIONS] ...` + +###### **Arguments:** + +* `` — The reference(s) to pull/localize + + These can be individual tags or digests, or they may also be a collection of items joined by a '+' + +###### **Options:** + +* `--sync` — Sync the latest information for each tag even if it already exists +* `--check` — Traverse and check the entire graph, filling in any missing data + + When a repository is in good health, this should not be necessary, but if some subset of the data has been deleted or lost, this option may help recover it. +* `--resync` — Forcefully sync all associated graph data even if it already exists + + When a repository is in good health, this should not be necessary, but if some subset of the data has been deleted, lost, or corrupted this option may help recover it. +* `--max-concurrent-manifests ` — The total number of manifests that can be synced concurrently + + Default value: `100` +* `--max-concurrent-payloads ` — The total number of file payloads that can be synced concurrently + + Default value: `100` +* `--progress ` — Options for showing progress + + Possible values: + - `bars`: + Show progress bars (default) + - `none`: + Do not show any progress + +* `-v`, `--verbose` +* `-r`, `--remote ` — The name or address of the remote server to pull from + + Defaults to searching all configured remotes + + + +## `spfs-cli-main push` + +Push one or more objects to a remote repository + +**Usage:** `spfs-cli-main push [OPTIONS] ...` + +###### **Arguments:** + +* `` — The reference(s) to push + + These can be individual tags or digests, or they may also be a collection of items joined by a '+' + +###### **Options:** + +* `--sync` — Sync the latest information for each tag even if it already exists +* `--check` — Traverse and check the entire graph, filling in any missing data + + When a repository is in good health, this should not be necessary, but if some subset of the data has been deleted or lost, this option may help recover it. +* `--resync` — Forcefully sync all associated graph data even if it already exists + + When a repository is in good health, this should not be necessary, but if some subset of the data has been deleted, lost, or corrupted this option may help recover it. +* `--max-concurrent-manifests ` — The total number of manifests that can be synced concurrently + + Default value: `100` +* `--max-concurrent-payloads ` — The total number of file payloads that can be synced concurrently + + Default value: `100` +* `--progress ` — Options for showing progress + + Possible values: + - `bars`: + Show progress bars (default) + - `none`: + Do not show any progress + +* `-v`, `--verbose` +* `-r`, `--remote ` — The name or address of the remote server to push to + + Default value: `origin` + + + +## `spfs-cli-main log` + +Log the history of a given tag over time + +**Usage:** `spfs-cli-main log [OPTIONS] ` + +###### **Arguments:** + +* `` — The tag to show history of + +###### **Options:** + +* `-r`, `--remote ` — Load the tag from remote repository instead of the local one + + + +## `spfs-cli-main search` + +Search for available tags by substring + +**Usage:** `spfs-cli-main search ` + +###### **Arguments:** + +* `` — The search term/substring to look for + + + +## `spfs-cli-main diff` + +Compare two spfs file system states + +**Usage:** `spfs-cli-main diff [FROM] [TO]` + +###### **Arguments:** + +* `` — The tag or id to use as the base of the computed diff, defaults to the current runtime +* `` — The tag or id to diff the base against, defaults to the contents of the spfs filesystem + + + +## `spfs-cli-main ls-tags` + +List tags by their path + +**Usage:** `spfs-cli-main ls-tags [OPTIONS] [PATH]` + +**Command Alias:** `list-tags` + +###### **Arguments:** + +* `` — The tag path to list under + + Default value: `/` + +###### **Options:** + +* `-r`, `--remote ` — List tags from a remote repository instead of the local one +* `--recursive` — Walk the tag tree recursively listing all tags under the specified dir + + + +## `spfs-cli-main ls` + +List the contents of a committed directory + +**Usage:** `spfs-cli-main ls [OPTIONS] [PATH]` + +**Command Aliases:** `list-dir`, `list` + +###### **Arguments:** + +* `` — The tag or digest of the file tree to read from +* `` — The subdirectory to list + + Default value: `/spfs` + +###### **Options:** + +* `-r`, `--remote ` — List files on a remote repository instead of the local one +* `-R`, `--recursive` — Recursively list all files and directories +* `-l` — Long listing format +* `-H`, `--human-readable` — Lists file sizes in human readable format + + + +## `spfs-cli-main migrate` + +Migrate the data from and older repository format to the latest one + +**Usage:** `spfs-cli-main migrate [OPTIONS] ` + +###### **Arguments:** + +* `` — The path to the filesystem repository to migrate + +###### **Options:** + +* `--upgrade` — Replace old data with migrated data one complete + + + +## `spfs-cli-main check` + +Check a repositories internal integrity + +**Usage:** `spfs-cli-main check [OPTIONS] [REF]...` + +###### **Arguments:** + +* `` — Objects to recursively check, defaults to everything + +###### **Options:** + +* `-r`, `--remote ` — Trigger the check operation on a remote repository instead of the local one +* `--max-tag-stream-concurrency ` — The maximum number of tag streams that can be read and processed at once + + Default value: `1000` +* `--max-object-concurrency ` — The maximum number of objects that can be validated at once + + Default value: `5000` +* `--pull ` — Attempt to fix problems by pulling from another repository. Defaults to "origin" + + + +## `spfs-cli-main read` + +Output the contents of a blob to stdout + +**Usage:** `spfs-cli-main read [OPTIONS] [PATH]` + +**Command Aliases:** `read-file`, `cat`, `cat-file` + +###### **Arguments:** + +* `` — The tag or digest of the blob/payload to output +* `` — If the given ref is not a blob, read the blob found at this path + +###### **Options:** + +* `-r`, `--remote ` — Read from a remote repository instead of the local one + + + +## `spfs-cli-main write` + +Store an arbitrary blob of data in spfs + +**Usage:** `spfs-cli-main write [OPTIONS]` + +**Command Alias:** `write-file` + +###### **Options:** + +* `-t`, `--tag ` — A human-readable tag for the generated object + + Can be provided more than once. +* `-r`, `--remote ` — Write to a remote repository instead of the local one +* `-f`, `--file ` — Store the contents of this file instead of reading from stdin + + + +
+ + + This document was generated automatically by + clap-markdown. +