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
7 changes: 7 additions & 0 deletions .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,10 @@ jobs:
persist-credentials: false
- name: Run the tests
run: npx --yes bats@1.11.0 tests
# A shell that is not interactive loads no aliases: gitrid must be a
# command on the PATH
- name: Install with setup_linux.sh and check gitrid is on the PATH
run: |
bash setup_linux.sh
bash -c 'command -v gitrid'
[ "$(bash -c 'gitrid --version')" = "$(bash gitrid.sh --version)" ]
12 changes: 5 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ Without `--yes`, and with nothing to answer the prompt, gitrid deletes nothing a

To decide for itself what is safe, a script reads `gitrid --list --porcelain` ([above](#listing-branches)): a branch is safe to delete if its status is `merged` or its commits on no remote are `0`.

The setup scripts for Linux, Mac, WSL and Git Bash make `gitrid` an alias in `~/.bashrc`, and a shell that is not interactive does not load aliases. If an agent or script gets "command not found", call the script by its path: `/usr/local/bin/gitrid.sh`, or `~/Scripts/gitrid.sh` in Git Bash. In PowerShell `gitrid` is a script on the PATH and works as it is.
The setup scripts make `gitrid` a command on the PATH, so it works in a shell that is not interactive (a script, a hook, an agent) as it does at the prompt. Versions before 3.1.1 made it an alias in `~/.bashrc`, which such a shell does not load: if an agent or script gets "command not found", run the setup script again.

The exit code says what happened:

Expand All @@ -169,13 +169,11 @@ To install gitrid, simply run the appropriate setup script for your system. The
bash setup_linux.sh
```

If gitrid is already installed, the script replaces it with this version.
This copies the script to `/usr/local/bin/gitrid.sh` and makes `/usr/local/bin/gitrid` a link to it. If gitrid is already installed, the script replaces it with this version.

2. Check it works:

```bash
source ~/.bashrc

gitrid --help
```

Expand Down Expand Up @@ -214,13 +212,13 @@ gitrid --help
bash setup_gitbash.sh
```

This creates a Scripts directory in the user's home directory (if one doesn't already exist) and copies the gitrid.sh script into it, makes it executable and adds an alias for easy access. The script will detect existing installations and update them automatically.
This creates a Scripts directory in the user's home directory (if one doesn't already exist), copies the gitrid.sh script into it and makes it executable. It then writes the `gitrid` command to `~/bin/gitrid`, a small script that runs `~/Scripts/gitrid.sh`. Run it again to update an existing installation.

Git Bash puts `~/bin` on the PATH when the folder exists. If the setup script had to create it, open a new Git Bash window before using `gitrid`.

2. Check it works:

```bash
source ~/.bashrc

gitrid --help
```

Expand Down
2 changes: 1 addition & 1 deletion gitrid.sh
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env bash

# Version information
VERSION="3.1.0"
VERSION="3.1.1"

# Exit codes, so a script or an AI agent can tell the outcomes apart
EXIT_OK=0 # Branches deleted, or a list, dry run, help or version shown
Expand Down
6 changes: 3 additions & 3 deletions llms.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# gitrid

> A bash script that deletes LOCAL git branches in bulk: by name pattern, by "merged into main", or by "upstream branch gone". Describes gitrid 3.1.0 (`gitrid --version`). This file is the reference for AI agents and scripts; `README.md` is the human guide. `gitrid --help` prints a short version of the same rules.
> A bash script that deletes LOCAL git branches in bulk: by name pattern, by "merged into main", or by "upstream branch gone". Describes gitrid 3.1.1 (`gitrid --version`). This file is the reference for AI agents and scripts; `README.md` is the human guide. `gitrid --help` prints a short version of the same rules.

## What it does and does not do

Expand Down Expand Up @@ -37,7 +37,7 @@ Without `--yes` gitrid asks "Are you sure? (y/n)" on stdin. With no terminal and
| `--yes`, `-y` | With any of the above: delete without asking |
| `gitrid --list`, `-l` | List every local branch with its status. Read-only |
| `gitrid --list --porcelain` | The same list in a fixed format for a program to read |
| `gitrid --version` | `gitrid version 3.1.0` |
| `gitrid --version` | `gitrid version 3.1.1` |
| `gitrid --help`, `-h` | Usage |

