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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
# names it by hand — so the glob is what makes the next invented name safe.
/mutants.out*/

# herdr: the released bdi herdr/fetch.sh installs.
/bin/

# nix
result
result-*
Expand Down
82 changes: 80 additions & 2 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -1946,10 +1946,10 @@
touch $out
'';

# The version is written in three places and two of them are held to
# The version is written in four places and two of them are held to
# the crate: `flake.nix` reads it out of `Cargo.toml`, and `cargo
# publish --locked` refuses a `Cargo.lock` that disagrees. README's
# flake example is the third, and a bump that forgets it lands green —
# flake example is a third, and a bump that forgets it lands green —
# then the release ships a page telling a reader to pin the tag before
# the one being released.
#
Expand Down Expand Up @@ -2060,6 +2060,76 @@ $pinned"
touch $out
'';

# The herdr plugin manifest is the fourth. Its version is the release
# herdr/fetch.sh downloads, so a bump that forgets it installs the
# previous release under the new one's name.
pluginDeclaresTheVersion = pkgs.writeShellScriptBin "plugin-declares-the-version" ''
set -u

cd "''${1:-.}" || exit 1

version="$(awk -F'"' '
/^\[/ { package = ($0 == "[package]") }
package && /^version *=/ { print $2; exit }
' Cargo.toml)"

declared="$(awk -F'"' '
/^\[/ { exit }
/^version *=/ { print $2; exit }
' herdr-plugin.toml)"

if [ "$declared" != "$version" ]; then
echo "herdr-plugin.toml declares a version the crate does not."
echo
echo "Cargo.toml declares $version."
echo "herdr-plugin.toml declares ''${declared:-no version}."
echo
echo "herdr/fetch.sh installs the release the manifest names, so it"
echo "reads version = \"$version\"."
exit 1
fi
'';

pluginDeclaresTheVersionTest = pkgs.runCommand "plugin-declares-the-version-test"
{ nativeBuildInputs = [ pluginDeclaresTheVersion ]; } ''
set -u

tree="$TMPDIR/tree"
mkdir -p "$tree"
printf '[package]\nname = "beady-eye"\nversion = "0.2.0"\n' > "$tree/Cargo.toml"

manifest() {
printf '%s\n' "id = \"example.plugin\"" "$1" "" \
'[[panes]]' 'id = "eye"' 'version = "0.2.0"' > "$tree/herdr-plugin.toml"
}

fail() { echo "FAIL: $1"; echo "$output"; exit 1; }

manifest 'version = "0.2.0"'
output="$( plugin-declares-the-version "$tree" 2>&1 )" ||
fail "it refused a manifest declaring the version the crate declares:"

# The bump that forgets the manifest, which is the whole of this.
manifest 'version = "0.1.0"'
if output="$( plugin-declares-the-version "$tree" 2>&1 )"; then
fail "it accepted a manifest declaring another version:"
fi
case "$output" in
*"declares 0.1.0"*"version = \"0.2.0\""*) ;;
*) fail "the refusal did not name both versions:" ;;
esac

# A version under a table belongs to that entry, not the plugin, so a
# manifest whose top level has none is refused rather than read as
# matching.
manifest ""
if output="$( plugin-declares-the-version "$tree" 2>&1 )"; then
fail "it read a table's version as the plugin's:"
fi

touch $out
'';

# The Release body is RELEASE-NOTES/<version>.md byte for byte, and
# GitHub renders that body with its hard line break extension on — so a
# newline inside a paragraph becomes a <br> and the published page
Expand Down Expand Up @@ -3463,6 +3533,14 @@ and a second line"
"colours-come-from-the-palette";
palette-test = coloursComeFromThePaletteTest;

# A source of its own for the same reason readme-pin has one.
plugin-version = pkgs.runCommand "plugin-version"
{ nativeBuildInputs = [ pluginDeclaresTheVersion ]; } ''
plugin-declares-the-version ${sourceOf [ ./herdr-plugin.toml ./Cargo.toml ]}
touch $out
'';
plugin-version-test = pluginDeclaresTheVersionTest;

# A source of its own, holding the two files this reads. It cannot be
# a `checkOf` entry the way the scans above are: those are built from
# `source`, which carries no documentation and
Expand Down
26 changes: 26 additions & 0 deletions herdr-plugin.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
id = "codeforbreakfast.beady-eye"
name = "beady-eye"
version = "0.16.0"
min_herdr_version = "0.9.1"
platforms = ["linux", "macos"]
description = "A tree of work in flight: bead graphs annotated with the live agents working them."

