@@ -3,19 +3,28 @@ use crate::config::{DATA_DIR, IdMode};
33use anyhow:: { Context , Result , bail} ;
44use colored:: Colorize ;
55
6- pub fn handle_mv ( ctx : & CommandContext , id : String , new_suffix : String , force : bool ) -> Result < ( ) > {
6+ pub fn handle_mv (
7+ ctx : & CommandContext ,
8+ old_suffix : String ,
9+ new_suffix : String ,
10+ force : bool ,
11+ ) -> Result < ( ) > {
712 let prefix = & ctx. config . peas . prefix ;
813 let id_length = ctx. config . peas . id_length ;
914 let id_mode = ctx. config . peas . id_mode ;
1015
16+ // Build full IDs from suffixes (strip prefix if user included it)
17+ let old_suffix = old_suffix. strip_prefix ( prefix) . unwrap_or ( & old_suffix) ;
18+ let new_suffix = new_suffix. strip_prefix ( prefix) . unwrap_or ( & new_suffix) ;
19+
20+ let old_id = format ! ( "{}{}" , prefix, old_suffix) ;
21+ let new_id = format ! ( "{}{}" , prefix, new_suffix) ;
22+
1123 // Validate source ticket exists
1224 let pea = ctx
1325 . repo
14- . get ( & id)
15- . with_context ( || format ! ( "Ticket not found: {}" , id) ) ?;
16-
17- // Build the new ID
18- let new_id = format ! ( "{}{}" , prefix, new_suffix) ;
26+ . get ( & old_id)
27+ . with_context ( || format ! ( "Ticket not found: {}" , old_id) ) ?;
1928
2029 // Check if new ID already exists
2130 if ctx. repo . get ( & new_id) . is_ok ( ) {
@@ -34,9 +43,11 @@ pub fn handle_mv(ctx: &CommandContext, id: String, new_suffix: String, force: bo
3443 // Validate ID mode
3544 let is_all_digits = new_suffix. chars ( ) . all ( |c| c. is_ascii_digit ( ) ) ;
3645 match id_mode {
37- IdMode :: Random if is_all_digits && !force => {
38- bail ! (
39- "Suffix '{}' is all digits but id_mode is 'random'. Use --force to override." ,
46+ IdMode :: Random if is_all_digits => {
47+ // Warn but don't block in random mode
48+ eprintln ! (
49+ "{}: Suffix '{}' is all digits (unusual for random mode)" ,
50+ "warning" . yellow( ) . bold( ) ,
4051 new_suffix
4152 ) ;
4253 }
@@ -49,7 +60,7 @@ pub fn handle_mv(ctx: &CommandContext, id: String, new_suffix: String, force: bo
4960 _ => { }
5061 }
5162
52- // Show warnings if force was used
63+ // Show warnings for force overrides
5364 if force {
5465 if new_suffix. len ( ) != id_length {
5566 eprintln ! (
@@ -59,26 +70,16 @@ pub fn handle_mv(ctx: &CommandContext, id: String, new_suffix: String, force: bo
5970 id_length
6071 ) ;
6172 }
62- match id_mode {
63- IdMode :: Random if is_all_digits => {
64- eprintln ! (
65- "{}: Suffix '{}' is all digits but id_mode is 'random'" ,
66- "warning" . yellow( ) . bold( ) ,
67- new_suffix
68- ) ;
69- }
70- IdMode :: Sequential if !is_all_digits => {
71- eprintln ! (
72- "{}: Suffix '{}' contains non-digits but id_mode is 'sequential'" ,
73- "warning" . yellow( ) . bold( ) ,
74- new_suffix
75- ) ;
76- }
77- _ => { }
73+ if id_mode == IdMode :: Sequential && !is_all_digits {
74+ eprintln ! (
75+ "{}: Suffix '{}' contains non-digits but id_mode is 'sequential'" ,
76+ "warning" . yellow( ) . bold( ) ,
77+ new_suffix
78+ ) ;
7879 }
7980 }
8081
81- println ! ( "Renaming {} → {}" , id , new_id) ;
82+ println ! ( "Renaming {} → {}" , old_id , new_id) ;
8283
8384 // Find all tickets that reference this ID
8485 let all_peas = ctx. repo . list ( ) ?;
@@ -89,26 +90,32 @@ pub fn handle_mv(ctx: &CommandContext, id: String, new_suffix: String, force: bo
8990
9091 // Update references in other tickets
9192 for other_pea in & all_peas {
92- if other_pea. id == id {
93+ if other_pea. id == old_id {
9394 continue ; // Skip the ticket we're renaming
9495 }
9596
9697 let mut needs_update = false ;
9798 let mut updated_pea = other_pea. clone ( ) ;
9899
99100 // Check parent reference
100- if updated_pea. parent . as_ref ( ) == Some ( & id ) {
101+ if updated_pea. parent . as_ref ( ) == Some ( & old_id ) {
101102 updated_pea. parent = Some ( new_id. clone ( ) ) ;
102103 needs_update = true ;
103104 updated_parents += 1 ;
104105 }
105106
106107 // Check blocking references
107- if updated_pea. blocking . contains ( & id ) {
108+ if updated_pea. blocking . contains ( & old_id ) {
108109 updated_pea. blocking = updated_pea
109110 . blocking
110111 . iter ( )
111- . map ( |b| if b == & id { new_id. clone ( ) } else { b. clone ( ) } )
112+ . map ( |b| {
113+ if b == & old_id {
114+ new_id. clone ( )
115+ } else {
116+ b. clone ( )
117+ }
118+ } )
112119 . collect ( ) ;
113120 needs_update = true ;
114121 updated_blocking += 1 ;
@@ -126,7 +133,7 @@ pub fn handle_mv(ctx: &CommandContext, id: String, new_suffix: String, force: bo
126133 // Get old and new file paths
127134 let old_filename = format ! (
128135 "{}--{}.md" ,
129- id ,
136+ old_id ,
130137 slug:: slugify( & pea. title)
131138 . chars( )
132139 . take( 50 )
@@ -160,16 +167,16 @@ pub fn handle_mv(ctx: &CommandContext, id: String, new_suffix: String, force: bo
160167 let undo_path = data_dir. join ( ".undo" ) ;
161168 if undo_path. exists ( ) {
162169 let undo_content = std:: fs:: read_to_string ( & undo_path) ?;
163- if undo_content. contains ( & id ) {
164- let updated_undo = undo_content. replace ( & id , & new_id) ;
170+ if undo_content. contains ( & old_id ) {
171+ let updated_undo = undo_content. replace ( & old_id , & new_id) ;
165172 // Also update file paths in undo
166173 let updated_undo = updated_undo. replace ( & old_filename, & new_filename) ;
167174 std:: fs:: write ( & undo_path, updated_undo) ?;
168175 println ! ( " Updated .undo file" ) ;
169176 }
170177 }
171178
172- println ! ( "{} Renamed {} → {}" , "✓" . green( ) , id , new_id) ;
179+ println ! ( "{} Renamed {} → {}" , "✓" . green( ) , old_id , new_id) ;
173180 if updated_parents > 0 {
174181 println ! ( " Updated {} parent reference(s)" , updated_parents) ;
175182 }
0 commit comments