512
513
/*** Function Grouping: functions related to collect_merge_info() ***/
514
515
+static int traverse_trees_wrapper_callback(int n,
516
+ unsigned long mask,
517
+ unsigned long dirmask,
518
+ struct name_entry *names,
519
+ struct traverse_info *info)
520
+{
521
+ struct merge_options *opt = info->data;
522
+ struct rename_info *renames = &opt->priv->renames;
523
+
524
+ assert(n==3);
525
+
526
+ if (!renames->callback_data_traverse_path)
527
+ renames->callback_data_traverse_path = xstrdup(info->traverse_path);
528
+
529
+ ALLOC_GROW(renames->callback_data, renames->callback_data_nr + 1,
530
+ renames->callback_data_alloc);
531
+ renames->callback_data[renames->callback_data_nr].mask = mask;
532
+ renames->callback_data[renames->callback_data_nr].dirmask = dirmask;
533
+ COPY_ARRAY(renames->callback_data[renames->callback_data_nr].names,
534
+ names, 3);
535
+ renames->callback_data_nr++;
536
+
537
+ return mask;
538
+}
539
+
540
+/*
541
+ * Much like traverse_trees(), BUT:
542
+ * - read all the tree entries FIRST, saving them
543
+ * - note that the above step provides an opportunity to compute necessary
544
+ * additional details before the "real" traversal
545
+ * - loop through the saved entries and call the original callback on them
546
+ */
547
+MAYBE_UNUSED
548
+static int traverse_trees_wrapper(struct index_state *istate,
549
+ int n,
550
+ struct tree_desc *t,
551
+ struct traverse_info *info)
552
+{
553
+ int ret, i, old_offset;
554
+ traverse_callback_t old_fn;
555
+ char *old_callback_data_traverse_path;
556
+ struct merge_options *opt = info->data;
557
+ struct rename_info *renames = &opt->priv->renames;
558
+
559
+ old_callback_data_traverse_path = renames->callback_data_traverse_path;
560
+ old_fn = info->fn;
561
+ old_offset = renames->callback_data_nr;
562
+
563
+ renames->callback_data_traverse_path = NULL;
564
+ info->fn = traverse_trees_wrapper_callback;
565
+ ret = traverse_trees(istate, n, t, info);
566
+ if (ret < 0)
567
+ return ret;
568
+
569
+ info->traverse_path = renames->callback_data_traverse_path;
570
+ info->fn = old_fn;
571
+ for (i = old_offset; i < renames->callback_data_nr; ++i) {
572
+ info->fn(n,
573
+ renames->callback_data[i].mask,
574
+ renames->callback_data[i].dirmask,
575
+ renames->callback_data[i].names,
576
+ info);
577
+ }
578
+
579
+ renames->callback_data_nr = old_offset;
580
+ free(renames->callback_data_traverse_path);
581
+ renames->callback_data_traverse_path = old_callback_data_traverse_path;
582
+ info->traverse_path = NULL;
583
+ return 0;
584
+}
585
+
586
static void setup_path_info(struct merge_options *opt,
587
struct string_list_item *result,
588
const char *current_dir_name,