From ebd42456124ca861f32d62c5fccd1f12116c4418 Mon Sep 17 00:00:00 2001 From: Mark Dittmer Date: Tue, 19 May 2026 16:53:37 +0000 Subject: [PATCH] [anneal][v2][exocrate] Crate-level documentation - Documentation with examples crate `lib.rs` - Simple explanation, diagram, and link to crate docs in `README.md` - Test-data archive referenced in doc-tested example code - Can also be used in future integration tests if desired gherrit-pr-id: Gmum75fawi66ursah6w4azlcro7hvrkf4 --- anneal/v2/exocrate/README.md | 9 ++ anneal/v2/exocrate/src/lib.rs | 139 +++++++++++++++++- anneal/v2/exocrate/tests/my-tool-deps.tar.zst | Bin 0 -> 184 bytes 3 files changed, 147 insertions(+), 1 deletion(-) create mode 100644 anneal/v2/exocrate/README.md create mode 100644 anneal/v2/exocrate/tests/my-tool-deps.tar.zst diff --git a/anneal/v2/exocrate/README.md b/anneal/v2/exocrate/README.md new file mode 100644 index 0000000000..f925e2c718 --- /dev/null +++ b/anneal/v2/exocrate/README.md @@ -0,0 +1,9 @@ +# Exocrate: An exoskeleton for your crate + +Exocrate is a manager for rust crate dependencies which are not managed by the `cargo` tool itself, such as external toolchains, large binary files, etc. + + + +See [crate documentation](src/lib.rs) for details. + + diff --git a/anneal/v2/exocrate/src/lib.rs b/anneal/v2/exocrate/src/lib.rs index 895b018544..20892a8d05 100644 --- a/anneal/v2/exocrate/src/lib.rs +++ b/anneal/v2/exocrate/src/lib.rs @@ -10,7 +10,144 @@ //! Exocrate: An exoskeleton for your crate. //! //! Exocrate is a manager for crate dependencies which are not managed by Cargo -//! itself. This might include external toolchains, large binary files, etc. +//! itself such as external toolchains, large binary files, etc. +//! +//! Exocrate *assumes*: +//! +//! - An external mechanism that packages external dependencies into a single archive. +//! +//! Exocrate *supports*: +//! +//! - Remote archives loaded by URL and verified by checksum; +//! - Local archives designated by file path. +//! +//! Exocrate *provides* mechanisms to: +//! +//! - Install external dependencies: +//! - Download and extract an archive; +//! - Fix up archive artifacts that depend on the installed environment (e.g., rewriting absolute +//! paths in dependency files); +//! - Install archive contents in a versioned filesystem location. +//! - Access extracted external dependencies: +//! - Resolve current installation location. +//! +//! # How exocrate installations are versioned +//! +//! ## Platform + versioned files list +//! +//! The simplest way to auto-version your installations is using macros that tie your installation +//! platform (i.e., `std::env::consts::OS` and `std::env::consts::ARCH` values) and versioning +//! files that will change anytime your external dependencies might. Here is an example of +//! realizing this versioning strategy using the macros exported by `exocrate`: +//! +//! ```rust +//! exocrate::config! { +//! const CONFIG: Config = Config { +//! // Path components that are joined to establish the base directory for all exocrate +//! // installations. +//! // +//! // For `my-tool` developers: `/target/.my-tool/exocrate/` +//! // For `my-tool` users: `~/.my-tool/exocrate/` +//! rel_dir_path: [".my-tool", "exocrate"], +//! // Since the definition of platform-specific exocrate releases for `my-tool` will be +//! // specified in its `Cargo.toml` file (see below), we use that file as a "change +//! // detector" to change the version whenever `Cargo.toml` changes. +//! // +//! // This is an over-approximation: unrelated changes to `Cargo.toml` (e.g., change in +//! // crate dependencies, shipping an exocrate release for some other platform, etc.) will +//! // also change the exocrate version. This is generally not a problem because only +//! // developers of `my-tool` itself need to deal with noisy exocrate version changes; +//! // users will only install versions associated with less frequent releases of +//! // `my-tool`. +//! versioned_files: &["../Cargo.toml"], +//! }; +//! } +//! +//! exocrate::parse_remote_archive! { +//! const REMOTE: RemoteArchive = "Cargo.toml" [ +//! // `(std::env::consts::OS, std::env::consts::ARCH)` pairs you support. +//! (linux, x86_64), +//! (macos, x86_64), +//! (linux, aarch64), +//! (macos, aarch64), +//! ]; +//! } +//! +//! +//! // FIXME: Detect whether running in tool-installed or tool-development environment. The typical +//! // pattern would be: +//! // - tool-installed => use `exocrate::Location::UserGlobal`, +//! // - tool-development => use `exocrate::Location::Local`. +//! let location: exocrate::Location = exocrate::Location::Local; +//! +//! // FIXME: Use environment detection here too. The typical pattern would be: +//! // - tool-installed => use `exocrate::Source::Remote(REMOTE)`, +//! // - tool-development => use +//! // `exocrate::Source::Local("/path/to/dep-archive-builder-output.tar.zst".into())`. +//! let source: exocrate::Source = exocrate::Source::Local("tests/my-tool-deps.tar.zst".into()); +//! +//! // Check whether `source` archive is already installed at `location`, and if not, install it. +//! let installed_exocrate_dir = CONFIG.resolve_installation_dir_or_install(location, source) +//! .expect("failed to resolve or install my-tool's exocrate"); +//! +//! // Invoke tool installed from `tests/my-tool-deps.tar.zst` extracted to versioned exocrate +//! // directory. +//! let tool_status = std::process::Command::new(installed_exocrate_dir.join("bin").join("tool")) +//! .status() +//! .expect("failed to start external dependency located at `bin/tool`"); +//! assert!(tool_status.success()); +//! ``` +//! +//! And in your `Cargo.toml`: +//! +//! ```toml +//! # +//! # Prepares `REMOTE = exocrate::RemoteArchive { sha256, url }` according to compile-time machine +//! # `std::env::consts::OS . std::env::consts::ARCH` listed as supported in your invocation of +//! # `exocrate::parse_remote_archive`. +//! # +//! [package.metadata.exocrate.linux.x86_64] +//! # FIXME: Replace `sha256` with actual linux-x86_64.tar.zst checksum. +//! sha256 = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" +//! url = "https://example.com/linux-x86_64.tar.zst" +//! +//! [package.metadata.exocrate.macos.x86_64] +//! # FIXME: Replace `sha256` with actual macos-x86_64.tar.zst checksum. +//! sha256 = "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" +//! url = "https://example.com/macos-x86_64.tar.zst" +//! +//! [package.metadata.exocrate.linux.aarch64] +//! # FIXME: Replace `sha256` with actual linux-aarch64.tar.zst checksum. +//! sha256 = "cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc" +//! url = "https://example.com/linux-aarch64.tar.zst" +//! +//! [package.metadata.exocrate.macos.aarch64] +//! # FIXME: Replace `sha256` with actual macos-aarch64.tar.zst checksum. +//! sha256 = "dddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddd" +//! url = "https://example.com/macos-aarch64.tar.zst" +//! ``` +//! +//! ### Limitations +//! +//! This versioning strategy does not distinguish between changes to `package.metadata.exocrate` and +//! other changes to `Cargo.toml`. This can result in proliferation of distinct exocrate versions +//! that developers need to clear out if your exocrate is particularly large. This cleanup can be +//! achieved using `cargo clean`. +//! +//! ## Custom versioning +//! +//! Manually constructing an [`exocrate::Config`] offers you full control over the base directory +//! (relative to one or another `exocrate::Location` for installation) and version string that is +//! used to construct this `Config`'s version of the exocrate. By using this pattern, you take +//! responsbility for determining what version of your exocrate corresponds with the code consuming +//! the `exocrate` library. +//! +//! # Limitations +//! +//! Exocrate does not currently support any helpers for cleaning up old versions of your exocrate +//! installations. All installed versions will be stored somewhere inside the directories designated +//! by one of the [`exocrate::Location`] variants, but there are no other guarantees about how these +//! directory trees are managed at this time. mod sync; diff --git a/anneal/v2/exocrate/tests/my-tool-deps.tar.zst b/anneal/v2/exocrate/tests/my-tool-deps.tar.zst new file mode 100644 index 0000000000000000000000000000000000000000..f6f79fe9cfc1cb05cde1041c64688baf52e71a42 GIT binary patch literal 184 zcmV;p07w5QwJ-eySX~7G(g+f$$;FnoEf8&ks|K0-@KMDQM-ehOn3890Lew zcl`~^{v22rX2 literal 0 HcmV?d00001