Merge branch 'rs/child-process-init'
authorJunio C Hamano <gitster@pobox.com>
Thu, 11 Sep 2014 17:33:27 +0000 (10:33 -0700)
committerJunio C Hamano <gitster@pobox.com>
Thu, 11 Sep 2014 17:33:27 +0000 (10:33 -0700)
Code clean-up.

* rs/child-process-init:
run-command: inline prepare_run_command_v_opt()
run-command: call run_command_v_opt_cd_env() instead of duplicating it
run-command: introduce child_process_init()
run-command: introduce CHILD_PROCESS_INIT

1  2 
archive-tar.c
builtin/commit.c
bundle.c
daemon.c
fetch-pack.c
http-backend.c
imap-send.c
pager.c
diff --combined archive-tar.c
index 603650fa3cc83e844cd6b0e61f145ed99a67158c,0d1e6bd7542dd7c76d2f349de0d0238a8d1b55af..df2f4c8a643796ee96a31185f2a49fa7e00ca991
@@@ -192,7 -192,7 +192,7 @@@ static int write_extended_header(struc
        unsigned int mode;
        memset(&header, 0, sizeof(header));
        *header.typeflag = TYPEFLAG_EXT_HEADER;
 -      mode = 0100666;
 +      mode = 0100666 & ~tar_umask;
        sprintf(header.name, "%s.paxheader", sha1_to_hex(sha1));
        prepare_header(args, &header, mode, size);
        write_blocked(&header, sizeof(header));
@@@ -300,7 -300,7 +300,7 @@@ static int write_global_extended_header
        strbuf_append_ext_header(&ext_header, "comment", sha1_to_hex(sha1), 40);
        memset(&header, 0, sizeof(header));
        *header.typeflag = TYPEFLAG_GLOBAL_HEADER;
 -      mode = 0100666;
 +      mode = 0100666 & ~tar_umask;
        strcpy(header.name, "pax_global_header");
        prepare_header(args, &header, mode, ext_header.len);
        write_blocked(&header, sizeof(header));
@@@ -395,7 -395,7 +395,7 @@@ static int write_tar_filter_archive(con
                                    struct archiver_args *args)
  {
        struct strbuf cmd = STRBUF_INIT;
-       struct child_process filter;
+       struct child_process filter = CHILD_PROCESS_INIT;
        const char *argv[2];
        int r;
  
        if (args->compression_level >= 0)
                strbuf_addf(&cmd, " -%d", args->compression_level);
  
-       memset(&filter, 0, sizeof(filter));
        argv[0] = cmd.buf;
        argv[1] = NULL;
        filter.argv = argv;
diff --combined builtin/commit.c
index 36e3a2eef2b65e1e9977fd66e5bd514e492c3e56,b8b8663cc8ceb8af362a67f251cd036081c8558a..ec0048e8b05d5a54e1507b9a8f3e73f06be0fa39
@@@ -42,20 -42,7 +42,20 @@@ static const char * const builtin_statu
        NULL
  };
  
 -static const char implicit_ident_advice[] =
 +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"
@@@ -1061,8 -1048,7 +1061,8 @@@ static const char *find_author_by_nickn
        revs.mailmap = &mailmap;
        read_mailmap(revs.mailmap, NULL);
  
 -      prepare_revision_walk(&revs);
 +      if (prepare_revision_walk(&revs))
 +              die(_("revision walk setup failed"));
        commit = get_revision(&revs);
        if (commit) {
                struct pretty_print_context ctx = {0};
@@@ -1416,24 -1402,6 +1416,24 @@@ int cmd_status(int argc, const char **a
        return 0;
  }
  
 +static const char *implicit_ident_advice(void)
 +{
 +      char *user_config = NULL;
 +      char *xdg_config = NULL;
 +      int config_exists;
 +
 +      home_config_paths(&user_config, &xdg_config, "config");
 +      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);
 +
 +}
 +
  static void print_summary(const char *prefix, const unsigned char *sha1,
                          int initial_commit)
  {
                strbuf_addbuf_percentquote(&format, &committer_ident);
                if (advice_implicit_identity) {
                        strbuf_addch(&format, '\n');
 -                      strbuf_addstr(&format, _(implicit_ident_advice));
 +                      strbuf_addstr(&format, implicit_ident_advice());
                }
        }
        strbuf_release(&author_ident);
@@@ -1540,7 -1508,7 +1540,7 @@@ static int run_rewrite_hook(const unsig
  {
        /* oldsha1 SP newsha1 LF NUL */
        static char buf[2*40 + 3];
-       struct child_process proc;
+       struct child_process proc = CHILD_PROCESS_INIT;
        const char *argv[3];
        int code;
        size_t n;
        argv[1] = "amend";
        argv[2] = NULL;
  
-       memset(&proc, 0, sizeof(proc));
        proc.argv = argv;
        proc.in = -1;
        proc.stdout_to_stderr = 1;
diff --combined bundle.c
index b708906cdbd2a14d0e5bcd1e1288c78777cf6a5e,d6b4df861b6264162a6e1b6dbb9467fada1903cf..b2b89fe8628eb29b613754ee8e837fd56de185da
+++ b/bundle.c
@@@ -221,8 -221,8 +221,8 @@@ static int is_tag_in_date_range(struct 
        line = memmem(buf, size, "\ntagger ", 8);
        if (!line++)
                return 1;
 -      lineend = memchr(line, buf + size - line, '\n');
 -      line = memchr(line, lineend ? lineend - line : buf + size - line, '>');
 +      lineend = memchr(line, '\n', buf + size - line);
 +      line = memchr(line, '>', lineend ? lineend - line : buf + size - line);
        if (!line++)
                return 1;
        date = strtoul(line, NULL, 10);
@@@ -240,7 -240,7 +240,7 @@@ int create_bundle(struct bundle_header 
        int i, ref_count = 0;
        struct strbuf buf = STRBUF_INIT;
        struct rev_info revs;
-       struct child_process rls;
+       struct child_process rls = CHILD_PROCESS_INIT;
        FILE *rls_fout;
  
        bundle_to_stdout = !strcmp(path, "-");
        init_revisions(&revs, NULL);
  
        /* write prerequisites */
-       memset(&rls, 0, sizeof(rls));
        argv_array_pushl(&rls.args,
                         "rev-list", "--boundary", "--pretty=oneline",
                         NULL);
@@@ -417,14 -416,13 +416,13 @@@ int unbundle(struct bundle_header *head
  {
        const char *argv_index_pack[] = {"index-pack",
                                         "--fix-thin", "--stdin", NULL, NULL};
-       struct child_process ip;
+       struct child_process ip = CHILD_PROCESS_INIT;
  
        if (flags & BUNDLE_VERBOSE)
                argv_index_pack[3] = "-v";
  
        if (verify_bundle(header, 0))
                return -1;
-       memset(&ip, 0, sizeof(ip));
        ip.argv = argv_index_pack;
        ip.in = bundle_fd;
        ip.no_stdout = 1;
diff --combined daemon.c
index 6f78b615a48faec60a53a39a817b6eaa5b674017,a5953de407e15ec70979b43b5e43e1563b8b8a3f..4dcfff9352c8d034bfaec4efa0c36df41e7813a7
+++ b/daemon.c
@@@ -230,6 -230,23 +230,6 @@@ struct daemon_service 
        int overridable;
  };
  
 -static struct daemon_service *service_looking_at;
 -static int service_enabled;
 -
 -static int git_daemon_config(const char *var, const char *value, void *cb)
 -{
 -      const char *service;
 -
 -      if (skip_prefix(var, "daemon.", &service) &&
 -          !strcmp(service, service_looking_at->config_name)) {
 -              service_enabled = git_config_bool(var, value);
 -              return 0;
 -      }
 -
 -      /* we are not interested in parsing any other configuration here */
 -      return 0;
 -}
 -
  static int daemon_error(const char *dir, const char *msg)
  {
        if (!informative_errors)
@@@ -242,7 -259,7 +242,7 @@@ static const char *access_hook
  
  static int run_access_hook(struct daemon_service *service, const char *dir, const char *path)
  {
-       struct child_process child;
+       struct child_process child = CHILD_PROCESS_INIT;
        struct strbuf buf = STRBUF_INIT;
        const char *argv[8];
        const char **arg = argv;
        *arg = NULL;
  #undef STRARG
  
-       memset(&child, 0, sizeof(child));
        child.use_shell = 1;
        child.argv = argv;
        child.no_stdin = 1;
@@@ -307,7 -323,6 +306,7 @@@ static int run_service(const char *dir
  {
        const char *path;
        int enabled = service->enabled;
 +      struct strbuf var = STRBUF_INIT;
  
        loginfo("Request %s for '%s'", service->name, dir);
  
        }
  
        if (service->overridable) {
 -              service_looking_at = service;
 -              service_enabled = -1;
 -              git_config(git_daemon_config, NULL);
 -              if (0 <= service_enabled)
 -                      enabled = service_enabled;
 +              strbuf_addf(&var, "daemon.%s", service->config_name);
 +              git_config_get_bool(var.buf, &enabled);
 +              strbuf_release(&var);
        }
        if (!enabled) {
                logerror("'%s': service not enabled for '%s'",
@@@ -388,9 -405,8 +387,8 @@@ static void copy_to_log(int fd
  
  static int run_service_command(const char **argv)
  {
-       struct child_process cld;
+       struct child_process cld = CHILD_PROCESS_INIT;
  
-       memset(&cld, 0, sizeof(cld));
        cld.argv = argv;
        cld.git_cmd = 1;
        cld.err = -1;
@@@ -715,7 -731,7 +713,7 @@@ static void check_dead_children(void
  static char **cld_argv;
  static void handle(int incoming, struct sockaddr *addr, socklen_t addrlen)
  {
-       struct child_process cld = { NULL };
+       struct child_process cld = CHILD_PROCESS_INIT;
        char addrbuf[300] = "REMOTE_ADDR=", portbuf[300];
        char *env[] = { addrbuf, portbuf, NULL };
  
diff --combined fetch-pack.c
index a13e9dbd94a7494bfffd6072feea68f450dba2b7,18d4c8fc564e43de344ae399dd8fed018b2c90b0..7487aa730630e8b45874e3487db8e71c05e1968c
@@@ -666,7 -666,7 +666,7 @@@ static int get_pack(struct fetch_pack_a
        char hdr_arg[256];
        const char **av, *cmd_name;
        int do_keep = args->keep_pack;
-       struct child_process cmd;
+       struct child_process cmd = CHILD_PROCESS_INIT;
        int ret;
  
        memset(&demux, 0, sizeof(demux));
        else
                demux.out = xd[0];
  
-       memset(&cmd, 0, sizeof(cmd));
        cmd.argv = argv;
        av = argv;
        *hdr_arg = 0;
@@@ -869,15 -868,34 +868,15 @@@ static struct ref *do_fetch_pack(struc
        return ref;
  }
  
 -static int fetch_pack_config(const char *var, const char *value, void *cb)
 +static void fetch_pack_config(void)
  {
 -      if (strcmp(var, "fetch.unpacklimit") == 0) {
 -              fetch_unpack_limit = git_config_int(var, value);
 -              return 0;
 -      }
 -
 -      if (strcmp(var, "transfer.unpacklimit") == 0) {
 -              transfer_unpack_limit = git_config_int(var, value);
 -              return 0;
 -      }
 -
 -      if (strcmp(var, "repack.usedeltabaseoffset") == 0) {
 -              prefer_ofs_delta = git_config_bool(var, value);
 -              return 0;
 -      }
 -
 -      if (!strcmp(var, "fetch.fsckobjects")) {
 -              fetch_fsck_objects = git_config_bool(var, value);
 -              return 0;
 -      }
 -
 -      if (!strcmp(var, "transfer.fsckobjects")) {
 -              transfer_fsck_objects = git_config_bool(var, value);
 -              return 0;
 -      }
 +      git_config_get_int("fetch.unpacklimit", &fetch_unpack_limit);
 +      git_config_get_int("transfer.unpacklimit", &transfer_unpack_limit);
 +      git_config_get_bool("repack.usedeltabaseoffset", &prefer_ofs_delta);
 +      git_config_get_bool("fetch.fsckobjects", &fetch_fsck_objects);
 +      git_config_get_bool("transfer.fsckobjects", &transfer_fsck_objects);
  
 -      return git_default_config(var, value, cb);
 +      git_config(git_default_config, NULL);
  }
  
  static void fetch_pack_setup(void)
        static int did_setup;
        if (did_setup)
                return;
 -      git_config(fetch_pack_config, NULL);
 +      fetch_pack_config();
        if (0 <= transfer_unpack_limit)
                unpack_limit = transfer_unpack_limit;
        else if (0 <= fetch_unpack_limit)
diff --combined http-backend.c
index 106ca6bf2926fd6fd88c2b6a44bfbbaacbea1c61,2d4d105d92b6546ea1ec74758cdc229c3741511f..404e682593ecfca218d0aee0634f5c21356ef69c
@@@ -219,22 -219,29 +219,22 @@@ static void get_idx_file(char *name
        send_local_file("application/x-git-packed-objects-toc", name);
  }
  
 -static int http_config(const char *var, const char *value, void *cb)
 +static void http_config(void)
  {
 -      const char *p;
 +      int i, value = 0;
 +      struct strbuf var = STRBUF_INIT;
  
 -      if (!strcmp(var, "http.getanyfile")) {
 -              getanyfile = git_config_bool(var, value);
 -              return 0;
 -      }
 +      git_config_get_bool("http.getanyfile", &getanyfile);
  
 -      if (skip_prefix(var, "http.", &p)) {
 -              int i;
 -
 -              for (i = 0; i < ARRAY_SIZE(rpc_service); i++) {
 -                      struct rpc_service *svc = &rpc_service[i];
 -                      if (!strcmp(p, svc->config_name)) {
 -                              svc->enabled = git_config_bool(var, value);
 -                              return 0;
 -                      }
 -              }
 +      for (i = 0; i < ARRAY_SIZE(rpc_service); i++) {
 +              struct rpc_service *svc = &rpc_service[i];
 +              strbuf_addf(&var, "http.%s", svc->config_name);
 +              if (!git_config_get_bool(var.buf, &value))
 +                      svc->enabled = value;
 +              strbuf_reset(&var);
        }
  
 -      /* we are not interested in parsing any other configuration here */
 -      return 0;
 +      strbuf_release(&var);
  }
  
  static struct rpc_service *select_service(const char *name)
@@@ -316,7 -323,7 +316,7 @@@ static void run_service(const char **ar
        const char *host = getenv("REMOTE_ADDR");
        struct argv_array env = ARGV_ARRAY_INIT;
        int gzipped_request = 0;
-       struct child_process cld;
+       struct child_process cld = CHILD_PROCESS_INIT;
  
        if (encoding && !strcmp(encoding, "gzip"))
                gzipped_request = 1;
                argv_array_pushf(&env, "GIT_COMMITTER_EMAIL=%s@http.%s",
                                 user, host);
  
-       memset(&cld, 0, sizeof(cld));
        cld.argv = argv;
        cld.env = env.argv;
        if (gzipped_request)
@@@ -620,7 -626,7 +619,7 @@@ int main(int argc, char **argv
            access("git-daemon-export-ok", F_OK) )
                not_found("Repository not exported: '%s'", dir);
  
 -      git_config(http_config, NULL);
 +      http_config();
        cmd->imp(cmd_arg);
        return 0;
  }
diff --combined imap-send.c
index 614b744106d95a52eec5fa1e23564b303c77295b,d8fb10f660575ce8d40b4312927b8aa65feec219..b7601f6359987ec4c414c9bc295f9b40fcd51e97
@@@ -128,6 -128,7 +128,6 @@@ struct imap_cmd_cb 
        char *data;
        int dlen;
        int uid;
 -      unsigned create:1, trycreate:1;
  };
  
  struct imap_cmd {
@@@ -492,9 -493,9 +492,9 @@@ static int nfsnprintf(char *buf, int bl
        return ret;
  }
  
 -static struct imap_cmd *v_issue_imap_cmd(struct imap_store *ctx,
 -                                       struct imap_cmd_cb *cb,
 -                                       const char *fmt, va_list ap)
 +static struct imap_cmd *issue_imap_cmd(struct imap_store *ctx,
 +                                     struct imap_cmd_cb *cb,
 +                                     const char *fmt, va_list ap)
  {
        struct imap *imap = ctx->imap;
        struct imap_cmd *cmd;
        return cmd;
  }
  
 -__attribute__((format (printf, 3, 4)))
 -static struct imap_cmd *issue_imap_cmd(struct imap_store *ctx,
 -                                     struct imap_cmd_cb *cb,
 -                                     const char *fmt, ...)
 -{
 -      struct imap_cmd *ret;
 -      va_list ap;
 -
 -      va_start(ap, fmt);
 -      ret = v_issue_imap_cmd(ctx, cb, fmt, ap);
 -      va_end(ap);
 -      return ret;
 -}
 -
  __attribute__((format (printf, 3, 4)))
  static int imap_exec(struct imap_store *ctx, struct imap_cmd_cb *cb,
                     const char *fmt, ...)
        struct imap_cmd *cmdp;
  
        va_start(ap, fmt);
 -      cmdp = v_issue_imap_cmd(ctx, cb, fmt, ap);
 +      cmdp = issue_imap_cmd(ctx, cb, fmt, ap);
        va_end(ap);
        if (!cmdp)
                return RESP_BAD;
@@@ -581,7 -596,7 +581,7 @@@ static int imap_exec_m(struct imap_stor
        struct imap_cmd *cmdp;
  
        va_start(ap, fmt);
 -      cmdp = v_issue_imap_cmd(ctx, cb, fmt, ap);
 +      cmdp = issue_imap_cmd(ctx, cb, fmt, ap);
        va_end(ap);
        if (!cmdp)
                return DRV_STORE_BAD;
@@@ -699,8 -714,8 +699,8 @@@ static int parse_response_code(struct i
  static int get_cmd_result(struct imap_store *ctx, struct imap_cmd *tcmd)
  {
        struct imap *imap = ctx->imap;
 -      struct imap_cmd *cmdp, **pcmdp, *ncmdp;
 -      char *cmd, *arg, *arg1, *p;
 +      struct imap_cmd *cmdp, **pcmdp;
 +      char *cmd, *arg, *arg1;
        int n, resp, resp2, tag;
  
        for (;;) {
                        if (!strcmp("OK", arg))
                                resp = DRV_OK;
                        else {
 -                              if (!strcmp("NO", arg)) {
 -                                      if (cmdp->cb.create && cmd && (cmdp->cb.trycreate || !memcmp(cmd, "[TRYCREATE]", 11))) { /* SELECT, APPEND or UID COPY */
 -                                              p = strchr(cmdp->cmd, '"');
 -                                              if (!issue_imap_cmd(ctx, NULL, "CREATE \"%.*s\"", (int)(strchr(p + 1, '"') - p + 1), p)) {
 -                                                      resp = RESP_BAD;
 -                                                      goto normal;
 -                                              }
 -                                              /* not waiting here violates the spec, but a server that does not
 -                                                 grok this nonetheless violates it too. */
 -                                              cmdp->cb.create = 0;
 -                                              if (!(ncmdp = issue_imap_cmd(ctx, &cmdp->cb, "%s", cmdp->cmd))) {
 -                                                      resp = RESP_BAD;
 -                                                      goto normal;
 -                                              }
 -                                              free(cmdp->cmd);
 -                                              free(cmdp);
 -                                              if (!tcmd)
 -                                                      return 0;       /* ignored */
 -                                              if (cmdp == tcmd)
 -                                                      tcmd = ncmdp;
 -                                              continue;
 -                                      }
 +                              if (!strcmp("NO", arg))
                                        resp = RESP_NO;
 -                              else /*if (!strcmp("BAD", arg))*/
 +                              else /*if (!strcmp("BAD", arg))*/
                                        resp = RESP_BAD;
                                fprintf(stderr, "IMAP command '%s' returned response (%s) - %s\n",
                                         memcmp(cmdp->cmd, "LOGIN", 5) ?
                        }
                        if ((resp2 = parse_response_code(ctx, &cmdp->cb, cmd)) > resp)
                                resp = resp2;
 -              normal:
                        if (cmdp->cb.done)
                                cmdp->cb.done(ctx, cmdp, resp);
                        free(cmdp->cb.data);
@@@ -907,7 -944,7 +907,7 @@@ static int auth_cram_md5(struct imap_st
        return 0;
  }
  
 -static struct imap_store *imap_open_store(struct imap_server_conf *srvc)
 +static struct imap_store *imap_open_store(struct imap_server_conf *srvc, char *folder)
  {
        struct credential cred = CREDENTIAL_INIT;
        struct imap_store *ctx;
  
        if (srvc->tunnel) {
                const char *argv[] = { srvc->tunnel, NULL };
-               struct child_process tunnel = {NULL};
+               struct child_process tunnel = CHILD_PROCESS_INIT;
  
                imap_info("Starting tunnel '%s'... ", srvc->tunnel);
  
                credential_approve(&cred);
        credential_clear(&cred);
  
 +      /* check the target mailbox exists */
 +      ctx->name = folder;
 +      switch (imap_exec(ctx, NULL, "EXAMINE \"%s\"", ctx->name)) {
 +      case RESP_OK:
 +              /* ok */
 +              break;
 +      case RESP_BAD:
 +              fprintf(stderr, "IMAP error: could not check mailbox\n");
 +              goto out;
 +      case RESP_NO:
 +              if (imap_exec(ctx, NULL, "CREATE \"%s\"", ctx->name) == RESP_OK) {
 +                      imap_info("Created missing mailbox\n");
 +              } else {
 +                      fprintf(stderr, "IMAP error: could not create missing mailbox\n");
 +                      goto out;
 +              }
 +              break;
 +      }
 +
        ctx->prefix = "";
        return ctx;
  
@@@ -1146,7 -1164,6 +1146,7 @@@ bail
                credential_reject(&cred);
        credential_clear(&cred);
  
 + out:
        imap_close_store(ctx);
        return NULL;
  }
@@@ -1202,6 -1219,7 +1202,6 @@@ static int imap_store_msg(struct imap_s
  
        box = ctx->name;
        prefix = !strcmp(box, "INBOX") ? "" : ctx->prefix;
 -      cb.create = 0;
        ret = imap_exec_m(ctx, &cb, "APPEND \"%s%s\" ", prefix, box);
        imap->caps = imap->rcaps;
        if (ret != DRV_OK)
@@@ -1308,35 -1326,43 +1308,35 @@@ static int split_msg(struct strbuf *all
  
  static char *imap_folder;
  
 -static int git_imap_config(const char *key, const char *val, void *cb)
 +static void git_imap_config(void)
  {
 -      if (!skip_prefix(key, "imap.", &key))
 -              return 0;
 +      const char *val = NULL;
  
 -      /* check booleans first, and barf on others */
 -      if (!strcmp("sslverify", key))
 -              server.ssl_verify = git_config_bool(key, val);
 -      else if (!strcmp("preformattedhtml", key))
 -              server.use_html = git_config_bool(key, val);
 -      else if (!val)
 -              return config_error_nonbool(key);
 -
 -      if (!strcmp("folder", key)) {
 -              imap_folder = xstrdup(val);
 -      } else if (!strcmp("host", key)) {
 -              if (starts_with(val, "imap:"))
 -                      val += 5;
 -              else if (starts_with(val, "imaps:")) {
 -                      val += 6;
 -                      server.use_ssl = 1;
 +      git_config_get_bool("imap.sslverify", &server.ssl_verify);
 +      git_config_get_bool("imap.preformattedhtml", &server.use_html);
 +      git_config_get_string("imap.folder", &imap_folder);
 +
 +      if (!git_config_get_value("imap.host", &val)) {
 +              if (!val) {
 +                      git_die_config("imap.host", "Missing value for 'imap.host'");
 +              } else {
 +                      if (starts_with(val, "imap:"))
 +                              val += 5;
 +                      else if (starts_with(val, "imaps:")) {
 +                              val += 6;
 +                              server.use_ssl = 1;
 +                      }
 +                      if (starts_with(val, "//"))
 +                              val += 2;
 +                      server.host = xstrdup(val);
                }
 -              if (starts_with(val, "//"))
 -                      val += 2;
 -              server.host = xstrdup(val);
 -      } else if (!strcmp("user", key))
 -              server.user = xstrdup(val);
 -      else if (!strcmp("pass", key))
 -              server.pass = xstrdup(val);
 -      else if (!strcmp("port", key))
 -              server.port = git_config_int(key, val);
 -      else if (!strcmp("tunnel", key))
 -              server.tunnel = xstrdup(val);
 -      else if (!strcmp("authmethod", key))
 -              server.auth_method = xstrdup(val);
 +      }
  
 -      return 0;
 +      git_config_get_string("imap.user", &server.user);
 +      git_config_get_string("imap.pass", &server.pass);
 +      git_config_get_int("imap.port", &server.port);
 +      git_config_get_string("imap.tunnel", &server.tunnel);
 +      git_config_get_string("imap.authmethod", &server.auth_method);
  }
  
  int main(int argc, char **argv)
                usage(imap_send_usage);
  
        setup_git_directory_gently(&nongit_ok);
 -      git_config(git_imap_config, NULL);
 +      git_imap_config();
  
        if (!server.port)
                server.port = server.use_ssl ? 993 : 143;
        }
  
        /* write it to the imap server */
 -      ctx = imap_open_store(&server);
 +      ctx = imap_open_store(&server, imap_folder);
        if (!ctx) {
                fprintf(stderr, "failed to open store\n");
                return 1;
        }
  
        fprintf(stderr, "sending %d message%s\n", total, (total != 1) ? "s" : "");
 -      ctx->name = imap_folder;
        while (1) {
                unsigned percent = n * 100 / total;
  
diff --combined pager.c
index b7eb7e7957f5e6340e0590fad9a362fd0086e6fa,d0e4bc822c0e3d0f4fe93685b485cbc83c05ee46..b2b805af98552061a723f3b8e2ac3093d0b897f7
+++ b/pager.c
@@@ -6,13 -6,19 +6,13 @@@
  #define DEFAULT_PAGER "less"
  #endif
  
 -struct pager_config {
 -      const char *cmd;
 -      int want;
 -      char *value;
 -};
 -
  /*
   * This is split up from the rest of git so that we can do
   * something different on Windows.
   */
  
  static const char *pager_argv[] = { NULL, NULL };
- static struct child_process pager_process;
+ static struct child_process pager_process = CHILD_PROCESS_INIT;
  
  static void wait_for_pager(void)
  {
@@@ -149,22 -155,30 +149,22 @@@ int decimal_width(int number
        return width;
  }
  
 -static int pager_command_config(const char *var, const char *value, void *data)
 +/* returns 0 for "no pager", 1 for "use pager", and -1 for "not specified" */
 +int check_pager_config(const char *cmd)
  {
 -      struct pager_config *c = data;
 -      if (starts_with(var, "pager.") && !strcmp(var + 6, c->cmd)) {
 -              int b = git_config_maybe_bool(var, value);
 +      int want = -1;
 +      struct strbuf key = STRBUF_INIT;
 +      const char *value = NULL;
 +      strbuf_addf(&key, "pager.%s", cmd);
 +      if (!git_config_get_value(key.buf, &value)) {
 +              int b = git_config_maybe_bool(key.buf, value);
                if (b >= 0)
 -                      c->want = b;
 +                      want = b;
                else {
 -                      c->want = 1;
 -                      c->value = xstrdup(value);
 +                      want = 1;
 +                      pager_program = xstrdup(value);
                }
        }
 -      return 0;
 -}
 -
 -/* returns 0 for "no pager", 1 for "use pager", and -1 for "not specified" */
 -int check_pager_config(const char *cmd)
 -{
 -      struct pager_config c;
 -      c.cmd = cmd;
 -      c.want = -1;
 -      c.value = NULL;
 -      git_config(pager_command_config, &c);
 -      if (c.value)
 -              pager_program = c.value;
 -      return c.want;
 +      strbuf_release(&key);
 +      return want;
  }