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
39 changes: 39 additions & 0 deletions TODO.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Todo

- diff-tool selection is consistent with `git help difftool`
- Command line args are consistent with `git dif`
Use -t and --tool, NOT -d
See: git difftool --tool-help

# Starter code

```bash
get_git_difftool() {
# Check if --tool argument is provided in command line arguments
while [[ $# -gt 0 ]]; do
case "$1" in
-t|--tool)
echo "$2"
return 0
;;
*) shift ;;
esac
done

# Check if GIT_DIFF_TOOL environment variable is set
if [[ -n "$GIT_DIFF_TOOL" ]]; then
echo "$GIT_DIFF_TOOL"
return 0
fi

# Fallback to the configured diff.tool in git config
git_config_tool="$(git config --get diff.tool)"
if [[ -n "$git_config_tool" ]]; then
echo "$git_config_tool"
return 0
fi

# Default return if no tool is set (to avoid empty return)
echo "default-diff-tool" # Replace this with the actual default tool if needed
}
```
48 changes: 42 additions & 6 deletions bash/test.sh
Original file line number Diff line number Diff line change
@@ -1,10 +1,46 @@
#!/bin/bash

echo "test: pass"
./verify.sh -t test1 <<< "test 1 approves this message
function test1() {
test_name="${FUNCNAME[0]}"
echo "test: pass"
./verify.sh -t "$test_name" <<<"test 1 approves this message
line 2"
echo ""
echo ""
}

echo "test: fails and triggers diff tool"
./verify.sh -t test3 -d diff <<< "test 3 receives this input"
echo ""
function test2() {
true
}

function test3() {
test_name="${FUNCNAME[0]}"
echo "test: fails and triggers diff tool"
./verify.sh -t "$test_name" -d diff <<<"test 3 receives this input"
echo ""
}

function test4() {
test_name="${FUNCNAME[0]}"
./verify.sh -d meld <<<"Input to test without a name"
}

function test_diff_tool_selection() {
test_name="${FUNCNAME[0]}"
cat <<DIFF_TOOL_SELECTION | ./verify.sh -t "$test_name"
# Logic for diff tool
# 1. --tool argument takes top priority.
# 2. If no --tool is specified, GIT_DIFF_TOOL is checked next.
# 3. If GIT_DIFF_TOOL is unset, git config --get diff.tool is used.
# 4. If neither is set, Git falls back to its internal diff.
DIFF_TOOL_SELECTION
}

function test_all() {
test1
test2
test3
test4
test_diff_tool_selection
}

test_all
Empty file added bash/test5.approved
Empty file.
Empty file.
5 changes: 5 additions & 0 deletions bash/test_diff_tool_selection.approved
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Logic for diff tool
# 1. --tool argument takes top priority.
# 2. If no --tool is specified, GIT_DIFF_TOOL is checked next.
# 3. If GIT_DIFF_TOOL is unset, git config --get diff.tool is used.
# 4. If neither is set, Git falls back to its internal diff.
1 change: 1 addition & 0 deletions bash/unspecified_test_name.approved
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Input to test without a name
114 changes: 88 additions & 26 deletions bash/verify.sh
Original file line number Diff line number Diff line change
@@ -1,35 +1,97 @@
#!/bin/bash
set -euo pipefail

default_diff_tool="code --diff"
diff_tool=$default_diff_tool
true <<TODO
See:
- git config --get diff.tool
- git difftool
- git difftool --no-index
TODO

while getopts ":r:t:d:" opt; do
case $opt in
d) diff_tool=$OPTARG;;
r) received_text=$OPTARG;;
t) test_name=$OPTARG;;
\?) echo "Invalid option: -$OPTARG" >&2;;
esac
git_difftool="$(git config --get diff.tool)"
vs_code_path=$(command -v code)

if [[ -n "${git_difftool}" ]] && command -v "${git_difftool}"; then
difftool="git difftool --tool ${git_difftool} --no-index"
elif [[ -n "${vs_code_path}" ]]; then
difftool="${vs_code_path} --diff"
else
difftool=""
fi

function warn() {
echo "$*" >&2
}

while getopts ":r:t:d:D" opt; do
case $opt in
d) difftool=$OPTARG ;;
r) received_text=$OPTARG ;;
t) test_name=$OPTARG ;;
D) debug_without_compare_and_approve="true" ;;
\?) warn "Invalid option: -$OPTARG" ;;
esac
done

if [[ "${test_name=}" == '' ]]; then
test_name="unspecified_test_name"
fi

received="$test_name.received"
approved="$test_name.approved"

if [ "$received_text" == "" ];
then
cat - > "$received"
else
echo "$received_text" > "$received"
fi
function debug_arguments() {
cat <<REPORT
$0 -d '$difftool' -r '$received_text' -t '$test_name'
REPORT
}

function main() {
if [ "${received_text=}" == "" ]; then
cat - >"$received"
else
echo "$received_text" >"$received"
fi

touch "$approved"

if [[ -n "${debug_without_compare_and_approve=}" ]]; then
debug_arguments
else
compare_and_approve "$test_name"
fi
}

function pass() {
echo "${1:=unnamed-test} passed"
}

function fail() {
echo "${1:unnamed-test} failed"
}

function fail_and_diff() {
if [ -e /dev/tty ]; then
$difftool "$received" "$approved" </dev/tty
else
$difftool "$received" "$approved"
fi
false
}

function pass_and_rm_received() {
pass "$1"
rm "$received"
}

function compare_and_approve() {
# NB: Following are run in sub-shells to prevent their errors from
# terminating this shell. I'm not sure if that's still necessary.
if diff -q "$received" "$approved" >/dev/null; then
(pass_and_rm_received "$1");
else
(fail_and_diff "$1")
fi
}

touch "$approved"

diff -q "$received" "$approved" > /dev/null \
&& (echo "test passed"; rm "$received") \
|| (echo "test failed";
if [ -e /dev/tty ]; then
$diff_tool "$received" "$approved" </dev/tty
else
$diff_tool "$received" "$approved"
fi;
false)
main
Empty file added unspecified_test_name.approved
Empty file.