Merge branch 'dl/rebase-i-keep-base'
[gitweb.git] / diff.c
diff --git a/diff.c b/diff.c
index a654d46f6a93de96d85706c7373ef0d617081a21..6db6927369e5c18ae3cb7ea27a0ebce37fd2b357 100644 (file)
--- a/diff.c
+++ b/diff.c
@@ -25,7 +25,7 @@
 #include "packfile.h"
 #include "parse-options.h"
 #include "help.h"
-#include "fetch-object.h"
+#include "promisor-remote.h"
 
 #ifdef NO_FAST_WORKING_DIRECTORY
 #define FAST_WORKING_DIRECTORY 0
@@ -1673,7 +1673,10 @@ static void emit_hunk_header(struct emit_callback *ecbdata,
        if (ecbdata->opt->flags.dual_color_diffed_diffs)
                strbuf_addstr(&msgbuf, reverse);
        strbuf_addstr(&msgbuf, frag);
-       strbuf_add(&msgbuf, line, ep - line);
+       if (ecbdata->opt->flags.suppress_hunk_header_line_count)
+               strbuf_add(&msgbuf, atat, sizeof(atat));
+       else
+               strbuf_add(&msgbuf, line, ep - line);
        strbuf_addstr(&msgbuf, reset);
 
        /*
@@ -4206,6 +4209,8 @@ static void run_external_diff(const char *pgm,
        argv_array_pushf(&env, "GIT_DIFF_PATH_COUNTER=%d", ++o->diff_path_counter);
        argv_array_pushf(&env, "GIT_DIFF_PATH_TOTAL=%d", q->nr);
 
+       diff_free_filespec_data(one);
+       diff_free_filespec_data(two);
        if (run_command_v_opt_cd_env(argv.argv, RUN_USING_SHELL, NULL, env.argv))
                die(_("external diff died, stopping at %s"), name);
 
@@ -5990,6 +5995,22 @@ static int remove_space(char *line, int len)
        return dst - line;
 }
 
+void flush_one_hunk(struct object_id *result, git_SHA_CTX *ctx)
+{
+       unsigned char hash[GIT_MAX_RAWSZ];
+       unsigned short carry = 0;
+       int i;
+
+       git_SHA1_Final(hash, ctx);
+       git_SHA1_Init(ctx);
+       /* 20-byte sum, with carry */
+       for (i = 0; i < GIT_SHA1_RAWSZ; ++i) {
+               carry += result->hash[i] + hash[i];
+               result->hash[i] = carry;
+               carry >>= 8;
+       }
+}
+
 static void patch_id_consume(void *priv, char *line, unsigned long len)
 {
        struct patch_id_t *data = priv;
@@ -6014,8 +6035,8 @@ static void patch_id_add_mode(git_SHA_CTX *ctx, unsigned mode)
        git_SHA1_Update(ctx, buf, len);
 }
 
-/* returns 0 upon success, and writes result into sha1 */
-static int diff_get_patch_id(struct diff_options *options, struct object_id *oid, int diff_header_only)
+/* returns 0 upon success, and writes result into oid */
+static int diff_get_patch_id(struct diff_options *options, struct object_id *oid, int diff_header_only, int stable)
 {
        struct diff_queue_struct *q = &diff_queued_diff;
        int i;
@@ -6025,6 +6046,7 @@ static int diff_get_patch_id(struct diff_options *options, struct object_id *oid
        git_SHA1_Init(&ctx);
        memset(&data, 0, sizeof(struct patch_id_t));
        data.ctx = &ctx;
+       oidclr(oid);
 
        for (i = 0; i < q->nr; i++) {
                xpparam_t xpp;
@@ -6100,17 +6122,22 @@ static int diff_get_patch_id(struct diff_options *options, struct object_id *oid
                                  patch_id_consume, &data, &xpp, &xecfg))
                        return error("unable to generate patch-id diff for %s",
                                     p->one->path);
+
+               if (stable)
+                       flush_one_hunk(oid, &ctx);
        }
 
-       git_SHA1_Final(oid->hash, &ctx);
+       if (!stable)
+               git_SHA1_Final(oid->hash, &ctx);
+
        return 0;
 }
 
-int diff_flush_patch_id(struct diff_options *options, struct object_id *oid, int diff_header_only)
+int diff_flush_patch_id(struct diff_options *options, struct object_id *oid, int diff_header_only, int stable)
 {
        struct diff_queue_struct *q = &diff_queued_diff;
        int i;
-       int result = diff_get_patch_id(options, oid, diff_header_only);
+       int result = diff_get_patch_id(options, oid, diff_header_only, stable);
 
        for (i = 0; i < q->nr; i++)
                diff_free_filepair(q->queue[i]);
@@ -6485,6 +6512,7 @@ static void add_if_missing(struct repository *r,
                           const struct diff_filespec *filespec)
 {
        if (filespec && filespec->oid_valid &&
+           !S_ISGITLINK(filespec->mode) &&
            oid_object_info_extended(r, &filespec->oid, NULL,
                                     OBJECT_INFO_FOR_PREFETCH))
                oid_array_append(to_fetch, &filespec->oid);
@@ -6492,8 +6520,7 @@ static void add_if_missing(struct repository *r,
 
 void diffcore_std(struct diff_options *options)
 {
-       if (options->repo == the_repository &&
-           repository_format_partial_clone) {
+       if (options->repo == the_repository && has_promisor_remote()) {
                /*
                 * Prefetch the diff pairs that are about to be flushed.
                 */
@@ -6510,8 +6537,8 @@ void diffcore_std(struct diff_options *options)
                        /*
                         * NEEDSWORK: Consider deduplicating the OIDs sent.
                         */
-                       fetch_objects(repository_format_partial_clone,
-                                     to_fetch.oid, to_fetch.nr);
+                       promisor_remote_get_direct(options->repo,
+                                                  to_fetch.oid, to_fetch.nr);
                oid_array_clear(&to_fetch);
        }