@san-siva/gitsy 1.0.4 → 1.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -109,6 +109,7 @@ g-wa -t new-feature
109
109
  - Moves your repository into a `main` subdirectory
110
110
  - Creates a `worktrees` directory for branch isolation
111
111
  - Provides clear step-by-step feedback throughout the process
112
+ - Requires confirmation before making any changes
112
113
 
113
114
  **Structure after setup:**
114
115
  ```
@@ -121,7 +122,9 @@ your-repo/
121
122
  ```
122
123
 
123
124
  **Key features:**
124
- - Only creates worktrees from the default branch (main/master)
125
+ - Creates new branches from your current branch (preserves branch context)
126
+ - If you're on `develop` and create a new branch, it will be cut from `develop`
127
+ - During restructuring, automatically creates worktrees for both the original branch and target branch
125
128
  - Automatically sanitizes branch names for directory creation
126
129
  - Converts paths to absolute paths for clarity
127
130
  - Checks for existing worktrees to prevent duplicates
package/bin/g-wa CHANGED
@@ -78,7 +78,7 @@ check_branch_in_worktree() {
78
78
  local branch=$1
79
79
  local step_number=$2
80
80
 
81
- print_message "${BLUE}Checking if branch exists in worktrees...${NC}" $step_number
81
+ print_message "${BLUE}Checking if ${NC}${branch}${BLUE} branch exists...${NC}" $step_number
82
82
 
83
83
  # Check if branch is already checked out in another worktree
84
84
  local existing_worktree=$(git worktree list | grep "\[${branch}\]" | awk '{print $1}')
@@ -92,7 +92,6 @@ check_branch_in_worktree() {
92
92
 
93
93
  generate_worktree_path() {
94
94
  local target_branch=$1
95
- local step_number=$2
96
95
 
97
96
  # Determine worktree directory based on current location
98
97
  local worktree_dir
@@ -142,7 +141,7 @@ checkout_or_create_branch() {
142
141
  # Check if branch exists locally
143
142
  if git show-ref --verify --quiet "refs/heads/${target_branch}"; then
144
143
  try_fetching_branch
145
- print_message "${BLUE}Creating worktree for branch ${NC}${target_branch}${BLUE} at ${NC}${path}${NC}" $((step_number + 1))
144
+ print_message "${BLUE}Creating ${NC}${target_branch}${BLUE} worktree...${NC}" $((step_number + 1))
146
145
  create_worktree "${target_branch}" "${path}"
147
146
  return
148
147
  fi
@@ -153,7 +152,7 @@ checkout_or_create_branch() {
153
152
  if git ls-remote --heads origin "${target_branch}" | grep -q "${target_branch}"; then
154
153
  print_message "${GREEN}Branch available on remote.${NC}"
155
154
  try_fetching_branch
156
- print_message "${BLUE}Creating worktree for branch ${NC}${target_branch}${BLUE} at ${NC}${path}${NC}" $((step_number + 2))
155
+ print_message "${BLUE}Creating ${NC}${target_branch}${BLUE} worktree...${NC}" $((step_number + 2))
157
156
  create_worktree "${target_branch}" "${path}"
158
157
  return
159
158
  fi
@@ -162,7 +161,7 @@ checkout_or_create_branch() {
162
161
 
163
162
  create_new_branch=$(prompt_user true "Create new branch?" $((step_number + 2)))
164
163
  if [ "${create_new_branch}" = "y" ]; then
165
- print_message "${BLUE}Creating worktree for branch ${NC}${target_branch}${BLUE} at ${NC}${path}${NC}" $((step_number + 3))
164
+ print_message "${BLUE}Creating ${NC}${target_branch}${BLUE} worktree...${NC}" $((step_number + 3))
166
165
  create_worktree "${target_branch}" "${path}" true
167
166
  return
168
167
  fi
@@ -177,6 +176,7 @@ prompt_restructure_confirmation() {
177
176
  local repo_name=$2
178
177
  local default_branch=$3
179
178
  local step_number=$4
179
+ local target_branch=$5
180
180
 
181
181
  # Save the current branch before restructuring
182
182
  local original_branch=$(get_current_branch)
@@ -197,13 +197,24 @@ prompt_restructure_confirmation() {
197
197
 
198
198
  # If not on default branch, mention worktree will be created
199
199
  if [ "$original_branch" != "$default_branch" ]; then
200
- local sanitized_name=$(sanitize_branch_name "$original_branch")
200
+ local sanitized_original=$(sanitize_branch_name "$original_branch")
201
+ local sanitized_target=$(sanitize_branch_name "$target_branch")
201
202
  print_message "" 0 >&2
202
203
  print_message "Note: You're currently on ${BLUE}${original_branch}${NC} (not ${BLUE}${default_branch}${NC})" 0 >&2
203
- print_message "Two directories will be created:" 0 >&2
204
- print_message "" 0 >&2
205
- print_message "${BLUE}${repo_name}/main${NC} ${BLUE}${default_branch}${NC} branch" 0 >&2
206
- print_message " ${BLUE}${repo_name}/worktrees/${sanitized_name}${NC} ${BLUE}${original_branch}${NC} branch" 0 >&2
204
+
205
+ # Check if target branch is the same as original branch
206
+ if [ "$target_branch" = "$original_branch" ]; then
207
+ print_message "Two directories will be created:" 0 >&2
208
+ print_message "" 0 >&2
209
+ print_message "• ${BLUE}${repo_name}/main${NC} → ${BLUE}${default_branch}${NC} branch" 0 >&2
210
+ print_message "• ${BLUE}${repo_name}/worktrees/${sanitized_original}${NC} → ${BLUE}${original_branch}${NC} branch" 0 >&2
211
+ else
212
+ print_message "Three directories will be created:" 0 >&2
213
+ print_message "" 0 >&2
214
+ print_message "• ${BLUE}${repo_name}/main${NC} → ${BLUE}${default_branch}${NC} branch" 0 >&2
215
+ print_message "• ${BLUE}${repo_name}/worktrees/${sanitized_original}${NC} → ${BLUE}${original_branch}${NC} branch" 0 >&2
216
+ print_message "• ${BLUE}${repo_name}/worktrees/${sanitized_target}${NC} → ${BLUE}${target_branch}${NC} branch (cut from ${BLUE}${original_branch}${NC})" 0 >&2
217
+ fi
207
218
  fi
208
219
 
209
220
  # Prompt user for confirmation
@@ -266,7 +277,7 @@ checkout_main_in_main_branch() {
266
277
  local step_number=$4
267
278
 
268
279
  # Checkout the default branch into main
269
- print_message "${BLUE}Checking out branch ${NC}${default_branch}${BLUE} into main directory...${NC}" $step_number
280
+ print_message "${BLUE}Creating main worktree...${NC}" $step_number
270
281
  if ! git -c color.ui=always checkout "$default_branch" 2>&1 | indent; then
271
282
  print_message "" -1
272
283
  print_message "${RED}Failed to checkout ${NC}${default_branch}${RED} branch. [Fail]${NC}" -1
@@ -276,16 +287,48 @@ checkout_main_in_main_branch() {
276
287
  print_message "${GREEN}Repository restructured successfully to ${NC}${repo_name}/main/${GREEN}. [DONE]${NC}"
277
288
  }
278
289
 
279
- should_trigger_from_default_branch() {
280
- local default_branch=$1
281
- local original_branch=$2
290
+ checkout_current_branch() {
291
+ local step_number=$1
292
+ local default_branch=$2
293
+ local original_branch=$3
282
294
 
283
- if [ "$original_branch" != "$default_branch" ]; then
295
+ if [ -z "$step_number" ]; then
296
+ step_number=0
297
+ fi
298
+
299
+ if [ -z "$default_branch" ]; then
300
+ print_message "" -1
301
+ print_message "${RED}Default branch is not set. [Fail]${NC}" -1
302
+ exit 1
303
+ fi
304
+
305
+ if [ "$default_branch" = "$original_branch" ]; then
306
+ return 0
307
+ fi
308
+
309
+ local path=$(generate_worktree_path "$original_branch" $step_number)
310
+ print_message "${BLUE}Creating ${NC}${original_branch}${BLUE} worktree...${NC}" $step_number
311
+ create_worktree "$original_branch" "$path"
312
+
313
+ # Navigate to the created worktree
314
+ if ! navigate_to_dir "$path"; then
315
+ print_message "" -1
316
+ print_message "${RED}Failed to navigate to ${original_branch} worktree. [Fail]${NC}" -1
317
+ exit 1
318
+ fi
319
+ }
320
+
321
+ already_restructured() {
322
+ local current_dir=$(pwd)
323
+ if ! navigate_to_main_dir "false"; then
324
+ return 1
325
+ fi
326
+ if ! navigate_to_dir "$current_dir"; then
284
327
  print_message "" -1
285
- print_message "${RED}Warning: We only support creating worktrees from the default branch.${NC}" -1
286
- print_message "${RED}Commit or stash changes, checkout to ${NC}${default_branch}${RED}, and try again.${NC}" -1
328
+ print_message "${RED}Failed to navigate back to original directory. [Fail]${NC}" -1
287
329
  exit 1
288
330
  fi
331
+ return 0
289
332
  }
290
333
 
291
334
  create_main_dir_if_necessary() {
@@ -301,17 +344,15 @@ create_main_dir_if_necessary() {
301
344
  local parent_dir=$(basename "$(dirname "$git_root")")
302
345
  local repo_name=$(get_repo_name)
303
346
 
304
- # Check if already in correct structure (repo_name/main/.git)
305
- if [ "$current_dir" = "main" ] && [ "$parent_dir" = "$repo_name" ]; then
347
+ if already_restructured; then
306
348
  return 0
307
349
  fi
308
350
 
351
+ # Save original branch before restructuring
352
+ local original_branch=$(get_current_branch)
353
+
309
354
  # Prompt user for restructuring
310
- prompt_restructure_confirmation "$git_root" "$repo_name" "$default_branch" "$step_number"
311
- local prompt_exit_code=$?
312
- if [ $prompt_exit_code -ne 0 ]; then
313
- exit $prompt_exit_code
314
- fi
355
+ prompt_restructure_confirmation "$git_root" "$repo_name" "$default_branch" "$step_number" "$target_branch"
315
356
 
316
357
  # Get parent directory path
317
358
  local parent_path=$(dirname "$git_root")
@@ -329,18 +370,11 @@ create_main_dir_if_necessary() {
329
370
 
330
371
  # Checkout the default branch into main directory
331
372
  checkout_main_in_main_branch "$repo_name" "$main_dir" "$default_branch" $((step_number + 2))
332
- }
333
373
 
334
- create_target_dir_if_necessary() {
335
- # Generate worktree path
336
- local path=$(generate_worktree_path "${target_branch}" $step_number)
374
+ # Create worktree for original branch and navigate to it (if different from default)
375
+ checkout_current_branch $((step_number + 3)) "$default_branch" "$original_branch"
337
376
 
338
- # Check if branch exists locally
339
- if git show-ref --verify --quiet "refs/heads/${target_branch}"; then
340
- try_fetching_branch
341
- create_worktree "${target_branch}" "${path}"
342
- return
343
- fi
377
+ return 1
344
378
  }
345
379
 
346
380
  main() {
@@ -369,8 +403,6 @@ main() {
369
403
  local default_branch=$(get_default_branch)
370
404
  local current_branch=$(get_current_branch)
371
405
 
372
- should_trigger_from_default_branch "$default_branch" "$current_branch"
373
-
374
406
  local step_number=2
375
407
  if [ "$stash" = true ]; then
376
408
  step_number=3
@@ -381,22 +413,29 @@ main() {
381
413
  local current_dir=$(basename "$git_root")
382
414
  local parent_dir=$(basename "$(dirname "$git_root")")
383
415
  local repo_name=$(get_repo_name)
384
- local needs_restructure=false
416
+ create_main_dir_if_necessary "$default_branch" $step_number
417
+ local needs_restructure=$?
385
418
 
386
- if [ "$current_dir" != "main" ] || [ "$parent_dir" != "$repo_name" ]; then
387
- needs_restructure=true
388
- fi
419
+ if [ $needs_restructure -eq 1 ]; then
420
+ checkout_or_create_branch $((step_number + 4))
421
+ else
422
+ # Notify user that worktree will be created
423
+ local sanitized_target=$(sanitize_branch_name "$target_branch")
424
+ print_message "" -1
425
+ print_message "${BLUE}Will create ${NC}${target_branch}${BLUE} worktree (cut from ${NC}${current_branch}${BLUE})${NC}" -1
426
+ print_message "Location: ${BLUE}${repo_name}/worktrees/${sanitized_target}${NC}" -1
427
+ print_message "" -1
389
428
 
390
- create_main_dir_if_necessary "$default_branch" $step_number
429
+ # Prompt user for confirmation
430
+ local proceed=$(prompt_user false "Proceed with creating worktree?" "$step_number")
431
+ if [ "$proceed" != "y" ]; then
432
+ print_message "" -1
433
+ print_message "${RED}Worktree creation cancelled by user.${NC}" -1
434
+ exit 1
435
+ fi
391
436
 
392
- # Calculate next step number
393
- local next_step=$((step_number + 1))
394
- if [ "$needs_restructure" = true ]; then
395
- # Restructuring uses 3 steps: prompt, move, checkout
396
- next_step=$((step_number + 3))
437
+ checkout_or_create_branch $((step_number + 1))
397
438
  fi
398
-
399
- checkout_or_create_branch $next_step
400
439
  }
401
440
 
402
441
  main "$@"
package/bin/g-wr CHANGED
@@ -87,27 +87,34 @@ set_flags() {
87
87
  }
88
88
 
89
89
  cd_to_worktrees_dir() {
90
- local current_dir=$(pwd)
91
- local current_dirname=$(basename "$current_dir")
92
- if [ "$current_dirname" = "worktrees" ]; then
90
+ # Get git root and navigate to repo root's worktrees directory
91
+ local git_root=$(git rev-parse --show-toplevel)
92
+ local git_root_parent=$(dirname "$git_root")
93
+ local git_root_parent_name=$(basename "$git_root_parent")
94
+
95
+ # If we're in a worktree (parent is "worktrees"), use that directory
96
+ if [ "$git_root_parent_name" = "worktrees" ]; then
97
+ if ! navigate_to_dir "$git_root_parent"; then
98
+ print_message "" -1 >&2
99
+ print_message "${RED}Failed to navigate to worktrees directory. [Fail]${NC}" -1 >&2
100
+ exit 1
101
+ fi
93
102
  return 0
94
103
  fi
95
104
 
96
- if [ -d "../worktrees" ]; then
97
- if navigate_to_dir "../worktrees"; then
98
- return 0
99
- fi
105
+ # Otherwise, we're in main, so look for ../worktrees
106
+ local worktrees_dir="$git_root_parent/worktrees"
107
+ if [ ! -d "$worktrees_dir" ]; then
108
+ print_message "" -1 >&2
109
+ print_message "${RED}Worktrees directory not found at ${NC}${worktrees_dir}${RED}. [Fail]${NC}" -1 >&2
110
+ exit 1
100
111
  fi
101
112
 
102
- if [ -d "../../worktrees" ]; then
103
- if navigate_to_dir "../../worktrees"; then
104
- return 0
105
- fi
113
+ if ! navigate_to_dir "$worktrees_dir"; then
114
+ print_message "" -1 >&2
115
+ print_message "${RED}Failed to navigate to worktrees directory. [Fail]${NC}" -1 >&2
116
+ exit 1
106
117
  fi
107
-
108
- print_message "" -1 >&2
109
- print_message "${RED}Worktrees directory not found. [Fail]${NC}" -1 >&2
110
- exit 1
111
118
  }
112
119
 
113
120
  find_worktree_by_name() {
@@ -122,13 +129,11 @@ find_worktree_by_name() {
122
129
  fi
123
130
 
124
131
  if [ "$dir" = "$worktree_name" ]; then
125
- navigate_to_main_dir
126
132
  echo "$worktrees_dir/$dir"
127
133
  return 0
128
134
  fi
129
135
  done
130
136
 
131
- navigate_to_main_dir
132
137
  return 1
133
138
  }
134
139
 
@@ -145,26 +150,22 @@ find_worktree_by_branch() {
145
150
  continue
146
151
  fi
147
152
 
148
- if ! navigate_to_dir "$dir"; then
153
+ local worktree_path="$worktrees_dir/$dir"
154
+ if ! navigate_to_dir "$worktree_path"; then
149
155
  continue
150
156
  fi
151
157
 
152
158
  local branch=$(get_current_branch 2>/dev/null)
153
159
  if [ -z "$branch" ]; then
154
- navigate_to_dir "$worktrees_dir"
155
160
  continue
156
161
  fi
157
162
 
158
163
  if [ "$branch" = "$target_branch" ]; then
159
- navigate_to_main_dir
160
- echo "$worktrees_dir/$dir"
164
+ echo "$worktree_path"
161
165
  return 0
162
166
  fi
163
-
164
- navigate_to_dir "$worktrees_dir"
165
167
  done
166
168
 
167
- navigate_to_main_dir
168
169
  return 1
169
170
  }
170
171
 
@@ -182,12 +183,18 @@ check_if_worktree_is_clean() {
182
183
  local worktree_path=$1
183
184
  local step_number=$2
184
185
 
186
+ print_message "${BLUE}Checking for uncommitted changes...${NC}" $step_number
187
+
185
188
  if has_uncommitted_changes "$worktree_path"; then
186
- response=$(prompt_user "false" "Your worktree has uncommitted changes. Do you want to discard them?" $step_number)
189
+ print_message "${PROMPT}Worktree has uncommitted changes.${NC}" 0
190
+ response=$(prompt_user "false" "Do you want to discard them and remove the worktree?" $step_number)
187
191
  if [ "$response" = "n" ]; then
188
- print_message "${RED}Skipping worktree removal.${NC}" 0
192
+ print_message "" -1
193
+ print_message "${RED}Worktree removal cancelled. Your changes are safe.${NC}" -1
189
194
  exit 0
190
195
  fi
196
+ else
197
+ print_message "${GREEN}No uncommitted changes found.${NC}" 0
191
198
  fi
192
199
  }
193
200
 
@@ -197,27 +204,23 @@ remove_worktree() {
197
204
 
198
205
  print_message "${BLUE}Removing worktree at ${NC}${worktree_path}${BLUE}...${NC}" $step_number
199
206
 
200
- if [ -z "$worktree_name" ]; then
201
- # Try using git worktree remove first with --force flag
202
- if git -c color.ui=always worktree remove --force "$worktree_path" 2>&1 | indent; then
203
- # Verify the directory was actually removed
204
- if [ ! -d "$worktree_path" ]; then
205
- print_message "${GREEN}Worktree removed successfully using git.${NC}" 0
206
- return 0
207
- fi
207
+ # Always try using git worktree remove first with --force flag
208
+ if git -c color.ui=always worktree remove --force "$worktree_path" 2>&1 | indent; then
209
+ # Verify the directory was actually removed
210
+ if [ ! -d "$worktree_path" ]; then
211
+ print_message "${GREEN}Worktree removed successfully.${NC}" 0
212
+ return 0
208
213
  fi
209
- print_message "${PROMPT}Git worktree remove incomplete. Attempting manual removal...${NC}" 0
210
214
  fi
211
215
 
212
- # Fallback to rm -rf
216
+ # Fallback to rm -rf if git worktree remove failed
217
+ print_message "${PROMPT}Git worktree remove incomplete. Attempting manual removal...${NC}" 0
213
218
  if rm -rf "$worktree_path" 2>&1 | indent; then
214
- if [ -z "$worktree_name" ]; then
215
- # Also need to prune the worktree from git's records
216
- git -c color.ui=always worktree prune 2>&1 | indent
217
- fi
219
+ # Also need to prune the worktree from git's records
220
+ git -c color.ui=always worktree prune 2>&1 | indent
218
221
  # Verify the directory was actually removed
219
222
  if [ ! -d "$worktree_path" ]; then
220
- print_message "${GREEN}Worktree removed successfully using rm -rf.${NC}" 0
223
+ print_message "${GREEN}Worktree removed successfully.${NC}" 0
221
224
  return 0
222
225
  fi
223
226
  fi
@@ -262,7 +265,13 @@ main() {
262
265
  print_message "${GREEN}Found worktree: ${NC}${worktree_dirname}${GREEN} at ${NC}${worktree_path}${NC}" $((step_number + 1))
263
266
  fi
264
267
 
265
- print_message "${BLUE}Checking for uncommitted changes...${NC}" $((step_number + 2))
268
+ # Prevent removal of main directory
269
+ if [ "$worktree_dirname" = "main" ]; then
270
+ print_message "" -1
271
+ print_message "${RED}Cannot remove main directory. This is your default branch worktree. [Fail]${NC}" -1
272
+ exit 1
273
+ fi
274
+
266
275
  check_if_worktree_is_clean "$worktree_path" $((step_number + 2))
267
276
 
268
277
  remove_worktree "$worktree_path" $((step_number + 3))
package/bin/utils CHANGED
@@ -468,6 +468,7 @@ navigate_to_main_dir() {
468
468
  local current_dir=$(pwd)
469
469
  local current_dirname=$(basename "$current_dir")
470
470
  local parent_dirname=$(basename "$(dirname "$current_dir")")
471
+ local should_exit_on_failure=$1
471
472
 
472
473
  # Already in main directory (but not nested main/main)
473
474
  if [ "$current_dirname" = "main" ] && [ "$parent_dirname" != "main" ]; then
@@ -488,9 +489,13 @@ navigate_to_main_dir() {
488
489
  fi
489
490
  fi
490
491
 
491
- print_message "" -1
492
- print_message "${RED}Failed to find main directory. [Fail]${NC}" -1
493
- exit 1
492
+ if [ "$should_exit_on_failure" = "true" ]; then
493
+ print_message "" -1
494
+ print_message "${RED}Failed to find main directory. [Fail]${NC}" -1
495
+ exit 1
496
+ fi
497
+
498
+ return 1
494
499
  }
495
500
 
496
501
  check_uncommitted_changes() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@san-siva/gitsy",
3
- "version": "1.0.4",
3
+ "version": "1.0.6",
4
4
  "description": "A set of bash utilities for managing Git repositories with ease",
5
5
  "keywords": [
6
6
  "git",