- Options can come before or after the pattern. An option that is not listed is an error (exit `1`).
Expand Down Expand Up @@ -115,4 +115,4 @@ gitrid --list --porcelain | awk -F'\t' '$1 != "protected" && ($1 == "merged" ||

## Installed copies

On Windows the PowerShell command is `gitrid.ps1`, which runs the script in WSL (`wsl --exec /usr/local/bin/gitrid.sh`) and passes the pattern through unchanged. cmd uses `gitrid.bat`, where a pattern with a `^` must be in double quotes (`gitrid "^fix/"`) or cmd drops the `^`. Git Bash uses an alias to `~/Scripts/gitrid.sh`, and aliases are not loaded in a non-interactive shell, so a script there calls `~/Scripts/gitrid.sh` by path. Linux, macOS and WSL use `/usr/local/bin/gitrid.sh`. The copies are updated separately, by rerunning the setup script for each.
On Windows the PowerShell command is `gitrid.ps1`, which runs the script in WSL (`wsl --exec /usr/local/bin/gitrid.sh`) and passes the pattern through unchanged. cmd uses `gitrid.bat`, where a pattern with a `^` must be in double quotes (`gitrid "^fix/"`) or cmd drops the `^`. In Git Bash `gitrid` is `~/bin/gitrid`, a wrapper that runs `~/Scripts/gitrid.sh`. On Linux, macOS and WSL it is `/usr/local/bin/gitrid`, a link to `/usr/local/bin/gitrid.sh`. Both are commands on the PATH, so `gitrid` works in a non-interactive shell. An installation made by an older setup script has only an alias in `~/.bashrc`, which a non-interactive shell does not load: there, call the script by its path (`~/Scripts/gitrid.sh` or `/usr/local/bin/gitrid.sh`) or rerun the setup script. The copies are updated separately, by rerunning the setup script for each.
32 changes: 22 additions & 10 deletions setup_gitbash.sh
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,31 @@ fi
# Define the source script and destination
SOURCE_SCRIPT="gitrid.sh"
DESTINATION="$HOME/Scripts/gitrid.sh"
# The 'gitrid' command: Git for Windows puts ~/bin on the PATH when it exists
COMMAND="$HOME/bin/gitrid"

# Ensure the script is executable
chmod +x "$SOURCE_SCRIPT"

# Move the script, overwriting if necessary
cp -f "$SOURCE_SCRIPT" "$DESTINATION"

# Create an alias for easy access
if ! grep -q "alias gitrid" ~/.bashrc; then
echo "alias gitrid='~/Scripts/gitrid.sh'" >> ~/.bashrc
echo "Alias 'gitrid' added to ~/.bashrc"
else
echo "Alias 'gitrid' already exists in ~/.bashrc"
fi
cp -f "$SOURCE_SCRIPT" "$DESTINATION" || exit 1

echo "Script successfully installed to $DESTINATION"

# Make 'gitrid' a command on the PATH. An alias in ~/.bashrc is not enough: a
# shell that is not interactive (a script, a hook, an AI agent) does not load
# aliases. A wrapper, not 'ln -s': Git Bash copies the file where it can not
# make a link, and the copy would go stale when gitrid is updated.
mkdir -p "$HOME/bin"
cat > "$COMMAND" <<'EOF' || exit 1
#!/usr/bin/env bash
exec "$HOME/Scripts/gitrid.sh" "$@"
EOF
chmod +x "$COMMAND"

echo "Command 'gitrid' installed to $COMMAND"

echo "Script successfully installed to $DESTINATION"
case ":$PATH:" in
*":$HOME/bin:"*) ;;
*) echo "$HOME/bin is not on the PATH of this shell: open a new Git Bash window to use 'gitrid'" ;;
esac
17 changes: 9 additions & 8 deletions setup_linux.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
# Define the source script and destination
SOURCE_SCRIPT="gitrid.sh"
DESTINATION="/usr/local/bin/gitrid.sh"
# The 'gitrid' command, a link to the script
COMMAND="/usr/local/bin/gitrid"

