Merge branch 'jk/common-main' into maint
authorJunio C Hamano <gitster@pobox.com>
Fri, 9 Sep 2016 04:35:50 +0000 (21:35 -0700)
committerJunio C Hamano <gitster@pobox.com>
Fri, 9 Sep 2016 04:35:51 +0000 (21:35 -0700)
There are certain house-keeping tasks that need to be performed at
the very beginning of any Git program, and programs that are not
built-in commands had to do them exactly the same way as "git"
potty does. It was easy to make mistakes in one-off standalone
programs (like test helpers). A common "main()" function that
calls cmd_main() of individual program has been introduced to
make it harder to make mistakes.

* jk/common-main:
mingw: declare main()'s argv as const
common-main: call git_setup_gettext()
common-main: call restore_sigpipe_to_default()
common-main: call sanitize_stdfds()
common-main: call git_extract_argv0_path()
add an extra level of indirection to main()

1  2 
Makefile
compat/mingw.h
daemon.c
http-push.c
t/helper/test-date.c
t/helper/test-regex.c
t/helper/test-run-command.c
t/helper/test-submodule-config.c
upload-pack.c
diff --combined Makefile
index 4579eab43bafc2221c6a2ee8fb4d05140ee57e18,717dc344ab131a5c8ee2d048bae60fa9336f69d0..13ed57fd0866f3e31cf6bbfb94260de5f9f3dd4b
+++ b/Makefile
@@@ -939,7 -939,7 +939,7 @@@ BUILTIN_OBJS += builtin/verify-tag.
  BUILTIN_OBJS += builtin/worktree.o
  BUILTIN_OBJS += builtin/write-tree.o
  
- GITLIBS = $(LIB_FILE) $(XDIFF_LIB)
+ GITLIBS = common-main.o $(LIB_FILE) $(XDIFF_LIB)
  EXTLIBS =
  
  GIT_USER_AGENT = git/$(GIT_VERSION)
@@@ -1572,7 -1572,15 +1572,15 @@@ TCLTK_PATH_SQ = $(subst ','\'',$(TCLTK_
  DIFF_SQ = $(subst ','\'',$(DIFF))
  PERLLIB_EXTRA_SQ = $(subst ','\'',$(PERLLIB_EXTRA))
  
- LIBS = $(GITLIBS) $(EXTLIBS)
+ # We must filter out any object files from $(GITLIBS),
+ # as it is typically used like:
+ #
+ #   foo: foo.o $(GITLIBS)
+ #     $(CC) $(filter %.o,$^) $(LIBS)
+ #
+ # where we use it as a dependency. Since we also pull object files
+ # from the dependency list, that would make each entry appear twice.
+ LIBS = $(filter-out %.o, $(GITLIBS)) $(EXTLIBS)
  
  BASIC_CFLAGS += -DSHA1_HEADER='$(SHA1_HEADER_SQ)' \
        $(COMPAT_CFLAGS)
@@@ -1708,8 -1716,8 +1716,8 @@@ git.sp git.s git.o: EXTRA_CPPFLAGS = 
        '-DGIT_INFO_PATH="$(infodir_relative_SQ)"'
  
  git$X: git.o GIT-LDFLAGS $(BUILTIN_OBJS) $(GITLIBS)
-       $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) git.o \
-               $(BUILTIN_OBJS) $(LIBS)
+       $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) \
+               $(filter %.o,$^) $(LIBS)
  
  help.sp help.s help.o: common-cmds.h
  
