@@ -221,35 +221,82 @@ fn parse_range(ctx: &mut CommandContext, source: &str) -> anyhow::Result<Vec<Cli
221
221
let start_id = & start_matches[ 0 ] ;
222
222
let end_id = & end_matches[ 0 ] ;
223
223
224
- // Get all files from status to find the range
225
- let all_files = crate :: status :: all_files ( ctx) ?;
224
+ // Get all files in display order (same order as shown in status)
225
+ let all_files_in_order = get_all_files_in_display_order ( ctx) ?;
226
226
227
- // Find the positions of start and end in the file list
228
- let start_pos = all_files . iter ( ) . position ( |id| id == start_id) ;
229
- let end_pos = all_files . iter ( ) . position ( |id| id == end_id) ;
227
+ // Find the positions of start and end in the ordered file list
228
+ let start_pos = all_files_in_order . iter ( ) . position ( |id| id == start_id) ;
229
+ let end_pos = all_files_in_order . iter ( ) . position ( |id| id == end_id) ;
230
230
231
231
if let ( Some ( start_idx) , Some ( end_idx) ) = ( start_pos, end_pos) {
232
232
if start_idx <= end_idx {
233
- return Ok ( all_files [ start_idx..=end_idx] . to_vec ( ) ) ;
233
+ return Ok ( all_files_in_order [ start_idx..=end_idx] . to_vec ( ) ) ;
234
234
} else {
235
- return Ok ( all_files [ end_idx..=start_idx] . to_vec ( ) ) ;
235
+ return Ok ( all_files_in_order [ end_idx..=start_idx] . to_vec ( ) ) ;
236
236
}
237
237
}
238
238
239
- // If not found in files, try committed files
240
- let all_committed_files = crate :: status:: all_committed_files ( ctx) ?;
241
- let start_pos = all_committed_files. iter ( ) . position ( |id| id == start_id) ;
242
- let end_pos = all_committed_files. iter ( ) . position ( |id| id == end_id) ;
239
+ Err ( anyhow:: anyhow!( "Could not find range from '{}' to '{}' in the displayed file list" , start_str, end_str) )
240
+ }
243
241
244
- if let ( Some ( start_idx) , Some ( end_idx) ) = ( start_pos, end_pos) {
245
- if start_idx <= end_idx {
246
- return Ok ( all_committed_files[ start_idx..=end_idx] . to_vec ( ) ) ;
247
- } else {
248
- return Ok ( all_committed_files[ end_idx..=start_idx] . to_vec ( ) ) ;
242
+ fn get_all_files_in_display_order ( ctx : & mut CommandContext ) -> anyhow:: Result < Vec < CliId > > {
243
+ use std:: collections:: BTreeMap ;
244
+ use bstr:: BString ;
245
+ use but_hunk_assignment:: HunkAssignment ;
246
+
247
+ let project = gitbutler_project:: Project :: from_path ( & ctx. project ( ) . path ) ?;
248
+ let changes =
249
+ but_core:: diff:: ui:: worktree_changes_by_worktree_dir ( project. path . clone ( ) ) ?. changes ;
250
+ let ( assignments, _) =
251
+ but_hunk_assignment:: assignments_with_fallback ( ctx, false , Some ( changes. clone ( ) ) , None ) ?;
252
+
253
+ // Group assignments by file, same as status display logic
254
+ let mut by_file: BTreeMap < BString , Vec < HunkAssignment > > = BTreeMap :: new ( ) ;
255
+ for assignment in & assignments {
256
+ by_file
257
+ . entry ( assignment. path_bytes . clone ( ) )
258
+ . or_default ( )
259
+ . push ( assignment. clone ( ) ) ;
260
+ }
261
+
262
+ let mut all_files = Vec :: new ( ) ;
263
+
264
+ // First, get files assigned to branches (they appear first in status display)
265
+ let stacks = crate :: log:: stacks ( ctx) ?;
266
+ for stack in stacks {
267
+ for ( _stack_id, details_result) in stack. id . map ( |id| ( stack. id , crate :: log:: stack_details ( ctx, id) ) ) {
268
+ if let Ok ( details) = details_result {
269
+ for branch in & details. branch_details {
270
+ for ( path_bytes, assignments) in & by_file {
271
+ for assignment in assignments {
272
+ if let Some ( stack_id) = assignment. stack_id {
273
+ if stack. id == Some ( stack_id) {
274
+ let file_id = CliId :: file_from_assignment ( assignment) ;
275
+ if !all_files. contains ( & file_id) {
276
+ all_files. push ( file_id) ;
277
+ }
278
+ }
279
+ }
280
+ }
281
+ }
282
+ }
283
+ }
284
+ }
285
+ }
286
+
287
+ // Then add unassigned files (they appear last in status display)
288
+ for ( path_bytes, assignments) in & by_file {
289
+ for assignment in assignments {
290
+ if assignment. stack_id . is_none ( ) {
291
+ let file_id = CliId :: file_from_assignment ( assignment) ;
292
+ if !all_files. contains ( & file_id) {
293
+ all_files. push ( file_id) ;
294
+ }
295
+ }
249
296
}
250
297
}
251
298
252
- Err ( anyhow :: anyhow! ( "Could not find range from '{}' to '{}' in the same file list" , start_str , end_str ) )
299
+ Ok ( all_files )
253
300
}
254
301
255
302
fn parse_list ( ctx : & mut CommandContext , source : & str ) -> anyhow:: Result < Vec < CliId > > {
0 commit comments