Skip to content

Commit 76ae9dc

Browse files
Copilotelifarleyaider-chat-bot
authored
Require GNU getopt and leverage it for enhanced CLI option parsing with short options (#112)
* Initial plan * Integrate GNU getopt for enhanced option handling in hug-cli-flags Co-authored-by: elifarley <[email protected]> * Update documentation to reflect -q short option and GNU getopt integration Co-authored-by: elifarley <[email protected]> * Make getopt a hard requirement and leverage it in git-bdel-backup - Remove fallback to manual parsing in hug-cli-flags (getopt is now required) - Update hug-cli-flags documentation to reflect getopt as a requirement - Refactor git-bdel-backup to use getopt directly for all option parsing (common + custom) - Update git-bdel-backup help text to show -q short option - Update tests to match getopt's error messages - Handle set -e interaction with getopt failures properly Co-authored-by: elifarley <[email protected]> * Add short options and leverage getopt in more commands - Add -k and -o short options for --keep and --delete-older-than in git-bdel-backup - Convert git-bc to use getopt with -t short option for --point-to - Convert git-bpush to use getopt for all options - Update help text and examples to show short options - Update tests to match getopt error messages Co-authored-by: elifarley <[email protected]> * fix: correct getopt test grouping and improve error handling Co-authored-by: aider (openai/Grok-4-Fast-Reasoning) <[email protected]> * ♻️ Introduce centralized validate_commitish function Refactor git-bc, git-bdel, and git-bdel-backup to use shared validation logic from hug-git-kit instead of duplicated git rev-parse checks. Improve error message clarity for --keep option in git-bdel-backup. Centralizing commitish validation reduces duplication, ensures consistent error handling, and simplifies maintenance across hug git tools while preserving existing behavior. * refactor: use validate_commitish for commit validation Co-authored-by: aider (openai/Grok-4-Fast-Reasoning) <[email protected]> * Fix tests to match validate_commitish error messages Update test expectations to match the error messages from the new validate_commitish function introduced in recent commits. The function provides more descriptive error messages that include the context of where validation failed. Co-authored-by: elifarley <[email protected]> * refactor: consolidate validation by moving validate_commitish and dropping validate_commit Co-authored-by: aider (openai/Grok-4-Fast-Reasoning) <[email protected]> --------- Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: elifarley <[email protected]> Co-authored-by: Elifarley C <[email protected]> Co-authored-by: aider (openai/Grok-4-Fast-Reasoning) <[email protected]>
1 parent 2766b75 commit 76ae9dc

File tree

16 files changed

+371
-146
lines changed

16 files changed

+371
-146
lines changed

git-config/bin/git-bc

Lines changed: 51 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -12,36 +12,36 @@ show_help() {
1212
hug bc: Create a new branch and switch to it
1313
1414
USAGE:
15-
hug bc [<branch-name>] [--point-to <commitish>] [-h, --help]
16-
hug bc [--point-to <commitish>] [<branch-name>] [-h, --help]
15+
hug bc [<branch-name>] [-t, --point-to <commitish>] [--no-switch] [-h, --help]
16+
hug bc [-t, --point-to <commitish>] [<branch-name>] [--no-switch] [-h, --help]
1717
1818
ARGUMENTS:
19-
<branch-name> Name for the new branch (optional with --point-to)
19+
<branch-name> Name for the new branch (optional with -t/--point-to)
2020
2121
OPTIONS:
22-
--point-to <commitish> Create branch pointing to a specific commit, tag, or branch
23-
If specified without a branch name, generates one automatically
24-
--no-switch Create branch without switching to it
25-
-h, --help Show this help
22+
-t, --point-to <commitish> Create branch pointing to a specific commit, tag, or branch
23+
If specified without a branch name, generates one automatically
24+
--no-switch Create branch without switching to it
25+
-h, --help Show this help
2626
2727
DESCRIPTION:
2828
Creates a new branch and switches to it. By default, creates from the current HEAD.
2929
30-
With --point-to, you can create a branch from any commit, tag, or branch.
31-
When --point-to is used without a branch name, automatically generates a name:
30+
With -t/--point-to, you can create a branch from any commit, tag, or branch.
31+
When -t/--point-to is used without a branch name, automatically generates a name:
3232
- If target is a branch: <branch>.copy.<iso-datetime>
3333
- If target is not a branch: <target>.branch.<iso-datetime>
3434
3535
The ISO datetime format is YYYYMMDD-HHMM (e.g., 20251109-1430).
3636
3737
EXAMPLES:
3838
hug bc new-feature # Create branch from current HEAD
39-
hug bc --point-to abc123 my-feature # Create branch from commit abc123
40-
hug bc --point-to v1.0.0 # Auto-generate name from tag
41-
hug bc --point-to main # Auto-generate name from branch
42-
hug bc my-feature --point-to abc123 # Flag can come after branch name
39+
hug bc -t abc123 my-feature # Create branch from commit abc123
40+
hug bc -t v1.0.0 # Auto-generate name from tag
41+
hug bc -t main # Auto-generate name from branch
42+
hug bc my-feature -t abc123 # Flag can come after branch name
4343
hug bc --no-switch backup-branch # Create without switching
44-
hug bc --no-switch --point-to v1.0.0 # Auto-generate and create without switching
44+
hug bc --no-switch -t v1.0.0 # Auto-generate and create without switching
4545
4646
SEE ALSO:
4747
hug b Switch to an existing branch
@@ -53,59 +53,69 @@ FURTHER READING:
5353
EOF
5454
}
5555

56-
# Check for help flag first
57-
for arg in "$@"; do
58-
if [[ "$arg" == "-h" || "$arg" == "--help" ]]; then
59-
show_help
60-
exit 0
61-
fi
62-
done
63-
6456
check_git_repo
6557

66-
# Parse arguments
58+
# Parse arguments using getopt
59+
set +e # Temporarily disable exit on error to capture getopt failure
60+
PARSED=$(getopt --options ht: --longoptions help,point-to:,no-switch --name "hug bc" -- "$@" 2>&1)
61+
getopt_status=$?
62+
set -e # Re-enable exit on error
63+
64+
if [ $getopt_status -ne 0 ]; then
65+
# getopt failed - print the error message if available
66+
if [ -n "$PARSED" ]; then
67+
echo "$PARSED" >&2
68+
fi
69+
exit 1
70+
fi
71+
72+
eval set -- "$PARSED"
73+
74+
# Initialize variables
6775
branch_name=""
6876
point_to=""
6977
no_switch=false
70-
while [[ $# -gt 0 ]]; do
78+
79+
# Process options
80+
while true; do
7181
case "$1" in
72-
--point-to)
73-
if [[ $# -lt 2 ]]; then
74-
error "--point-to requires a commitish argument"
75-
fi
82+
-h|--help)
83+
show_help
84+
exit 0
85+
;;
86+
-t|--point-to)
87+
validate_commitish "-t/--point-to" "$2"
7688
point_to="$2"
7789
shift 2
7890
;;
7991
--no-switch)
8092
no_switch=true
8193
shift
8294
;;
83-
-*)
84-
error "Unknown option: $1. See 'hug bc --help'."
95+
--)
96+
shift
97+
break
8598
;;
8699
*)
87-
if [[ -z "$branch_name" ]]; then
88-
branch_name="$1"
89-
else
90-
error "Too many arguments. Expected one branch name. See 'hug bc --help'."
91-
fi
92-
shift
100+
error "Internal error in option parsing"
93101
;;
94102
esac
95103
done
96104

