@@ -10,54 +10,112 @@ set -eu
1010
1111IFS='
1212'
13-
1413# -------------------------------------------------------------------
15- # Paths & Defaults
14+ # Path detection for libraries, templates, and docs (POSIX compatible)
1615# -------------------------------------------------------------------
17- # Resolve script directory robustly, whether sourced or executed
18- # Works in POSIX sh, bash, zsh, dash
16+
17+ # Get the directory where this script is located (absolute, even if symlinked)
1918get_script_dir () {
20- # $1: path to script (may be $0 or ${BASH_SOURCE[0]})
21- script=" $1 "
22- case " ${script} " in
23- /* ) dir=$( dirname " ${script} " ) ;;
24- * ) dir=$( cd " $( dirname " ${script} " ) " 2> /dev/null && pwd) ;;
25- esac
26- printf ' %s\n' " ${dir} "
19+ # $1: path to script (may be $0 or a shell-specific value)
20+ target=" $1 "
21+ [ -z " ${target} " ] && target=" $0 "
22+ # Prefer readlink -f if available, fallback to manual cd/pwd
23+ if command -v readlink > /dev/null 2>&1 && readlink -f " ${target} " > /dev/null 2>&1 ; then
24+ dirname " $( readlink -f " ${target} " ) "
25+ else
26+ cd " $( dirname " ${target} " ) " 2> /dev/null && pwd
27+ fi
2728}
2829
29- # Detect if sourced (works in bash, zsh, dash, sh)
30- _is_sourced=0
31- # shellcheck disable=SC2292
32- if [ " ${BASH_SOURCE:- } " != " " ] && [ " ${BASH_SOURCE:- } " != " $0 " ]; then
33- _is_sourced=1
34- elif [ -n " ${ZSH_EVAL_CONTEXT:- } " ] && [ " ${ZSH_EVAL_CONTEXT#*: } " = " file" ]; then
35- _is_sourced=1
36- fi
37- # Use BASH_SOURCE if available, else $0
30+ # Try to detect the actual script path
31+ SCRIPT_PATH=" $0 "
32+ # shellcheck disable=SC2296
3833if [ -n " ${BASH_SOURCE:- } " ]; then
39- _SCRIPT_PATH=" ${BASH_SOURCE} "
34+ SCRIPT_PATH=" ${BASH_SOURCE} "
35+ elif [ -n " ${ZSH_VERSION:- } " ] && [ -n " ${(% ):-% x} " ]; then
36+ SCRIPT_PATH=" ${(% ):-% x} "
37+ fi
38+ SCRIPT_DIR=" $( get_script_dir " ${SCRIPT_PATH} " ) "
39+
40+ # Allow overrides for advanced/testing/dev
41+ GIV_LIB_DIR=" ${GIV_LIB_DIR:- } "
42+ GIV_TEMPLATE_DIR=" ${GIV_TEMPLATE_DIR:- } "
43+ GIV_DOCS_DIR=" ${GIV_DOCS_DIR:- } "
44+
45+ # Library location (.sh files)
46+ if [ -n " $GIV_LIB_DIR " ]; then
47+ LIB_DIR=" $GIV_LIB_DIR "
48+ elif [ -d " $SCRIPT_DIR " ]; then
49+ # Local or system install: helpers in same dir
50+ LIB_DIR=" $SCRIPT_DIR "
51+ elif [ -d " /usr/local/lib/giv" ]; then
52+ LIB_DIR=" /usr/local/lib/giv"
53+ elif [ -n " ${SNAP:- } " ] && [ -d " $SNAP /lib/giv" ]; then
54+ LIB_DIR=" $SNAP /lib/giv"
4055else
41- _SCRIPT_PATH=" $0 "
56+ printf ' Error: Could not find giv lib directory.\n' >&2
57+ exit 1
4258fi
4359
44- SCRIPT_DIR=" $( get_script_dir " ${_SCRIPT_PATH} " ) "
45- PROMPT_DIR=" ${SCRIPT_DIR} /../templates"
46- GIV_TMPDIR=" "
60+ # Template location
61+ if [ -n " $GIV_TEMPLATE_DIR " ]; then
62+ TEMPLATE_DIR=" $GIV_TEMPLATE_DIR "
63+ elif [ -d " $LIB_DIR /../templates" ]; then
64+ TEMPLATE_DIR=" $LIB_DIR /../templates"
65+ elif [ -d " /usr/local/share/giv/templates" ]; then
66+ TEMPLATE_DIR=" /usr/local/share/giv/templates"
67+ elif [ -n " ${SNAP:- } " ] && [ -d " $SNAP /share/giv/templates" ]; then
68+ TEMPLATE_DIR=" $SNAP /share/giv/templates"
69+ else
70+ printf ' Error: Could not find giv template directory.\n' >&2
71+ exit 1
72+ fi
73+
74+ # Docs location (optional)
75+ if [ -n " $GIV_DOCS_DIR " ]; then
76+ DOCS_DIR=" $GIV_DOCS_DIR "
77+ elif [ -d " $LIB_DIR /../docs" ]; then
78+ DOCS_DIR=" $LIB_DIR /../docs"
79+ elif [ -d " /usr/local/share/giv/docs" ]; then
80+ DOCS_DIR=" /usr/local/share/giv/docs"
81+ elif [ -n " ${SNAP:- } " ] && [ -d " $SNAP /share/giv/docs" ]; then
82+ DOCS_DIR=" $SNAP /share/giv/docs"
83+ else
84+ DOCS_DIR=" " # It's optional; do not fail if not found
85+ fi
4786
4887# shellcheck source=helpers.sh
4988. " ${SCRIPT_DIR} /helpers.sh"
5089# shellcheck source=markdown.sh
5190. " ${SCRIPT_DIR} /markdown.sh"
5291
92+ # Detect if sourced (works in bash, zsh, dash, sh)
93+ _is_sourced=0
94+ # shellcheck disable=SC2296
95+ # if [ "${BATS_TEST_FILENAME:-}" ]; then
96+ # _is_sourced=1
97+ # el
98+ if [ " $( basename -- " $0 " ) " = " sh" ] || [ " $( basename -- " $0 " ) " = " -sh" ]; then
99+ _is_sourced=1
100+ elif [ " ${0##*/ } " = " dash" ] || [ " ${0##*/ } " = " -dash" ]; then
101+ _is_sourced=1
102+ elif [ -n " ${ZSH_EVAL_CONTEXT:- } " ] && case $ZSH_EVAL_CONTEXT in * :file) true ;; * ) false ;; esac ; then
103+ _is_sourced=1
104+ elif [ -n " ${KSH_VERSION:- } " ] && [ -n " ${.sh.file:- } " ] && [ " ${.sh.file} " != " " ] && [ " ${.sh.file} " != " $0 " ]; then
105+ _is_sourced=1
106+ elif [ -n " ${BASH_VERSION:- } " ] && [ -n " ${BASH_SOURCE:- } " ] && [ " ${BASH_SOURCE} " != " $0 " ]; then
107+ _is_sourced=1
108+ fi
109+
110+ GIV_TMPDIR=" "
53111REVISION=" "
54112PATHSPEC=" "
55113
56114config_file=" "
57115is_config_loaded=false
58116debug=false
59117dry_run=" "
60- template_dir=" ${PROMPT_DIR } "
118+ template_dir=" ${TEMPLATE_DIR } "
61119output_file=' '
62120todo_pattern=' '
63121todo_files=" *todo*"
@@ -489,7 +547,7 @@ cmd_message() {
489547 build_history " ${hist} " " ${commit_id} " " ${todo_pattern} " " ${PATHSPEC} "
490548 print_debug " Generated history file ${hist} "
491549 pr=$( portable_mktemp " commit_message_prompt_XXXXXX.md" )
492- build_prompt " ${PROMPT_DIR } /message_prompt.md" " ${hist} " > " ${pr} "
550+ build_prompt " ${TEMPLATE_DIR } /message_prompt.md" " ${hist} " > " ${pr} "
493551 print_debug " Generated prompt file ${pr} "
494552 res=$( generate_response " ${pr} " " ${model_mode} " )
495553 if [ $? -ne 0 ]; then
@@ -550,7 +608,7 @@ cmd_summary() {
550608 fi
551609
552610 # Generate final summary from summaries
553- prompt_file_name=" ${PROMPT_DIR } /final_summary_prompt.md"
611+ prompt_file_name=" ${TEMPLATE_DIR } /final_summary_prompt.md"
554612 tmp_prompt_file=$( portable_mktemp " final_summary_prompt_XXXXXX.md" )
555613 build_prompt " ${prompt_file_name} " " ${summaries_file} " > " ${tmp_prompt_file} "
556614 print_debug " $( cat " ${tmp_prompt_file} " || true) "
@@ -566,7 +624,7 @@ cmd_release_notes() {
566624 exit 1
567625 fi
568626
569- prompt_file_name=" ${PROMPT_DIR } /release_notes_prompt.md"
627+ prompt_file_name=" ${TEMPLATE_DIR } /release_notes_prompt.md"
570628 tmp_prompt_file=$( portable_mktemp " release_notes_prompt_XXXXXX.md" )
571629 build_prompt " ${prompt_file_name} " " ${summaries_file} " > " ${tmp_prompt_file} "
572630 [ " ${debug} " = " true" ] && printf ' Debug: Generated prompt file %s\n' " ${tmp_prompt_file} "
@@ -585,7 +643,7 @@ cmd_announcement() {
585643 exit 1
586644 fi
587645
588- prompt_file_name=" ${PROMPT_DIR } /announcement_prompt.md"
646+ prompt_file_name=" ${TEMPLATE_DIR } /announcement_prompt.md"
589647 tmp_prompt_file=$( portable_mktemp " announcement_prompt_XXXXXX.md" )
590648 project_title=" $( parse_project_title " ${summaries_file} " ) "
591649 print_debug " Project title: ${project_title} "
@@ -624,7 +682,7 @@ cmd_changelog() {
624682 fi
625683
626684 # 4) Build the AI prompt
627- prompt_template=" ${PROMPT_DIR } /changelog_prompt.md"
685+ prompt_template=" ${TEMPLATE_DIR } /changelog_prompt.md"
628686 print_debug " Building prompt from template: $prompt_template "
629687 tmp_prompt_file=$( portable_mktemp " prompt.XXXXXXX.md" ) || {
630688 printf ' Error: cannot create temp file for prompt\n' >&2
0 commit comments