# Fetches this version's released bdi into bin/, so installing needs no Rust
# toolchain. `herdr plugin link` skips it: a linked checkout runs it by hand.
[[build]]
command = ["sh", "herdr/fetch.sh"]

# The pane starts in the focused pane's directory rather than the plugin root,
# so bdi is named by absolute path. bdi's own error is all that says why it
# refused to start, so a failed start holds the pane until the reader has read it.
[[panes]]
id = "eye"
title = "bdi"
placement = "split"
command = ["sh", "-c", "\"$HERDR_PLUGIN_ROOT/bin/bdi\" || { printf '\\nbdi exited %s. Press Enter to close.' \"$?\"; read -r _; }"]

[[actions]]
id = "open"
title = "beady-eye: open"
contexts = ["pane", "workspace"]
command = ["sh", "herdr/open.sh"]
53 changes: 53 additions & 0 deletions herdr/fetch.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
#!/bin/sh
# herdr's build step: download the released bdi for this machine into bin/,
# checked against the sha256 published beside it. The release is the tag for
# the manifest's version, so a checkout always fetches its own release.
#
# herdr runs this from the plugin checkout without the runtime environment, so
# the root is found from where the script lives.
set -eu

root="$(cd "$(dirname "$0")/.." && pwd)"
version="$(sed -n 's/^version *= *"\([^"]*\)".*/\1/p' "$root/herdr-plugin.toml" | head -n 1)"

case "$(uname -s)-$(uname -m)" in
Linux-x86_64) target=x86_64-unknown-linux-musl ;;
Linux-aarch64 | Linux-arm64) target=aarch64-unknown-linux-musl ;;
Darwin-x86_64) target=x86_64-apple-darwin ;;
Darwin-arm64) target=aarch64-apple-darwin ;;
*)
echo "beady-eye: no released bdi for $(uname -s) $(uname -m)." >&2
echo "Install it with 'cargo install beady-eye' and copy it to $root/bin/bdi." >&2
exit 1
;;
esac

asset="bdi-$target"
base="https://github.com/CodeForBreakfast/beady-eye/releases/download/v$version"

tmp="$(mktemp -d)"
trap 'rm -rf "$tmp"' EXIT

# GitHub's CDN can answer 404 for a few minutes after a release publishes, so a
# 404 is retried along with everything else.
fetch() { curl -fsSL --retry 5 --retry-delay 3 --retry-all-errors "$1" -o "$2"; }

echo "beady-eye: fetching $asset from v$version"
fetch "$base/$asset" "$tmp/bdi"
fetch "$base/$asset.sha256" "$tmp/bdi.sha256"

expected="$(awk '{ print $1 }' "$tmp/bdi.sha256")"
if command -v sha256sum >/dev/null 2>&1; then
actual="$(sha256sum "$tmp/bdi" | awk '{ print $1 }')"
else
actual="$(shasum -a 256 "$tmp/bdi" | awk '{ print $1 }')"
fi
if [ "$expected" != "$actual" ]; then
echo "beady-eye: $asset does not match its published sha256." >&2
echo "Expected $expected, got $actual." >&2
exit 1
fi

mkdir -p "$root/bin"
install -m 0755 "$tmp/bdi" "$root/bin/bdi"
echo "beady-eye: installed $root/bin/bdi"
21 changes: 21 additions & 0 deletions herdr/open.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#!/bin/sh
# herdr's open action: bdi in a split beside the focused pane, started in that
# pane's directory so it reads the project the reader is looking at. A plugin
# pane otherwise starts in the plugin root, which no tracker covers.
set -eu

# herdr writes the context as one line of JSON. A directory whose name needs
# escaping in JSON matches neither key, and bdi then starts in the plugin root
# and says what it could not find.
context_field() {
printf '%s' "$HERDR_PLUGIN_CONTEXT_JSON" | sed -n "s/.*\"$1\":\"\([^\"\\\\]*\)\".*/\1/p"
}

cwd="$(context_field focused_pane_cwd)"
[ -n "$cwd" ] || cwd="$(context_field workspace_cwd)"

set -- --plugin "$HERDR_PLUGIN_ID" --entrypoint eye --focus
[ -n "$cwd" ] && set -- "$@" --cwd "$cwd"
[ -n "${HERDR_PANE_ID:-}" ] && set -- "$@" --target-pane "$HERDR_PANE_ID"

exec "$HERDR_BIN_PATH" plugin pane open "$@"