Code

Merge branch 'jc/show-sig'
authorJunio C Hamano <gitster@pobox.com>
Fri, 6 Jan 2012 20:44:07 +0000 (12:44 -0800)
committerJunio C Hamano <gitster@pobox.com>
Fri, 6 Jan 2012 20:44:07 +0000 (12:44 -0800)
* jc/show-sig:
  log --show-signature: reword the common two-head merge case
  log-tree: show mergetag in log --show-signature output
  log-tree.c: small refactor in show_signature()
  commit --amend -S: strip existing gpgsig headers
  verify_signed_buffer: fix stale comment
  gpg-interface: allow use of a custom GPG binary
  pretty: %G[?GS] placeholders
  test "commit -S" and "log --show-signature"
  log: --show-signature
  commit: teach --gpg-sign option

Conflicts:
builtin/commit-tree.c
builtin/commit.c
builtin/merge.c
notes-cache.c
pretty.c

12 files changed:
1  2 
Documentation/RelNotes/1.7.9.txt
Documentation/config.txt
Documentation/git-tag.txt
builtin/commit-tree.c
builtin/commit.c
builtin/merge.c
commit.c
commit.h
log-tree.c
notes-cache.c
notes-merge.c
pretty.c

index 9689efa986c27ffdc9684f62767bfc7cd93fb113,0000000000000000000000000000000000000000..1c548d94362ec5d9fe36873d377b838d649cde9c
mode 100644,000000..100644
--- /dev/null
@@@ -1,112 -1,0 +1,108 @@@
-  * gitweb did not correctly fall back to configured $fallback_encoding
-    that is not 'latin1'.
-    (merge b13e3ea jn/maint-gitweb-utf8-fix later to maint).
 +Git v1.7.9 Release Notes (draft)
 +========================
 +
 +Updates since v1.7.8
 +--------------------
 +
 + * gitk updates accumulated since early 2011.
 +
 + * git-gui updated to 0.16.0.
 +
 + * git-p4 (in contrib/) updates.
 +
 + * Git uses gettext to translate its most common interface messages
 +   into the user's language if translations are available and the
 +   locale is appropriately set. Distributors can drop in new PO files
 +   in po/ to add new translations.
 +
 + * The code to handle username/password for HTTP transaction used in
 +   "git push" & "git fetch" learned to talk "credential API" to
 +   external programs to cache or store them, to allow integration with
 +   platform native keychain mechanisms.
 +
 + * The prompted input in the terminal use our own getpass() replacement
 +   when possible. HTTP transactions used to ask username without echoing
 +   back what was typed, but with this change you will see it as you type.
 +
 + * The internal of "revert/cherry-pick" has been tweaked to prepare
 +   building more generic "sequencer" on top of the implementation that
 +   drives them.
 +
 + * "git add" learned to stream large files directly into a packfile
 +   instead of writing them into individual loose object files.
 +
 + * "git checkout -B <current branch> <elsewhere>" is a more intuitive
 +   way to spell "git reset --keep <elsewhere>".
 +
 + * "git checkout" and "git merge" learned "--no-overwrite-ignore" option
 +   to tell Git that untracked and ignored files are not expendable.
 +
 + * "git commit --amend" learned "--no-edit" option to say that the
 +   user is amending the tree being recorded, without updating the
 +   commit log message.
 +
 + * "git commit" and "git reset" re-learned the optimization to prime
 +   the cache-tree information in the index, which makes it faster to
 +   write a tree object out after the index entries are updated.
 +
 + * "git commit" detects and rejects an attempt to stuff NUL byte in
 +   the commit log message.
 +
 + * fsck and prune are relatively lengthy operations that still go
 +   silent while making the end-user wait. They learned to give progress
 +   output like other slow operations.
 +
 + * The set of built-in function-header patterns for various languages
 +   knows MATLAB.
 +
 + * "git log --format='<format>'" learned new %g[nNeE] specifiers to
 +   show information from the reflog entries when warlking the reflog
 +   (i.e. with "-g").
 +
 + * "git pull" can be used to fetch and merge an annotated/signed tag,
 +   instead of the tip of a topic branch. The GPG signature from the
 +   signed tag is recorded in the resulting merge commit for later
 +   auditing.
 +
 + * "git branch --edit-description" can be used to add descriptive text
 +   to explain what a topic branch is about.
 +
 + * "git fmt-merge-msg" learned to take the branch description into
 +   account when preparing a merge summary that "git merge" records
 +   when merging a local branch.
 +
 + * "git request-pull" has been updated to convey more information
 +   useful for integrators to decide if a topic is worth merging and
 +   what is pulled is indeed what the requestor asked to pull,
 +   including:
 +
 +   - the tip of the branch being requested to be merged;
 +   - the branch description describing what the topic is about;
 +   - the contents of the annotated tag, when requesting to pull a tag.
 +
 + * "git pull" learned to notice 'pull.rebase' configuration variable,
 +   which serves as a global fallback for setting 'branch.<name>.rebase'
 +   configuration variable per branch.
 +
 + * "git tag" learned "--cleanup" option to control how the whitespaces
 +   and empty lines in tag message are cleaned up.
 +
 + * "gitweb" learned to show side-by-side diff.
 +
 +Also contains minor documentation updates and code clean-ups.
 +
 +
 +Fixes since v1.7.8
 +------------------
 +
 +Unless otherwise noted, all the fixes since v1.7.8 in the maintenance
 +releases are contained in this release (see release notes to them for
 +details).
 +
 +--
 +exec >/var/tmp/1
 +O=v1.7.8.2-301-g48de656
 +echo O=$(git describe master)
 +git log --first-parent --oneline --reverse ^$O master
 +echo
 +git shortlog --no-merges ^$O ^maint master
