Code

Merge branch 'jc/commit-hook-authorship'
authorJunio C Hamano <gitster@pobox.com>
Mon, 16 Apr 2012 05:51:01 +0000 (22:51 -0700)
committerJunio C Hamano <gitster@pobox.com>
Mon, 16 Apr 2012 05:51:01 +0000 (22:51 -0700)
"git commit --author=$name" did not tell the name that was being recorded
in the resulting commit to hooks, even though it does do so when the end
user overrode the authorship via the "GIT_AUTHOR_NAME" environment
variable.

* jc/commit-hook-authorship:
  commit: pass author/committer info to hooks
  t7503: does pre-commit-hook learn authorship?
  ident.c: add split_ident_line() to parse formatted ident line

1  2 
builtin/commit.c
cache.h

diff --combined builtin/commit.c
index 3714582e1988f7c286412afb779cbfefe4849657,57a60f9f4bf8d89c04433ba48fc76d0ced274edd..7808be30e181e9cc4f031cdfea3b155f32970da8
@@@ -400,7 -400,7 +400,7 @@@ static char *prepare_index(int argc, co
                fd = hold_locked_index(&index_lock, 1);
                add_files_to_cache(also ? prefix : NULL, pathspec, 0);
                refresh_cache_or_die(refresh_flags);
 -              update_main_cache_tree(1);
 +              update_main_cache_tree(WRITE_TREE_SILENT);
                if (write_cache(fd, active_cache, active_nr) ||
                    close_lock_file(&index_lock))
                        die(_("unable to write new_index file"));
                fd = hold_locked_index(&index_lock, 1);
                refresh_cache_or_die(refresh_flags);
                if (active_cache_changed) {
 -                      update_main_cache_tree(1);
 +                      update_main_cache_tree(WRITE_TREE_SILENT);
                        if (write_cache(fd, active_cache, active_nr) ||
                            commit_locked_index(&index_lock))
                                die(_("unable to write new_index file"));
@@@ -533,9 -533,20 +533,20 @@@ static int is_a_merge(const struct comm
  
  static const char sign_off_header[] = "Signed-off-by: ";
  
+ static void export_one(const char *var, const char *s, const char *e, int hack)
+ {
+       struct strbuf buf = STRBUF_INIT;
+       if (hack)
+               strbuf_addch(&buf, hack);
+       strbuf_addf(&buf, "%.*s", (int)(e - s), s);
+       setenv(var, buf.buf, 1);
+       strbuf_release(&buf);
+ }
  static void determine_author_info(struct strbuf *author_ident)
  {
        char *name, *email, *date;
+       struct ident_split author;
  
        name = getenv("GIT_AUTHOR_NAME");
        email = getenv("GIT_AUTHOR_EMAIL");
                date = force_date;
        strbuf_addstr(author_ident, fmt_ident(name, email, date,
                                              IDENT_ERROR_ON_NO_NAME));
+       if (!split_ident_line(&author, author_ident->buf, author_ident->len)) {
+               export_one("GIT_AUTHOR_NAME", author.name_begin, author.name_end, 0);
+               export_one("GIT_AUTHOR_EMAIL", author.mail_begin, author.mail_end, 0);
+               export_one("GIT_AUTHOR_DATE", author.date_begin, author.tz_end, '@');
+       }
  }
  
  static int ends_rfc2822_footer(struct strbuf *sb)
@@@ -652,6 -668,9 +668,9 @@@ static int prepare_to_commit(const cha
        int ident_shown = 0;
        int clean_message_contents = (cleanup_mode != CLEANUP_NONE);
  
+       /* This checks and barfs if author is badly specified */
+       determine_author_info(author_ident);
        if (!no_verify && run_hook(index_file, "pre-commit", NULL))
                return 0;
  
  
        strbuf_release(&sb);
  
-       /* This checks and barfs if author is badly specified */
-       determine_author_info(author_ident);
        /* This checks if committer ident is explicitly given */
        strbuf_addstr(&committer_ident, git_committer_info(0));
        if (use_editor && include_status) {
diff --combined cache.h
index e5e1aa4e15a336927376c63651d88d63f02c44bf,7c42ecaff836eb0f45259830931d610745a815d2..a8aceb5aee4fef0d7b06693921dea319690965d6
+++ b/cache.h
@@@ -928,6 -928,22 +928,22 @@@ extern const char *fmt_name(const char 
  extern const char *git_editor(void);
  extern const char *git_pager(int stdout_is_tty);
  
+ struct ident_split {
+       const char *name_begin;
+       const char *name_end;
+       const char *mail_begin;
+       const char *mail_end;
+       const char *date_begin;
+       const char *date_end;
+       const char *tz_begin;
+       const char *tz_end;
+ };
+ /*
+  * Signals an success with 0, but time part of the result may be NULL
+  * if the input lacks timestamp and zone
+  */
+ extern int split_ident_line(struct ident_split *, const char *, int);
  struct checkout {
        const char *base_dir;
        int base_dir_len;
@@@ -950,9 -966,7 +966,9 @@@ struct cache_def 
  extern int has_symlink_leading_path(const char *name, int len);
  extern int threaded_has_symlink_leading_path(struct cache_def *, const char *, int);
  extern int check_leading_path(const char *name, int len);
 +extern int threaded_check_leading_path(struct cache_def *cache, const char *name, int len);
  extern int has_dirs_only_path(const char *name, int len, int prefix_len);
 +extern int threaded_has_dirs_only_path(struct cache_def *cache, const char *name, int len, int prefix_len);
  extern void schedule_dir_for_removal(const char *name, int len);
  extern void remove_scheduled_dirs(void);
  
@@@ -1117,8 -1131,6 +1133,8 @@@ extern int git_config_from_file(config_
  extern void git_config_push_parameter(const char *text);
  extern int git_config_from_parameters(config_fn_t fn, void *data);
  extern int git_config(config_fn_t fn, void *);
 +extern int git_config_with_options(config_fn_t fn, void *,
 +                                 const char *filename, int respect_includes);
  extern int git_config_early(config_fn_t fn, void *, const char *repo_config);
  extern int git_parse_ulong(const char *, unsigned long *);
  extern int git_config_int(const char *, const char *);
@@@ -1134,7 -1146,6 +1150,7 @@@ extern int git_config_parse_key(const c
  extern int git_config_set_multivar(const char *, const char *, const char *, int);
  extern int git_config_set_multivar_in_file(const char *, const char *, const char *, const char *, int);
  extern int git_config_rename_section(const char *, const char *);
 +extern int git_config_rename_section_in_file(const char *, const char *, const char *);
  extern const char *git_etc_gitconfig(void);
  extern int check_repository_format_version(const char *var, const char *value, void *cb);
  extern int git_env_bool(const char *, int);
@@@ -1145,13 -1156,7 +1161,13 @@@ extern const char *get_commit_output_en
  
  extern int git_config_parse_parameter(const char *, config_fn_t fn, void *data);
  
 -extern const char *config_exclusive_filename;
 +struct config_include_data {
 +      int depth;
 +      config_fn_t fn;
 +      void *data;
 +};
 +#define CONFIG_INCLUDE_INIT { 0 }
 +extern int git_config_include(const char *name, const char *value, void *data);
  
  #define MAX_GITNAME (1000)
  extern char git_default_email[MAX_GITNAME];
@@@ -1189,7 -1194,6 +1205,7 @@@ extern const char *pager_program
  extern int pager_in_use(void);
  extern int pager_use_color;
  extern int term_columns(void);
 +extern int decimal_width(int);
  
  extern const char *editor_program;
  extern const char *askpass_program;