Merge branch 'wh/author-committer-ident-config'
authorJunio C Hamano <gitster@pobox.com>
Thu, 7 Mar 2019 00:59:53 +0000 (09:59 +0900)
committerJunio C Hamano <gitster@pobox.com>
Thu, 7 Mar 2019 00:59:53 +0000 (09:59 +0900)
Four new configuration variables {author,committer}.{name,email}
have been introduced to override user.{name,email} in more specific
cases.

* wh/author-committer-ident-config:
config: allow giving separate author and committer idents

1  2 
blame.c
builtin/am.c
builtin/commit.c
cache.h
config.c
log-tree.c
sequencer.c
diff --combined blame.c
index da57233cbbd98d41bdfeba46e861b1f5f61dfbe2,c9c351eb3676adbcd390375b10b5f227fc5ca337..5c07dec1903545738642c17e94cc1fa060ba15d3
+++ b/blame.c
@@@ -188,7 -188,7 +188,7 @@@ static struct commit *fake_working_tree
        unsigned mode;
        struct strbuf msg = STRBUF_INIT;
  
 -      read_index(r->index);
 +      repo_read_index(r);
        time(&now);
        commit = alloc_commit_node(r);
        commit->object.parsed = 1;
  
        origin = make_origin(commit, path);
  
-       ident = fmt_ident("Not Committed Yet", "not.committed.yet", NULL, 0);
+       ident = fmt_ident("Not Committed Yet", "not.committed.yet",
+                       WANT_BLANK_IDENT, NULL, 0);
        strbuf_addstr(&msg, "tree 0000000000000000000000000000000000000000\n");
        for (parent = commit->parents; parent; parent = parent->next)
                strbuf_addf(&msg, "parent %s\n",
         * want to run "diff-index --cached".
         */
        discard_index(r->index);
 -      read_index(r->index);
 +      repo_read_index(r);
  
        len = strlen(path);
        if (!mode) {
diff --combined builtin/am.c
index 58a2aef28bbcd715660422dc37042e79d4d350c1,3727d4d267655ea6b98cbff3456948983251e081..cd051fecdfc8e178496a698d9c7e7df5a6dd894e
@@@ -3,7 -3,6 +3,7 @@@
   *
   * Based on git-am.sh by Junio C Hamano.
   */
 +#define USE_THE_INDEX_COMPATIBILITY_MACROS
  #include "cache.h"
  #include "config.h"
  #include "builtin.h"
  #include "packfile.h"
  #include "repository.h"
  
 -/**
 - * Returns 1 if the file is empty or does not exist, 0 otherwise.
 - */
 -static int is_empty_file(const char *filename)
 -{
 -      struct stat st;
 -
 -      if (stat(filename, &st) < 0) {
 -              if (errno == ENOENT)
 -                      return 1;
 -              die_errno(_("could not stat %s"), filename);
 -      }
 -
 -      return !st.st_size;
 -}
 -
  /**
   * Returns the length of the first line of msg.
   */
@@@ -512,7 -527,7 +512,7 @@@ static int copy_notes_for_rebase(const 
        }
  
  finish:
 -      finish_copy_notes_for_rewrite(c, msg);
 +      finish_copy_notes_for_rewrite(the_repository, c, msg);
        fclose(fp);
        strbuf_release(&sb);
        return ret;
@@@ -1205,7 -1220,7 +1205,7 @@@ static int parse_mail(struct am_state *
                goto finish;
        }
  
 -      if (is_empty_file(am_path(state, "patch"))) {
 +      if (is_empty_or_missing_file(am_path(state, "patch"))) {
                printf_ln(_("Patch is empty."));
                die_user_resolve(state);
        }
@@@ -1530,7 -1545,7 +1530,7 @@@ static int fall_back_threeway(const str
         * changes.
         */
  
 -      init_merge_options(&o);
 +      init_merge_options(&o, the_repository);
  
        o.branch1 = "HEAD";
        their_tree_name = xstrfmt("%.*s", linelen(state->msg), state->msg);
@@@ -1579,6 -1594,7 +1579,7 @@@ static void do_commit(const struct am_s
        }
  
        author = fmt_ident(state->author_name, state->author_email,
+               WANT_AUTHOR_IDENT,
                        state->ignore_date ? NULL : state->author_date,
                        IDENT_STRICT);
  
@@@ -1704,7 -1720,7 +1705,7 @@@ static void am_run(struct am_state *sta
  
        refresh_and_write_cache();
  
 -      if (index_has_changes(&the_index, NULL, &sb)) {
 +      if (repo_index_has_changes(the_repository, NULL, &sb)) {
                write_state_bool(state, "dirtyindex", 1);
                die(_("Dirty index: cannot apply patches (dirty: %s)"), sb.buf);
        }
                         * the result may have produced the same tree as ours.
                         */
                        if (!apply_status &&
 -                          !index_has_changes(&the_index, NULL, NULL)) {
 +                          !repo_index_has_changes(the_repository, NULL, NULL)) {
                                say(state, stdout, _("No changes -- Patch already applied."));
                                goto next;
                        }
@@@ -1788,7 -1804,7 +1789,7 @@@ next
                resume = 0;
        }
  
 -      if (!is_empty_file(am_path(state, "rewritten"))) {
 +      if (!is_empty_or_missing_file(am_path(state, "rewritten"))) {
                assert(state->rebasing);
                copy_notes_for_rebase(state);
                run_post_rewrite_hook(state);
@@@ -1816,7 -1832,7 +1817,7 @@@ static void am_resolve(struct am_state 
  
        say(state, stdout, _("Applying: %.*s"), linelen(state->msg), state->msg);
  
 -      if (!index_has_changes(&the_index, NULL, NULL)) {
 +      if (!repo_index_has_changes(the_repository, NULL, NULL)) {
                printf_ln(_("No changes - did you forget to use 'git add'?\n"
                        "If there is nothing left to stage, chances are that something else\n"
                        "already introduced the same changes; you might want to skip this patch."));
@@@ -1985,15 -2001,6 +1986,15 @@@ static void am_skip(struct am_state *st
        if (clean_index(&head, &head))
                die(_("failed to clean index"));
  
 +      if (state->rebasing) {
 +              FILE *fp = xfopen(am_path(state, "rewritten"), "a");
 +
 +              assert(!is_null_oid(&state->orig_commit));
 +              fprintf(fp, "%s ", oid_to_hex(&state->orig_commit));
 +              fprintf(fp, "%s\n", oid_to_hex(&head));
 +              fclose(fp);
 +      }
 +
        am_next(state);
        am_load(state);
        am_run(state, 0);
@@@ -2272,7 -2279,7 +2273,7 @@@ int cmd_am(int argc, const char **argv
        /* Ensure a valid committer ident can be constructed */
        git_committer_info(IDENT_STRICT);
  
 -      if (read_index_preload(&the_index, NULL, 0) < 0)
 +      if (repo_read_index_preload(the_repository, NULL, 0) < 0)
                die(_("failed to read the index"));
  
        if (in_progress) {
diff --combined builtin/commit.c
index 2986553d5ffb97f0798e4d4eb921073439fb9a92,f96b90daeb5390b44fd9cef403a6048609fbad66..8d7a613fda3595380a84d97bbaa7c203954e8dd0
@@@ -5,7 -5,6 +5,7 @@@
   * Based on git-commit.sh by Junio C Hamano and Linus Torvalds
   */
  
 +#define USE_THE_INDEX_COMPATIBILITY_MACROS
  #include "cache.h"
  #include "config.h"
  #include "lockfile.h"
@@@ -352,7 -351,7 +352,7 @@@ static const char *prepare_index(int ar
                if (write_locked_index(&the_index, &index_lock, 0))
                        die(_("unable to create temporary index"));
  
 -              old_index_env = getenv(INDEX_ENVIRONMENT);
 +              old_index_env = xstrdup_or_null(getenv(INDEX_ENVIRONMENT));
                setenv(INDEX_ENVIRONMENT, get_lock_file_path(&index_lock), 1);
  
                if (interactive_add(argc, argv, prefix, patch_interactive) != 0)
                        setenv(INDEX_ENVIRONMENT, old_index_env, 1);
                else
                        unsetenv(INDEX_ENVIRONMENT);
 +              FREE_AND_NULL(old_index_env);
  
                discard_cache();
                read_cache_from(get_lock_file_path(&index_lock));
@@@ -609,7 -607,8 +609,8 @@@ static void determine_author_info(struc
                set_ident_var(&date, strbuf_detach(&date_buf, NULL));
        }
  
-       strbuf_addstr(author_ident, fmt_ident(name, email, date, IDENT_STRICT));
+       strbuf_addstr(author_ident, fmt_ident(name, email, WANT_AUTHOR_IDENT, date,
+                               IDENT_STRICT));
        assert_split_ident(&author, author_ident);
        export_one("GIT_AUTHOR_NAME", author.name_begin, author.name_end, 0);
        export_one("GIT_AUTHOR_EMAIL", author.mail_begin, author.mail_end, 0);
@@@ -1369,7 -1368,7 +1370,7 @@@ int cmd_status(int argc, const char **a
        if (status_format != STATUS_FORMAT_PORCELAIN &&
            status_format != STATUS_FORMAT_PORCELAIN_V2)
                progress_flag = REFRESH_PROGRESS;
 -      read_index(&the_index);
 +      repo_read_index(the_repository);
        refresh_index(&the_index,
                      REFRESH_QUIET|REFRESH_UNMERGED|progress_flag,
                      &s.pathspec, NULL, NULL);
        wt_status_collect(&s);
  
        if (0 <= fd)
 -              update_index_if_able(&the_index, &index_lock);
 +              repo_update_index_if_able(the_repository, &index_lock);
  
        if (s.relative_paths)
                s.prefix = prefix;
@@@ -1676,7 -1675,7 +1677,7 @@@ int cmd_commit(int argc, const char **a
        run_command_v_opt(argv_gc_auto, RUN_GIT_CMD);
        run_commit_hook(use_editor, get_index_file(), "post-commit", NULL);
        if (amend && !no_post_rewrite) {
 -              commit_post_rewrite(current_head, &oid);
 +              commit_post_rewrite(the_repository, current_head, &oid);
        }
        if (!quiet) {
                unsigned int flags = 0;
diff --combined cache.h
index 473fa1eff10acf6f6e8357c6dabff6289883cdd0,bb78eb9a3aefd377c5d73325793f0453cb427dc4..bff556e7720b2aec7c2824b7101a0c5bd175551b
+++ b/cache.h
@@@ -45,20 -45,10 +45,20 @@@ unsigned long git_deflate_bound(git_zst
  /* The length in bytes and in hex digits of an object name (SHA-1 value). */
  #define GIT_SHA1_RAWSZ 20
  #define GIT_SHA1_HEXSZ (2 * GIT_SHA1_RAWSZ)
 +/* The block size of SHA-1. */
 +#define GIT_SHA1_BLKSZ 64
 +
 +/* The length in bytes and in hex digits of an object name (SHA-256 value). */
 +#define GIT_SHA256_RAWSZ 32
 +#define GIT_SHA256_HEXSZ (2 * GIT_SHA256_RAWSZ)
 +/* The block size of SHA-256. */
 +#define GIT_SHA256_BLKSZ 64
  
  /* The length in byte and in hex digits of the largest possible hash value. */
 -#define GIT_MAX_RAWSZ GIT_SHA1_RAWSZ
 -#define GIT_MAX_HEXSZ GIT_SHA1_HEXSZ
 +#define GIT_MAX_RAWSZ GIT_SHA256_RAWSZ
 +#define GIT_MAX_HEXSZ GIT_SHA256_HEXSZ
 +/* The largest possible block size for any supported hash. */
 +#define GIT_MAX_BLKSZ GIT_SHA256_BLKSZ
  
  struct object_id {
        unsigned char hash[GIT_MAX_RAWSZ];
@@@ -348,6 -338,8 +348,6 @@@ struct index_state 
        struct mem_pool *ce_mem_pool;
  };
  
 -extern struct index_state the_index;
 -
  /* Name hashing */
  extern int test_lazy_init_name_hash(struct index_state *istate, int try_threaded);
  extern void add_name_hash(struct index_state *istate, struct cache_entry *ce);
@@@ -409,20 -401,18 +409,20 @@@ struct cache_entry *dup_cache_entry(con
   */
  void validate_cache_entries(const struct index_state *istate);
  
 -#ifndef NO_THE_INDEX_COMPATIBILITY_MACROS
 +#ifdef USE_THE_INDEX_COMPATIBILITY_MACROS
 +extern struct index_state the_index;
 +
  #define active_cache (the_index.cache)
  #define active_nr (the_index.cache_nr)
  #define active_alloc (the_index.cache_alloc)
  #define active_cache_changed (the_index.cache_changed)
  #define active_cache_tree (the_index.cache_tree)
  
 -#define read_cache() read_index(&the_index)
 +#define read_cache() repo_read_index(the_repository)
  #define read_cache_from(path) read_index_from(&the_index, (path), (get_git_dir()))
 -#define read_cache_preload(pathspec) read_index_preload(&the_index, (pathspec), 0)
 +#define read_cache_preload(pathspec) repo_read_index_preload(the_repository, (pathspec), 0)
  #define is_cache_unborn() is_index_unborn(&the_index)
 -#define read_cache_unmerged() read_index_unmerged(&the_index)
 +#define read_cache_unmerged() repo_read_index_unmerged(the_repository)
  #define discard_cache() discard_index(&the_index)
  #define unmerged_cache() unmerged_index(&the_index)
  #define cache_name_pos(name, namelen) index_name_pos(&the_index,(name),(namelen))
  #define unmerge_cache_entry_at(at) unmerge_index_entry_at(&the_index, at)
  #define unmerge_cache(pathspec) unmerge_index(&the_index, pathspec)
  #define read_blob_data_from_cache(path, sz) read_blob_data_from_index(&the_index, (path), (sz))
 +#define hold_locked_index(lock_file, flags) repo_hold_locked_index(the_repository, (lock_file), (flags))
  #endif
  
  #define TYPE_BITS 3
@@@ -671,14 -660,19 +671,14 @@@ extern int daemonize(void)
  
  /* Initialize and use the cache information */
  struct lock_file;
 -extern int read_index(struct index_state *);
  extern void preload_index(struct index_state *index,
                          const struct pathspec *pathspec,
                          unsigned int refresh_flags);
 -extern int read_index_preload(struct index_state *,
 -                            const struct pathspec *pathspec,
 -                            unsigned int refresh_flags);
  extern int do_read_index(struct index_state *istate, const char *path,
                         int must_exist); /* for testting only! */
  extern int read_index_from(struct index_state *, const char *path,
                           const char *gitdir);
  extern int is_index_unborn(struct index_state *);
 -extern int read_index_unmerged(struct index_state *);
  
  /* For use with `write_locked_index()`. */
  #define COMMIT_LOCK           (1 << 0)
@@@ -716,9 -710,9 +716,9 @@@ extern int unmerged_index(const struct 
   * provided, the space-separated list of files that differ will be appended
   * to it.
   */
 -extern int index_has_changes(struct index_state *istate,
 -                           struct tree *tree,
 -                           struct strbuf *sb);
 +extern int repo_index_has_changes(struct repository *repo,
 +                                struct tree *tree,
 +                                struct strbuf *sb);
  
  extern int verify_path(const char *path, unsigned mode);
  extern int strcmp_offset(const char *s1, const char *s2, size_t *first_change);
@@@ -751,14 -745,13 +751,14 @@@ extern int index_name_pos(const struct 
  #define ADD_CACHE_JUST_APPEND 8               /* Append only; tree.c::read_tree() */
  #define ADD_CACHE_NEW_ONLY 16         /* Do not replace existing ones */
  #define ADD_CACHE_KEEP_CACHE_TREE 32  /* Do not invalidate cache-tree */
 +#define ADD_CACHE_RENORMALIZE 64        /* Pass along HASH_RENORMALIZE */
  extern int add_index_entry(struct index_state *, struct cache_entry *ce, int option);
  extern void rename_index_entry_at(struct index_state *, int pos, const char *new_name);
  
  /* Remove entry, return true if there are more entries to go. */
  extern int remove_index_entry_at(struct index_state *, int pos);
  
 -extern void remove_marked_cache_entries(struct index_state *istate);
 +extern void remove_marked_cache_entries(struct index_state *istate, int invalidate);
  extern int remove_file_from_index(struct index_state *, const char *path);
  #define ADD_CACHE_VERBOSE 1
  #define ADD_CACHE_PRETEND 2
@@@ -834,6 -827,13 +834,6 @@@ extern void fill_stat_cache_info(struc
  extern int refresh_index(struct index_state *, unsigned int flags, const struct pathspec *pathspec, char *seen, const char *header_msg);
  extern struct cache_entry *refresh_cache_entry(struct index_state *, struct cache_entry *, unsigned int);
  
 -/*
 - * Opportunistically update the index but do not complain if we can't.
 - * The lockfile is always committed or rolled back.
 - */
 -extern void update_index_if_able(struct index_state *, struct lock_file *);
 -
 -extern int hold_locked_index(struct lock_file *, int);
  extern void set_alternate_index_output(const char *);
  
  extern int verify_index_checksum;
@@@ -1028,12 -1028,16 +1028,12 @@@ extern const struct object_id null_oid
  static inline int hashcmp(const unsigned char *sha1, const unsigned char *sha2)
  {
        /*
 -       * This is a temporary optimization hack. By asserting the size here,
 -       * we let the compiler know that it's always going to be 20, which lets
 -       * it turn this fixed-size memcmp into a few inline instructions.
 -       *
 -       * This will need to be extended or ripped out when we learn about
 -       * hashes of different sizes.
 +       * Teach the compiler that there are only two possibilities of hash size
 +       * here, so that it can optimize for this case as much as possible.
         */
 -      if (the_hash_algo->rawsz != 20)
 -              BUG("hash size not yet supported by hashcmp");
 -      return memcmp(sha1, sha2, the_hash_algo->rawsz);
 +      if (the_hash_algo->rawsz == GIT_MAX_RAWSZ)
 +              return memcmp(sha1, sha2, GIT_MAX_RAWSZ);
 +      return memcmp(sha1, sha2, GIT_SHA1_RAWSZ);
  }
  
  static inline int oidcmp(const struct object_id *oid1, const struct object_id *oid2)
  
  static inline int hasheq(const unsigned char *sha1, const unsigned char *sha2)
  {
 -      return !hashcmp(sha1, sha2);
 +      /*
 +       * We write this here instead of deferring to hashcmp so that the
 +       * compiler can properly inline it and avoid calling memcmp.
 +       */
 +      if (the_hash_algo->rawsz == GIT_MAX_RAWSZ)
 +              return !memcmp(sha1, sha2, GIT_MAX_RAWSZ);
 +      return !memcmp(sha1, sha2, GIT_SHA1_RAWSZ);
  }
  
  static inline int oideq(const struct object_id *oid1, const struct object_id *oid2)
@@@ -1074,7 -1072,7 +1074,7 @@@ static inline void hashcpy(unsigned cha
  
  static inline void oidcpy(struct object_id *dst, const struct object_id *src)
  {
 -      hashcpy(dst->hash, src->hash);
 +      memcpy(dst->hash, src->hash, GIT_MAX_RAWSZ);
  }
  
  static inline struct object_id *oiddup(const struct object_id *src)
@@@ -1271,8 -1269,8 +1271,8 @@@ extern char *xdg_cache_home(const char 
  
  extern int git_open_cloexec(const char *name, int flags);
  #define git_open(name) git_open_cloexec(name, O_RDONLY)
 -extern int unpack_sha1_header(git_zstream *stream, unsigned char *map, unsigned long mapsize, void *buffer, unsigned long bufsiz);
 -extern int parse_sha1_header(const char *hdr, unsigned long *sizep);
 +extern int unpack_loose_header(git_zstream *stream, unsigned char *map, unsigned long mapsize, void *buffer, unsigned long bufsiz);
 +extern int parse_loose_header(const char *hdr, unsigned long *sizep);
  
  extern int check_object_signature(const struct object_id *oid, void *buf, unsigned long size, const char *type);
  
@@@ -1334,24 -1332,6 +1334,24 @@@ struct object_context 
        GET_OID_TREE | GET_OID_TREEISH | \
        GET_OID_BLOB)
  
 +enum get_oid_result {
 +      FOUND = 0,
 +      MISSING_OBJECT = -1, /* The requested object is missing */
 +      SHORT_NAME_AMBIGUOUS = -2,
 +      /* The following only apply when symlinks are followed */
 +      DANGLING_SYMLINK = -4, /*
 +                              * The initial symlink is there, but
 +                              * (transitively) points to a missing
 +                              * in-tree file
 +                              */
 +      SYMLINK_LOOP = -5,
 +      NOT_DIR = -6, /*
 +                     * Somewhere along the symlink chain, a path is
 +                     * requested which contains a file as a
 +                     * non-final element.
 +                     */
 +};
 +
  extern int get_oid(const char *str, struct object_id *oid);
  extern int get_oid_commit(const char *str, struct object_id *oid);
  extern int get_oid_committish(const char *str, struct object_id *oid);
@@@ -1359,9 -1339,8 +1359,9 @@@ extern int get_oid_tree(const char *str
  extern int get_oid_treeish(const char *str, struct object_id *oid);
  extern int get_oid_blob(const char *str, struct object_id *oid);
  extern void maybe_die_on_misspelt_object_name(const char *name, const char *prefix);
 -extern int get_oid_with_context(const char *str, unsigned flags, struct object_id *oid, struct object_context *oc);
 -
 +extern enum get_oid_result get_oid_with_context(struct repository *repo, const char *str,
 +                              unsigned flags, struct object_id *oid,
 +                              struct object_context *oc);
  
  typedef int each_abbrev_fn(const struct object_id *oid, void *);
  extern int for_each_abbrev(const char *prefix, each_abbrev_fn, void *);
@@@ -1386,9 -1365,9 +1386,9 @@@ extern int get_oid_hex(const char *hex
  extern int hex_to_bytes(unsigned char *binary, const char *hex, size_t len);
  
  /*
 - * Convert a binary sha1 to its hex equivalent. The `_r` variant is reentrant,
 + * Convert a binary hash to its hex equivalent. The `_r` variant is reentrant,
   * and writes the NUL-terminated output to the buffer `out`, which must be at
 - * least `GIT_SHA1_HEXSZ + 1` bytes, and returns a pointer to out for
 + * least `GIT_MAX_HEXSZ + 1` bytes, and returns a pointer to out for
   * convenience.
   *
   * The non-`_r` variant returns a static buffer, but uses a ring of 4
   *
   *   printf("%s -> %s", sha1_to_hex(one), sha1_to_hex(two));
   */
 -extern char *sha1_to_hex_r(char *out, const unsigned char *sha1);
 -extern char *oid_to_hex_r(char *out, const struct object_id *oid);
 -extern char *sha1_to_hex(const unsigned char *sha1);  /* static buffer result! */
 -extern char *oid_to_hex(const struct object_id *oid); /* same static buffer as sha1_to_hex */
 +char *hash_to_hex_algop_r(char *buffer, const unsigned char *hash, const struct git_hash_algo *);
 +char *sha1_to_hex_r(char *out, const unsigned char *sha1);
 +char *oid_to_hex_r(char *out, const struct object_id *oid);
 +char *hash_to_hex_algop(const unsigned char *hash, const struct git_hash_algo *);     /* static buffer result! */
 +char *sha1_to_hex(const unsigned char *sha1);                                         /* same static buffer */
 +char *hash_to_hex(const unsigned char *hash);                                         /* same static buffer */
 +char *oid_to_hex(const struct object_id *oid);                                                /* same static buffer */
  
  /*
   * Parse a 40-character hexadecimal object ID starting from hex, updating the
@@@ -1463,7 -1439,6 +1463,7 @@@ extern struct object *peel_to_type(cons
  
  enum date_mode_type {
        DATE_NORMAL = 0,
 +      DATE_HUMAN,
        DATE_RELATIVE,
        DATE_SHORT,
        DATE_ISO8601,
@@@ -1489,9 -1464,7 +1489,9 @@@ struct date_mode 
  struct date_mode *date_mode_from_type(enum date_mode_type type);
  
  const char *show_date(timestamp_t time, int timezone, const struct date_mode *mode);
 -void show_date_relative(timestamp_t time, int tz, const struct timeval *now,
 +void show_date_relative(timestamp_t time, const struct timeval *now,
 +                      struct strbuf *timebuf);
 +void show_date_human(timestamp_t time, int tz, const struct timeval *now,
                        struct strbuf *timebuf);
  int parse_date(const char *date, struct strbuf *out);
  int parse_date_basic(const char *date, timestamp_t *timestamp, int *offset);
@@@ -1506,10 -1479,19 +1506,19 @@@ int date_overflows(timestamp_t date)
  #define IDENT_STRICT         1
  #define IDENT_NO_DATE        2
  #define IDENT_NO_NAME        4
+ enum want_ident {
+       WANT_BLANK_IDENT,
+       WANT_AUTHOR_IDENT,
+       WANT_COMMITTER_IDENT
+ };
  extern const char *git_author_info(int);
  extern const char *git_committer_info(int);
- extern const char *fmt_ident(const char *name, const char *email, const char *date_str, int);
- extern const char *fmt_name(const char *name, const char *email);
+ extern const char *fmt_ident(const char *name, const char *email,
+               enum want_ident whose_ident,
+               const char *date_str, int);
+ extern const char *fmt_name(enum want_ident);
  extern const char *ident_default_name(void);
  extern const char *ident_default_email(void);
  extern const char *git_editor(void);
@@@ -1569,11 -1551,6 +1578,11 @@@ struct checkout 
  extern int checkout_entry(struct cache_entry *ce, const struct checkout *state, char *topath, int *nr_checkouts);
  extern void enable_delayed_checkout(struct checkout *state);
  extern int finish_delayed_checkout(struct checkout *state, int *nr_checkouts);
 +/*
 + * Unlink the last component and schedule the leading directories for
 + * removal, such that empty directories get removed.
 + */
 +extern void unlink_entry(const struct cache_entry *ce);
  
  struct cache_def {
        struct strbuf path;
@@@ -1624,7 -1601,7 +1633,7 @@@ extern int odb_mkstemp(struct strbuf *t
  extern int odb_pack_keep(const char *name);
  
  /*
 - * Set this to 0 to prevent sha1_object_info_extended() from fetching missing
 + * Set this to 0 to prevent oid_object_info_extended() from fetching missing
   * blobs. This has a difference only if extensions.partialClone is set.
   *
   * Its default value is 1.
@@@ -1820,7 -1797,4 +1829,7 @@@ void safe_create_dir(const char *dir, i
   */
  extern int print_sha1_ellipsis(void);
  
 +/* Return 1 if the file is empty or does not exists, 0 otherwise. */
 +extern int is_empty_or_missing_file(const char *filename);
 +
  #endif /* CACHE_H */
diff --combined config.c
index 24ad1a985400168e33778781d01d6e9e6c6ededf,fd36db77901ccaae9c91a933d98d12bd766cdc8b..921f73dc962e578e9aed7ae11ae6746f4f6b75c8
+++ b/config.c
@@@ -1445,7 -1445,9 +1445,9 @@@ int git_default_config(const char *var
        if (starts_with(var, "core."))
                return git_default_core_config(var, value, cb);
  
-       if (starts_with(var, "user."))
+       if (starts_with(var, "user.") ||
+           starts_with(var, "author.") ||
+           starts_with(var, "committer."))
                return git_ident_config(var, value, cb);
  
        if (starts_with(var, "i18n."))
@@@ -2565,6 -2567,7 +2567,6 @@@ static ssize_t write_pair(int fd, cons
   * entry (which all are to be removed).
   */
  static void maybe_remove_section(struct config_store_data *store,
 -                               const char *contents,
                                 size_t *begin_offset, size_t *end_offset,
                                 int *seen_ptr)
  {
@@@ -2849,7 -2852,7 +2851,7 @@@ int git_config_set_multivar_in_file_gen
                                replace_end = store.parsed[j].end;
                                copy_end = store.parsed[j].begin;
                                if (!value)
 -                                      maybe_remove_section(&store, contents,
 +                                      maybe_remove_section(&store,
                                                             &copy_end,
                                                             &replace_end, &i);
                                /*
diff --combined log-tree.c
index 3cb14256ec5b7a2712e23b8feb12b1a91328bc34,43ef4f430099c6c64904677690912bb9ad96d841..1e56df62a79c0d221fa55ba351b6b16f8027d12b
@@@ -687,8 -687,7 +687,7 @@@ void show_log(struct rev_info *opt
         */
        if (ctx.need_8bit_cte >= 0 && opt->add_signoff)
                ctx.need_8bit_cte =
-                       has_non_ascii(fmt_name(getenv("GIT_COMMITTER_NAME"),
-                                              getenv("GIT_COMMITTER_EMAIL")));
+                       has_non_ascii(fmt_name(WANT_COMMITTER_IDENT));
        ctx.date_mode = opt->date_mode;
        ctx.date_mode_explicit = opt->date_mode_explicit;
        ctx.abbrev = opt->diffopt.abbrev;
        ctx.color = opt->diffopt.use_color;
        ctx.expand_tabs_in_log = opt->expand_tabs_in_log;
        ctx.output_encoding = get_log_output_encoding();
 +      ctx.rev = opt;
        if (opt->from_ident.mail_begin && opt->from_ident.name_begin)
                ctx.from_ident = &opt->from_ident;
        if (opt->graph)
diff --combined sequencer.c
index 0db410d59023e4b2fdd21bc342872324e7c2e7b3,3505d52bb99a6429607ec363d2731cfaf0c1c011..3209cdefd1d9287ecd8c077cc254fd63a600112c
@@@ -35,7 -35,7 +35,7 @@@
  
  #define GIT_REFLOG_ACTION "GIT_REFLOG_ACTION"
  
 -const char sign_off_header[] = "Signed-off-by: ";
 +static const char sign_off_header[] = "Signed-off-by: ";
  static const char cherry_picked_prefix[] = "(cherry picked from commit ";
  
  GIT_PATH_FUNC(git_path_commit_editmsg, "COMMIT_EDITMSG")
@@@ -150,7 -150,6 +150,7 @@@ static GIT_PATH_FUNC(rebase_path_refs_t
  static GIT_PATH_FUNC(rebase_path_gpg_sign_opt, "rebase-merge/gpg_sign_opt")
  static GIT_PATH_FUNC(rebase_path_orig_head, "rebase-merge/orig-head")
  static GIT_PATH_FUNC(rebase_path_verbose, "rebase-merge/verbose")
 +static GIT_PATH_FUNC(rebase_path_quiet, "rebase-merge/quiet")
  static GIT_PATH_FUNC(rebase_path_signoff, "rebase-merge/signoff")
  static GIT_PATH_FUNC(rebase_path_head_name, "rebase-merge/head-name")
  static GIT_PATH_FUNC(rebase_path_onto, "rebase-merge/onto")
@@@ -158,7 -157,7 +158,7 @@@ static GIT_PATH_FUNC(rebase_path_autost
  static GIT_PATH_FUNC(rebase_path_strategy, "rebase-merge/strategy")
  static GIT_PATH_FUNC(rebase_path_strategy_opts, "rebase-merge/strategy_opts")
  static GIT_PATH_FUNC(rebase_path_allow_rerere_autoupdate, "rebase-merge/allow_rerere_autoupdate")
 -static GIT_PATH_FUNC(rebase_path_quiet, "rebase-merge/quiet")
 +static GIT_PATH_FUNC(rebase_path_reschedule_failed_exec, "rebase-merge/reschedule-failed-exec")
  
  static int git_sequencer_config(const char *k, const char *v, void *cb)
  {
@@@ -447,9 -446,9 +447,9 @@@ static struct tree *empty_tree(struct r
        return lookup_tree(r, the_hash_algo->empty_tree);
  }
  
 -static int error_dirty_index(struct index_state *istate, struct replay_opts *opts)
 +static int error_dirty_index(struct repository *repo, struct replay_opts *opts)
  {
 -      if (read_index_unmerged(istate))
 +      if (repo_read_index_unmerged(repo))
                return error_resolve_conflict(_(action_name(opts)));
  
        error(_("your local changes would be overwritten by %s."),
@@@ -484,7 -483,7 +484,7 @@@ static int fast_forward_to(struct repos
        struct strbuf sb = STRBUF_INIT;
        struct strbuf err = STRBUF_INIT;
  
 -      read_index(r->index);
 +      repo_read_index(r);
        if (checkout_fast_forward(r, from, to, 1))
                return -1; /* the callee should have complained already */
  
@@@ -541,12 -540,12 +541,12 @@@ static int do_recursive_merge(struct re
        char **xopt;
        struct lock_file index_lock = LOCK_INIT;
  
 -      if (hold_locked_index(&index_lock, LOCK_REPORT_ON_ERROR) < 0)
 +      if (repo_hold_locked_index(r, &index_lock, LOCK_REPORT_ON_ERROR) < 0)
                return -1;
  
 -      read_index(r->index);
 +      repo_read_index(r);
  
 -      init_merge_options(&o);
 +      init_merge_options(&o, r);
        o.ancestor = base ? base_label : "(empty tree)";
        o.branch1 = "HEAD";
        o.branch2 = next ? next_label : "(empty tree)";
@@@ -837,7 -836,7 +837,7 @@@ static const char *read_author_ident(st
        }
  
        strbuf_reset(&out);
-       strbuf_addstr(&out, fmt_ident(name, email, date, 0));
+       strbuf_addstr(&out, fmt_ident(name, email, WANT_AUTHOR_IDENT, date, 0));
        strbuf_swap(buf, &out);
        strbuf_release(&out);
        free(name);
@@@ -1116,8 -1115,7 +1116,8 @@@ static int run_rewrite_hook(const struc
        return finish_command(&proc);
  }
  
 -void commit_post_rewrite(const struct commit *old_head,
 +void commit_post_rewrite(struct repository *r,
 +                       const struct commit *old_head,
                         const struct object_id *new_head)
  {
        struct notes_rewrite_cfg *cfg;
        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'");
 +              finish_copy_notes_for_rewrite(r, cfg, "Notes added by 'git commit --amend'");
        }
        run_rewrite_hook(&old_head->object.oid, new_head);
  }
@@@ -1407,7 -1405,7 +1407,7 @@@ static int try_to_commit(struct reposit
        }
  
        if (flags & AMEND_MSG)
 -              commit_post_rewrite(current_head, oid);
 +              commit_post_rewrite(r, current_head, oid);
  
  out:
        free_commit_extra_headers(extra);
@@@ -1769,7 -1767,7 +1769,7 @@@ static int do_pick_commit(struct reposi
                        oidcpy(&head, the_hash_algo->empty_tree);
                if (index_differs_from(r, unborn ? empty_tree_oid_hex() : "HEAD",
                                       NULL, 0))
 -                      return error_dirty_index(r->index, opts);
 +                      return error_dirty_index(r, opts);
        }
        discard_index(r->index);
  
@@@ -1999,8 -1997,8 +1999,8 @@@ static int read_and_refresh_cache(struc
                                  struct replay_opts *opts)
  {
        struct lock_file index_lock = LOCK_INIT;
 -      int index_fd = hold_locked_index(&index_lock, 0);
 -      if (read_index(r->index) < 0) {
 +      int index_fd = repo_hold_locked_index(r, &index_lock, 0);
 +      if (repo_read_index(r) < 0) {
                rollback_lock_file(&index_lock);
                return error(_("git %s: failed to read the index"),
                        _(action_name(opts)));
@@@ -2391,17 -2389,11 +2391,17 @@@ static int read_populate_opts(struct re
                if (file_exists(rebase_path_verbose()))
                        opts->verbose = 1;
  
 +              if (file_exists(rebase_path_quiet()))
 +                      opts->quiet = 1;
 +
                if (file_exists(rebase_path_signoff())) {
                        opts->allow_ff = 0;
                        opts->signoff = 1;
                }
  
 +              if (file_exists(rebase_path_reschedule_failed_exec()))
 +                      opts->reschedule_failed_exec = 1;
 +
                read_strategy_opts(opts, &buf);
                strbuf_release(&buf);
  
@@@ -2464,6 -2456,9 +2464,6 @@@ int write_basic_state(struct replay_opt
  
        if (quiet)
                write_file(rebase_path_quiet(), "%s\n", quiet);
 -      else
 -              write_file(rebase_path_quiet(), "\n");
 -
        if (opts->verbose)
                write_file(rebase_path_verbose(), "%s", "");
        if (opts->strategy)
                write_file(rebase_path_gpg_sign_opt(), "-S%s\n", opts->gpg_sign);
        if (opts->signoff)
                write_file(rebase_path_signoff(), "--signoff\n");
 +      if (opts->reschedule_failed_exec)
 +              write_file(rebase_path_reschedule_failed_exec(), "%s", "");
  
        return 0;
  }
@@@ -2866,7 -2859,7 +2866,7 @@@ static int do_exec(struct repository *r
                                          child_env.argv);
  
        /* force re-reading of the cache */
 -      if (discard_index(r->index) < 0 || read_index(r->index) < 0)
 +      if (discard_index(r->index) < 0 || repo_read_index(r) < 0)
                return error(_("could not read index"));
  
        dirty = require_clean_work_tree(r, "rebase", NULL, 1, 1);
@@@ -2990,7 -2983,7 +2990,7 @@@ static int do_reset(struct repository *
        struct unpack_trees_options unpack_tree_opts;
        int ret = 0;
  
 -      if (hold_locked_index(&lock, LOCK_REPORT_ON_ERROR) < 0)
 +      if (repo_hold_locked_index(r, &lock, LOCK_REPORT_ON_ERROR) < 0)
                return -1;
  
        if (len == 10 && !strncmp("[new root]", name, len)) {
        unpack_tree_opts.merge = 1;
        unpack_tree_opts.update = 1;
  
 -      if (read_index_unmerged(r->index)) {
 +      if (repo_read_index_unmerged(r)) {
                rollback_lock_file(&lock);
                strbuf_release(&ref_name);
                return error_resolve_conflict(_(action_name(opts)));
@@@ -3108,7 -3101,7 +3108,7 @@@ static int do_merge(struct repository *
        static struct lock_file lock;
        const char *p;
  
 -      if (hold_locked_index(&lock, LOCK_REPORT_ON_ERROR) < 0) {
 +      if (repo_hold_locked_index(r, &lock, LOCK_REPORT_ON_ERROR) < 0) {
                ret = -1;
                goto leave_merge;
        }
  
                /* force re-reading of the cache */
                if (!ret && (discard_index(r->index) < 0 ||
 -                           read_index(r->index) < 0))
 +                           repo_read_index(r) < 0))
                        ret = error(_("could not read index"));
                goto leave_merge;
        }
                commit_list_insert(j->item, &reversed);
        free_commit_list(bases);
  
 -      read_index(r->index);
 -      init_merge_options(&o);
 +      repo_read_index(r);
 +      init_merge_options(&o, r);
        o.branch1 = "HEAD";
        o.branch2 = ref_name.buf;
        o.buffer_output = 2;
@@@ -3556,11 -3549,10 +3556,11 @@@ static int pick_commits(struct reposito
                                        fprintf(f, "%d\n", todo_list->done_nr);
                                        fclose(f);
                                }
 -                              fprintf(stderr, "Rebasing (%d/%d)%s",
 -                                      todo_list->done_nr,
 -                                      todo_list->total_nr,
 -                                      opts->verbose ? "\n" : "\r");
 +                              if (!opts->quiet)
 +                                      fprintf(stderr, "Rebasing (%d/%d)%s",
 +                                              todo_list->done_nr,
 +                                              todo_list->total_nr,
 +                                              opts->verbose ? "\n" : "\r");
                        }
                        unlink(rebase_path_message());
                        unlink(rebase_path_author_script());
                        *end_of_arg = saved;
  
                        /* Reread the todo file if it has changed. */
 -                      if (res)
 -                              ; /* fall through */
 -                      else if (stat(get_todo_path(opts), &st))
 +                      if (res) {
 +                              if (opts->reschedule_failed_exec)
 +                                      reschedule = 1;
 +                      } else if (stat(get_todo_path(opts), &st))
                                res = error_errno(_("could not stat '%s'"),
                                                  get_todo_path(opts));
                        else if (match_stat_data(&todo_list->stat, &st)) {
@@@ -3794,10 -3785,8 +3794,10 @@@ cleanup_head_ref
                }
                apply_autostash(opts);
  
 -              fprintf(stderr, "Successfully rebased and updated %s.\n",
 -                      head_ref.buf);
 +              if (!opts->quiet)
 +                      fprintf(stderr,
 +                              "Successfully rebased and updated %s.\n",
 +                              head_ref.buf);
  
                strbuf_release(&buf);
                strbuf_release(&head_ref);
@@@ -3988,7 -3977,7 +3988,7 @@@ int sequencer_continue(struct repositor
                                goto release_todo_list;
                }
                if (index_differs_from(r, "HEAD", NULL, 0)) {
 -                      res = error_dirty_index(r->index, opts);
 +                      res = error_dirty_index(r, opts);
                        goto release_todo_list;
                }
                todo_list.current++;
@@@ -4098,8 -4087,7 +4098,7 @@@ void append_signoff(struct strbuf *msgb
        int has_footer;
  
        strbuf_addstr(&sob, sign_off_header);
-       strbuf_addstr(&sob, fmt_name(getenv("GIT_COMMITTER_NAME"),
-                               getenv("GIT_COMMITTER_EMAIL")));
+       strbuf_addstr(&sob, fmt_name(WANT_COMMITTER_IDENT));
        strbuf_addch(&sob, '\n');
  
        if (!ignore_footer)