# Ensure the script is executable
chmod +x "$SOURCE_SCRIPT"
Expand All @@ -13,15 +15,14 @@ chmod +x "$SOURCE_SCRIPT"
if [ -f "$DESTINATION" ]; then
sudo rm -f "$DESTINATION"
fi
sudo cp "$SOURCE_SCRIPT" "$DESTINATION"
sudo cp "$SOURCE_SCRIPT" "$DESTINATION" || exit 1


echo "Scripts successfully installed to $DESTINATION"

# Create an alias for easy access
if ! grep -q "alias gitrid" ~/.bashrc; then
echo "alias gitrid=$DESTINATION" >> ~/.bashrc
echo "Alias 'gitrid' added to ~/.bashrc"
else
echo "Alias 'gitrid' already exists in ~/.bashrc"
fi
# Make 'gitrid' a command on the PATH. An alias in ~/.bashrc is not enough: a
# shell that is not interactive (a script, a hook, an AI agent) does not load
# aliases.
sudo ln -sf "$DESTINATION" "$COMMAND" || exit 1

echo "Command 'gitrid' installed to $COMMAND"
70 changes: 70 additions & 0 deletions tests/setup.bats
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
#!/usr/bin/env bats

# Tests for setup_gitbash.sh, which installs into $HOME only, so each test gives
# it a throwaway home. setup_linux.sh writes to /usr/local/bin with sudo and is
# run for real by the workflow in .github/workflows/tests.yml.

REPO="$BATS_TEST_DIRNAME/.."

setup() {
export HOME="$BATS_TEST_TMPDIR/home"
mkdir -p "$HOME"
# The setup script takes gitrid.sh from the current directory
cd "$REPO"
}

# What a new Git Bash window has: ~/bin on the PATH
with_home_bin() {
PATH="$HOME/bin:$PATH" "$@"
}

@test "setup_gitbash.sh installs the script and the gitrid command" {
run bash setup_gitbash.sh
[ "$status" -eq 0 ]
[ -x "$HOME/Scripts/gitrid.sh" ]
[ -x "$HOME/bin/gitrid" ]
cmp gitrid.sh "$HOME/Scripts/gitrid.sh"
}

@test "gitrid resolves in a non-interactive shell after setup_gitbash.sh" {
bash setup_gitbash.sh
run with_home_bin bash -c 'command -v gitrid'
[ "$status" -eq 0 ]
[ "$output" = "$HOME/bin/gitrid" ]
}

@test "the installed gitrid command runs the installed script" {
bash setup_gitbash.sh
run with_home_bin bash -c 'gitrid --version'
[ "$status" -eq 0 ]
[ "$output" = "$(bash gitrid.sh --version)" ]
}

@test "the installed gitrid command passes its arguments and exit code through" {
bash setup_gitbash.sh
run with_home_bin bash -c 'gitrid --no-such-option'
[ "$status" -eq 1 ]
}

@test "setup_gitbash.sh does not touch ~/.bashrc" {
echo "# mine" > "$HOME/.bashrc"
bash setup_gitbash.sh
[ "$(cat "$HOME/.bashrc")" = "# mine" ]
}

@test "setup_gitbash.sh run again updates the installed script" {
bash setup_gitbash.sh
echo "stale" > "$HOME/Scripts/gitrid.sh"
echo "stale" > "$HOME/bin/gitrid"
bash setup_gitbash.sh
cmp gitrid.sh "$HOME/Scripts/gitrid.sh"
run with_home_bin bash -c 'gitrid --version'
[ "$status" -eq 0 ]
}

@test "setup_gitbash.sh says to open a new window when ~/bin is not on the PATH" {
run bash setup_gitbash.sh
[[ "$output" == *"open a new Git Bash window"* ]]
run with_home_bin bash setup_gitbash.sh
[[ "$output" != *"open a new Git Bash window"* ]]
}
Loading