@@ -115,27 +115,23 @@ get_highest_from_specs() {
115115
116116# Function to get highest number from git branches
117117get_highest_from_branches () {
118+ git branch -a 2> /dev/null | sed ' s/^[* ]*//; s|^remotes/[^/]*/||' | _extract_highest_number
119+ }
120+
121+ # Extract the highest sequential feature number from a list of ref names (one per line).
122+ # Shared by get_highest_from_branches and get_highest_from_remote_refs.
123+ _extract_highest_number () {
118124 local highest=0
119-
120- # Get all branches (local and remote)
121- branches=$( git branch -a 2> /dev/null || echo " " )
122-
123- if [ -n " $branches " ]; then
124- while IFS= read -r branch; do
125- # Clean branch name: remove leading markers and remote prefixes
126- clean_branch=$( echo " $branch " | sed ' s/^[* ]*//; s|^remotes/[^/]*/||' )
127-
128- # Extract sequential feature number (>=3 digits), skip timestamp branches.
129- if echo " $clean_branch " | grep -Eq ' ^[0-9]{3,}-' && ! echo " $clean_branch " | grep -Eq ' ^[0-9]{8}-[0-9]{6}-' ; then
130- number=$( echo " $clean_branch " | grep -Eo ' ^[0-9]+' || echo " 0" )
131- number=$(( 10 #$number ))
132- if [ " $number " -gt " $highest " ]; then
133- highest=$number
134- fi
125+ while IFS= read -r name; do
126+ [ -z " $name " ] && continue
127+ if echo " $name " | grep -Eq ' ^[0-9]{3,}-' && ! echo " $name " | grep -Eq ' ^[0-9]{8}-[0-9]{6}-' ; then
128+ number=$( echo " $name " | grep -Eo ' ^[0-9]+' || echo " 0" )
129+ number=$(( 10 #$number ))
130+ if [ " $number " -gt " $highest " ]; then
131+ highest=$number
135132 fi
136- done <<< " $branches"
137- fi
138-
133+ fi
134+ done
139135 echo " $highest "
140136}
141137
@@ -144,32 +140,34 @@ get_highest_from_remote_refs() {
144140 local highest=0
145141
146142 for remote in $( git remote 2> /dev/null) ; do
147- while IFS= read -r line; do
148- [ -z " $line " ] && continue
149- # Extract ref name from ls-remote output (hash\trefs/heads/branch-name)
150- ref=" ${line##*/ } "
151- if echo " $ref " | grep -Eq ' ^[0-9]{3,}-' && ! echo " $ref " | grep -Eq ' ^[0-9]{8}-[0-9]{6}-' ; then
152- number=$( echo " $ref " | grep -Eo ' ^[0-9]+' || echo " 0" )
153- number=$(( 10 #$number ))
154- if [ " $number " -gt " $highest " ]; then
155- highest=$number
156- fi
157- fi
158- done <<< " $(git ls-remote --heads " $remote " 2>/dev/null || echo " " )"
143+ local remote_highest
144+ remote_highest=$( git ls-remote --heads " $remote " 2> /dev/null | sed ' s|.*refs/heads/||' | _extract_highest_number)
145+ if [ " $remote_highest " -gt " $highest " ]; then
146+ highest=$remote_highest
147+ fi
159148 done
160149
161150 echo " $highest "
162151}
163152
164- # Function to check existing branches (local and remote) and return next available number
153+ # Function to check existing branches (local and remote) and return next available number.
154+ # When skip_fetch is true, queries remotes via ls-remote (read-only) instead of fetching.
165155check_existing_branches () {
166156 local specs_dir=" $1 "
167-
168- # Fetch all remotes to get latest branch info (suppress errors if no remotes)
169- git fetch --all --prune > /dev/null 2>&1 || true
170-
171- # Get highest number from ALL branches (not just matching short name)
172- local highest_branch=$( get_highest_from_branches)
157+ local skip_fetch=" ${2:- false} "
158+
159+ if [ " $skip_fetch " = true ]; then
160+ # Side-effect-free: query remotes via ls-remote
161+ local highest_remote=$( get_highest_from_remote_refs)
162+ local highest_branch=$( get_highest_from_branches)
163+ if [ " $highest_remote " -gt " $highest_branch " ]; then
164+ highest_branch=$highest_remote
165+ fi
166+ else
167+ # Fetch all remotes to get latest branch info (suppress errors if no remotes)
168+ git fetch --all --prune > /dev/null 2>&1 || true
169+ local highest_branch=$( get_highest_from_branches)
170+ fi
173171
174172 # Get highest number from ALL specs (not just matching short name)
175173 local highest_spec=$( get_highest_from_specs " $specs_dir " )
@@ -280,22 +278,13 @@ if [ "$USE_TIMESTAMP" = true ]; then
280278else
281279 # Determine branch number
282280 if [ -z " $BRANCH_NUMBER " ]; then
283- if [ " $DRY_RUN " = true ]; then
284- # Dry-run: query remote refs without fetching (side-effect-free)
285- _highest_branch=0
286- if [ " $HAS_GIT " = true ]; then
287- _highest_branch=$( get_highest_from_branches)
288- _highest_remote=$( get_highest_from_remote_refs)
289- if [ " $_highest_remote " -gt " $_highest_branch " ]; then
290- _highest_branch=$_highest_remote
291- fi
292- fi
293- _highest_spec=$( get_highest_from_specs " $SPECS_DIR " )
294- _max_num=$_highest_branch
295- if [ " $_highest_spec " -gt " $_max_num " ]; then
296- _max_num=$_highest_spec
297- fi
298- BRANCH_NUMBER=$(( _max_num + 1 ))
281+ if [ " $DRY_RUN " = true ] && [ " $HAS_GIT " = true ]; then
282+ # Dry-run: query remotes via ls-remote (side-effect-free, no fetch)
283+ BRANCH_NUMBER=$( check_existing_branches " $SPECS_DIR " true)
284+ elif [ " $DRY_RUN " = true ]; then
285+ # Dry-run without git: local spec dirs only
286+ HIGHEST=$( get_highest_from_specs " $SPECS_DIR " )
287+ BRANCH_NUMBER=$(( HIGHEST + 1 ))
299288 elif [ " $HAS_GIT " = true ]; then
300289 # Check existing branches on remotes
301290 BRANCH_NUMBER=$( check_existing_branches " $SPECS_DIR " )
0 commit comments