diff: return diff_filepair from diff queue helpers

The `diff_addremove()` and `diff_change()` functions set up and queue diffs, but do not return the `diff_filepair` added to the queue. In a subsequent commit, modifications to `diff_filepair` need to occur in certain cases after being queued. Since the existing `diff_addremove()` and `diff_change()` are also used for callbacks in `diff_options` as types `add_remove_fn_t` and `change_fn_t`, modifying the existing function signatures requires further changes. The diff options for pruning use `file_add_remove()` and `file_change()` where file pairs do not even get queued. Thus, separate functions are implemented instead. Split out the queuing operations into `diff_queue_addremove()` and `diff_queue_change()` which also return a handle to the queued `diff_filepair`. Both `diff_addremove()` and `diff_change()` are reimplemented as thin wrappers around the new functions. Signed-off-by: Justin Tobler <jltobler@gmail.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Justin Tobler committed Feb 28, 2025 at 15:33 UTC 7c67d2a07055150b76e81efa8850221d52705305
2 files changed +75 -20
diff.c
+50 -20
@@ -7161,16 +7161,19 @@ void compute_diffstat(struct diff_options *options,
7161 options->found_changes = !!diffstat->nr;
7162 }
7163
7164 -void diff_addremove(struct diff_options *options,
7165 - int addremove, unsigned mode,
7166 - const struct object_id *oid,
7167 - int oid_valid,
7168 - const char *concatpath, unsigned dirty_submodule)
7164 +struct diff_filepair *diff_queue_addremove(struct diff_queue_struct *queue,
7165 + struct diff_options *options,
7166 + int addremove, unsigned mode,
7167 + const struct object_id *oid,
7168 + int oid_valid,
7169 + const char *concatpath,
7170 + unsigned dirty_submodule)
7171 {
7172 struct diff_filespec *one, *two;
7173 + struct diff_filepair *pair;
7174
7175 if (S_ISGITLINK(mode) && is_submodule_ignored(concatpath, options))
7173 - return;
7176 + return NULL;
7177
7178 /* This may look odd, but it is a preparation for
7179 * feeding "there are unchanged files which should
@@ -7190,7 +7193,7 @@ void diff_addremove(struct diff_options *options,
7193
7194 if (options->prefix &&
7195 strncmp(concatpath, options->prefix, options->prefix_length))
7193 - return;
7196 + return NULL;
7197
7198 one = alloc_filespec(concatpath);
7199 two = alloc_filespec(concatpath);
@@ -7202,25 +7205,29 @@ void diff_addremove(struct diff_options *options,
7205 two->dirty_submodule = dirty_submodule;
7206 }
7207
7205 - diff_queue(&diff_queued_diff, one, two);
7208 + pair = diff_queue(queue, one, two);
7209 if (!options->flags.diff_from_contents)
7210 options->flags.has_changes = 1;
7211 +
7212 + return pair;
7213 }
7214
7210 -void diff_change(struct diff_options *options,
7211 - unsigned old_mode, unsigned new_mode,
7212 - const struct object_id *old_oid,
7213 - const struct object_id *new_oid,
7214 - int old_oid_valid, int new_oid_valid,
7215 - const char *concatpath,
7216 - unsigned old_dirty_submodule, unsigned new_dirty_submodule)
7215 +struct diff_filepair *diff_queue_change(struct diff_queue_struct *queue,
7216 + struct diff_options *options,
7217 + unsigned old_mode, unsigned new_mode,
7218 + const struct object_id *old_oid,
7219 + const struct object_id *new_oid,
7220 + int old_oid_valid, int new_oid_valid,
7221 + const char *concatpath,
7222 + unsigned old_dirty_submodule,
7223 + unsigned new_dirty_submodule)
7224 {
7225 struct diff_filespec *one, *two;
7226 struct diff_filepair *p;
7227
7228 if (S_ISGITLINK(old_mode) && S_ISGITLINK(new_mode) &&
7229 is_submodule_ignored(concatpath, options))
7223 - return;
7230 + return NULL;
7231
7232 if (options->flags.reverse_diff) {
7233 SWAP(old_mode, new_mode);
@@ -7231,7 +7238,7 @@ void diff_change(struct diff_options *options,
7238
7239 if (options->prefix &&
7240 strncmp(concatpath, options->prefix, options->prefix_length))
7234 - return;
7241 + return NULL;
7242
7243 one = alloc_filespec(concatpath);
7244 two = alloc_filespec(concatpath);
@@ -7239,19 +7246,42 @@ void diff_change(struct diff_options *options,
7246 fill_filespec(two, new_oid, new_oid_valid, new_mode);
7247 one->dirty_submodule = old_dirty_submodule;
7248 two->dirty_submodule = new_dirty_submodule;
7242 - p = diff_queue(&diff_queued_diff, one, two);
7249 + p = diff_queue(queue, one, two);
7250
7251 if (options->flags.diff_from_contents)
7245 - return;
7252 + return p;
7253
7254 if (options->flags.quick && options->skip_stat_unmatch &&
7255 !diff_filespec_check_stat_unmatch(options->repo, p)) {
7256 diff_free_filespec_data(p->one);
7257 diff_free_filespec_data(p->two);
7251 - return;
7258 + return p;
7259 }
7260
7261 options->flags.has_changes = 1;
7262 +
7263 + return p;
7264 +}
7265 +
7266 +void diff_addremove(struct diff_options *options, int addremove, unsigned mode,
7267 + const struct object_id *oid, int oid_valid,
7268 + const char *concatpath, unsigned dirty_submodule)
7269 +{
7270 + diff_queue_addremove(&diff_queued_diff, options, addremove, mode, oid,
7271 + oid_valid, concatpath, dirty_submodule);
7272 +}
7273 +
7274 +void diff_change(struct diff_options *options,
7275 + unsigned old_mode, unsigned new_mode,
7276 + const struct object_id *old_oid,
7277 + const struct object_id *new_oid,
7278 + int old_oid_valid, int new_oid_valid,
7279 + const char *concatpath,
7280 + unsigned old_dirty_submodule, unsigned new_dirty_submodule)
7281 +{
7282 + diff_queue_change(&diff_queued_diff, options, old_mode, new_mode,
7283 + old_oid, new_oid, old_oid_valid, new_oid_valid,
7284 + concatpath, old_dirty_submodule, new_dirty_submodule);
7285 }
7286
7287 struct diff_filepair *diff_unmerge(struct diff_options *options, const char *path)
diff.h
+25
@@ -508,6 +508,31 @@ void diff_set_default_prefix(struct diff_options *options);
508
509 int diff_can_quit_early(struct diff_options *);
510
511 +/*
512 + * Stages changes in the provided diff queue for file additions and deletions.
513 + * If a file pair gets queued, it is returned.
514 + */
515 +struct diff_filepair *diff_queue_addremove(struct diff_queue_struct *queue,
516 + struct diff_options *,
517 + int addremove, unsigned mode,
518 + const struct object_id *oid,
519 + int oid_valid, const char *fullpath,
520 + unsigned dirty_submodule);
521 +
522 +/*
523 + * Stages changes in the provided diff queue for file modifications.
524 + * If a file pair gets queued, it is returned.
525 + */
526 +struct diff_filepair *diff_queue_change(struct diff_queue_struct *queue,
527 + struct diff_options *,
528 + unsigned mode1, unsigned mode2,
529 + const struct object_id *old_oid,
530 + const struct object_id *new_oid,
531 + int old_oid_valid, int new_oid_valid,
532 + const char *fullpath,
533 + unsigned dirty_submodule1,
534 + unsigned dirty_submodule2);
535 +
536 void diff_addremove(struct diff_options *,
537 int addremove,
538 unsigned mode,