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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,45 @@
# Changelog

## Unreleased

**Features**

* Walkfile inheritance: walk(1) now searches up the directory tree for a Walkfile, allowing a single Walkfile at the project root to handle targets in any subdirectory. This eliminates the need to create a Walkfile in every directory.

* Walkfile fallback (exit code 200): A local Walkfile can delegate to a parent Walkfile by exiting with code 200. This enables composition where a local Walkfile handles specific targets while inheriting generic rules from a parent:
```bash
case $target in
special) ;; # handle locally
*) exit 200 ;; # delegate to parent
esac
```
Comment on lines +7 to +15

Copilot AI Mar 7, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This changelog entry says delegation is “exit code 200” but then says “exiting with code 127”. That’s contradictory and doesn’t match ExitCodeDelegate=200 elsewhere in the PR. Please correct the text to consistently use 200.

Copilot uses AI. Check for mistakes.

**Breaking Changes**

* **Target name (`$2`) format changed**: When a Walkfile is found in a parent directory, `$2` now contains the path relative to the Walkfile's directory (e.g., `subdir/foo.o` instead of `foo.o`). Walkfiles that assume `$2` is a simple filename may need adjustment:
```bash
# Before: worked when $2 was "foo.o"
echo ${target}.c

# After: use basename or adjust patterns
echo ${target%.o}.c # works for both "foo.o" and "subdir/foo.o"
```

* **Working directory changed**: The Walkfile now runs from its own directory, not the target's directory. Commands using relative paths like `ls *.c` should be updated to use paths relative to the Walkfile.

* **Unintended Walkfile discovery**: Directories that previously had no Walkfile (treating targets as static files) may now inherit a Walkfile from a parent directory. If the parent Walkfile doesn't handle the target, this will produce an error instead of a no-op.

**Migration Guide**

1. If your Walkfile uses `$2` directly as a filename, consider using `basename "$target"` or updating patterns to handle paths.

2. If you rely on "no Walkfile means static file" behavior in a subdirectory, add an explicit case to the parent Walkfile:
```bash
subdir/*) ;; # treat as static files
```

3. Review any Walkfiles higher in your directory tree that might now be discovered unexpectedly.

## 0.3.3 (2017-09-20)

**Improvements**
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ Create an executable file called `Walkfile`:
#!/bin/bash

phase=$1 # "deps" or "exec"
target=$2 # the target name
target=$2 # the target path (relative to the Walkfile)

case $target in
hello)
Expand Down
19 changes: 18 additions & 1 deletion Walkfile
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,24 @@ EOF
exec) exec bundle install ;
esac ;;

bin|test|docs|man|dist)
# docs/* targets handled here via Walkfile inheritance
docs)
case $phase in
deps) echo docs/all ;;
esac ;;

docs/all)
case $phase in
deps) echo docs/index.html ;;
esac ;;

docs/index.html)
case $phase in
deps) echo man/walk.1.html ;;
exec) cp man/walk.1.html $target ;;
esac ;;

bin|test|man|dist)
case $phase in
deps) echo $target/all ;;
esac ;;
Expand Down
15 changes: 0 additions & 15 deletions docs/Walkfile

This file was deleted.

28 changes: 21 additions & 7 deletions docs/index.html

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 13 additions & 3 deletions man/walk.1

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

28 changes: 21 additions & 7 deletions man/walk.1.html

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

29 changes: 21 additions & 8 deletions man/walk.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,28 +60,41 @@ to files that need to be built, like `src/hello.o`. When a target does not
relate to an actual file on disk, it's synonymous with `.PHONY` targets in
make(1).

walk(1) delegates to an executable file called [Walkfile][WALKFILE] within the same
directory as the target, to determine what dependencies the target has, and how
to execute it.
walk(1) delegates to an executable file called [Walkfile][WALKFILE] to determine
what dependencies the target has, and how to execute it. walk(1) searches for a
Walkfile starting from the target's directory and walking up the directory tree
until one is found. This allows a single Walkfile at the project root to handle
targets in any subdirectory.

## WALKFILE

The `Walkfile` determines _how_ a target is executed, and what other targets it
depends on.

When walk(1) begins execution of a target, it attempts to find an executable
file called `Walkfile` in the same directory as the target, and then executes
it with the following positional arguments:
When walk(1) begins execution of a target, it searches for an executable file
called `Walkfile` starting from the target's directory and walking up the
directory tree. Once found, it executes the Walkfile with the following
positional arguments:

* `$1`:
The [phase][PHASES] (`deps` or `exec`).

* `$2`:
The name of the target to build (e.g. `hello.o`).
The target path relative to the Walkfile's directory (e.g. `hello.o` or
`subdir/hello.o` if the Walkfile is in a parent directory).

It's up to the `Walkfile` to determine what dependencies the target has, and
how to execute it.

If a Walkfile exits with code `200`, walk(1) will try the next Walkfile up the
directory tree. This allows a local Walkfile to handle specific targets while
delegating unknown targets to a parent Walkfile:

case $target in
special) ;; # handle locally
*) exit 200 ;; # delegate to parent
esac

Comment on lines +63 to +97

Copilot AI Mar 7, 2026

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The new inheritance/$2 text is added, but later in this man page the PHASES/EXAMPLES sections still say dependency paths are “relative to the target” and that targets are executed “relative to the directory of the target”. With inheritance, dependency interpretation/execution are now relative to the selected Walkfile’s directory. Please update the later sections to avoid contradicting the new behavior.

Copilot uses AI. Check for mistakes.
## PHASES

walk(1) has two phases:
Expand Down
Loading
Loading