- Added comprehensive bounds checking to prevent buffer overruns in multicall parsing - Implemented graduated validation system (Strict/Moderate/Permissive) to reduce false positives - Added LRU caching system for address validation with 10-minute TTL - Enhanced ABI decoder with missing Universal Router and Arbitrum-specific DEX signatures - Fixed duplicate function declarations and import conflicts across multiple files - Added error recovery mechanisms with multiple fallback strategies - Updated tests to handle new validation behavior for suspicious addresses - Fixed parser test expectations for improved validation system - Applied gofmt formatting fixes to ensure code style compliance - Fixed mutex copying issues in monitoring package by introducing MetricsSnapshot - Resolved critical security vulnerabilities in heuristic address extraction - Progress: Updated TODO audit from 10% to 35% complete 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
716 lines
18 KiB
Bash
Executable File
716 lines
18 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Enhanced Git Workflow for Local Self-Contained Development
|
|
# Provides full branching, forking, PR simulation, and merge workflows
|
|
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
PROJECT_ROOT="$(cd "$SCRIPT_DIR/.." && pwd)"
|
|
cd "$PROJECT_ROOT"
|
|
|
|
# Configuration
|
|
DEFAULT_MAIN_BRANCH="master"
|
|
DEFAULT_DEV_BRANCH="develop"
|
|
LOCAL_FORK_PREFIX="fork"
|
|
BACKUP_DIR="$PROJECT_ROOT/.git-backups"
|
|
|
|
# Colors for output
|
|
RED='\033[0;31m'
|
|
GREEN='\033[0;32m'
|
|
YELLOW='\033[1;33m'
|
|
BLUE='\033[0;34m'
|
|
NC='\033[0m' # No Color
|
|
|
|
log() {
|
|
echo -e "${GREEN}[GIT-WORKFLOW]${NC} $*"
|
|
}
|
|
|
|
warn() {
|
|
echo -e "${YELLOW}[WARNING]${NC} $*"
|
|
}
|
|
|
|
error() {
|
|
echo -e "${RED}[ERROR]${NC} $*"
|
|
}
|
|
|
|
info() {
|
|
echo -e "${BLUE}[INFO]${NC} $*"
|
|
}
|
|
|
|
usage() {
|
|
cat << EOF
|
|
Enhanced Git Workflow for MEV Bot - Self-Contained Development Stack
|
|
|
|
USAGE: $0 <command> [args]
|
|
|
|
BRANCH OPERATIONS:
|
|
feature <name> - Create feature branch from develop
|
|
fix <name> - Create hotfix branch from master
|
|
release <version> - Create release branch
|
|
branch-list - List all branches with status
|
|
branch-clean - Clean merged branches
|
|
|
|
FORK & PR SIMULATION:
|
|
fork-create <name> - Create local fork simulation
|
|
fork-list - List all local forks
|
|
pr-create <base> - Create PR simulation (local merge preparation)
|
|
pr-review - Review changes for PR
|
|
pr-merge <branch> - Merge PR with validation
|
|
|
|
MERGE & REBASE:
|
|
merge <branch> - Smart merge with CI validation
|
|
rebase <base> - Interactive rebase with conflict resolution
|
|
sync - Sync current branch with upstream
|
|
|
|
CI INTEGRATION:
|
|
ci-branch - Run CI on current branch
|
|
ci-pr <branch> - Run CI for PR validation
|
|
pre-commit - Manual pre-commit validation
|
|
pre-push - Manual pre-push validation
|
|
|
|
BACKUP & RESTORE:
|
|
backup - Create full git backup
|
|
restore <backup> - Restore from backup
|
|
checkpoint <name> - Create named checkpoint
|
|
|
|
ADVANCED WORKFLOWS:
|
|
flow-init - Initialize gitflow-style workflows
|
|
hotfix <name> - Complete hotfix workflow
|
|
release-finish <version> - Complete release workflow
|
|
conflict-resolve - Interactive conflict resolution
|
|
|
|
EXAMPLES:
|
|
$0 feature add-math-optimizations
|
|
$0 fork-create experimental-trading
|
|
$0 pr-create develop
|
|
$0 merge feature/new-arbitrage-engine
|
|
$0 ci-pr feature/fix-parser-bug
|
|
EOF
|
|
}
|
|
|
|
# Check if we're in a git repository
|
|
check_git_repo() {
|
|
if ! git rev-parse --git-dir >/dev/null 2>&1; then
|
|
error "Not in a git repository"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# Get current branch
|
|
get_current_branch() {
|
|
git rev-parse --abbrev-ref HEAD
|
|
}
|
|
|
|
# Check if branch exists
|
|
branch_exists() {
|
|
git show-ref --verify --quiet "refs/heads/$1"
|
|
}
|
|
|
|
# Run CI pipeline for branch validation
|
|
run_ci_for_branch() {
|
|
local branch="$1"
|
|
log "Running CI validation for branch: $branch"
|
|
|
|
# Switch to branch temporarily if not current
|
|
local current_branch
|
|
current_branch=$(get_current_branch)
|
|
|
|
if [[ "$current_branch" != "$branch" ]]; then
|
|
git checkout "$branch"
|
|
fi
|
|
|
|
# Run appropriate CI level based on branch type
|
|
if [[ "$branch" =~ ^(feature|fix)/ ]]; then
|
|
log "Running development CI for $branch"
|
|
make ci-dev
|
|
elif [[ "$branch" =~ ^release/ ]] || [[ "$branch" == "$DEFAULT_MAIN_BRANCH" ]]; then
|
|
log "Running full CI for $branch"
|
|
make ci-full
|
|
else
|
|
log "Running quick CI for $branch"
|
|
make ci-quick
|
|
fi
|
|
|
|
# Switch back if we changed branches
|
|
if [[ "$current_branch" != "$branch" ]]; then
|
|
git checkout "$current_branch"
|
|
fi
|
|
}
|
|
|
|
# Create feature branch
|
|
create_feature_branch() {
|
|
local feature_name="$1"
|
|
|
|
if [[ -z "$feature_name" ]]; then
|
|
error "Feature name required"
|
|
echo "Usage: $0 feature <name>"
|
|
exit 1
|
|
fi
|
|
|
|
local branch_name="feature/$feature_name"
|
|
|
|
if branch_exists "$branch_name"; then
|
|
error "Branch $branch_name already exists"
|
|
exit 1
|
|
fi
|
|
|
|
log "Creating feature branch: $branch_name"
|
|
|
|
# Ensure we're on develop and it's up to date
|
|
if branch_exists "$DEFAULT_DEV_BRANCH"; then
|
|
git checkout "$DEFAULT_DEV_BRANCH"
|
|
git pull origin "$DEFAULT_DEV_BRANCH" 2>/dev/null || true
|
|
else
|
|
warn "Develop branch doesn't exist, creating from master"
|
|
git checkout "$DEFAULT_MAIN_BRANCH"
|
|
git checkout -b "$DEFAULT_DEV_BRANCH"
|
|
fi
|
|
|
|
# Create and switch to feature branch
|
|
git checkout -b "$branch_name"
|
|
|
|
log "✅ Feature branch '$branch_name' created and active"
|
|
log "💡 Run tests with: make ci-dev"
|
|
}
|
|
|
|
# Create hotfix branch
|
|
create_fix_branch() {
|
|
local fix_name="$1"
|
|
|
|
if [[ -z "$fix_name" ]]; then
|
|
error "Fix name required"
|
|
echo "Usage: $0 fix <name>"
|
|
exit 1
|
|
fi
|
|
|
|
local branch_name="fix/$fix_name"
|
|
|
|
if branch_exists "$branch_name"; then
|
|
error "Branch $branch_name already exists"
|
|
exit 1
|
|
fi
|
|
|
|
log "Creating hotfix branch: $branch_name"
|
|
|
|
# Create from master
|
|
git checkout "$DEFAULT_MAIN_BRANCH"
|
|
git pull origin "$DEFAULT_MAIN_BRANCH" 2>/dev/null || true
|
|
git checkout -b "$branch_name"
|
|
|
|
log "✅ Hotfix branch '$branch_name' created and active"
|
|
log "💡 Run tests with: make ci-full"
|
|
}
|
|
|
|
# Create local fork simulation
|
|
create_fork() {
|
|
local fork_name="$1"
|
|
|
|
if [[ -z "$fork_name" ]]; then
|
|
error "Fork name required"
|
|
echo "Usage: $0 fork-create <name>"
|
|
exit 1
|
|
fi
|
|
|
|
local fork_branch="${LOCAL_FORK_PREFIX}/$fork_name"
|
|
|
|
if branch_exists "$fork_branch"; then
|
|
error "Fork $fork_branch already exists"
|
|
exit 1
|
|
fi
|
|
|
|
log "Creating local fork: $fork_branch"
|
|
|
|
# Create orphan branch for fork simulation
|
|
git checkout --orphan "$fork_branch"
|
|
git reset --hard "$DEFAULT_MAIN_BRANCH"
|
|
|
|
# Create initial commit for fork
|
|
git commit --allow-empty -m "chore: initialize fork '$fork_name'"
|
|
|
|
log "✅ Local fork '$fork_name' created"
|
|
log "💡 This simulates a separate fork for experimental development"
|
|
}
|
|
|
|
# List all branches with status
|
|
list_branches() {
|
|
log "Repository branch overview:"
|
|
echo ""
|
|
|
|
echo "📋 Local Branches:"
|
|
git branch -v
|
|
|
|
echo ""
|
|
echo "🔀 Remote Branches:"
|
|
git branch -rv 2>/dev/null || echo "No remote branches"
|
|
|
|
echo ""
|
|
echo "🍴 Local Forks:"
|
|
git branch | grep "^ $LOCAL_FORK_PREFIX/" || echo "No local forks"
|
|
|
|
echo ""
|
|
echo "📊 Branch Status:"
|
|
local current_branch
|
|
current_branch=$(get_current_branch)
|
|
echo "Current: $current_branch"
|
|
|
|
# Check if current branch has uncommitted changes
|
|
if ! git diff --quiet || ! git diff --cached --quiet; then
|
|
warn "Current branch has uncommitted changes"
|
|
fi
|
|
|
|
# Check if current branch is ahead/behind
|
|
local upstream
|
|
upstream=$(git rev-parse --abbrev-ref @{u} 2>/dev/null || echo "")
|
|
if [[ -n "$upstream" ]]; then
|
|
local ahead behind
|
|
ahead=$(git rev-list --count "$upstream..HEAD" 2>/dev/null || echo "0")
|
|
behind=$(git rev-list --count "HEAD..$upstream" 2>/dev/null || echo "0")
|
|
|
|
if [[ "$ahead" -gt 0 ]]; then
|
|
info "Current branch is $ahead commits ahead of $upstream"
|
|
fi
|
|
if [[ "$behind" -gt 0 ]]; then
|
|
warn "Current branch is $behind commits behind $upstream"
|
|
fi
|
|
fi
|
|
}
|
|
|
|
# Create PR simulation (prepare for merge)
|
|
create_pr() {
|
|
local target_branch="$1"
|
|
local current_branch
|
|
current_branch=$(get_current_branch)
|
|
|
|
if [[ -z "$target_branch" ]]; then
|
|
error "Target branch required"
|
|
echo "Usage: $0 pr-create <target-branch>"
|
|
exit 1
|
|
fi
|
|
|
|
if ! branch_exists "$target_branch"; then
|
|
error "Target branch '$target_branch' does not exist"
|
|
exit 1
|
|
fi
|
|
|
|
log "Creating PR simulation: $current_branch → $target_branch"
|
|
|
|
# Run CI validation for PR
|
|
run_ci_for_branch "$current_branch"
|
|
|
|
# Show diff summary
|
|
echo ""
|
|
log "PR Summary:"
|
|
echo "From: $current_branch"
|
|
echo "To: $target_branch"
|
|
echo ""
|
|
|
|
echo "📝 Changed files:"
|
|
git diff --name-status "$target_branch..$current_branch"
|
|
|
|
echo ""
|
|
echo "📊 Commit summary:"
|
|
git log --oneline "$target_branch..$current_branch"
|
|
|
|
echo ""
|
|
echo "🔍 Conflict check:"
|
|
if git merge-tree "$(git merge-base "$target_branch" "$current_branch")" "$target_branch" "$current_branch" | grep -q "<<<<<<< "; then
|
|
warn "Potential merge conflicts detected"
|
|
echo "Run: $0 conflict-resolve"
|
|
else
|
|
log "No merge conflicts detected"
|
|
fi
|
|
|
|
echo ""
|
|
log "✅ PR simulation ready"
|
|
log "Next steps:"
|
|
log " - Review changes: $0 pr-review"
|
|
log " - Merge PR: $0 pr-merge $target_branch"
|
|
}
|
|
|
|
# Review PR changes
|
|
review_pr() {
|
|
local current_branch
|
|
current_branch=$(get_current_branch)
|
|
|
|
log "Reviewing changes for: $current_branch"
|
|
|
|
# Show detailed diff
|
|
echo ""
|
|
echo "📝 Detailed changes:"
|
|
git diff develop.."$current_branch" --stat
|
|
|
|
echo ""
|
|
read -p "View full diff? (y/N): " -n 1 -r
|
|
echo
|
|
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
|
git diff develop.."$current_branch"
|
|
fi
|
|
|
|
echo ""
|
|
log "Code quality checks:"
|
|
|
|
# Run linting
|
|
if make ci-quick; then
|
|
log "✅ Code quality checks passed"
|
|
else
|
|
error "❌ Code quality checks failed"
|
|
echo "Fix issues before merging"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# Merge PR with validation
|
|
merge_pr() {
|
|
local target_branch="$1"
|
|
local current_branch
|
|
current_branch=$(get_current_branch)
|
|
|
|
if [[ -z "$target_branch" ]]; then
|
|
error "Target branch required"
|
|
echo "Usage: $0 pr-merge <target-branch>"
|
|
exit 1
|
|
fi
|
|
|
|
log "Merging PR: $current_branch → $target_branch"
|
|
|
|
# Final CI validation
|
|
log "Running final CI validation..."
|
|
run_ci_for_branch "$current_branch"
|
|
|
|
# Create backup before merge
|
|
local backup_name="before-merge-$(date +%Y%m%d-%H%M%S)"
|
|
create_backup "$backup_name"
|
|
|
|
# Switch to target branch and merge
|
|
git checkout "$target_branch"
|
|
|
|
# Update target branch
|
|
git pull origin "$target_branch" 2>/dev/null || true
|
|
|
|
# Perform merge
|
|
if git merge --no-ff "$current_branch" -m "Merge branch '$current_branch' into $target_branch
|
|
|
|
🤖 Generated with [Claude Code](https://claude.com/claude-code)
|
|
Co-Authored-By: Claude <noreply@anthropic.com>"; then
|
|
log "✅ Merge completed successfully"
|
|
|
|
# Run post-merge CI
|
|
log "Running post-merge validation..."
|
|
run_ci_for_branch "$target_branch"
|
|
|
|
# Optional: Delete merged branch
|
|
read -p "Delete merged branch '$current_branch'? (y/N): " -n 1 -r
|
|
echo
|
|
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
|
git branch -d "$current_branch"
|
|
log "Deleted merged branch: $current_branch"
|
|
fi
|
|
else
|
|
error "Merge failed - conflicts need resolution"
|
|
echo "Run: $0 conflict-resolve"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# Smart merge with CI validation
|
|
smart_merge() {
|
|
local source_branch="$1"
|
|
local current_branch
|
|
current_branch=$(get_current_branch)
|
|
|
|
if [[ -z "$source_branch" ]]; then
|
|
error "Source branch required"
|
|
echo "Usage: $0 merge <source-branch>"
|
|
exit 1
|
|
fi
|
|
|
|
log "Smart merge: $source_branch → $current_branch"
|
|
|
|
# Validate both branches
|
|
run_ci_for_branch "$current_branch"
|
|
run_ci_for_branch "$source_branch"
|
|
|
|
# Create backup
|
|
local backup_name="before-smart-merge-$(date +%Y%m%d-%H%M%S)"
|
|
create_backup "$backup_name"
|
|
|
|
# Perform merge
|
|
if git merge "$source_branch"; then
|
|
log "✅ Smart merge completed"
|
|
run_ci_for_branch "$current_branch"
|
|
else
|
|
error "Merge conflicts detected"
|
|
echo "Run: $0 conflict-resolve"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# Interactive conflict resolution
|
|
resolve_conflicts() {
|
|
log "Interactive conflict resolution"
|
|
|
|
# Check if we're in a merge
|
|
if [[ ! -f .git/MERGE_HEAD ]]; then
|
|
error "No merge in progress"
|
|
exit 1
|
|
fi
|
|
|
|
# Show conflicted files
|
|
echo ""
|
|
echo "📝 Conflicted files:"
|
|
git diff --name-only --diff-filter=U
|
|
|
|
echo ""
|
|
echo "🔧 Resolution options:"
|
|
echo "1) Open merge tool (if configured)"
|
|
echo "2) Show conflicts in terminal"
|
|
echo "3) Abort merge"
|
|
|
|
read -p "Choose option (1-3): " -n 1 -r
|
|
echo
|
|
|
|
case $REPLY in
|
|
1)
|
|
if git config merge.tool >/dev/null; then
|
|
git mergetool
|
|
else
|
|
warn "No merge tool configured"
|
|
echo "Configure with: git config merge.tool <tool>"
|
|
fi
|
|
;;
|
|
2)
|
|
echo ""
|
|
echo "📝 Conflicts:"
|
|
git diff --diff-filter=U
|
|
;;
|
|
3)
|
|
git merge --abort
|
|
log "Merge aborted"
|
|
return
|
|
;;
|
|
*)
|
|
error "Invalid option"
|
|
return
|
|
;;
|
|
esac
|
|
|
|
# After resolution
|
|
echo ""
|
|
read -p "Have conflicts been resolved? (y/N): " -n 1 -r
|
|
echo
|
|
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
|
git add .
|
|
git commit --no-edit
|
|
log "✅ Merge completed"
|
|
|
|
# Run CI after merge
|
|
run_ci_for_branch "$(get_current_branch)"
|
|
fi
|
|
}
|
|
|
|
# Create backup
|
|
create_backup() {
|
|
local backup_name="${1:-backup-$(date +%Y%m%d-%H%M%S)}"
|
|
|
|
mkdir -p "$BACKUP_DIR"
|
|
|
|
log "Creating backup: $backup_name"
|
|
|
|
# Create git bundle
|
|
git bundle create "$BACKUP_DIR/$backup_name.bundle" --all
|
|
|
|
# Create stash backup if there are changes
|
|
if ! git diff --quiet || ! git diff --cached --quiet; then
|
|
git stash push -m "Backup stash: $backup_name"
|
|
echo "backup-stash-$backup_name" > "$BACKUP_DIR/$backup_name.stash"
|
|
fi
|
|
|
|
# Save current branch info
|
|
echo "$(get_current_branch)" > "$BACKUP_DIR/$backup_name.branch"
|
|
|
|
log "✅ Backup created: $backup_name"
|
|
log "Location: $BACKUP_DIR/"
|
|
}
|
|
|
|
# Restore from backup
|
|
restore_backup() {
|
|
local backup_name="$1"
|
|
|
|
if [[ -z "$backup_name" ]]; then
|
|
error "Backup name required"
|
|
echo "Available backups:"
|
|
ls -1 "$BACKUP_DIR"/*.bundle 2>/dev/null | sed 's/.*\///' | sed 's/\.bundle$//' || echo "No backups found"
|
|
exit 1
|
|
fi
|
|
|
|
local bundle_file="$BACKUP_DIR/$backup_name.bundle"
|
|
|
|
if [[ ! -f "$bundle_file" ]]; then
|
|
error "Backup not found: $backup_name"
|
|
exit 1
|
|
fi
|
|
|
|
warn "This will restore git state from backup: $backup_name"
|
|
read -p "Continue? (y/N): " -n 1 -r
|
|
echo
|
|
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
|
|
echo "Restore cancelled"
|
|
exit 0
|
|
fi
|
|
|
|
log "Restoring from backup: $backup_name"
|
|
|
|
# Restore from bundle
|
|
git fetch "$bundle_file"
|
|
|
|
# Restore branch if saved
|
|
if [[ -f "$BACKUP_DIR/$backup_name.branch" ]]; then
|
|
local saved_branch
|
|
saved_branch=$(cat "$BACKUP_DIR/$backup_name.branch")
|
|
if branch_exists "$saved_branch"; then
|
|
git checkout "$saved_branch"
|
|
fi
|
|
fi
|
|
|
|
log "✅ Backup restored: $backup_name"
|
|
}
|
|
|
|
# Run CI for current branch
|
|
run_ci_branch() {
|
|
local current_branch
|
|
current_branch=$(get_current_branch)
|
|
run_ci_for_branch "$current_branch"
|
|
}
|
|
|
|
# Run CI for PR validation
|
|
run_ci_pr() {
|
|
local branch="$1"
|
|
|
|
if [[ -z "$branch" ]]; then
|
|
branch=$(get_current_branch)
|
|
fi
|
|
|
|
log "Running PR validation CI for: $branch"
|
|
run_ci_for_branch "$branch"
|
|
|
|
# Additional PR-specific checks
|
|
log "Running PR-specific validations..."
|
|
|
|
# Check commit messages
|
|
log "Checking commit message format..."
|
|
git log --oneline "develop..$branch" | while read -r line; do
|
|
if [[ ! "$line" =~ ^[a-f0-9]+\ (feat|fix|chore|docs|style|refactor|perf|test)(\(.+\))?:\ .+ ]]; then
|
|
warn "Commit message format: $line"
|
|
warn "Should follow: type(scope): description"
|
|
fi
|
|
done
|
|
|
|
log "✅ PR validation completed"
|
|
}
|
|
|
|
# Clean merged branches
|
|
clean_branches() {
|
|
log "Cleaning merged branches..."
|
|
|
|
# Get merged branches (excluding master, develop, and current)
|
|
local current_branch
|
|
current_branch=$(get_current_branch)
|
|
|
|
local merged_branches
|
|
merged_branches=$(git branch --merged "$DEFAULT_MAIN_BRANCH" | grep -v "$DEFAULT_MAIN_BRANCH" | grep -v "$DEFAULT_DEV_BRANCH" | grep -v "^* $current_branch" | grep -v "^ $current_branch" | sed 's/^[ *]*//')
|
|
|
|
if [[ -z "$merged_branches" ]]; then
|
|
log "No merged branches to clean"
|
|
return
|
|
fi
|
|
|
|
echo "📝 Merged branches to delete:"
|
|
echo "$merged_branches"
|
|
|
|
echo ""
|
|
read -p "Delete these branches? (y/N): " -n 1 -r
|
|
echo
|
|
if [[ $REPLY =~ ^[Yy]$ ]]; then
|
|
echo "$merged_branches" | while read -r branch; do
|
|
if [[ -n "$branch" ]]; then
|
|
git branch -d "$branch"
|
|
log "Deleted: $branch"
|
|
fi
|
|
done
|
|
fi
|
|
}
|
|
|
|
# Main command dispatcher
|
|
main() {
|
|
check_git_repo
|
|
|
|
if [[ $# -eq 0 ]]; then
|
|
usage
|
|
exit 0
|
|
fi
|
|
|
|
local command="$1"
|
|
shift
|
|
|
|
case "$command" in
|
|
feature)
|
|
create_feature_branch "$@"
|
|
;;
|
|
fix)
|
|
create_fix_branch "$@"
|
|
;;
|
|
fork-create)
|
|
create_fork "$@"
|
|
;;
|
|
fork-list)
|
|
git branch | grep "^ $LOCAL_FORK_PREFIX/" || echo "No local forks"
|
|
;;
|
|
pr-create)
|
|
create_pr "$@"
|
|
;;
|
|
pr-review)
|
|
review_pr
|
|
;;
|
|
pr-merge)
|
|
merge_pr "$@"
|
|
;;
|
|
merge)
|
|
smart_merge "$@"
|
|
;;
|
|
conflict-resolve)
|
|
resolve_conflicts
|
|
;;
|
|
branch-list)
|
|
list_branches
|
|
;;
|
|
branch-clean)
|
|
clean_branches
|
|
;;
|
|
backup)
|
|
create_backup "$@"
|
|
;;
|
|
restore)
|
|
restore_backup "$@"
|
|
;;
|
|
ci-branch)
|
|
run_ci_branch
|
|
;;
|
|
ci-pr)
|
|
run_ci_pr "$@"
|
|
;;
|
|
pre-commit)
|
|
make ci-precommit
|
|
;;
|
|
pre-push)
|
|
make ci-dev
|
|
;;
|
|
*)
|
|
error "Unknown command: $command"
|
|
usage
|
|
exit 1
|
|
;;
|
|
esac
|
|
}
|
|
|
|
# Run main function
|
|
main "$@" |