diff --git a/gp/gp b/gp/gp index dccbe67..785c65b 100755 --- a/gp/gp +++ b/gp/gp @@ -49,27 +49,43 @@ EOF # Function to generate commit message based on changes generate_commit_message() { - local files_changed - files_changed=$(git diff --cached --name-only) - local files_count - files_count=$(echo "$files_changed" | wc -l) - - if [ -z "$files_changed" ]; then - files_changed=$(git diff --name-only) - files_count=$(echo "$files_changed" | wc -l) + # First check if we have staged changes + local has_staged_changes=false + if ! git diff --cached --quiet; then + has_staged_changes=true fi - # If add-all is enabled, also include untracked files - if [ "$ADD_ALL" = true ] && [ -z "$files_changed" ]; then - files_changed=$(git ls-files --others --exclude-standard) - files_count=$(echo "$files_changed" | wc -l) + # Determine which changes to analyze based on staging status and ADD_ALL setting + local status_command="" + if [ "$has_staged_changes" = true ]; then + status_command="git diff --cached --name-status" + else + status_command="git diff --name-status" fi - if [ -z "$files_changed" ]; then + # Get all changes (staged or unstaged depending on context) + local all_changes + all_changes=$($status_command) + + # If no changes from diff, check for untracked files when add-all is enabled + if [ -z "$all_changes" ] && [ "$ADD_ALL" = true ]; then + local untracked_files + untracked_files=$(git ls-files --others --exclude-standard) + if [ -n "$untracked_files" ]; then + # Convert untracked files to "A" (added) status format + all_changes=$(echo "$untracked_files" | sed 's/^/A\t/') + fi + fi + + if [ -z "$all_changes" ]; then echo "No changes to commit" return 1 fi + # Count total files + local files_count + files_count=$(echo "$all_changes" | wc -l) + # Generate smart commit message based on file types and changes local has_source_files=false local has_config_files=false @@ -77,7 +93,8 @@ generate_commit_message() { local has_tests=false local message="" - while IFS= read -r file; do + # Extract just the filenames for type detection + while IFS=$'\t' read -r status file; do [ -z "$file" ] && continue case "$file" in @@ -94,15 +111,18 @@ generate_commit_message() { has_tests=true ;; esac - done <<< "$files_changed" + done <<< "$all_changes" # Create descriptive commit message if [ "$files_count" -eq 1 ]; then + local change_line + change_line=$(echo "$all_changes" | head -1) + local status local single_file - single_file=$(echo "$files_changed" | head -1) - local change_type - change_type=$(git diff --cached --name-status -- "$single_file" 2>/dev/null || git diff --name-status -- "$single_file") - case "${change_type:0:1}" in + status=$(echo "$change_line" | cut -f1) + single_file=$(echo "$change_line" | cut -f2) + + case "${status:0:1}" in A) message="Add $single_file" ;; M) message="Update $single_file" ;; D) message="Remove $single_file" ;; @@ -110,6 +130,58 @@ generate_commit_message() { *) message="Modify $single_file" ;; esac else + # For multiple files, analyze the types of changes + local added_count=0 + local modified_count=0 + local deleted_count=0 + local renamed_count=0 + + # Use the all_changes variable we already have + + # Count different types of changes + while IFS=$'\t' read -r status file; do + [ -z "$status" ] && continue + case "${status:0:1}" in + A) ((added_count++)) ;; + M) ((modified_count++)) ;; + D) ((deleted_count++)) ;; + R) ((renamed_count++)) ;; + esac + done <<< "$all_changes" + + # Also count untracked files if add-all is enabled + if [ "$ADD_ALL" = true ]; then + local untracked_files + untracked_files=$(git ls-files --others --exclude-standard) + if [ -n "$untracked_files" ]; then + local untracked_count + untracked_count=$(echo "$untracked_files" | wc -l) + ((added_count += untracked_count)) + fi + fi + + # Generate message based on change types + local change_parts=() + [ $added_count -gt 0 ] && change_parts+=("add $added_count") + [ $modified_count -gt 0 ] && change_parts+=("update $modified_count") + [ $deleted_count -gt 0 ] && change_parts+=("remove $deleted_count") + [ $renamed_count -gt 0 ] && change_parts+=("rename $renamed_count") + + local change_desc="" + if [ ${#change_parts[@]} -eq 1 ]; then + change_desc="${change_parts[0]}" + elif [ ${#change_parts[@]} -eq 2 ]; then + change_desc="${change_parts[0]} and ${change_parts[1]}" + else + # Join all but last with commas, last with "and" + local last_idx=$((${#change_parts[@]} - 1)) + for i in $(seq 0 $((last_idx - 1))); do + [ $i -gt 0 ] && change_desc+=", " + change_desc+="${change_parts[i]}" + done + change_desc+=" and ${change_parts[last_idx]}" + fi + local prefix="" if $has_tests; then prefix="test: " @@ -121,7 +193,10 @@ generate_commit_message() { prefix="feat: " fi - message="${prefix}Update $files_count files" + # Capitalize first letter of change description + change_desc="$(echo "${change_desc:0:1}" | tr '[:lower:]' '[:upper:]')${change_desc:1}" + + message="${prefix}${change_desc} files" fi echo "$message"