Merge branch 'po/object-id'
authorJunio C Hamano <gitster@pobox.com>
Thu, 15 Feb 2018 22:55:43 +0000 (14:55 -0800)
committerJunio C Hamano <gitster@pobox.com>
Thu, 15 Feb 2018 22:55:43 +0000 (14:55 -0800)
Conversion from uchar[20] to struct object_id continues.

* po/object-id:
  sha1_file: rename hash_sha1_file_literally
  sha1_file: convert write_loose_object to object_id
  sha1_file: convert force_object_loose to object_id
  sha1_file: convert write_sha1_file to object_id
  notes: convert write_notes_tree to object_id
  notes: convert combine_notes_* to object_id
  commit: convert commit_tree* to object_id
  match-trees: convert splice_tree to object_id
  cache: clear whole hash buffer with oidclr
  sha1_file: convert hash_sha1_file to object_id
  dir: convert struct sha1_stat to use object_id
  sha1_file: convert pretend_sha1_file to object_id

15 files changed:
1  2 
apply.c
builtin/am.c
builtin/commit.c
builtin/index-pack.c
builtin/pack-objects.c
cache-tree.c
cache.h
commit.c
convert.c
diffcore-rename.c
dir.c
merge-recursive.c
read-cache.c
sequencer.c
sha1_file.c

diff --cc apply.c
Simple merge
diff --cc builtin/am.c
Simple merge
Simple merge
Simple merge
Simple merge
diff --cc cache-tree.c
Simple merge
diff --cc cache.h
Simple merge
diff --cc commit.c
Simple merge
diff --cc convert.c
Simple merge
Simple merge
diff --cc dir.c
Simple merge
Simple merge
diff --cc read-cache.c
Simple merge
diff --cc sequencer.c
@@@ -750,461 -694,6 +750,461 @@@ static int run_git_commit(const char *d
        return run_command(&cmd);
  }
  
