Skip to content

Commit 57da3a6

Browse files
author
Test
committed
feat: update GIV_HOME directory structure and improve debug output
fix: enhance metadata retrieval with additional commit options and error handling test: initialize git repository in test setup for consistent environment refactor: rename GIV_METADATA_PROJECT_TYPE to GIV_PROJECT_TYPE for clarity test: update version extraction tests to use new project type variable test: implement integration tests for dispatcher functionality test: create integration tests for subcommands with various scenarios test: add comprehensive workflow integration tests for end-to-end scenarios chore: maintain consistent project structure and improve test coverage
1 parent b7d4f56 commit 57da3a6

13 files changed

+1287
-85
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,3 +16,5 @@ dist
1616
tests/.giv
1717
.notes
1818
.giv/config.bak
19+
CLAUDE.md
20+
.giv/config.bak2

.giv/config

Lines changed: 1 addition & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,9 @@
1-
# # GIV Configuration Example
2-
# ## Check the docs/configuration.md for more details.
3-
4-
# ## Debugging
5-
# # ### Set to "true" to enable debug mode, which provides detailed logging
6-
# # GIV_DEBUG=""
7-
# # ### If set to "true", enables dry run mode (no changes will be made)
8-
# # GIV_DRY_RUN=""
9-
# # ### Set to "true" to preserve temporary directories after execution for debugging purposes
10-
# # GIV_TMPDIR_SAVE=""
11-
12-
13-
# ## Model and API configuration
14-
# # GIV_MODEL="devstral"
15-
# # GIV_API_URL="http://localhost:11434/v1/chat/completions"
16-
# # GIV_API_KEY="giv"
17-
# # GIV_API_MODEL="devstral"
18-
19-
# # ## Remote: groq API Configuration
20-
# # GIV_API_URL="https://api.groq.com/openai/v1/chat/completions"
21-
# # GIV_API_MODEL="compound-beta"
22-
# # GIV_API_KEY="${GROQ_API_KEY:-}"
23-
24-
25-
# # ## Remote: OpenAI Compatible API Configuration
26-
# # GIV_API_MODEL=gpt-4o-mini
27-
# # GIV_API_URL=https://api.openai.com/v1/chat/completions
28-
# # GIV_API_KEY="${OPENAI_API_KEY:-}"
29-
30-
31-
32-
# ### Regex pattern to identify TODO comments in code (e.g., 'TODO:(.*)')
33-
# GIV_TODO_PATTERN=""
34-
35-
# ### Comma-separated list of files or glob patterns to search for TODOs (e.g., "*.py,src/**/*.js")
36-
# GIV_TODO_FILES="docs/todos.md"
37-
38-
# GIV_METADATA_PROJECT_TYPE=custom
39-
40-
### Regex pattern to extract the version string from the version file (e.g., 'version\s*=\s*"([0-9\.]+)"')
41-
421
GIV_PROJECT_TYPE="custom"
432
GIV_PROJECT_VERSION_FILE="src/config.sh"
443
GIV_PROJECT_VERSION_PATTERN="version[[:space:]]*=[[:space:]]*([0-9]+\.[0-9]+\.[0-9]+)"
454
GIV_PROJECT_TITLE="giv"
465
GIV_PROJECT_DESCRIPTION="cli tool"
47-
GIV_PROJECT_URL="giv.sh"
6+
GIV_PROJECT_URL="giv is a CLI utility for generating changelogs and summaries."
487
GIV_API_URL="http://localhost:11434/v1/chat/completions"
498
GIV_API_MODEL="devstral"
509
GIV_INITIALIZED="true"

src/commands/config.sh

Lines changed: 33 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,18 @@
33

44
set -eu
55

6+
# Ensure GIV_HOME points to the .giv directory
67
: "${GIV_HOME:=$(git rev-parse --show-toplevel 2>/dev/null || pwd)/.giv}"
8+
# Ensure GIV_CONFIG_FILE points to the config file within .giv directory
79
: "${GIV_CONFIG_FILE:=${GIV_HOME}/config}"
810

911

1012

11-
# If called as 'giv.sh config ...', shift off the 'config' argument
12-
if [ "${1:-}" = "config" ]; then
13-
shift
14-
fi
13+
# Configuration management functions
14+
# This file should only be executed by the dispatcher, not sourced by other scripts
1515

