Merge branch 'sb/format-patch-base-patch-id-fix'
authorJunio C Hamano <gitster@pobox.com>
Thu, 13 Jun 2019 20:18:46 +0000 (13:18 -0700)
committerJunio C Hamano <gitster@pobox.com>
Thu, 13 Jun 2019 20:18:46 +0000 (13:18 -0700)
The "--base" option of "format-patch" computed the patch-ids for
prerequisite patches in an unstable way, which has been updated to
compute in a way that is compatible with "git patch-id --stable".

* sb/format-patch-base-patch-id-fix:
format-patch: make --base patch-id output stable
format-patch: inform user that patch-id generation is unstable

1  2 
diff.c
diff.h
diff --combined diff.c
index a654d46f6a93de96d85706c7373ef0d617081a21,8e3675b416a2a8925320133fba153cddbb6b49a6..1ee04e321b1b5cc4e3f6bde37f49b7d3c0694aa6
--- 1/diff.c
--- 2/diff.c
+++ b/diff.c
@@@ -5211,11 -5211,9 +5211,11 @@@ static int diff_opt_unified(const struc
  
        BUG_ON_OPT_NEG(unset);
  
 -      options->context = strtol(arg, &s, 10);
 -      if (*s)
 -              return error(_("%s expects a numerical value"), "--unified");
 +      if (arg) {
 +              options->context = strtol(arg, &s, 10);
 +              if (*s)
 +                      return error(_("%s expects a numerical value"), "--unified");
 +      }
        enable_patch_output(&options->output_format);
  
        return 0;
@@@ -5274,7 -5272,7 +5274,7 @@@ static void prep_parse_options(struct d
                          DIFF_FORMAT_PATCH, DIFF_FORMAT_NO_OUTPUT),
                OPT_CALLBACK_F('U', "unified", options, N_("<n>"),
                               N_("generate diffs with <n> lines context"),
 -                             PARSE_OPT_NONEG, diff_opt_unified),
 +                             PARSE_OPT_NONEG | PARSE_OPT_OPTARG, diff_opt_unified),
                OPT_BOOL('W', "function-context", &options->flags.funccontext,
                         N_("generate diffs with <n> lines context")),
                OPT_BIT_F(0, "raw", &options->output_format,
                             N_("show the given source prefix instead of \"a/\""),
                             PARSE_OPT_NONEG),
                OPT_STRING_F(0, "dst-prefix", &options->b_prefix, N_("<prefix>"),
 -                           N_("show the given source prefix instead of \"b/\""),
 +                           N_("show the given destination prefix instead of \"b/\""),
                             PARSE_OPT_NONEG),
                OPT_CALLBACK_F(0, "line-prefix", options, N_("<prefix>"),
                               N_("prepend an additional prefix to every line of output"),
                               N_("equivalent to --word-diff=color --word-diff-regex=<regex>"),
                               PARSE_OPT_NONEG | PARSE_OPT_OPTARG, diff_opt_color_words),
                OPT_CALLBACK_F(0, "color-moved", options, N_("<mode>"),
 -                             N_("move lines of code are colored differently"),
 +                             N_("moved lines of code are colored differently"),
                               PARSE_OPT_OPTARG, diff_opt_color_moved),
                OPT_CALLBACK_F(0, "color-moved-ws", options, N_("<mode>"),
                               N_("how white spaces are ignored in --color-moved"),
                               0, diff_opt_color_moved_ws),
  
 -              OPT_GROUP(N_("Diff other options")),
 +              OPT_GROUP(N_("Other diff options")),
                OPT_CALLBACK_F(0, "relative", options, N_("<prefix>"),
                               N_("when run from subdir, exclude changes outside and show relative paths"),
                               PARSE_OPT_NONEG | PARSE_OPT_OPTARG,
@@@ -5990,6 -5988,22 +5990,22 @@@ static int remove_space(char *line, in
        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 -6028,8 +6030,8 @@@ static void patch_id_add_mode(git_SHA_C
        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;
        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;
                                  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]);
diff --combined diff.h
index d5e44baa9640d2917c69ad3463be0228288b98e4,de24a048649e14cf93fc075fca45d98e3dc357d7..b680b377b2f5871ecb3a27856f8d15fe2b1c8621
--- 1/diff.h
--- 2/diff.h
+++ b/diff.h
@@@ -169,7 -169,7 +169,7 @@@ struct diff_options 
        const char *prefix;
        int prefix_length;
        const char *stat_sep;
 -      long xdl_opts;
 +      int xdl_opts;
  
        /* see Documentation/diff-options.txt */
        char **anchors;
@@@ -436,7 -436,8 +436,8 @@@ int run_diff_files(struct rev_info *rev
  int run_diff_index(struct rev_info *revs, int cached);
  
  int do_diff_cache(const struct object_id *, struct diff_options *);
- int diff_flush_patch_id(struct diff_options *, struct object_id *, int);
+ int diff_flush_patch_id(struct diff_options *, struct object_id *, int, int);
+ void flush_one_hunk(struct object_id *, git_SHA_CTX *);
  
  int diff_result_code(struct diff_options *, int);