105+
# Collect branch name from remaining arguments
106+
if [[ $# -gt 1 ]]; then
107+
error "Too many arguments. Expected one branch name. See 'hug bc --help'."
108+
elif [[ $# -eq 1 ]]; then
109+
branch_name="$1"
110+
fi
111+
97112
# If no branch name and no point-to, error
98113
if [[ -z "$branch_name" && -z "$point_to" ]]; then
99114
error "Branch name is required. See 'hug bc --help'."
100115
fi
101116

102117
# If point-to is specified without a branch name, generate one
103118
if [[ -n "$point_to" && -z "$branch_name" ]]; then
104-
# Verify the target exists
105-
if ! git rev-parse --verify --quiet "$point_to" >/dev/null 2>&1; then
106-
error "Invalid commitish: $point_to"
107-
fi
108-
109119
# Check if point_to is a branch name
110120
is_branch=false
111121
if git show-ref --verify --quiet "refs/heads/$point_to" 2>/dev/null; then
@@ -145,10 +155,6 @@ fi
145155

146156
# Create and switch to the branch
147157
if [[ -n "$point_to" ]]; then
148-
# Verify the target exists
149-
if ! git rev-parse --verify --quiet "$point_to" >/dev/null 2>&1; then
150-
error "Invalid commitish: $point_to"
151-
fi
152158
if [[ "$no_switch" == true ]]; then
153159
git branch "$branch_name" "$point_to"
154160
info "Created branch '$branch_name' pointing to $point_to (use 'hug b $branch_name' to switch)"

git-config/bin/git-bdel

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ show_help() {
1212
hug bdel: Delete one or more local branches safely
1313
1414
USAGE:
15-
hug bdel [<branch>...] [--dry-run] [-f, --force] [--quiet] [-h, --help]
15+
hug bdel [<branch>...] [--dry-run] [-f, --force] [-q, --quiet] [-h, --help]
1616
1717
ARGUMENTS:
1818
<branch>... One or more branch names to delete
@@ -21,7 +21,7 @@ ARGUMENTS:
2121
OPTIONS:
2222
--dry-run Preview the delete operation without applying changes
2323
-f, --force Skip confirmation prompts and force delete unmerged branches
24-
--quiet Suppress output (sets HUG_QUIET=T)
24+
-q, --quiet Suppress output (sets HUG_QUIET=T)
2525
-h, --help Show this help
2626
2727
DESCRIPTION:
@@ -52,7 +52,7 @@ SEE ALSO:
5252
EOF
5353
}
5454

55-
# Parse common flags (--dry-run, -f|--force, --quiet, -h|--help)
55+
# Parse common flags (--dry-run, -f|--force, -q|--quiet, -h|--help)
5656
eval "$(parse_common_flags "$@")"
5757

5858
# Collect branch names
@@ -147,10 +147,7 @@ hug_bdel() {
147147
error "Cannot delete current branch '$current_branch'. Switch to another branch first."
148148
fi
149149

150-
# Validate that branch exists
151-
if ! git rev-parse --verify "$branch" >/dev/null 2>&1; then
152-
error "Branch '$branch' does not exist."
153-
fi
150+
validate_commitish "bdel argument" "$branch"
154151
done
155152

156153
# Set dry_run default if not already set by parse_common_flags

git-config/bin/git-bdel-backup

Lines changed: 62 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ show_help() {
1212
hug bdel-backup: Delete backup branches with filtering options
1313
1414
USAGE:
15-
hug bdel-backup [<backup-branch>...] [--keep N] [--delete-older-than PATTERN] [--dry-run] [-f, --force] [--quiet] [-h, --help]
15+
hug bdel-backup [<backup-branch>...] [-k, --keep N] [-o, --delete-older-than PATTERN] [--dry-run] [-f, --force] [-q, --quiet] [-h, --help]
1616
1717
ARGUMENTS:
1818
<backup-branch>... One or more backup branch names to delete
@@ -21,14 +21,14 @@ ARGUMENTS:
2121
If not provided, shows interactive list for selection
2222
2323
OPTIONS:
24-
--keep N Keep N most recent backup branches (delete the rest)
25-
--delete-older-than P Delete backups older than pattern P
26-
Patterns: YYYY, YYYY-MM, YYYY-MM/DD, YYYY-MM/DD-HH, YYYY-MM/DD-HHMM
27-
Example: --delete-older-than 2024-11 deletes backups from Nov 2024 and earlier
28-
--dry-run Preview the delete operation without applying changes
29-
-f, --force Skip confirmation prompts
30-
--quiet Suppress output (sets HUG_QUIET=T)
31-
-h, --help Show this help
24+
-k, --keep N Keep N most recent backup branches (delete the rest)
25+
-o, --delete-older-than P Delete backups older than pattern P
26+
Patterns: YYYY, YYYY-MM, YYYY-MM/DD, YYYY-MM/DD-HH, YYYY-MM/DD-HHMM
27+
Example: -o 2024-11 deletes backups from Nov 2024 and earlier
28+
--dry-run Preview the delete operation without applying changes
29+
-f, --force Skip confirmation prompts
30+
-q, --quiet Suppress output (sets HUG_QUIET=T)
31+
-h, --help Show this help
3232
3333
DESCRIPTION:
3434
Manages deletion of backup branches created by commands like 'hug rb'.
@@ -45,12 +45,12 @@ DESCRIPTION:
4545
apply --keep filter on the remaining backups.
4646
4747
EXAMPLES:
48-
hug bdel-backup # Interactive: select backups to delete
48+
hug bdel-backup # Interactive: select backups to delete
4949
hug bdel-backup 2024-11/02-1234.feature # Delete specific backup
50-
hug bdel-backup --keep 5 # Keep 5 most recent, delete rest
50+
hug bdel-backup -k 5 # Keep 5 most recent, delete rest
5151
hug bdel-backup --delete-older-than 2024-11 # Delete backups from Nov 2024 and earlier
5252
hug bdel-backup --delete-older-than 2024-11/03 # Delete backups from Nov 3, 2024 and earlier
53-
hug bdel-backup --keep 3 --delete-older-than 2024 # Delete 2024 and earlier, then keep 3 most recent
53+
hug bdel-backup -k 3 -o 2024 # Delete 2024 and earlier, then keep 3 most recent
5454
5555
SEE ALSO:
5656
hug bdel Delete regular branches
@@ -59,45 +59,76 @@ SEE ALSO:
5959
EOF
6060
}
6161

62-
# Parse custom flags
62+
# Parse all flags using getopt
6363
keep_count=""
6464
delete_older_than=""
6565
backup_branches_to_delete=()
6666
formatted_backups_to_delete=() # Parallel array for display purposes
6767

68-
# Parse common flags first
69-
eval "$(parse_common_flags "$@")"
68+
# Use getopt for parsing all options (common + custom)
69+
set +e # Temporarily disable exit on error to capture getopt failure
70+
PARSED=$(getopt --options hfqk:o: --longoptions help,force,quiet,dry-run,keep:,delete-older-than: --name "hug bdel-backup" -- "$@" 2>&1)
71+
getopt_status=$?
72+
set -e # Re-enable exit on error
7073

71-
# Now parse remaining custom flags
72-
while [[ $# -gt 0 ]]; do
74+
if [ $getopt_status -ne 0 ]; then
75+
# getopt failed - print the error message if available
76+
if [ -n "$PARSED" ]; then
77+
echo "$PARSED" >&2
78+
fi
79+
exit 1
80+
fi
81+
82+
eval set -- "$PARSED"
83+
84+
# Initialize common flag variables
85+
dry_run=false
86+
force=false
87+
88+
# Process all options
89+
while true; do
7390
case "$1" in
74-
--keep)
75-
if [[ -z "${2:-}" ]]; then
76-
error "--keep requires a number argument"
77-
fi
91+
-h|--help)
92+
show_help
93+
exit 0
94+
;;
95+
-f|--force)
96+
force=true
97+
export HUG_FORCE=true
98+
shift
99+
;;
100+
-q|--quiet)
101+
export HUG_QUIET=T
102+
shift
103+
;;
104+
--dry-run)
105+
dry_run=true
106+
shift
107+
;;
108+
-k|--keep)
78109
if ! [[ "$2" =~ ^[0-9]+$ ]]; then
79-
error "--keep requires a positive integer, got: $2"
110+
error "Option -k/--keep requires a positive integer argument, got: $2"
80111
fi
81112
keep_count="$2"
82113
shift 2
83114
;;
84-
--delete-older-than)
85-
if [[ -z "${2:-}" ]]; then
86-
error "--delete-older-than requires a pattern argument"
87-
fi
115+
-o|--delete-older-than)
88116
delete_older_than="$2"
89117
shift 2
90118
;;
91-
-*)
92-
error "Unknown option: $1. See 'hug bdel-backup --help'."
119+
--)
120+
shift
121+
break
93122
;;
94123
*)
95-
backup_branches_to_delete+=("$1")
96-
shift
124+
error "Internal error in option parsing"
97125
;;
98126
esac
99127
done
100128

129+
# Collect remaining arguments (backup branch names)
130+
backup_branches_to_delete=("$@")
131+
101132
check_git_repo
102133

103134
# Validate delete_older_than pattern if provided
@@ -302,9 +333,7 @@ hug_bdel_backup() {
302333

303334
# Validate all branches exist
304335
for branch in "${backup_branches_to_delete[@]}"; do
305-
if ! git rev-parse --verify "$branch" >/dev/null 2>&1; then
306-
error "Backup branch '$branch' does not exist."
307-
fi
336+
validate_commitish "bdel-backup argument" "$branch"
308337
done
309338

310339
# Jump to deletion logic (skip interactive mode)

0 commit comments

Comments
 (0)