@@@ -1902,6 -1910,7 +1910,7 @@@ TEST_OBJS := $(patsubst %$X,%.o,$(TEST_
  OBJECTS := $(LIB_OBJS) $(BUILTIN_OBJS) $(PROGRAM_OBJS) $(TEST_OBJS) \
        $(XDIFF_OBJS) \
        $(VCSSVN_OBJS) \
+       common-main.o \
        git.o
  ifndef NO_CURL
        OBJECTS += http.o http-walker.o remote-curl.o
@@@ -2225,9 -2234,17 +2234,9 @@@ perf: al
  
  .PHONY: test perf
  
 -t/helper/test-ctype$X: ctype.o
 +t/helper/test-line-buffer$X: $(VCSSVN_LIB)
  
 -t/helper/test-date$X: date.o ctype.o
 -
 -t/helper/test-delta$X: diff-delta.o patch-delta.o
 -
 -t/helper/test-line-buffer$X: vcs-svn/lib.a
 -
 -t/helper/test-parse-options$X: parse-options.o parse-options-cb.o
 -
 -t/helper/test-svn-fe$X: vcs-svn/lib.a
 +t/helper/test-svn-fe$X: $(VCSSVN_LIB)
  
  .PRECIOUS: $(TEST_OBJS)
  
diff --combined compat/mingw.h
index ef22cbb05d140a210bd348ea1234fc60cdf09da8,1ac9086a8275341a1a9a66338cc196d6782e7371..95e128fcfd45e98c091256265c7d9bda95ec733f
@@@ -73,9 -73,6 +73,9 @@@ typedef int pid_t
  #ifndef ECONNABORTED
  #define ECONNABORTED WSAECONNABORTED
  #endif
 +#ifndef ENOTSOCK
 +#define ENOTSOCK WSAENOTSOCK
 +#endif
  
  struct passwd {
        char *pw_name;
@@@ -535,10 -532,10 +535,10 @@@ extern CRITICAL_SECTION pinfo_cs
   * A replacement of main() that adds win32 specific initialization.
   */
  
 -void mingw_startup();
 -#define main(c,v) dummy_decl_mingw_main(); \
 +void mingw_startup(void);
 +#define main(c,v) dummy_decl_mingw_main(void); \
  static int mingw_main(c,v); \
- int main(int argc, char **argv) \
+ int main(int argc, const char **argv) \
  { \
        mingw_startup(); \
        return mingw_main(__argc, (void *)__argv); \
diff --combined daemon.c
index a84495113e4c4e85243937ad0306a17981003c7b,569997c98fcb3a4e2dea9eae698a8cbb839d89b2..425aad0507f48ca07b11faa05828ea841bdd302f
+++ b/daemon.c
@@@ -1,6 -1,5 +1,5 @@@
  #include "cache.h"
  #include "pkt-line.h"
- #include "exec_cmd.h"
  #include "run-command.h"
  #include "strbuf.h"
  #include "string-list.h"
@@@ -32,7 -31,7 +31,7 @@@ static const char daemon_usage[] 
  "           [<directory>...]";
  
  /* List of acceptable pathname prefixes */
- static char **ok_paths;
+ static const char **ok_paths;
  static int strict_paths;
  
  /* If this is set, git-daemon-export-ok is not required */
@@@ -240,7 -239,7 +239,7 @@@ static const char *path_ok(const char *
        }
  
        if ( ok_paths && *ok_paths ) {
-               char **pp;
+               const char **pp;
                int pathlen = strlen(path);
  
                /* The validation is done on the paths after enter_repo
@@@ -669,17 -668,6 +668,17 @@@ static void hostinfo_clear(struct hosti
        strbuf_release(&hi->tcp_port);
  }
  
 +static void set_keep_alive(int sockfd)
 +{
 +      int ka = 1;
 +
 +      if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, &ka, sizeof(ka)) < 0) {
 +              if (errno != ENOTSOCK)
 +                      logerror("unable to set SO_KEEPALIVE on socket: %s",
 +                              strerror(errno));
 +      }
 +}
 +
  static int execute(void)
  {
        char *line = packet_buffer;
        if (addr)
                loginfo("Connection from %s:%s", addr, port);
  
 +      set_keep_alive(0);
        alarm(init_timeout ? init_timeout : timeout);
        pktlen = packet_read(0, NULL, NULL, packet_buffer, sizeof(packet_buffer), 0);
        alarm(0);
@@@ -963,8 -950,6 +962,8 @@@ static int setup_named_sock(char *liste
                        continue;
                }
  
 +              set_keep_alive(sockfd);
 +
                if (bind(sockfd, ai->ai_addr, ai->ai_addrlen) < 0) {
                        logerror("Could not bind to %s: %s",
                                 ip2str(ai->ai_family, ai->ai_addr, ai->ai_addrlen),
@@@ -1024,8 -1009,6 +1023,8 @@@ static int setup_named_sock(char *liste
                return 0;
        }
  
 +      set_keep_alive(sockfd);
 +
        if ( bind(sockfd, (struct sockaddr *)&sin, sizeof sin) < 0 ) {
                logerror("Could not bind to %s: %s",
                         ip2str(AF_INET, (struct sockaddr *)&sin, sizeof(sin)),
@@@ -1194,7 -1177,7 +1193,7 @@@ static int serve(struct string_list *li
        return service_loop(&socklist);
  }
  
- int main(int argc, char **argv)
+ int cmd_main(int argc, const char **argv)
  {
        int listen_port = 0;
        struct string_list listen_addr = STRING_LIST_INIT_NODUP;
        struct credentials *cred = NULL;
        int i;
  
-       git_setup_gettext();
-       git_extract_argv0_path(argv[0]);
        for (i = 1; i < argc; i++) {
-               char *arg = argv[i];
+               const char *arg = argv[i];
                const char *v;
  
                if (skip_prefix(arg, "--listen=", &v)) {
        if (detach) {
                if (daemonize())
                        die("--detach not supported on this platform");
-       } else
-               sanitize_stdfds();
+       }
  
        if (pid_file)
                write_file(pid_file, "%"PRIuMAX, (uintmax_t) getpid());
diff --combined http-push.c
index d0b29ac982028a26c97ebd24f1b3f2cbf188e503,dacada9094efd0c929319f39ca74a908668863c7..704b1c837c9feaa1215e5fd9767c04275a4c1beb
@@@ -1137,7 -1137,7 +1137,7 @@@ static void remote_ls(const char *path
        ls.userData = userData;
        ls.userFunc = userFunc;
  
 -      strbuf_addf(&out_buffer.buf, PROPFIND_ALL_REQUEST);
 +      strbuf_addstr(&out_buffer.buf, PROPFIND_ALL_REQUEST);
  
        dav_headers = curl_slist_append(dav_headers, "Depth: 1");
        dav_headers = curl_slist_append(dav_headers, "Content-Type: text/xml");
@@@ -1692,12 -1692,12 +1692,12 @@@ static void run_request_queue(void
  #endif
  }
  
- int main(int argc, char **argv)
+ int cmd_main(int argc, const char **argv)
  {
        struct transfer_request *request;
        struct transfer_request *next_request;
        int nr_refspec = 0;
-       char **refspec = NULL;
+       const char **refspec = NULL;
        struct remote_lock *ref_lock = NULL;
        struct remote_lock *info_ref_lock = NULL;
        struct rev_info revs;
        int new_refs;
        struct ref *ref, *local_refs;
  
-       git_setup_gettext();
-       git_extract_argv0_path(argv[0]);
        repo = xcalloc(1, sizeof(*repo));
  
        argv++;
        for (i = 1; i < argc; i++, argv++) {
-               char *arg = *argv;
+               const char *arg = *argv;
  
                if (*arg == '-') {
                        if (!strcmp(arg, "--all")) {
diff --combined t/helper/test-date.c
index d9ab3609094df80a1e3afc3d24d8fd158c96e496,0f3cfb1721b641b25267458edce93c9de2f923e2..506054bcd5dfbd76c8aec85382f35794514b9db9
@@@ -1,12 -1,11 +1,12 @@@
  #include "cache.h"
  
  static const char *usage_msg = "\n"
 -"  test-date show [time_t]...\n"
 +"  test-date relative [time_t]...\n"
 +"  test-date show:<format> [time_t]...\n"
  "  test-date parse [date]...\n"
  "  test-date approxidate [date]...\n";
  
- static void show_relative_dates(char **argv, struct timeval *now)
 -static void show_dates(const char **argv, struct timeval *now)
++static void show_relative_dates(const char **argv, struct timeval *now)
  {
        struct strbuf buf = STRBUF_INIT;
  
        strbuf_release(&buf);
  }
  
- static void show_dates(char **argv, const char *format)
++static void show_dates(const char **argv, const char *format)
 +{
 +      struct date_mode mode;
 +
 +      parse_date_format(format, &mode);
 +      for (; *argv; argv++) {
-               char *arg = *argv;
++              char *arg;
 +              time_t t;
 +              int tz;
 +
 +              /*
 +               * Do not use our normal timestamp parsing here, as the point
 +               * is to test the formatting code in isolation.
 +               */
-               t = strtol(arg, &arg, 10);
++              t = strtol(*argv, &arg, 10);
 +              while (*arg == ' ')
 +                      arg++;
 +              tz = atoi(arg);
 +
 +              printf("%s -> %s\n", *argv, show_date(t, tz, &mode));
 +      }
 +}
 +
- static void parse_dates(char **argv, struct timeval *now)
+ static void parse_dates(const char **argv, struct timeval *now)
  {
        struct strbuf result = STRBUF_INIT;
  
@@@ -60,7 -36,7 +60,7 @@@
        strbuf_release(&result);
  }
  
- static void parse_approxidate(char **argv, struct timeval *now)
+ static void parse_approxidate(const char **argv, struct timeval *now)
  {
        for (; *argv; argv++) {
                time_t t;
@@@ -69,7 -45,7 +69,7 @@@
        }
  }
  
- int main(int argc, char **argv)
+ int cmd_main(int argc, const char **argv)
  {
        struct timeval now;
        const char *x;
        argv++;
        if (!*argv)
                usage(usage_msg);
 -      if (!strcmp(*argv, "show"))
 -              show_dates(argv+1, &now);
 +      if (!strcmp(*argv, "relative"))
 +              show_relative_dates(argv+1, &now);
 +      else if (skip_prefix(*argv, "show:", &x))
 +              show_dates(argv+1, x);
        else if (!strcmp(*argv, "parse"))
                parse_dates(argv+1, &now);
        else if (!strcmp(*argv, "approxidate"))
diff --combined t/helper/test-regex.c
index eff26f534fc21e3d77bc3d6cf76fce2b5a74e981,37b7f06e552ef51c852f54e70d66c434ca50b6b2..b5ea8a97c54e1737d91dec894c1cc02e1baf64e5
@@@ -1,23 -1,6 +1,23 @@@
  #include "git-compat-util.h"
 +#include "gettext.h"
  
 -int cmd_main(int argc, const char **argv)
 +struct reg_flag {
 +      const char *name;
 +      int flag;
 +};
 +
 +static struct reg_flag reg_flags[] = {
 +      { "EXTENDED",    REG_EXTENDED   },
 +      { "NEWLINE",     REG_NEWLINE    },
 +      { "ICASE",       REG_ICASE      },
 +      { "NOTBOL",      REG_NOTBOL     },
 +#ifdef REG_STARTEND
 +      { "STARTEND",    REG_STARTEND   },
 +#endif
 +      { NULL, 0 }
 +};
 +
 +static int test_regex_bug(void)
  {
        char *pat = "[^={} \t]+";
        char *str = "={}\nfred";
        if (m[0].rm_so == 3) /* matches '\n' when it should not */
                die("regex bug confirmed: re-build git with NO_REGEX=1");
  
 -      exit(0);
 +      return 0;
 +}
 +
- int main(int argc, char **argv)
++int cmd_main(int argc, const char **argv)
 +{
 +      const char *pat;
 +      const char *str;
 +      int flags = 0;
 +      regex_t r;
 +      regmatch_t m[1];
 +
 +      if (argc == 2 && !strcmp(argv[1], "--bug"))
 +              return test_regex_bug();
 +      else if (argc < 3)
 +              usage("test-regex --bug\n"
 +                    "test-regex <pattern> <string> [<options>]");
 +
 +      argv++;
 +      pat = *argv++;
 +      str = *argv++;
 +      while (*argv) {
 +              struct reg_flag *rf;
 +              for (rf = reg_flags; rf->name; rf++)
 +                      if (!strcmp(*argv, rf->name)) {
 +                              flags |= rf->flag;
 +                              break;
 +                      }
 +              if (!rf->name)
 +                      die("do not recognize %s", *argv);
 +              argv++;
 +      }
 +      git_setup_gettext();
 +
 +      if (regcomp(&r, pat, flags))
 +              die("failed regcomp() for pattern '%s'", pat);
 +      if (regexec(&r, str, 1, m, 0))
 +              return 1;
 +
 +      return 0;
  }
index 6bb53da3c0faef2989d749d3df5c26ca3cd76b4a,c71ea4f759bf15253841bda5dd95f0783d0f7ad6..d24d157379f30cafdeeb772e82bf5ee4c862272c
@@@ -26,7 -26,7 +26,7 @@@ static int parallel_next(struct child_p
                return 0;
  
        argv_array_pushv(&cp->args, d->argv);
 -      strbuf_addf(err, "preloaded output of a child\n");
 +      strbuf_addstr(err, "preloaded output of a child\n");
        number_callbacks++;
        return 1;
  }
@@@ -36,7 -36,7 +36,7 @@@ static int no_job(struct child_process 
                  void *cb,
                  void **task_cb)
  {
 -      strbuf_addf(err, "no further jobs available\n");
 +      strbuf_addstr(err, "no further jobs available\n");
        return 0;
  }
  
@@@ -45,11 -45,11 +45,11 @@@ static int task_finished(int result
                         void *pp_cb,
                         void *pp_task_cb)
  {
 -      strbuf_addf(err, "asking for a quick stop\n");
 +      strbuf_addstr(err, "asking for a quick stop\n");
        return 1;
  }
  
- int main(int argc, char **argv)
+ int cmd_main(int argc, const char **argv)
  {
        struct child_process proc = CHILD_PROCESS_INIT;
        int jobs;
index a4e4098a0fc55f804524e4333a4e1685e38ad2a8,2cffded116f77d7c62ee718fa08558b52574a205..2a50217bf5957733f6920260d1b4ad8abf69fd57
@@@ -2,7 -2,7 +2,7 @@@
  #include "submodule-config.h"
  #include "submodule.h"
  
- static void die_usage(int argc, char **argv, const char *msg)
+ static void die_usage(int argc, const char **argv, const char *msg)
  {
        fprintf(stderr, "%s\n", msg);
        fprintf(stderr, "Usage: %s [<commit> <submodulepath>] ...\n", argv[0]);
@@@ -14,16 -14,16 +14,16 @@@ static int git_test_config(const char *
        return parse_submodule_config_option(var, value);
  }
  
- int main(int argc, char **argv)
+ int cmd_main(int argc, const char **argv)
  {
-       char **arg = argv;
+       const char **arg = argv;
        int my_argc = argc;
        int output_url = 0;
        int lookup_name = 0;
  
        arg++;
        my_argc--;
 -      while (starts_with(arg[0], "--")) {
 +      while (arg[0] && starts_with(arg[0], "--")) {
                if (!strcmp(arg[0], "--url"))
                        output_url = 1;
                if (!strcmp(arg[0], "--name"))
diff --combined upload-pack.c
index 44d63fba4168db1f741747f824439d9234315578,b97a7659d1f2ffeb8e63fa46a17ca1501db983ab..26746f67e2387f91c4e7052a2d5224c271a8174b
@@@ -58,21 -58,20 +58,21 @@@ static void reset_timeout(void
        alarm(timeout);
  }
  
 -static ssize_t send_client_data(int fd, const char *data, ssize_t sz)
 +static void send_client_data(int fd, const char *data, ssize_t sz)
  {
 -      if (use_sideband)
 -              return send_sideband(1, fd, data, sz, use_sideband);
 +      if (use_sideband) {
 +              send_sideband(1, fd, data, sz, use_sideband);
 +              return;
 +      }
        if (fd == 3)
                /* emergency quit */
                fd = 2;
        if (fd == 2) {
                /* XXX: are we happy to lose stuff here? */
                xwrite(fd, data, sz);
 -              return sz;
 +              return;
        }
        write_or_die(fd, data, sz);
 -      return sz;
  }
  
  static int write_one_shallow(const struct commit_graft *graft, void *cb_data)
@@@ -230,7 -229,9 +230,7 @@@ static void create_pack_file(void
                        }
                        else
                                buffered = -1;
 -                      sz = send_client_data(1, data, sz);
 -                      if (sz < 0)
 -                              goto fail;
 +                      send_client_data(1, data, sz);
                }
  
                /*
        /* flush the data */
        if (0 <= buffered) {
                data[0] = buffered;
 -              sz = send_client_data(1, data, 1);
 -              if (sz < 0)
 -                      goto fail;
 +              send_client_data(1, data, 1);
                fprintf(stderr, "flushed.\n");
        }
        if (use_sideband)
@@@ -813,20 -816,17 +813,17 @@@ static int upload_pack_config(const cha
        return parse_hide_refs_config(var, value, "uploadpack");
  }
  
- int main(int argc, char **argv)
+ int cmd_main(int argc, const char **argv)
  {
-       char *dir;
+       const char *dir;
        int i;
        int strict = 0;
  
-       git_setup_gettext();
        packet_trace_identity("upload-pack");
-       git_extract_argv0_path(argv[0]);
        check_replace_refs = 0;
  
        for (i = 1; i < argc; i++) {
-               char *arg = argv[i];
+               const char *arg = argv[i];
  
                if (arg[0] != '-')
                        break;