16-
# Default to --list if no arguments
17-
if [ $# -eq 0 ]; then
18-
set -- --list
19-
fi
16+
# Configuration management functions are defined below
17+
# Execution logic is at the end of the file
2018

2119
# Centralized key normalization
2220
normalize_key() {
@@ -26,7 +24,7 @@ normalize_key() {
2624
printf ''
2725
;;
2826
*)
29-
printf '%s' "$1" | tr '[:lower:].' '[:upper:]_'
27+
printf 'GIV_%s' "$1" | tr '[:lower:].' '[:upper:]_'
3028
;;
3129
esac
3230
}
@@ -42,10 +40,17 @@ giv_config() {
4240
# Check for malformed lines
4341
if [ -s "$GIV_CONFIG_FILE" ]; then
4442
# Updated malformed config check to ignore empty lines and lines with only whitespace
45-
if grep -qvE '^(#|[^=]+=[^\n]*|[[:space:]]*)$' "$GIV_CONFIG_FILE"; then
46-
printf '%s\n' "Malformed config" >&2
47-
return 1
48-
fi
43+
# Simple validation: check for lines that don't contain = and aren't comments or empty
44+
while IFS= read -r line; do
45+
case "$line" in
46+
'#'*|'') continue ;; # Skip comments and empty lines
47+
*=*) continue ;; # Valid config line
48+
*)
49+
printf '%s\n' "Malformed config line: $line" >&2
50+
return 1
51+
;;
52+
esac
53+
done < "$GIV_CONFIG_FILE"
4954
fi
5055
# Convert GIV_... keys to user keys for output
5156
while IFS= read -r line; do
@@ -87,6 +92,8 @@ giv_config() {
8792
givkey="$(normalize_key "$key")"
8893
val=$(grep -E "^$givkey=" "$GIV_CONFIG_FILE" | cut -d'=' -f2-)
8994
fi
95+
# Remove surrounding quotes if present
96+
val=$(printf '%s' "$val" | sed 's/^"\(.*\)"$/\1/')
9097
printf '%s\n' "$val"
9198
;;
9299
--unset|unset)
@@ -139,7 +146,7 @@ giv_config() {
139146
fi
140147
if [ -s "$GIV_CONFIG_FILE" ]; then
141148
# Updated malformed config check to ignore empty lines and lines with only whitespace
142-
if grep -qvE '^(#|[^=]+=[^\n]*|[[:space:]]*)$' "$GIV_CONFIG_FILE"; then
149+
if grep -qvE '^(#|[^=]+=.*|[[:space:]]*)$' "$GIV_CONFIG_FILE"; then
143150
printf '%s\n' "Malformed config" >&2
144151
return 1
145152
fi
@@ -149,6 +156,8 @@ giv_config() {
149156
givkey="$(normalize_key "$key")"
150157
val=$(grep -E "^$givkey=" "$GIV_CONFIG_FILE" | cut -d'=' -f2-)
151158
fi
159+
# Remove surrounding quotes if present
160+
val=$(printf '%s' "$val" | sed 's/^"\(.*\)"$/\1/')
152161
printf '%s\n' "$val"
153162
else
154163
mkdir -p "$GIV_HOME"
@@ -167,4 +176,14 @@ giv_config() {
167176
esac
168177
}
169178

179+
# Execute the config command when this script is run by the dispatcher
180+
if [ "${1:-}" = "config" ]; then
181+
shift
182+
fi
183+
184+
# Default to --list if no arguments
185+
if [ $# -eq 0 ]; then
186+
set -- --list
187+
fi
188+
170189
giv_config "$@"

src/giv.sh

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -97,15 +97,22 @@ GIV_LIB_DIR="${LIB_DIR}"
9797
. "$GIV_LIB_DIR/init.sh"
9898

9999

100-
# Ensure initialization steps
100+
# Ensure basic directory initialization
101101
ensure_giv_dir_init
102-
initialize_metadata
103-
#metadata_init
104-
#portable_mktemp_dir
105102

106-
# Parse global options and subcommand
103+
# Parse global options and subcommand first (for help/version)
107104
parse_global_args "$@"
108105

106+
# Initialize metadata only for commands that need it (not help/version)
107+
case "${subcmd:-}" in
108+
help|-h|--help|version|-v|--version)
109+
# Skip metadata initialization for help/version
110+
;;
111+
*)
112+
initialize_metadata
113+
;;
114+
esac
115+
109116
if [ -f "${GIV_LIB_DIR}/commands/${subcmd}.sh" ]; then
110117
# Delegate to the subcommand script
111118
printf 'Executing subcommand: %s\n' "${subcmd}"

src/history.sh

Lines changed: 44 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,10 @@
66

77
# Ensure GIV_HOME and GIV_TEMPLATE_DIR are initialized
88

9-
# Source config and project_metadata for tests and runtime
10-
if [ -n "$BATS_TEST_DIRNAME" ]; then
11-
. "$BATS_TEST_DIRNAME/../src/commands/config.sh"
9+
# Source project_metadata for tests and runtime
10+
if [ -n "${BATS_TEST_DIRNAME:-}" ]; then
1211
. "$BATS_TEST_DIRNAME/../src/project_metadata.sh"
1312
else
14-
. "$(dirname "$0")/commands/config.sh"
1513
. "$(dirname "$0")/project_metadata.sh"
1614
fi
1715

@@ -85,6 +83,27 @@ print_commit_metadata() {
8583
}
8684

8785

86+
# Get git diff output for a commit and write to file
87+
get_diff() {
88+
commit="$1"
89+
diff_pattern="$2"
90+
output_file="$3"
91+
92+
print_debug "Getting diff for commit: $commit with pattern: $diff_pattern"
93+
94+
case "$commit" in
95+
--cached)
96+
git --no-pager diff --cached --unified=3 --no-prefix --color=never -- $diff_pattern > "$output_file" 2>/dev/null || true
97+
;;
98+
--current | "")
99+
git --no-pager diff --unified=3 --no-prefix --color=never -- $diff_pattern > "$output_file" 2>/dev/null || true
100+
;;
101+
*)
102+
git --no-pager diff "${commit}^!" --unified=3 --no-prefix --color=never -- $diff_pattern > "$output_file" 2>/dev/null || true
103+
;;
104+
esac
105+
}
106+
88107
# helper: builds main diff output (tracked + optional untracked)
89108
build_diff() {
90109
commit="$1"
@@ -189,10 +208,12 @@ build_history() {
189208
printf '**Date:** %s\n' "$(get_commit_date "$commit")" >>"$hist" || { print_error "Failed to write commit date to history file"; return 1; }
190209

191210
print_debug "Getting version for commit $commit"
192-
ver=$(get_metadata_value "version" "$commit") || { print_error "Failed to get project version for commit: $commit"; return 1; }
211+
ver=$(get_metadata_value "version" "$commit" 2>/dev/null || true)
193212
if [ -n "$ver" ]; then
194213
print_debug "Version found: $ver"
195214
printf '**Version:** %s\n' "$ver" >>"$hist" || { print_error "Failed to write version to history file"; return 1; }
215+
else
216+
print_debug "No version found for commit $commit"
196217
fi
197218

198219
print_debug "Getting message header for commit $commit"
@@ -289,9 +310,15 @@ summarize_commit() {
289310
print_debug "Summary cache path: $summary_cache"
290311

291312
if [ -f "$summary_cache" ]; then
292-
print_debug "Cache hit for commit: $commit"
293-
cat "$summary_cache"
294-
return 0
313+
# Check if cache has proper metadata format (starts with "Commit:")
314+
if head -1 "$summary_cache" | grep -q "^Commit:"; then
315+
print_debug "Cache hit for commit: $commit with proper metadata"
316+
cat "$summary_cache"
317+
return 0
318+
else
319+
print_debug "Cache exists but lacks metadata, regenerating for commit: $commit"
320+
rm -f "$summary_cache"
321+
fi
295322
fi
296323

297324
hist=$(portable_mktemp "hist.${commit}.XXXXXXX") || { print_error "Failed to create temp file for history"; return 1; }
@@ -305,7 +332,7 @@ summarize_commit() {
305332
return 1
306333
fi
307334

308-
sc_version=$(get_metadata_value "version" "$commit") || { print_error "Failed to get project version for $commit"; return 1; }
335+
sc_version=$(get_metadata_value "version" "$commit" 2>/dev/null || true)
309336
print_debug "Commit version: $sc_version"
310337

311338
summary_template=$(build_commit_summary_prompt "$sc_version" "$hist")
@@ -322,8 +349,15 @@ summarize_commit() {
322349
return 1
323350
fi
324351

325-
mv "$res_file" "$summary_cache"
352+
# Prepend commit metadata to the response
353+
tmp_output=$(portable_mktemp "output.${commit}.XXXXXXX") || { print_error "Failed to create temp output file"; return 1; }
354+
print_debug "Saving commit metadata for: $commit"
355+
save_commit_metadata "$commit" "$tmp_output"
356+
cat "$res_file" >> "$tmp_output"
357+
358+
mv "$tmp_output" "$summary_cache"
326359
print_debug "Summary cached at: $summary_cache"
360+
print_debug "Final output contains: $(head -1 "$summary_cache")"
327361
cat "$summary_cache"
328362
}
329363

src/init.sh

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ IFS="$(printf '\n\t')"
77

88
# Defaults
99
## Directory locations
10-
export GIV_HOME="${GIV_HOME:-$(git rev-parse --show-toplevel 2>/dev/null || echo "${HOME}/.giv")}"
10+
export GIV_HOME="${GIV_HOME:-$(git rev-parse --show-toplevel 2>/dev/null || echo "${HOME}")/.giv}"
1111
export GIV_LIB_DIR="${GIV_LIB_DIR:-}"
1212
export GIV_DOCS_DIR="${GIV_DOCS_DIR:-}"
1313
export GIV_TEMPLATE_DIR="${GIV_TEMPLATE_DIR:-}"
@@ -126,6 +126,7 @@ fi
126126

127127
# Export resolved globals
128128
export GIV_LIB_DIR GIV_TEMPLATE_DIR GIV_DOCS_DIR
129+
[ "${GIV_DEBUG}" = "true" ] && printf 'Using giv home directory: %s\n' "${GIV_HOME}"
129130
[ "${GIV_DEBUG}" = "true" ] && printf 'Using giv lib directory: %s\n' "${GIV_LIB_DIR}"
130131
[ "${GIV_DEBUG}" = "true" ] && printf 'Using giv template directory: %s\n' "${GIV_TEMPLATE_DIR}"
131132
[ "${GIV_DEBUG}" = "true" ] && printf 'Using giv docs directory: %s\n' "${GIV_DOCS_DIR}"

src/project_metadata.sh

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@ metadata_get_file_content() {
88
file_path="$1"
99
commit="$2"
1010

11-
if [ "$commit" = "HEAD" ] || [ -z "$commit" ]; then
12-
cat "$file_path"
11+
if [ "$commit" = "HEAD" ] || [ "$commit" = "--current" ] || [ -z "$commit" ]; then
12+
cat "$file_path" 2>/dev/null || return 1
13+
elif [ "$commit" = "--cached" ]; then
14+
git show ":$file_path" 2>/dev/null || return 1
1315
else
1416
git show "$commit:$file_path" 2>/dev/null || return 1
1517
fi
@@ -85,7 +87,7 @@ metadata_parse_custom() {
8587
echo "$content" | awk -v k="$key" '
8688
BEGIN { found=0 }
8789
$0 ~ k "[[:space:]]*=" {
88-
match($0, k "[[:space:]]*=[[:space:]]*\"([^"]+)\"", arr)
90+
match($0, k "[[:space:]]*=[[:space:]]*\"([^\"]+)\"", arr)
8991
if (arr[1] != "") {
9092
print arr[1]
9193
found=1
@@ -158,15 +160,24 @@ get_metadata_value() {
158160
custom)
159161
file="${GIV_PROJECT_VERSION_FILE:-version.txt}"
160162
if ! content=$(metadata_get_file_content "$file" "$commit"); then
161-
return 1
163+
return 1
162164
fi
163165
value=$(printf '%s' "$content" | awk -v k="$key" '
164166
BEGIN { IGNORECASE = 1 }
165167
$0 ~ k {
166-
match($0, k "[[:space:]]*=[[:space:]]*\"([^\"]+)\"", arr)
167-
if (arr[1] != "") {
168-
print arr[1]
169-
exit
168+
gsub(/^[[:space:]]*/, "", $0) # Remove leading whitespace
169+
if ($0 ~ k "[[:space:]]*=") {
170+
# Extract value after =, removing quotes and whitespace
171+
split($0, parts, "=")
172+
if (length(parts) >= 2) {
173+
val = parts[2]
174+
gsub(/^[[:space:]]*/, "", val) # Remove leading whitespace
175+
gsub(/[[:space:]]*$/, "", val) # Remove trailing whitespace
176+
gsub(/^["'"'"']/, "", val) # Remove leading quote
177+
gsub(/["'"'"']$/, "", val) # Remove trailing quote
178+
print val
179+
exit
180+
}
170181
}
171182
}
172183
')

0 commit comments

Comments
 (0)