-       if (commit_tree_extended(msg->buf, msg->len, tree.hash, parents,
-                                oid->hash, author, opts->gpg_sign, extra)) {
 +static int rest_is_empty(const struct strbuf *sb, int start)
 +{
 +      int i, eol;
 +      const char *nl;
 +
 +      /* Check if the rest is just whitespace and Signed-off-by's. */
 +      for (i = start; i < sb->len; i++) {
 +              nl = memchr(sb->buf + i, '\n', sb->len - i);
 +              if (nl)
 +                      eol = nl - sb->buf;
 +              else
 +                      eol = sb->len;
 +
 +              if (strlen(sign_off_header) <= eol - i &&
 +                  starts_with(sb->buf + i, sign_off_header)) {
 +                      i = eol;
 +                      continue;
 +              }
 +              while (i < eol)
 +                      if (!isspace(sb->buf[i++]))
 +                              return 0;
 +      }
 +
 +      return 1;
 +}
 +
 +/*
 + * Find out if the message in the strbuf contains only whitespace and
 + * Signed-off-by lines.
 + */
 +int message_is_empty(const struct strbuf *sb,
 +                   enum commit_msg_cleanup_mode cleanup_mode)
 +{
 +      if (cleanup_mode == COMMIT_MSG_CLEANUP_NONE && sb->len)
 +              return 0;
 +      return rest_is_empty(sb, 0);
 +}
 +
 +/*
 + * See if the user edited the message in the editor or left what
 + * was in the template intact
 + */
 +int template_untouched(const struct strbuf *sb, const char *template_file,
 +                     enum commit_msg_cleanup_mode cleanup_mode)
 +{
 +      struct strbuf tmpl = STRBUF_INIT;
 +      const char *start;
 +
 +      if (cleanup_mode == COMMIT_MSG_CLEANUP_NONE && sb->len)
 +              return 0;
 +
 +      if (!template_file || strbuf_read_file(&tmpl, template_file, 0) <= 0)
 +              return 0;
 +
 +      strbuf_stripspace(&tmpl, cleanup_mode == COMMIT_MSG_CLEANUP_ALL);
 +      if (!skip_prefix(sb->buf, tmpl.buf, &start))
 +              start = sb->buf;
 +      strbuf_release(&tmpl);
 +      return rest_is_empty(sb, start - sb->buf);
 +}
 +
 +int update_head_with_reflog(const struct commit *old_head,
 +                          const struct object_id *new_head,
 +                          const char *action, const struct strbuf *msg,
 +                          struct strbuf *err)
 +{
 +      struct ref_transaction *transaction;
 +      struct strbuf sb = STRBUF_INIT;
 +      const char *nl;
 +      int ret = 0;
 +
 +      if (action) {
 +              strbuf_addstr(&sb, action);
 +              strbuf_addstr(&sb, ": ");
 +      }
 +
 +      nl = strchr(msg->buf, '\n');
 +      if (nl) {
 +              strbuf_add(&sb, msg->buf, nl + 1 - msg->buf);
 +      } else {
 +              strbuf_addbuf(&sb, msg);
 +              strbuf_addch(&sb, '\n');
 +      }
 +
 +      transaction = ref_transaction_begin(err);
 +      if (!transaction ||
 +          ref_transaction_update(transaction, "HEAD", new_head,
 +                                 old_head ? &old_head->object.oid : &null_oid,
 +                                 0, sb.buf, err) ||
 +          ref_transaction_commit(transaction, err)) {
 +              ret = -1;
 +      }
 +      ref_transaction_free(transaction);
 +      strbuf_release(&sb);
 +
 +      return ret;
 +}
 +
 +static int run_rewrite_hook(const struct object_id *oldoid,
 +                          const struct object_id *newoid)
 +{
 +      struct child_process proc = CHILD_PROCESS_INIT;
 +      const char *argv[3];
 +      int code;
 +      struct strbuf sb = STRBUF_INIT;
 +
 +      argv[0] = find_hook("post-rewrite");
 +      if (!argv[0])
 +              return 0;
 +
 +      argv[1] = "amend";
 +      argv[2] = NULL;
 +
 +      proc.argv = argv;
 +      proc.in = -1;
 +      proc.stdout_to_stderr = 1;
 +
 +      code = start_command(&proc);
 +      if (code)
 +              return code;
 +      strbuf_addf(&sb, "%s %s\n", oid_to_hex(oldoid), oid_to_hex(newoid));
 +      sigchain_push(SIGPIPE, SIG_IGN);
 +      write_in_full(proc.in, sb.buf, sb.len);
 +      close(proc.in);
 +      strbuf_release(&sb);
 +      sigchain_pop(SIGPIPE);
 +      return finish_command(&proc);
 +}
 +
 +void commit_post_rewrite(const struct commit *old_head,
 +                       const struct object_id *new_head)
 +{
 +      struct notes_rewrite_cfg *cfg;
 +
 +      cfg = init_copy_notes_for_rewrite("amend");
 +      if (cfg) {
 +              /* we are amending, so old_head is not NULL */
 +              copy_note_for_rewrite(cfg, &old_head->object.oid, new_head);
 +              finish_copy_notes_for_rewrite(cfg, "Notes added by 'git commit --amend'");
 +      }
 +      run_rewrite_hook(&old_head->object.oid, new_head);
 +}
 +
 +static int run_prepare_commit_msg_hook(struct strbuf *msg, const char *commit)
 +{
 +      struct argv_array hook_env = ARGV_ARRAY_INIT;
 +      int ret;
 +      const char *name;
 +
 +      name = git_path_commit_editmsg();
 +      if (write_message(msg->buf, msg->len, name, 0))
 +              return -1;
 +
 +      argv_array_pushf(&hook_env, "GIT_INDEX_FILE=%s", get_index_file());
 +      argv_array_push(&hook_env, "GIT_EDITOR=:");
 +      if (commit)
 +              ret = run_hook_le(hook_env.argv, "prepare-commit-msg", name,
 +                                "commit", commit, NULL);
 +      else
 +              ret = run_hook_le(hook_env.argv, "prepare-commit-msg", name,
 +                                "message", NULL);
 +      if (ret)
 +              ret = error(_("'prepare-commit-msg' hook failed"));
 +      argv_array_clear(&hook_env);
 +
 +      return ret;
 +}
 +
 +static const char implicit_ident_advice_noconfig[] =
 +N_("Your name and email address were configured automatically based\n"
 +"on your username and hostname. Please check that they are accurate.\n"
 +"You can suppress this message by setting them explicitly. Run the\n"
 +"following command and follow the instructions in your editor to edit\n"
 +"your configuration file:\n"
 +"\n"
 +"    git config --global --edit\n"
 +"\n"
 +"After doing this, you may fix the identity used for this commit with:\n"
 +"\n"
 +"    git commit --amend --reset-author\n");
 +
 +static const char implicit_ident_advice_config[] =
 +N_("Your name and email address were configured automatically based\n"
 +"on your username and hostname. Please check that they are accurate.\n"
 +"You can suppress this message by setting them explicitly:\n"
 +"\n"
 +"    git config --global user.name \"Your Name\"\n"
 +"    git config --global user.email you@example.com\n"
 +"\n"
 +"After doing this, you may fix the identity used for this commit with:\n"
 +"\n"
 +"    git commit --amend --reset-author\n");
 +
 +static const char *implicit_ident_advice(void)
 +{
 +      char *user_config = expand_user_path("~/.gitconfig", 0);
 +      char *xdg_config = xdg_config_home("config");
 +      int config_exists = file_exists(user_config) || file_exists(xdg_config);
 +
 +      free(user_config);
 +      free(xdg_config);
 +
 +      if (config_exists)
 +              return _(implicit_ident_advice_config);
 +      else
 +              return _(implicit_ident_advice_noconfig);
 +
 +}
 +
 +void print_commit_summary(const char *prefix, const struct object_id *oid,
 +                        unsigned int flags)
 +{
 +      struct rev_info rev;
 +      struct commit *commit;
 +      struct strbuf format = STRBUF_INIT;
 +      const char *head;
 +      struct pretty_print_context pctx = {0};
 +      struct strbuf author_ident = STRBUF_INIT;
 +      struct strbuf committer_ident = STRBUF_INIT;
 +
 +      commit = lookup_commit(oid);
 +      if (!commit)
 +              die(_("couldn't look up newly created commit"));
 +      if (parse_commit(commit))
 +              die(_("could not parse newly created commit"));
 +
 +      strbuf_addstr(&format, "format:%h] %s");
 +
 +      format_commit_message(commit, "%an <%ae>", &author_ident, &pctx);
 +      format_commit_message(commit, "%cn <%ce>", &committer_ident, &pctx);
 +      if (strbuf_cmp(&author_ident, &committer_ident)) {
 +              strbuf_addstr(&format, "\n Author: ");
 +              strbuf_addbuf_percentquote(&format, &author_ident);
 +      }
 +      if (flags & SUMMARY_SHOW_AUTHOR_DATE) {
 +              struct strbuf date = STRBUF_INIT;
 +
 +              format_commit_message(commit, "%ad", &date, &pctx);
 +              strbuf_addstr(&format, "\n Date: ");
 +              strbuf_addbuf_percentquote(&format, &date);
 +              strbuf_release(&date);
 +      }
 +      if (!committer_ident_sufficiently_given()) {
 +              strbuf_addstr(&format, "\n Committer: ");
 +              strbuf_addbuf_percentquote(&format, &committer_ident);
 +              if (advice_implicit_identity) {
 +                      strbuf_addch(&format, '\n');
 +                      strbuf_addstr(&format, implicit_ident_advice());
 +              }
 +      }
 +      strbuf_release(&author_ident);
 +      strbuf_release(&committer_ident);
 +
 +      init_revisions(&rev, prefix);
 +      setup_revisions(0, NULL, &rev, NULL);
 +
 +      rev.diff = 1;
 +      rev.diffopt.output_format =
 +              DIFF_FORMAT_SHORTSTAT | DIFF_FORMAT_SUMMARY;
 +
 +      rev.verbose_header = 1;
 +      rev.show_root_diff = 1;
 +      get_commit_format(format.buf, &rev);
 +      rev.always_show_header = 0;
 +      rev.diffopt.detect_rename = DIFF_DETECT_RENAME;
 +      rev.diffopt.break_opt = 0;
 +      diff_setup_done(&rev.diffopt);
 +
 +      head = resolve_ref_unsafe("HEAD", 0, NULL, NULL);
 +      if (!head)
 +              die_errno(_("unable to resolve HEAD after creating commit"));
 +      if (!strcmp(head, "HEAD"))
 +              head = _("detached HEAD");
 +      else
 +              skip_prefix(head, "refs/heads/", &head);
 +      printf("[%s%s ", head, (flags & SUMMARY_INITIAL_COMMIT) ?
 +                                              _(" (root-commit)") : "");
 +
 +      if (!log_tree_commit(&rev, commit)) {
 +              rev.always_show_header = 1;
 +              rev.use_terminator = 1;
 +              log_tree_commit(&rev, commit);
 +      }
 +
 +      strbuf_release(&format);
 +}
 +
 +static int parse_head(struct commit **head)
 +{
 +      struct commit *current_head;
 +      struct object_id oid;
 +
 +      if (get_oid("HEAD", &oid)) {
 +              current_head = NULL;
 +      } else {
 +              current_head = lookup_commit_reference(&oid);
 +              if (!current_head)
 +                      return error(_("could not parse HEAD"));
 +              if (oidcmp(&oid, &current_head->object.oid)) {
 +                      warning(_("HEAD %s is not a commit!"),
 +                              oid_to_hex(&oid));
 +              }
 +              if (parse_commit(current_head))
 +                      return error(_("could not parse HEAD commit"));
 +      }
 +      *head = current_head;
 +
 +      return 0;
 +}
 +
 +/*
 + * Try to commit without forking 'git commit'. In some cases we need
 + * to run 'git commit' to display an error message
 + *
 + * Returns:
 + *  -1 - error unable to commit
 + *   0 - success
 + *   1 - run 'git commit'
 + */
 +static int try_to_commit(struct strbuf *msg, const char *author,
 +                       struct replay_opts *opts, unsigned int flags,
 +                       struct object_id *oid)
 +{
 +      struct object_id tree;
 +      struct commit *current_head;
 +      struct commit_list *parents = NULL;
 +      struct commit_extra_header *extra = NULL;
 +      struct strbuf err = STRBUF_INIT;
 +      struct strbuf commit_msg = STRBUF_INIT;
 +      char *amend_author = NULL;
 +      const char *hook_commit = NULL;
 +      enum commit_msg_cleanup_mode cleanup;
 +      int res = 0;
 +
 +      if (parse_head(&current_head))
 +              return -1;
 +
 +      if (flags & AMEND_MSG) {
 +              const char *exclude_gpgsig[] = { "gpgsig", NULL };
 +              const char *out_enc = get_commit_output_encoding();
 +              const char *message = logmsg_reencode(current_head, NULL,
 +                                                    out_enc);
 +
 +              if (!msg) {
 +                      const char *orig_message = NULL;
 +
 +                      find_commit_subject(message, &orig_message);
 +                      msg = &commit_msg;
 +                      strbuf_addstr(msg, orig_message);
 +                      hook_commit = "HEAD";
 +              }
 +              author = amend_author = get_author(message);
 +              unuse_commit_buffer(current_head, message);
 +              if (!author) {
 +                      res = error(_("unable to parse commit author"));
 +                      goto out;
 +              }
 +              parents = copy_commit_list(current_head->parents);
 +              extra = read_commit_extra_headers(current_head, exclude_gpgsig);
 +      } else if (current_head) {
 +              commit_list_insert(current_head, &parents);
 +      }
 +
 +      if (write_cache_as_tree(tree.hash, 0, NULL)) {
 +              res = error(_("git write-tree failed to write a tree"));
 +              goto out;
 +      }
 +
 +      if (!(flags & ALLOW_EMPTY) && !oidcmp(current_head ?
 +                                            &current_head->tree->object.oid :
 +                                            &empty_tree_oid, &tree)) {
 +              res = 1; /* run 'git commit' to display error message */
 +              goto out;
 +      }
 +
 +      if (find_hook("prepare-commit-msg")) {
 +              res = run_prepare_commit_msg_hook(msg, hook_commit);
 +              if (res)
 +                      goto out;
 +              if (strbuf_read_file(&commit_msg, git_path_commit_editmsg(),
 +                                   2048) < 0) {
 +                      res = error_errno(_("unable to read commit message "
 +                                            "from '%s'"),
 +                                          git_path_commit_editmsg());
 +                      goto out;
 +              }
 +              msg = &commit_msg;
 +      }
 +
 +      cleanup = (flags & CLEANUP_MSG) ? COMMIT_MSG_CLEANUP_ALL :
 +                                        opts->default_msg_cleanup;
 +
 +      if (cleanup != COMMIT_MSG_CLEANUP_NONE)
 +              strbuf_stripspace(msg, cleanup == COMMIT_MSG_CLEANUP_ALL);
 +      if (!opts->allow_empty_message && message_is_empty(msg, cleanup)) {
 +              res = 1; /* run 'git commit' to display error message */
 +              goto out;
 +      }
 +
++      if (commit_tree_extended(msg->buf, msg->len, &tree, parents,
++                               oid, author, opts->gpg_sign, extra)) {
 +              res = error(_("failed to write commit object"));
 +              goto out;
 +      }
 +
 +      if (update_head_with_reflog(current_head, oid,
 +                                  getenv("GIT_REFLOG_ACTION"), msg, &err)) {
 +              res = error("%s", err.buf);
 +              goto out;
 +      }
 +
 +      if (flags & AMEND_MSG)
 +              commit_post_rewrite(current_head, oid);
 +
 +out:
 +      free_commit_extra_headers(extra);
 +      strbuf_release(&err);
 +      strbuf_release(&commit_msg);
 +      free(amend_author);
 +
 +      return res;
 +}
 +
 +static int do_commit(const char *msg_file, const char *author,
 +                   struct replay_opts *opts, unsigned int flags)
 +{
 +      int res = 1;
 +
 +      if (!(flags & EDIT_MSG) && !(flags & VERIFY_MSG)) {
 +              struct object_id oid;
 +              struct strbuf sb = STRBUF_INIT;
 +
 +              if (msg_file && strbuf_read_file(&sb, msg_file, 2048) < 0)
 +                      return error_errno(_("unable to read commit message "
 +                                           "from '%s'"),
 +                                         msg_file);
 +
 +              res = try_to_commit(msg_file ? &sb : NULL, author, opts, flags,
 +                                  &oid);
 +              strbuf_release(&sb);
 +              if (!res) {
 +                      unlink(git_path_cherry_pick_head());
 +                      unlink(git_path_merge_msg());
 +                      if (!is_rebase_i(opts))
 +                              print_commit_summary(NULL, &oid,
 +                                              SUMMARY_SHOW_AUTHOR_DATE);
 +                      return res;
 +              }
 +      }
 +      if (res == 1)
 +              return run_git_commit(msg_file, opts, flags);
 +
 +      return res;
 +}
 +
  static int is_original_commit_empty(struct commit *commit)
  {
        const struct object_id *ptree_oid;
diff --cc sha1_file.c
@@@ -1579,14 -1556,11 +1580,14 @@@ static int write_loose_object(const str
        unsigned char compressed[4096];
        git_zstream stream;
        git_SHA_CTX c;
-       unsigned char parano_sha1[20];
+       struct object_id parano_oid;
        static struct strbuf tmp_file = STRBUF_INIT;
 -      const char *filename = sha1_file_name(oid->hash);
 +      static struct strbuf filename = STRBUF_INIT;
 +
 +      strbuf_reset(&filename);
-       sha1_file_name(&filename, sha1);
++      sha1_file_name(&filename, oid->hash);
  
 -      fd = create_tmpfile(&tmp_file, filename);
 +      fd = create_tmpfile(&tmp_file, filename.buf);
        if (fd < 0) {
                if (errno == EACCES)
                        return error("insufficient permission for adding an object to repository database %s", get_object_directory());
@@@ -1813,14 -1792,14 +1819,14 @@@ static int index_stream_convert_blob(st
        assert(would_convert_to_git_filter_fd(path));
  
        convert_to_git_filter_fd(&the_index, path, fd, &sbuf,
 -                               get_safe_crlf(flags));
 +                               get_conv_flags(flags));
  
        if (write_object)
-               ret = write_sha1_file(sbuf.buf, sbuf.len, typename(OBJ_BLOB),
-                                     oid->hash);
+               ret = write_object_file(sbuf.buf, sbuf.len, typename(OBJ_BLOB),
+                                       oid);
        else
-               ret = hash_sha1_file(sbuf.buf, sbuf.len, typename(OBJ_BLOB),
-                                    oid->hash);
+               ret = hash_object_file(sbuf.buf, sbuf.len, typename(OBJ_BLOB),
+                                      oid);
        strbuf_release(&sbuf);
        return ret;
  }