]> git.ipfire.org Git - thirdparty/git.git/blobdiff - diff.c
Merge branch 'jt/v2-fetch-nego-fix'
[thirdparty/git.git] / diff.c
diff --git a/diff.c b/diff.c
index 61ce05d2190173430519a955a281ba6a58aeb594..d1ad6a3c4ad0bc5049d1af26ca0ea33fc9f68a1e 100644 (file)
--- a/diff.c
+++ b/diff.c
@@ -4034,10 +4034,18 @@ int diff_populate_filespec(struct repository *r,
                         */
                        info.contentp = &s->data;
 
+               if (options && options->missing_object_cb) {
+                       if (!oid_object_info_extended(r, &s->oid, &info,
+                                                     OBJECT_INFO_LOOKUP_REPLACE |
+                                                     OBJECT_INFO_SKIP_FETCH_OBJECT))
+                               goto object_read;
+                       options->missing_object_cb(options->missing_object_data);
+               }
                if (oid_object_info_extended(r, &s->oid, &info,
                                             OBJECT_INFO_LOOKUP_REPLACE))
                        die("unable to read %s", oid_to_hex(&s->oid));
 
+object_read:
                if (size_only || check_binary) {
                        if (size_only)
                                return 0;
@@ -4087,6 +4095,9 @@ static void prep_temp_blob(struct index_state *istate,
        struct strbuf tempfile = STRBUF_INIT;
        char *path_dup = xstrdup(path);
        const char *base = basename(path_dup);
+       struct checkout_metadata meta;
+
+       init_checkout_metadata(&meta, NULL, NULL, oid);
 
        /* Generate "XXXXXX_basename.ext" */
        strbuf_addstr(&tempfile, "XXXXXX_");
@@ -4096,7 +4107,7 @@ static void prep_temp_blob(struct index_state *istate,
        if (!temp->tempfile)
                die_errno("unable to create temp-file");
        if (convert_to_working_tree(istate, path,
-                       (const char *)blob, (size_t)size, &buf)) {
+                       (const char *)blob, (size_t)size, &buf, &meta)) {
                blob = buf.buf;
                size = buf.len;
        }
@@ -6444,6 +6455,8 @@ static int diff_filespec_check_stat_unmatch(struct repository *r,
 {
        struct diff_populate_filespec_options dpf_options = {
                .check_size_only = 1,
+               .missing_object_cb = diff_queued_diff_prefetch,
+               .missing_object_data = r,
        };
 
        if (p->done_skip_stat_unmatch)
@@ -6520,9 +6533,9 @@ void diffcore_fix_diff_index(void)
        QSORT(q->queue, q->nr, diffnamecmp);
 }
 
-static void add_if_missing(struct repository *r,
-                          struct oid_array *to_fetch,
-                          const struct diff_filespec *filespec)
+void diff_add_if_missing(struct repository *r,
+                        struct oid_array *to_fetch,
+                        const struct diff_filespec *filespec)
 {
        if (filespec && filespec->oid_valid &&
            !S_ISGITLINK(filespec->mode) &&
@@ -6531,29 +6544,48 @@ static void add_if_missing(struct repository *r,
                oid_array_append(to_fetch, &filespec->oid);
 }
 
-void diffcore_std(struct diff_options *options)
+void diff_queued_diff_prefetch(void *repository)
 {
-       if (options->repo == the_repository && has_promisor_remote()) {
-               /*
-                * Prefetch the diff pairs that are about to be flushed.
-                */
-               int i;
-               struct diff_queue_struct *q = &diff_queued_diff;
-               struct oid_array to_fetch = OID_ARRAY_INIT;
+       struct repository *repo = repository;
+       int i;
+       struct diff_queue_struct *q = &diff_queued_diff;
+       struct oid_array to_fetch = OID_ARRAY_INIT;
 
-               for (i = 0; i < q->nr; i++) {
-                       struct diff_filepair *p = q->queue[i];
-                       add_if_missing(options->repo, &to_fetch, p->one);
-                       add_if_missing(options->repo, &to_fetch, p->two);
-               }
-               /*
-                * NEEDSWORK: Consider deduplicating the OIDs sent.
-                */
-               promisor_remote_get_direct(options->repo,
-                                          to_fetch.oid, to_fetch.nr);
-               oid_array_clear(&to_fetch);
+       for (i = 0; i < q->nr; i++) {
+               struct diff_filepair *p = q->queue[i];
+               diff_add_if_missing(repo, &to_fetch, p->one);
+               diff_add_if_missing(repo, &to_fetch, p->two);
        }
 
+       /*
+        * NEEDSWORK: Consider deduplicating the OIDs sent.
+        */
+       promisor_remote_get_direct(repo, to_fetch.oid, to_fetch.nr);
+
+       oid_array_clear(&to_fetch);
+}
+
+void diffcore_std(struct diff_options *options)
+{
+       int output_formats_to_prefetch = DIFF_FORMAT_DIFFSTAT |
+               DIFF_FORMAT_NUMSTAT |
+               DIFF_FORMAT_PATCH |
+               DIFF_FORMAT_SHORTSTAT |
+               DIFF_FORMAT_DIRSTAT;
+
+       /*
+        * Check if the user requested a blob-data-requiring diff output and/or
+        * break-rewrite detection (which requires blob data). If yes, prefetch
+        * the diff pairs.
+        *
+        * If no prefetching occurs, diffcore_rename() will prefetch if it
+        * decides that it needs inexact rename detection.
+        */
+       if (options->repo == the_repository && has_promisor_remote() &&
+           (options->output_format & output_formats_to_prefetch ||
+            options->pickaxe_opts & DIFF_PICKAXE_KINDS_MASK))
+               diff_queued_diff_prefetch(options->repo);
+
        /* NOTE please keep the following in sync with diff_tree_combined() */
        if (options->skip_stat_unmatch)
                diffcore_skip_stat_unmatch(options);