Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ only on the last hyphen when the suffix starts with a digit.
Values resolve in this order: `${PACKAGE_ROOT}`, `${VERSION}`, `${NAME}`,
`${PATHSEP}` (`:` on Unix / `;` on Windows), `${EXE_SUFFIX}` (`""` on Unix /
`".exe"` on Windows), then any `${VAR}` set by previously resolved packages or
the inherited environment, and finally `~/` which expands at every path
the inherited environment, and finally `~/`, which expands at every path
segment, so `~/USD/bin${PATHSEP}~/USD/lib` works as expected. On Windows
PowerShell sessions `~/` falls back to `USERPROFILE` when `HOME` is unset.

Expand All @@ -147,7 +147,7 @@ through.

The `commands` map lets `anvil run` pick a program from the package definition.
Values expand the same way as `environment` values, and can include baked in
arguments with whitespace or tilde segments — anvil tokenises the value with
arguments with whitespace or tilde segments. Anvil tokenises the value with
POSIX shell rules, expands `~/` in every token, then runs the first token
with the remaining tokens prepended to whatever the user passes after `--`.

Expand All @@ -167,7 +167,7 @@ commands:
```

`anvil run nukex -- --view` therefore exec's
`${NUKE_HOME}/Nuke${VERSION} --nukex --view` — packages can ship sane defaults
`${NUKE_HOME}/Nuke${VERSION} --nukex --view`. Packages can ship sane defaults
for every tool they expose without forcing users to memorise flag soup. Quoted
substrings are preserved as a single argv element, so paths with spaces work
without escaping the whole value.
Expand Down
18 changes: 9 additions & 9 deletions docs/walkthrough.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,13 @@ anvil info houdini-20.5

```bash
anvil validate
# blender
# houdini
# nuke
# python
# studio-blender-tools
# studio-python
# usd
# OK blender
# OK houdini
# OK nuke
# OK python
# OK studio-blender-tools
# OK studio-python
# OK usd
# All packages valid!
```

Expand All @@ -94,7 +94,7 @@ anvil env python-3.11 --json | python3 -c "import sys,json; print(json.load(sys.

### Dependency resolution

Houdini depends on python-3.11 both are resolved automatically:
Houdini depends on python-3.11, and both are resolved automatically:

```bash
anvil env houdini-20.5 | grep -E "PYTHON_VERSION|HOUDINI_VERSION"
Expand Down Expand Up @@ -171,7 +171,7 @@ anvil run python-3.11 -e MY_VAR=hello -- env | grep MY_VAR

