Update 2 files
All checks were successful
Build-Test-Publish / build (linux/amd64) (push) Successful in 23s
Build-Test-Publish / build (linux/arm64) (push) Successful in 25s
Build-Test-Publish / test-install-from-scratch (linux/amd64) (push) Successful in 7s
Build-Test-Publish / test-install-from-scratch (linux/arm64) (push) Successful in 8s

This commit is contained in:
Your Name 2025-06-22 14:34:40 +12:00
parent 2eec3ba2ad
commit 9f4c2c7224
2 changed files with 315 additions and 333 deletions

324
gp/gp
View File

@ -1,18 +1,322 @@
#!/bin/bash #!/bin/bash
# find top folder of the git repo from current directory # gp - Git Push with AI-generated commit messages
# Improved version with better error handling, safety checks, and functionality
MYDIR=$(git rev-parse --show-toplevel) set -euo pipefail
if [ -z "$MYDIR" ]; then # Colors for output
echo "Not in a git repository" RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Function to print colored output
print_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
print_success() { echo -e "${GREEN}[SUCCESS]${NC} $1"; }
print_warning() { echo -e "${YELLOW}[WARNING]${NC} $1"; }
print_error() { echo -e "${RED}[ERROR]${NC} $1"; }
# Function to show help
show_help() {
cat << 'EOF'
gp - Git Push with smart commit messages
USAGE:
gp [options] [message]
OPTIONS:
-h, --help Show this help message
-n, --dry-run Show what would be committed without actually doing it
-f, --force Skip safety checks (use with caution)
-b, --branch Specify branch to push to (default: current branch)
-a, --add-all Add all files including untracked (default: only staged + modified)
ARGUMENTS:
message Optional custom commit message (overrides auto-generation)
EXAMPLES:
gp # Auto-generate commit message and push
gp "Fix bug in parser" # Use custom commit message
gp --dry-run # Preview what would be committed
gp -b develop # Push to develop branch instead of current
EOF
}
# Function to generate commit message based on changes
generate_commit_message() {
local files_changed=$(git diff --cached --name-only)
local 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)
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)
fi
if [ -z "$files_changed" ]; then
echo "No changes to commit"
return 1
fi
# Generate smart commit message based on file types and changes
local has_source_files=false
local has_config_files=false
local has_docs=false
local has_tests=false
local message=""
while IFS= read -r file; do
[ -z "$file" ] && continue
case "$file" in
*.cpp|*.hpp|*.c|*.h|*.js|*.ts|*.py|*.go|*.rs|*.java)
has_source_files=true
;;
*.json|*.yml|*.yaml|*.toml|*.ini|*.conf|CMakeLists.txt|Makefile)
has_config_files=true
;;
*.md|*.txt|*.rst|docs/*|README*)
has_docs=true
;;
*test*|*spec*|test/*|tests/*)
has_tests=true
;;
esac
done <<< "$files_changed"
# Create descriptive commit message
if [ "$files_count" -eq 1 ]; then
local single_file=$(echo "$files_changed" | head -1)
local change_type=$(git diff --cached --name-status "$single_file" 2>/dev/null || git diff --name-status "$single_file")
case "${change_type:0:1}" in
A) message="Add $single_file" ;;
M) message="Update $single_file" ;;
D) message="Remove $single_file" ;;
R) message="Rename $single_file" ;;
*) message="Modify $single_file" ;;
esac
else
local prefix=""
if $has_tests; then
prefix="test: "
elif $has_docs; then
prefix="docs: "
elif $has_config_files; then
prefix="config: "
elif $has_source_files; then
prefix="feat: "
fi
message="${prefix}Update $files_count files"
fi
echo "$message"
}
# Function to check if we're in a git repository
check_git_repo() {
if ! git rev-parse --git-dir >/dev/null 2>&1; then
print_error "Not in a git repository"
exit 1 exit 1
fi fi
}
# do a git diff, and use AI to determine a good commit message. # Function to check for uncommitted changes
check_for_changes() {
if git diff --cached --quiet && git diff --quiet; then
if [ "$ADD_ALL" = false ]; then
print_warning "No staged changes found"
print_info "Use 'gp -a' to add all files, or stage changes first with 'git add'"
exit 0
fi
fi
}
# add all changes at $MYDIR level, commit with the message from AI, and push to origin. # Function to show what would be committed
show_status() {
print_info "Current branch: $(git branch --show-current)"
print_info "Repository: $(git remote get-url origin 2>/dev/null || echo 'No remote')"
echo
git add . if git diff --cached --quiet; then
git commit -m "$(git diff --name-only | xargs -I{} sh -c 'echo "{}: "; git diff --color=always {} | head -n 1')" print_info "Staged changes: None"
git push origin main if ! git diff --quiet; then
print_info "Modified files (unstaged):"
git diff --name-only | sed 's/^/ /'
fi
else
print_info "Staged changes:"
git diff --cached --name-only | sed 's/^/ /'
fi
if [ "$ADD_ALL" = true ]; then
local untracked=$(git ls-files --others --exclude-standard)
if [ -n "$untracked" ]; then
print_info "Untracked files (will be added):"
echo "$untracked" | sed 's/^/ /'
fi
fi
}
# Function to perform the actual commit and push
do_commit_and_push() {
local commit_msg="$1"
local target_branch="$2"
# Add files if requested
if [ "$ADD_ALL" = true ]; then
print_info "Adding all files..."
git add .
fi
# Commit
print_info "Committing with message: '$commit_msg'"
git commit -m "$commit_msg"
# Push
print_info "Pushing to $target_branch..."
if git push origin "$target_branch"; then
print_success "Successfully pushed to origin/$target_branch"
else
print_error "Failed to push to origin/$target_branch"
print_info "You may need to pull first: git pull origin $target_branch"
exit 1
fi
}
# Default values
DRY_RUN=false
FORCE=false
ADD_ALL=false
CUSTOM_MESSAGE=""
TARGET_BRANCH=""
# Handle special commands first
case "${1:-}" in
autocomplete)
shift
autocomplete "$@"
exit 0
;;
version)
echo "gp version 2.0.0"
exit 0
;;
esac
# Parse command line arguments
while [[ $# -gt 0 ]]; do
case $1 in
-h|--help)
show_help
exit 0
;;
-n|--dry-run)
DRY_RUN=true
shift
;;
-f|--force)
FORCE=true
shift
;;
-a|--add-all)
ADD_ALL=true
shift
;;
-b|--branch)
TARGET_BRANCH="$2"
shift 2
;;
-*)
print_error "Unknown option: $1"
echo "Use 'gp --help' for usage information"
exit 1
;;
*)
CUSTOM_MESSAGE="$1"
shift
;;
esac
done
# Main execution
main() {
# Safety checks
check_git_repo
# Set target branch if not specified
if [ -z "$TARGET_BRANCH" ]; then
TARGET_BRANCH=$(git branch --show-current)
fi
# Check for changes
check_for_changes
# Show current status
show_status
echo
# Generate or use custom commit message
if [ -n "$CUSTOM_MESSAGE" ]; then
commit_message="$CUSTOM_MESSAGE"
print_info "Using custom commit message: '$commit_message'"
else
print_info "Generating commit message..."
commit_message=$(generate_commit_message)
if [ $? -ne 0 ]; then
print_error "Failed to generate commit message"
exit 1
fi
print_info "Generated commit message: '$commit_message'"
fi
# Dry run mode
if [ "$DRY_RUN" = true ]; then
print_warning "DRY RUN MODE - No changes will be made"
print_info "Would commit with message: '$commit_message'"
print_info "Would push to: origin/$TARGET_BRANCH"
exit 0
fi
# Safety confirmation (unless forced)
if [ "$FORCE" = false ]; then
echo
read -p "Proceed with commit and push? [y/N] " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
print_info "Aborted by user"
exit 0
fi
fi
# Execute the commit and push
do_commit_and_push "$commit_message" "$TARGET_BRANCH"
}
# Autocomplete function for bash
autocomplete() {
local args=("$@")
if [ ${#args[@]} -eq 0 ]; then
echo "--help"
echo "--dry-run"
echo "--force"
echo "--add-all"
echo "--branch"
echo "-h"
echo "-n"
echo "-f"
echo "-a"
echo "-b"
fi
}
# Run main function
main "$@"

View File

@ -1,322 +0,0 @@
#!/bin/bash
# gp - Git Push with AI-generated commit messages
# Improved version with better error handling, safety checks, and functionality
set -euo pipefail
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color
# Function to print colored output
print_info() { echo -e "${BLUE}[INFO]${NC} $1"; }
print_success() { echo -e "${GREEN}[SUCCESS]${NC} $1"; }
print_warning() { echo -e "${YELLOW}[WARNING]${NC} $1"; }
print_error() { echo -e "${RED}[ERROR]${NC} $1"; }
# Function to show help
show_help() {
cat << 'EOF'
gp - Git Push with smart commit messages
USAGE:
gp [options] [message]
OPTIONS:
-h, --help Show this help message
-n, --dry-run Show what would be committed without actually doing it
-f, --force Skip safety checks (use with caution)
-b, --branch Specify branch to push to (default: current branch)
-a, --add-all Add all files including untracked (default: only staged + modified)
ARGUMENTS:
message Optional custom commit message (overrides auto-generation)
EXAMPLES:
gp # Auto-generate commit message and push
gp "Fix bug in parser" # Use custom commit message
gp --dry-run # Preview what would be committed
gp -b develop # Push to develop branch instead of current
EOF
}
# Function to generate commit message based on changes
generate_commit_message() {
local files_changed=$(git diff --cached --name-only)
local 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)
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)
fi
if [ -z "$files_changed" ]; then
echo "No changes to commit"
return 1
fi
# Generate smart commit message based on file types and changes
local has_source_files=false
local has_config_files=false
local has_docs=false
local has_tests=false
local message=""
while IFS= read -r file; do
[ -z "$file" ] && continue
case "$file" in
*.cpp|*.hpp|*.c|*.h|*.js|*.ts|*.py|*.go|*.rs|*.java)
has_source_files=true
;;
*.json|*.yml|*.yaml|*.toml|*.ini|*.conf|CMakeLists.txt|Makefile)
has_config_files=true
;;
*.md|*.txt|*.rst|docs/*|README*)
has_docs=true
;;
*test*|*spec*|test/*|tests/*)
has_tests=true
;;
esac
done <<< "$files_changed"
# Create descriptive commit message
if [ "$files_count" -eq 1 ]; then
local single_file=$(echo "$files_changed" | head -1)
local change_type=$(git diff --cached --name-status "$single_file" 2>/dev/null || git diff --name-status "$single_file")
case "${change_type:0:1}" in
A) message="Add $single_file" ;;
M) message="Update $single_file" ;;
D) message="Remove $single_file" ;;
R) message="Rename $single_file" ;;
*) message="Modify $single_file" ;;
esac
else
local prefix=""
if $has_tests; then
prefix="test: "
elif $has_docs; then
prefix="docs: "
elif $has_config_files; then
prefix="config: "
elif $has_source_files; then
prefix="feat: "
fi
message="${prefix}Update $files_count files"
fi
echo "$message"
}
# Function to check if we're in a git repository
check_git_repo() {
if ! git rev-parse --git-dir >/dev/null 2>&1; then
print_error "Not in a git repository"
exit 1
fi
}
# Function to check for uncommitted changes
check_for_changes() {
if git diff --cached --quiet && git diff --quiet; then
if [ "$ADD_ALL" = false ]; then
print_warning "No staged changes found"
print_info "Use 'gp -a' to add all files, or stage changes first with 'git add'"
exit 0
fi
fi
}
# Function to show what would be committed
show_status() {
print_info "Current branch: $(git branch --show-current)"
print_info "Repository: $(git remote get-url origin 2>/dev/null || echo 'No remote')"
echo
if git diff --cached --quiet; then
print_info "Staged changes: None"
if ! git diff --quiet; then
print_info "Modified files (unstaged):"
git diff --name-only | sed 's/^/ /'
fi
else
print_info "Staged changes:"
git diff --cached --name-only | sed 's/^/ /'
fi
if [ "$ADD_ALL" = true ]; then
local untracked=$(git ls-files --others --exclude-standard)
if [ -n "$untracked" ]; then
print_info "Untracked files (will be added):"
echo "$untracked" | sed 's/^/ /'
fi
fi
}
# Function to perform the actual commit and push
do_commit_and_push() {
local commit_msg="$1"
local target_branch="$2"
# Add files if requested
if [ "$ADD_ALL" = true ]; then
print_info "Adding all files..."
git add .
fi
# Commit
print_info "Committing with message: '$commit_msg'"
git commit -m "$commit_msg"
# Push
print_info "Pushing to $target_branch..."
if git push origin "$target_branch"; then
print_success "Successfully pushed to origin/$target_branch"
else
print_error "Failed to push to origin/$target_branch"
print_info "You may need to pull first: git pull origin $target_branch"
exit 1
fi
}
# Default values
DRY_RUN=false
FORCE=false
ADD_ALL=false
CUSTOM_MESSAGE=""
TARGET_BRANCH=""
# Handle special commands first
case "${1:-}" in
autocomplete)
shift
autocomplete "$@"
exit 0
;;
version)
echo "gp version 2.0.0"
exit 0
;;
esac
# Parse command line arguments
while [[ $# -gt 0 ]]; do
case $1 in
-h|--help)
show_help
exit 0
;;
-n|--dry-run)
DRY_RUN=true
shift
;;
-f|--force)
FORCE=true
shift
;;
-a|--add-all)
ADD_ALL=true
shift
;;
-b|--branch)
TARGET_BRANCH="$2"
shift 2
;;
-*)
print_error "Unknown option: $1"
echo "Use 'gp --help' for usage information"
exit 1
;;
*)
CUSTOM_MESSAGE="$1"
shift
;;
esac
done
# Main execution
main() {
# Safety checks
check_git_repo
# Set target branch if not specified
if [ -z "$TARGET_BRANCH" ]; then
TARGET_BRANCH=$(git branch --show-current)
fi
# Check for changes
check_for_changes
# Show current status
show_status
echo
# Generate or use custom commit message
if [ -n "$CUSTOM_MESSAGE" ]; then
commit_message="$CUSTOM_MESSAGE"
print_info "Using custom commit message: '$commit_message'"
else
print_info "Generating commit message..."
commit_message=$(generate_commit_message)
if [ $? -ne 0 ]; then
print_error "Failed to generate commit message"
exit 1
fi
print_info "Generated commit message: '$commit_message'"
fi
# Dry run mode
if [ "$DRY_RUN" = true ]; then
print_warning "DRY RUN MODE - No changes will be made"
print_info "Would commit with message: '$commit_message'"
print_info "Would push to: origin/$TARGET_BRANCH"
exit 0
fi
# Safety confirmation (unless forced)
if [ "$FORCE" = false ]; then
echo
read -p "Proceed with commit and push? [y/N] " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
print_info "Aborted by user"
exit 0
fi
fi
# Execute the commit and push
do_commit_and_push "$commit_message" "$TARGET_BRANCH"
}
# Autocomplete function for bash
autocomplete() {
local args=("$@")
if [ ${#args[@]} -eq 0 ]; then
echo "--help"
echo "--dry-run"
echo "--force"
echo "--add-all"
echo "--branch"
echo "-h"
echo "-n"
echo "-f"
echo "-a"
echo "-b"
fi
}
# Run main function
main "$@"