Simple merge
Simple merge
index 05353c30f292684b44b42f7f744d8eb1b7062f69,d5e19af54702d5d2ab38a5e4ef2cab6c9b88eead..164b655df93fea1ec2f63f5238c1ad7a377c8385
@@@ -98,7 -116,8 +116,8 @@@ int cmd_commit_tree(int argc, const cha
                        die_errno("git commit-tree: failed to read");
        }
  
-       if (commit_tree(&buffer, tree_sha1, parents, commit_sha1, NULL)) {
 -      if (commit_tree(buffer.buf, tree_sha1, parents, commit_sha1,
++      if (commit_tree(&buffer, tree_sha1, parents, commit_sha1,
+                       NULL, sign_commit)) {
                strbuf_release(&buffer);
                return 1;
        }
index 5891e95758a0d2530b325bd5fd346e15702e3017,970a83662a67a8f1c6cb8a67fd2e6636a5260948..eba1377eb32c02e57c46364c381df940afa66048
@@@ -139,12 -141,14 +142,14 @@@ static struct option builtin_commit_opt
        OPT_STRING('C', "reuse-message", &use_message, "commit", "reuse message from specified commit"),
        OPT_STRING(0, "fixup", &fixup_message, "commit", "use autosquash formatted message to fixup specified commit"),
        OPT_STRING(0, "squash", &squash_message, "commit", "use autosquash formatted message to squash specified commit"),
 -      OPT_BOOLEAN(0, "reset-author", &renew_authorship, "the commit is authored by me now (used with -C-c/--amend)"),
 +      OPT_BOOLEAN(0, "reset-author", &renew_authorship, "the commit is authored by me now (used with -C/-c/--amend)"),
        OPT_BOOLEAN('s', "signoff", &signoff, "add Signed-off-by:"),
        OPT_FILENAME('t', "template", &template_file, "use specified template file"),
 -      OPT_BOOLEAN('e', "edit", &edit_flag, "force edit of commit"),
 +      OPT_BOOL('e', "edit", &edit_flag, "force edit of commit"),
        OPT_STRING(0, "cleanup", &cleanup_arg, "default", "how to strip spaces and #comments from message"),
        OPT_BOOLEAN(0, "status", &include_status, "include status in commit message template"),
+       { OPTION_STRING, 'S', "gpg-sign", &sign_commit, "key id",
+         "GPG sign commit", PARSE_OPT_OPTARG, NULL, (intptr_t) "" },
        /* end commit message options */
  
        OPT_GROUP("Commit contents options"),
@@@ -1492,8 -1501,8 +1502,8 @@@ int cmd_commit(int argc, const char **a
                append_merge_tag_headers(parents, &tail);
        }
  
 -      if (commit_tree_extended(sb.buf, active_cache_tree->sha1, parents, sha1,
 +      if (commit_tree_extended(&sb, active_cache_tree->sha1, parents, sha1,
-                                author_ident.buf, extra)) {
+                                author_ident.buf, sign_commit, extra)) {
                rollback_index_files();
                die(_("failed to write commit object"));
        }
diff --cc builtin/merge.c
index 4b0ca6550c130dc8efbf248c56503018b8bcb604,e5afe64cefba88cd435a89c9d4d87f459488853d..3a451727d0e637ae197c9a1193435e57e84e6c58
@@@ -26,7 -26,7 +26,8 @@@
  #include "merge-recursive.h"
  #include "resolve-undo.h"
  #include "remote.h"
 +#include "fmt-merge-msg.h"
+ #include "gpg-interface.h"
  
  #define DEFAULT_TWOHEAD (1<<0)
  #define DEFAULT_OCTOPUS (1<<1)
@@@ -209,7 -209,8 +211,9 @@@ static struct option builtin_merge_opti
        OPT_BOOLEAN(0, "abort", &abort_current_merge,
                "abort the current in-progress merge"),
        OPT_SET_INT(0, "progress", &show_progress, "force progress reporting", 1),
+       { OPTION_STRING, 'S', "gpg-sign", &sign_commit, "key id",
+         "GPG sign commit", PARSE_OPT_OPTARG, NULL, (intptr_t) "" },
 +      OPT_BOOLEAN(0, "overwrite-ignore", &overwrite_ignore, "update ignored files (default)"),
        OPT_END()
  };
  
@@@ -571,7 -576,8 +575,11 @@@ static int git_merge_config(const char 
                default_to_upstream = git_config_bool(k, v);
                return 0;
        }
 +      status = fmt_merge_msg_config(k, v, cb);
++      if (status)
++              return status;
+       status = git_gpg_config(k, v, NULL);
        if (status)
                return status;
        return git_diff_ui_config(k, v, cb);
@@@ -910,8 -912,8 +918,9 @@@ static int merge_trivial(struct commit 
        parent->next->item = remoteheads->item;
        parent->next->next = NULL;
        prepare_to_commit();
-       if (commit_tree(&merge_msg, result_tree, parent, result_commit, NULL))
 -      commit_tree(merge_msg.buf, result_tree, parent, result_commit, NULL,
 -                  sign_commit);
++      if (commit_tree(&merge_msg, result_tree, parent, result_commit, NULL,
++                      sign_commit))
 +              die(_("failed to write commit object"));
        finish(head, result_commit, "In-index merge");
        drop_save();
        return 0;
@@@ -942,8 -944,8 +951,9 @@@ static int finish_automerge(struct comm
        strbuf_addch(&merge_msg, '\n');
        prepare_to_commit();
        free_commit_list(remoteheads);
-       if (commit_tree(&merge_msg, result_tree, parents, result_commit, NULL))
 -      commit_tree(merge_msg.buf, result_tree, parents, result_commit,
 -                  NULL, sign_commit);
++      if (commit_tree(&merge_msg, result_tree, parents, result_commit,
++                      NULL, sign_commit))
 +              die(_("failed to write commit object"));
        strbuf_addf(&buf, "Merge made by the '%s' strategy.", wt_strategy);
        finish(head, result_commit, buf.buf);
        strbuf_release(&buf);
diff --cc commit.c
index 44bc96d44d391209d3a60e9e8c1b98ed209e6b4a,2162a7c5724c1dcdd42b249c11d1995e66abcd6f..35af4988f0ff83c6a3379ea9f6de4e4e1568c39f
+++ b/commit.c
@@@ -973,9 -1072,9 +1072,9 @@@ void free_commit_extra_headers(struct c
        }
  }
  
 -int commit_tree(const char *msg, unsigned char *tree,
 +int commit_tree(const struct strbuf *msg, unsigned char *tree,
                struct commit_list *parents, unsigned char *ret,
-               const char *author)
+               const char *author, const char *sign_commit)
  {
        struct commit_extra_header *extra = NULL, **tail = &extra;
        int result;
@@@ -991,9 -1091,10 +1091,10 @@@ static const char commit_utf8_warn[] 
  "You may want to amend it after fixing the message, or set the config\n"
  "variable i18n.commitencoding to the encoding your project uses.\n";
  
 -int commit_tree_extended(const char *msg, unsigned char *tree,
 +int commit_tree_extended(const struct strbuf *msg, unsigned char *tree,
                         struct commit_list *parents, unsigned char *ret,
-                        const char *author, struct commit_extra_header *extra)
+                        const char *author, const char *sign_commit,
+                        struct commit_extra_header *extra)
  {
        int result;
        int encoding_is_utf8;
diff --cc commit.h
index 4df397865abe7161a9f16e3177e3b486bf8434ca,123aea3a7ccf95821d4b4eb5eff9cf7f384d881d..154c0e34ff7d2dbaddcfb66b74d26697ffba6381
+++ b/commit.h
@@@ -191,17 -191,17 +191,17 @@@ struct commit_extra_header 
  extern void append_merge_tag_headers(struct commit_list *parents,
                                     struct commit_extra_header ***tail);
  
 -extern int commit_tree(const char *msg, unsigned char *tree,
 +extern int commit_tree(const struct strbuf *msg, unsigned char *tree,
                       struct commit_list *parents, unsigned char *ret,
-                      const char *author);
+                      const char *author, const char *sign_commit);
  
 -extern int commit_tree_extended(const char *msg, unsigned char *tree,
 +extern int commit_tree_extended(const struct strbuf *msg, unsigned char *tree,
                                struct commit_list *parents, unsigned char *ret,
-                               const char *author,
+                               const char *author, const char *sign_commit,
                                struct commit_extra_header *);
  
- extern struct commit_extra_header *read_commit_extra_headers(struct commit *);
- extern struct commit_extra_header *read_commit_extra_header_lines(const char *buf, size_t len);
+ extern struct commit_extra_header *read_commit_extra_headers(struct commit *, const char **);
+ extern struct commit_extra_header *read_commit_extra_header_lines(const char *buf, size_t len, const char **);
  
  extern void free_commit_extra_headers(struct commit_extra_header *extra);
  
diff --cc log-tree.c
Simple merge
diff --cc notes-cache.c
index bea013eeae70f360e12af01345058b1b217848c4,c36a960bc32a9bfa0d5da83b1f7c8cb6a315b17d..eabe4a0d9bf44050dba43cbd821642cdfd3fb40b
@@@ -57,9 -56,7 +57,9 @@@ int notes_cache_write(struct notes_cach
  
        if (write_notes_tree(&c->tree, tree_sha1))
                return -1;
 -      if (commit_tree(c->validity, tree_sha1, NULL, commit_sha1, NULL, NULL) < 0)
 +      strbuf_attach(&msg, c->validity,
 +                    strlen(c->validity), strlen(c->validity) + 1);
-       if (commit_tree(&msg, tree_sha1, NULL, commit_sha1, NULL) < 0)
++      if (commit_tree(&msg, tree_sha1, NULL, commit_sha1, NULL, NULL) < 0)
                return -1;
        if (update_ref("update notes cache", c->tree.ref, commit_sha1, NULL,
                       0, QUIET_ON_ERR) < 0)
diff --cc notes-merge.c
Simple merge
diff --cc pretty.c
index 1580299d4037ada9e1f0e3c11c6c5578f44f52dd,392d6565955febf10a5f03863d71a976ca3fe8dc..8688b8f2d45a493aa8b51b29f7d46b2abff7f30e
+++ b/pretty.c
@@@ -822,23 -829,59 +829,76 @@@ static void rewrap_message_tail(struct 
        c->indent2 = new_indent2;
  }
  
+ static struct {
+       char result;
+       const char *check;
+ } signature_check[] = {
+       { 'G', ": Good signature from " },
+       { 'B', ": BAD signature from " },
+ };
+ static void parse_signature_lines(struct format_commit_context *ctx)
+ {
+       const char *buf = ctx->signature.gpg_output;
+       int i;
+       for (i = 0; i < ARRAY_SIZE(signature_check); i++) {
+               const char *found = strstr(buf, signature_check[i].check);
+               const char *next;
+               if (!found)
+                       continue;
+               ctx->signature.good_bad = signature_check[i].result;
+               found += strlen(signature_check[i].check);
+               next = strchrnul(found, '\n');
+               ctx->signature.signer = xmemdupz(found, next - found);
+               break;
+       }
+ }
+ static void parse_commit_signature(struct format_commit_context *ctx)
+ {
+       struct strbuf payload = STRBUF_INIT;
+       struct strbuf signature = STRBUF_INIT;
+       struct strbuf gpg_output = STRBUF_INIT;
+       int status;
+       ctx->commit_signature_parsed = 1;
+       if (parse_signed_commit(ctx->commit->object.sha1,
+                               &payload, &signature) <= 0)
+               goto out;
+       status = verify_signed_buffer(payload.buf, payload.len,
+                                     signature.buf, signature.len,
+                                     &gpg_output);
+       if (status && !gpg_output.len)
+               goto out;
+       ctx->signature.gpg_output = strbuf_detach(&gpg_output, NULL);
+       parse_signature_lines(ctx);
+  out:
+       strbuf_release(&gpg_output);
+       strbuf_release(&payload);
+       strbuf_release(&signature);
+ }
 +static int format_reflog_person(struct strbuf *sb,
 +                              char part,
 +                              struct reflog_walk_info *log,
 +                              enum date_mode dmode)
 +{
 +      const char *ident;
 +
 +      if (!log)
 +              return 2;
 +
 +      ident = get_reflog_ident(log);
 +      if (!ident)
 +              return 2;
 +
 +      return format_person_part(sb, part, ident, strlen(ident), dmode);
 +}
 +
  static size_t format_commit_one(struct strbuf *sb, const char *placeholder,
                                void *context)
  {