```bash
# Start a shell with packages loaded
# (will replace the current process type 'exit' to return)
# (will replace the current process; type 'exit' to return)
anvil shell python-3.11

# Specify a different shell
Expand Down
7 changes: 4 additions & 3 deletions src/cache.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,14 +41,12 @@ pub fn compute_fingerprint(package_paths: &[PathBuf], config_salt: &str) -> u64
base.hash(&mut hasher);
hash_dir_entries(base, &mut hasher);

// One level deeper for nested packages
if let Ok(entries) = std::fs::read_dir(base) {
for entry in entries.flatten() {
let path = entry.path();
if path.is_dir() {
hash_dir_entries(&path, &mut hasher);

// Check package.yaml files inside version dirs
if let Ok(sub_entries) = std::fs::read_dir(&path) {
for sub in sub_entries.flatten() {
if sub.path().is_dir() {
Expand Down Expand Up @@ -116,7 +114,10 @@ fn hash_file_mtime(path: &Path, hasher: &mut impl Hasher) {

/// Try to load cached packages. Returns `Some(packages)` if the cache
/// is valid (fingerprint matches), `None` otherwise.
pub fn load(package_paths: &[PathBuf], config_salt: &str) -> Option<HashMap<String, HashMap<String, Package>>> {
pub fn load(
package_paths: &[PathBuf],
config_salt: &str,
) -> Option<HashMap<String, HashMap<String, Package>>> {
let path = cache_path()?;
if !path.exists() {
return None;
Expand Down
11 changes: 3 additions & 8 deletions src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use clap::{CommandFactory, Parser, Subcommand};
#[command(name = "anvil")]
#[command(author = "Alejandro Cabrera <voidreamer@gmail.com>")]
#[command(version)]
#[command(about = "Forge your environment 🔨 — Fast package resolution for VFX pipelines", long_about = None)]
#[command(about = "Forge your environment. Fast package resolution for VFX pipelines", long_about = None)]
pub struct Cli {
/// Ignore any cached package scan and re-read all package files.
#[arg(long, global = true)]
Expand Down Expand Up @@ -63,7 +63,7 @@ pub enum Commands {
#[arg(short, long)]
shell: Option<String>,

/// Don't materialise `commands:` as PATH shims compose the env only.
/// Don't materialise `commands:` as PATH shims; compose the env only.
#[arg(long)]
env_only: bool,

Expand Down Expand Up @@ -170,12 +170,7 @@ pub enum Commands {
impl Cli {
/// Generate shell completions and write to stdout.
pub fn print_completions(shell: clap_complete::Shell) {
clap_complete::generate(
shell,
&mut Self::command(),
"anvil",
&mut std::io::stdout(),
);
clap_complete::generate(shell, &mut Self::command(), "anvil", &mut std::io::stdout());
}
}

Expand Down
12 changes: 9 additions & 3 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,6 @@ impl Config {
config.merge(project);
}

// Apply platform overrides and expand paths after merging
config.apply_platform_overrides();
config.expand_paths();

Expand Down Expand Up @@ -420,7 +419,10 @@ impl Config {
}

/// Run a list of hook commands. Returns Err if any hook exits non-zero.
pub fn run_hooks(hooks: &[String], env: &std::collections::HashMap<String, String>) -> Result<()> {
pub fn run_hooks(
hooks: &[String],
env: &std::collections::HashMap<String, String>,
) -> Result<()> {
for cmd in hooks {
let shell = if cfg!(target_os = "windows") {
"cmd"
Expand All @@ -441,7 +443,11 @@ impl Config {
.with_context(|| format!("Failed to run hook: {}", cmd))?;

if !status.success() {
anyhow::bail!("Hook failed (exit {}): {}", status.code().unwrap_or(-1), cmd);
anyhow::bail!(
"Hook failed (exit {}): {}",
status.code().unwrap_or(-1),
cmd
);
}
}
Ok(())
Expand Down
13 changes: 4 additions & 9 deletions src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,6 @@ use std::path::{Path, PathBuf};
use anyhow::{Context as _, Result};
use serde::{Deserialize, Serialize};

// ---------------------------------------------------------------------------
// Lockfile
// ---------------------------------------------------------------------------

/// Pins package versions for reproducible resolution.
///
/// Stored as `anvil.lock` in the project directory. When present, the
Expand All @@ -35,7 +31,10 @@ impl Lockfile {
/// Write the lockfile to a YAML file.
pub fn save(&self, path: &Path) -> Result<()> {
let content = serde_yaml::to_string(self)?;
let output = format!("# anvil.lock — generated by `anvil lock`, do not edit\n{}", content);
let output = format!(
"# anvil.lock: generated by `anvil lock`, do not edit\n{}",
content
);
std::fs::write(path, output)
.with_context(|| format!("Failed to write lockfile: {:?}", path))
}
Expand All @@ -55,10 +54,6 @@ impl Lockfile {
}
}

// ---------------------------------------------------------------------------
// Saved context
// ---------------------------------------------------------------------------

/// A fully resolved environment that can be saved, shared, and re-loaded
/// without re-running resolution. Useful for render farms, CI, and
/// sharing reproducible environments across machines.
Expand Down
Loading
Loading