|
5 | 5 | JSON_MODE=false |
6 | 6 | SHORT_NAME="" |
7 | 7 | BRANCH_NUMBER="" |
| 8 | +USE_TIMESTAMP=false |
8 | 9 | ARGS=() |
9 | 10 | i=1 |
10 | 11 | while [ $i -le $# ]; do |
11 | 12 | arg="${!i}" |
12 | 13 | case "$arg" in |
13 | | - --json) |
14 | | - JSON_MODE=true |
| 14 | + --json) |
| 15 | + JSON_MODE=true |
15 | 16 | ;; |
16 | 17 | --short-name) |
17 | 18 | if [ $((i + 1)) -gt $# ]; then |
@@ -40,22 +41,27 @@ while [ $i -le $# ]; do |
40 | 41 | fi |
41 | 42 | BRANCH_NUMBER="$next_arg" |
42 | 43 | ;; |
43 | | - --help|-h) |
44 | | - echo "Usage: $0 [--json] [--short-name <name>] [--number N] <feature_description>" |
| 44 | + --timestamp) |
| 45 | + USE_TIMESTAMP=true |
| 46 | + ;; |
| 47 | + --help|-h) |
| 48 | + echo "Usage: $0 [--json] [--short-name <name>] [--number N] [--timestamp] <feature_description>" |
45 | 49 | echo "" |
46 | 50 | echo "Options:" |
47 | 51 | echo " --json Output in JSON format" |
48 | 52 | echo " --short-name <name> Provide a custom short name (2-4 words) for the branch" |
49 | 53 | echo " --number N Specify branch number manually (overrides auto-detection)" |
| 54 | + echo " --timestamp Use timestamp prefix (YYYYMMDD-HHMMSS) instead of sequential numbering" |
50 | 55 | echo " --help, -h Show this help message" |
51 | 56 | echo "" |
52 | 57 | echo "Examples:" |
53 | 58 | echo " $0 'Add user authentication system' --short-name 'user-auth'" |
54 | 59 | echo " $0 'Implement OAuth2 integration for API' --number 5" |
| 60 | + echo " $0 --timestamp --short-name 'user-auth' 'Add user authentication'" |
55 | 61 | exit 0 |
56 | 62 | ;; |
57 | | - *) |
58 | | - ARGS+=("$arg") |
| 63 | + *) |
| 64 | + ARGS+=("$arg") |
59 | 65 | ;; |
60 | 66 | esac |
61 | 67 | i=$((i + 1)) |
@@ -96,10 +102,13 @@ get_highest_from_specs() { |
96 | 102 | for dir in "$specs_dir"/*; do |
97 | 103 | [ -d "$dir" ] || continue |
98 | 104 | dirname=$(basename "$dir") |
99 | | - number=$(echo "$dirname" | grep -o '^[0-9]\+' || echo "0") |
100 | | - number=$((10#$number)) |
101 | | - if [ "$number" -gt "$highest" ]; then |
102 | | - highest=$number |
| 105 | + # Only match sequential prefixes (###-*), skip timestamp dirs |
| 106 | + if echo "$dirname" | grep -q '^[0-9]\{3\}-'; then |
| 107 | + number=$(echo "$dirname" | grep -o '^[0-9]\{3\}') |
| 108 | + number=$((10#$number)) |
| 109 | + if [ "$number" -gt "$highest" ]; then |
| 110 | + highest=$number |
| 111 | + fi |
103 | 112 | fi |
104 | 113 | done |
105 | 114 | fi |
@@ -242,29 +251,42 @@ else |
242 | 251 | BRANCH_SUFFIX=$(generate_branch_name "$FEATURE_DESCRIPTION") |
243 | 252 | fi |
244 | 253 |
|
245 | | -# Determine branch number |
246 | | -if [ -z "$BRANCH_NUMBER" ]; then |
247 | | - if [ "$HAS_GIT" = true ]; then |
248 | | - # Check existing branches on remotes |
249 | | - BRANCH_NUMBER=$(check_existing_branches "$SPECS_DIR") |
250 | | - else |
251 | | - # Fall back to local directory check |
252 | | - HIGHEST=$(get_highest_from_specs "$SPECS_DIR") |
253 | | - BRANCH_NUMBER=$((HIGHEST + 1)) |
254 | | - fi |
| 254 | +# Warn if --number and --timestamp are both specified |
| 255 | +if [ "$USE_TIMESTAMP" = true ] && [ -n "$BRANCH_NUMBER" ]; then |
| 256 | + >&2 echo "[specify] Warning: --number is ignored when --timestamp is used" |
| 257 | + BRANCH_NUMBER="" |
255 | 258 | fi |
256 | 259 |
|
257 | | -# Force base-10 interpretation to prevent octal conversion (e.g., 010 → 8 in octal, but should be 10 in decimal) |
258 | | -FEATURE_NUM=$(printf "%03d" "$((10#$BRANCH_NUMBER))") |
259 | | -BRANCH_NAME="${FEATURE_NUM}-${BRANCH_SUFFIX}" |
| 260 | +# Determine branch prefix |
| 261 | +if [ "$USE_TIMESTAMP" = true ]; then |
| 262 | + FEATURE_NUM=$(date +%Y%m%d-%H%M%S) |
| 263 | + BRANCH_NAME="${FEATURE_NUM}-${BRANCH_SUFFIX}" |
| 264 | +else |
| 265 | + # Determine branch number |
| 266 | + if [ -z "$BRANCH_NUMBER" ]; then |
| 267 | + if [ "$HAS_GIT" = true ]; then |
| 268 | + # Check existing branches on remotes |
| 269 | + BRANCH_NUMBER=$(check_existing_branches "$SPECS_DIR") |
| 270 | + else |
| 271 | + # Fall back to local directory check |
| 272 | + HIGHEST=$(get_highest_from_specs "$SPECS_DIR") |
| 273 | + BRANCH_NUMBER=$((HIGHEST + 1)) |
| 274 | + fi |
| 275 | + fi |
| 276 | + |
| 277 | + # Force base-10 interpretation to prevent octal conversion (e.g., 010 → 8 in octal, but should be 10 in decimal) |
| 278 | + FEATURE_NUM=$(printf "%03d" "$((10#$BRANCH_NUMBER))") |
| 279 | + BRANCH_NAME="${FEATURE_NUM}-${BRANCH_SUFFIX}" |
| 280 | +fi |
260 | 281 |
|
261 | 282 | # GitHub enforces a 244-byte limit on branch names |
262 | 283 | # Validate and truncate if necessary |
263 | 284 | MAX_BRANCH_LENGTH=244 |
264 | 285 | if [ ${#BRANCH_NAME} -gt $MAX_BRANCH_LENGTH ]; then |
265 | 286 | # Calculate how much we need to trim from suffix |
266 | | - # Account for: feature number (3) + hyphen (1) = 4 chars |
267 | | - MAX_SUFFIX_LENGTH=$((MAX_BRANCH_LENGTH - 4)) |
| 287 | + # Account for prefix length: timestamp (15) + hyphen (1) = 16, or sequential (3) + hyphen (1) = 4 |
| 288 | + PREFIX_LENGTH=$(( ${#FEATURE_NUM} + 1 )) |
| 289 | + MAX_SUFFIX_LENGTH=$((MAX_BRANCH_LENGTH - PREFIX_LENGTH)) |
268 | 290 |
|
269 | 291 | # Truncate suffix at word boundary if possible |
270 | 292 | TRUNCATED_SUFFIX=$(echo "$BRANCH_SUFFIX" | cut -c1-$MAX_SUFFIX_LENGTH) |
|
0 commit comments