Merge branch 'jk/common-main-2.8' into jk/common-main
authorJunio C Hamano <gitster@pobox.com>
Wed, 6 Jul 2016 17:02:57 +0000 (10:02 -0700)
committerJunio C Hamano <gitster@pobox.com>
Wed, 6 Jul 2016 17:02:57 +0000 (10:02 -0700)
* jk/common-main-2.8:
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()

41 files changed:
1  2 
Makefile
credential-cache--daemon.c
fast-import.c
git-compat-util.h
http-backend.c
http-push.c
remote-curl.c
t/helper/test-chmtime.c
t/helper/test-config.c
t/helper/test-ctype.c
t/helper/test-date.c
t/helper/test-delta.c
t/helper/test-dump-cache-tree.c
t/helper/test-dump-split-index.c
t/helper/test-dump-untracked-cache.c
t/helper/test-fake-ssh.c
t/helper/test-genrandom.c
t/helper/test-hashmap.c
t/helper/test-index-version.c
t/helper/test-line-buffer.c
t/helper/test-match-trees.c
t/helper/test-mergesort.c
t/helper/test-mktemp.c
t/helper/test-parse-options.c
t/helper/test-path-utils.c
t/helper/test-prio-queue.c
t/helper/test-read-cache.c
t/helper/test-regex.c
t/helper/test-revision-walking.c
t/helper/test-run-command.c
t/helper/test-scrap-cache-tree.c
t/helper/test-sha1-array.c
t/helper/test-sha1.c
t/helper/test-sigchain.c
t/helper/test-string-list.c
t/helper/test-submodule-config.c
t/helper/test-subprocess.c
t/helper/test-svn-fe.c
t/helper/test-urlmatch-normalization.c
t/helper/test-wildmatch.c
upload-pack.c
diff --combined Makefile
index de5a0302565899a90482631e2267f3c413f347d4,15f37d58e9ed1c0236b3a67f4474e67522fa8ab1..717dc344ab131a5c8ee2d048bae60fa9336f69d0
+++ b/Makefile
@@@ -375,7 -375,13 +375,7 @@@ GIT-VERSION-FILE: FORC
  # CFLAGS and LDFLAGS are for the users to override from the command line.
  
  CFLAGS = -g -O2 -Wall
 -LDFLAGS =
 -ALL_CFLAGS = $(CPPFLAGS) $(CFLAGS)
 -ALL_LDFLAGS = $(LDFLAGS)
 -STRIP ?= strip
 -
 -ifdef DEVELOPER
 -CFLAGS += -Werror \
 +DEVELOPER_CFLAGS = -Werror \
        -Wdeclaration-after-statement \
        -Wno-format-zero-length \
        -Wold-style-definition \
        -Wstrict-prototypes \
        -Wunused \
        -Wvla
 -endif
 +LDFLAGS =
 +ALL_CFLAGS = $(CPPFLAGS) $(CFLAGS)
 +ALL_LDFLAGS = $(LDFLAGS)
 +STRIP ?= strip
  
  # Create as necessary, replace existing, make ranlib unneeded.
  ARFLAGS = rcs
@@@ -437,6 -440,7 +437,6 @@@ DIFF = dif
  TAR = tar
  FIND = find
  INSTALL = install
 -RPMBUILD = rpmbuild
  TCL_PATH = tclsh
  TCLTK_PATH = wish
  XGETTEXT = xgettext
@@@ -617,7 -621,7 +617,7 @@@ TEST_PROGRAMS_NEED_X += test-svn-f
  TEST_PROGRAMS_NEED_X += test-urlmatch-normalization
  TEST_PROGRAMS_NEED_X += test-wildmatch
  
 -TEST_PROGRAMS = $(patsubst %,%$X,$(TEST_PROGRAMS_NEED_X))
 +TEST_PROGRAMS = $(patsubst %,t/helper/%$X,$(TEST_PROGRAMS_NEED_X))
  
  # List built-in command $C whose implementation cmd_$C() is not in
  # builtin/$C.o but is linked in as part of some other command.
@@@ -939,7 -943,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)
@@@ -948,10 -952,6 +948,10 @@@ include config.mak.unam
  -include config.mak.autogen
  -include config.mak
  
 +ifdef DEVELOPER
 +CFLAGS += $(DEVELOPER_CFLAGS)
 +endif
 +
  ifndef sysconfdir
  ifeq ($(prefix),/usr)
  sysconfdir = /etc
@@@ -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
  
@@@ -1898,10 -1906,11 +1906,11 @@@ VCSSVN_OBJS += vcs-svn/fast_export.
  VCSSVN_OBJS += vcs-svn/svndiff.o
  VCSSVN_OBJS += vcs-svn/svndump.o
  
 -TEST_OBJS := $(patsubst test-%$X,test-%.o,$(TEST_PROGRAMS))
 +TEST_OBJS := $(patsubst %$X,%.o,$(TEST_PROGRAMS))
  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
@@@ -2205,7 -2214,7 +2214,7 @@@ bin-wrappers/%: wrap-for-bin.s
        @mkdir -p bin-wrappers
        $(QUIET_GEN)sed -e '1s|#!.*/sh|#!$(SHELL_PATH_SQ)|' \
             -e 's|@@BUILD_DIR@@|$(shell pwd)|' \
 -           -e 's|@@PROG@@|$(@F)|' < $< > $@ && \
 +           -e 's|@@PROG@@|$(patsubst test-%,t/helper/test-%,$(@F))|' < $< > $@ && \
        chmod +x $@
  
  # GNU make supports exporting all variables by "export" without parameters.
@@@ -2225,25 -2234,25 +2234,25 @@@ perf: al
  
  .PHONY: test perf
  
 -test-ctype$X: ctype.o
 +t/helper/test-ctype$X: ctype.o
  
 -test-date$X: date.o ctype.o
 +t/helper/test-date$X: date.o ctype.o
  
 -test-delta$X: diff-delta.o patch-delta.o
 +t/helper/test-delta$X: diff-delta.o patch-delta.o
  
 -test-line-buffer$X: vcs-svn/lib.a
 +t/helper/test-line-buffer$X: vcs-svn/lib.a
  
 -test-parse-options$X: parse-options.o parse-options-cb.o
 +t/helper/test-parse-options$X: parse-options.o parse-options-cb.o
  
 -test-svn-fe$X: vcs-svn/lib.a
 +t/helper/test-svn-fe$X: vcs-svn/lib.a
  
  .PRECIOUS: $(TEST_OBJS)
  
 -test-%$X: test-%.o GIT-LDFLAGS $(GITLIBS)
 +t/helper/test-%$X: t/helper/test-%.o GIT-LDFLAGS $(GITLIBS)
        $(QUIET_LINK)$(CC) $(ALL_CFLAGS) -o $@ $(ALL_LDFLAGS) $(filter %.o,$^) $(filter %.a,$^) $(LIBS)
  
 -check-sha1:: test-sha1$X
 -      ./test-sha1.sh
 +check-sha1:: t/helper/test-sha1$X
 +      t/helper/test-sha1.sh
  
  SP_OBJ = $(patsubst %.o,%.sp,$(C_OBJ))
  
@@@ -2390,25 -2399,31 +2399,25 @@@ quick-install-html
  
  ### Maintainer's dist rules
  
 -git.spec: git.spec.in GIT-VERSION-FILE
 -      sed -e 's/@@VERSION@@/$(GIT_VERSION)/g' < $< > $@+
 -      mv $@+ $@
 -
  GIT_TARNAME = git-$(GIT_VERSION)
 -dist: git.spec git-archive$(X) configure
 +dist: git-archive$(X) configure
        ./git-archive --format=tar \
                --prefix=$(GIT_TARNAME)/ HEAD^{tree} > $(GIT_TARNAME).tar
        @mkdir -p $(GIT_TARNAME)
 -      @cp git.spec configure $(GIT_TARNAME)
 +      @cp configure $(GIT_TARNAME)
        @echo $(GIT_VERSION) > $(GIT_TARNAME)/version
        @$(MAKE) -C git-gui TARDIR=../$(GIT_TARNAME)/git-gui dist-version
        $(TAR) rf $(GIT_TARNAME).tar \
 -              $(GIT_TARNAME)/git.spec \
                $(GIT_TARNAME)/configure \
                $(GIT_TARNAME)/version \
                $(GIT_TARNAME)/git-gui/version
        @$(RM) -r $(GIT_TARNAME)
        gzip -f -9 $(GIT_TARNAME).tar
  
 -rpm: dist
 -      $(RPMBUILD) \
 -              --define "_source_filedigest_algorithm md5" \
 -              --define "_binary_filedigest_algorithm md5" \
 -              -ta $(GIT_TARNAME).tar.gz
 +rpm::
 +      @echo >&2 "Use distro packaged sources to run rpmbuild"
 +      @false
 +.PHONY: rpm
  
  htmldocs = git-htmldocs-$(GIT_VERSION)
  manpages = git-manpages-$(GIT_VERSION)
@@@ -2444,8 -2459,8 +2453,8 @@@ profile-clean
        $(RM) $(addsuffix *.gcno,$(addprefix $(PROFILE_DIR)/, $(object_dirs)))
  
  clean: profile-clean coverage-clean
 -      $(RM) *.o *.res refs/*.o block-sha1/*.o ppc/*.o compat/*.o compat/*/*.o
 -      $(RM) xdiff/*.o vcs-svn/*.o ewah/*.o builtin/*.o
 +      $(RM) *.res
 +      $(RM) $(OBJECTS)
        $(RM) $(LIB_FILE) $(XDIFF_LIB) $(VCSSVN_LIB)
        $(RM) $(ALL_PROGRAMS) $(SCRIPT_LIB) $(BUILT_INS) git$X
        $(RM) $(TEST_PROGRAMS) $(NO_INSTALL)
@@@ -2484,7 -2499,6 +2493,7 @@@ ALL_COMMANDS += git-gui git-citoo
  
  .PHONY: check-docs
  check-docs::
 +      $(MAKE) -C Documentation lint-docs
        @(for v in $(ALL_COMMANDS); \
        do \
                case "$$v" in \
index 1f14d56e98834e73dce91f3a20c3e3795ba6fb37,a4bf2366ab49701c99453d805e47eeade204d2c5..1e5f16a3a1272d4a87478525585951d76307750a
@@@ -179,12 -179,12 +179,12 @@@ static int serve_cache_loop(int fd
  
                client = accept(fd, NULL, NULL);
                if (client < 0) {
 -                      warning("accept failed: %s", strerror(errno));
 +                      warning_errno("accept failed");
                        return 1;
                }
                client2 = dup(client);
                if (client2 < 0) {
 -                      warning("dup failed: %s", strerror(errno));
 +                      warning_errno("dup failed");
                        close(client);
                        return 1;
                }
@@@ -257,7 -257,7 +257,7 @@@ static void init_socket_directory(cons
        free(path_copy);
  }
  
- int main(int argc, const char **argv)
+ int cmd_main(int argc, const char **argv)
  {
        const char *socket_path;
        int ignore_sighup = 0;
diff --combined fast-import.c
index c504ef752db124e21156be5b92360dbe432e568f,c434272566158a5e46d367510848c69875c3041c..84a13756cc6387d7546ebda8d3c92a6c49a53cf8
@@@ -164,7 -164,6 +164,6 @@@ Format of STDIN stream
  #include "refs.h"
  #include "csum-file.h"
  #include "quote.h"
- #include "exec_cmd.h"
  #include "dir.h"
  
  #define PACK_ID_BITS 16
@@@ -300,7 -299,7 +299,7 @@@ static int failure
  static FILE *pack_edges;
  static unsigned int show_stats = 1;
  static int global_argc;
- static char **global_argv;
+ static const char **global_argv;
  
  /* Memory pools */
  static size_t mem_pool_alloc = 2*1024*1024 - sizeof(struct mem_pool);
@@@ -329,7 -328,6 +328,7 @@@ static const char *export_marks_file
  static const char *import_marks_file;
  static int import_marks_file_from_stream;
  static int import_marks_file_ignore_missing;
 +static int import_marks_file_done;
  static int relative_marks_paths;
  
  /* Our last blob */
@@@ -415,7 -413,7 +414,7 @@@ static void write_crash_report(const ch
        struct recent_command *rc;
  
        if (!rpt) {
 -              error("can't write crash report %s: %s", loc, strerror(errno));
 +              error_errno("can't write crash report %s", loc);
                free(loc);
                return;
        }
@@@ -1513,7 -1511,7 +1512,7 @@@ static int tree_content_set
        t = root->tree;
        for (i = 0; i < t->entry_count; i++) {
                e = t->entries[i];
 -              if (e->name->str_len == n && !strncmp_icase(p, e->name->str_dat, n)) {
 +              if (e->name->str_len == n && !fspathncmp(p, e->name->str_dat, n)) {
                        if (!*slash1) {
                                if (!S_ISDIR(mode)
                                                && e->versions[1].mode == mode
@@@ -1603,7 -1601,7 +1602,7 @@@ static int tree_content_remove
        t = root->tree;
        for (i = 0; i < t->entry_count; i++) {
                e = t->entries[i];
 -              if (e->name->str_len == n && !strncmp_icase(p, e->name->str_dat, n)) {
 +              if (e->name->str_len == n && !fspathncmp(p, e->name->str_dat, n)) {
                        if (*slash1 && !S_ISDIR(e->versions[1].mode))
                                /*
                                 * If p names a file in some subdirectory, and a
@@@ -1670,7 -1668,7 +1669,7 @@@ static int tree_content_get
        t = root->tree;
        for (i = 0; i < t->entry_count; i++) {
                e = t->entries[i];
 -              if (e->name->str_len == n && !strncmp_icase(p, e->name->str_dat, n)) {
 +              if (e->name->str_len == n && !fspathncmp(p, e->name->str_dat, n)) {
                        if (!*slash1)
                                goto found_entry;
                        if (!S_ISDIR(e->versions[1].mode))
@@@ -1803,12 -1801,12 +1802,12 @@@ static void dump_marks(void
        static struct lock_file mark_lock;
        FILE *f;
  
 -      if (!export_marks_file)
 +      if (!export_marks_file || (import_marks_file && !import_marks_file_done))
                return;
  
        if (hold_lock_file_for_update(&mark_lock, export_marks_file, 0) < 0) {
 -              failure |= error("Unable to write marks file %s: %s",
 -                      export_marks_file, strerror(errno));
 +              failure |= error_errno("Unable to write marks file %s",
 +                                     export_marks_file);
                return;
        }
  
  
        dump_marks_helper(f, 0, marks);
        if (commit_lock_file(&mark_lock)) {
 -              failure |= error("Unable to write file %s: %s",
 -                      export_marks_file, strerror(errno));
 +              failure |= error_errno("Unable to write file %s",
 +                                     export_marks_file);
                return;
        }
  }
@@@ -1836,7 -1834,7 +1835,7 @@@ static void read_marks(void
        if (f)
                ;
        else if (import_marks_file_ignore_missing && errno == ENOENT)
 -              return; /* Marks file does not exist */
 +              goto done; /* Marks file does not exist */
        else
                die_errno("cannot read '%s'", import_marks_file);
        while (fgets(line, sizeof(line), f)) {
                insert_mark(mark, e);
        }
        fclose(f);
 +done:
 +      import_marks_file_done = 1;
  }
  
  
@@@ -3384,14 -3380,10 +3383,10 @@@ static void parse_argv(void
                read_marks();
  }
  
- int main(int argc, char **argv)
+ int cmd_main(int argc, const char **argv)
  {
        unsigned int i;
  
-       git_extract_argv0_path(argv[0]);
-       git_setup_gettext();
        if (argc == 2 && !strcmp(argv[1], "-h"))
                usage(fast_import_usage);
  
diff --combined git-compat-util.h
index 49d4029b8dddcb06dc6bea3d5f47c020785e3ddf,91e366d1dd50902dc5249907e405339ed104e964..1930444ef092f2b5834d12b73b4d2d0c050f3551
@@@ -409,9 -409,7 +409,9 @@@ extern NORETURN void usagef(const char 
  extern NORETURN void die(const char *err, ...) __attribute__((format (printf, 1, 2)));
  extern NORETURN void die_errno(const char *err, ...) __attribute__((format (printf, 1, 2)));
  extern int error(const char *err, ...) __attribute__((format (printf, 1, 2)));
 +extern int error_errno(const char *err, ...) __attribute__((format (printf, 1, 2)));
  extern void warning(const char *err, ...) __attribute__((format (printf, 1, 2)));
 +extern void warning_errno(const char *err, ...) __attribute__((format (printf, 1, 2)));
  
  #ifndef NO_OPENSSL
  #ifdef APPLE_COMMON_CRYPTO
@@@ -1045,3 -1043,5 +1045,5 @@@ struct tm *git_gmtime_r(const time_t *
  #endif
  
  #endif
+ extern int cmd_main(int, const char **);
diff --combined http-backend.c
index 214881459d828101fa0927321c5a8facb3a540f0,5a17bcac87e26fd29683d114a82a5a580ca3e9b2..0d59499a51d7f1eecf5b28254b624a991f0e1db4
@@@ -484,9 -484,9 +484,9 @@@ static int show_head_ref(const char *re
                const char *target = resolve_ref_unsafe(refname,
                                                        RESOLVE_REF_READING,
                                                        unused.hash, NULL);
 -              const char *target_nons = strip_namespace(target);
  
 -              strbuf_addf(buf, "ref: %s\n", target_nons);
 +              if (target)
 +                      strbuf_addf(buf, "ref: %s\n", strip_namespace(target));
        } else {
                strbuf_addf(buf, "%s\n", oid_to_hex(oid));
        }
@@@ -632,7 -632,7 +632,7 @@@ static struct service_cmd 
        {"POST", "/git-receive-pack$", service_rpc}
  };
  
- int main(int argc, char **argv)
+ int cmd_main(int argc, const char **argv)
  {
        char *method = getenv("REQUEST_METHOD");
        char *dir;
        char *cmd_arg = NULL;
        int i;
  
-       git_setup_gettext();
-       git_extract_argv0_path(argv[0]);
        set_die_routine(die_webcgi);
        set_die_is_recursing_routine(die_webcgi_recursing);
  
diff --combined http-push.c
index a092f0288bd6944be036a1a051a0954216c382e6,366794d70742ad641f2dfd4832653c460b23b9d0..dacada9094efd0c929319f39ca74a908668863c7
@@@ -211,7 -211,7 +211,7 @@@ static void curl_setup_http(CURL *curl
  static struct curl_slist *get_dav_token_headers(struct remote_lock *lock, enum dav_header_flag options)
  {
        struct strbuf buf = STRBUF_INIT;
 -      struct curl_slist *dav_headers = NULL;
 +      struct curl_slist *dav_headers = http_copy_default_headers();
  
        if (options & DAV_HEADER_IF) {
                strbuf_addf(&buf, "If: (<%s>)", lock->token);
@@@ -417,7 -417,7 +417,7 @@@ static void start_put(struct transfer_r
  static void start_move(struct transfer_request *request)
  {
        struct active_request_slot *slot;
 -      struct curl_slist *dav_headers = NULL;
 +      struct curl_slist *dav_headers = http_copy_default_headers();
  
        slot = get_active_slot();
        slot->callback_func = process_response;
@@@ -845,7 -845,7 +845,7 @@@ static struct remote_lock *lock_remote(
        char *ep;
        char timeout_header[25];
        struct remote_lock *lock = NULL;
 -      struct curl_slist *dav_headers = NULL;
 +      struct curl_slist *dav_headers = http_copy_default_headers();
        struct xml_ctx ctx;
        char *escaped;
  
@@@ -1126,7 -1126,7 +1126,7 @@@ static void remote_ls(const char *path
        struct slot_results results;
        struct strbuf in_buffer = STRBUF_INIT;
        struct buffer out_buffer = { STRBUF_INIT, 0 };
 -      struct curl_slist *dav_headers = NULL;
 +      struct curl_slist *dav_headers = http_copy_default_headers();
        struct xml_ctx ctx;
        struct remote_ls_ctx ls;
  
@@@ -1204,7 -1204,7 +1204,7 @@@ static int locking_available(void
        struct slot_results results;
        struct strbuf in_buffer = STRBUF_INIT;
        struct buffer out_buffer = { STRBUF_INIT, 0 };
 -      struct curl_slist *dav_headers = NULL;
 +      struct curl_slist *dav_headers = http_copy_default_headers();
        struct xml_ctx ctx;
        int lock_flags = 0;
        char *escaped;
@@@ -1312,10 -1312,10 +1312,10 @@@ static struct object_list **process_tre
        while (tree_entry(&desc, &entry))
                switch (object_type(entry.mode)) {
                case OBJ_TREE:
 -                      p = process_tree(lookup_tree(entry.sha1), p);
 +                      p = process_tree(lookup_tree(entry.oid->hash), p);
                        break;
                case OBJ_BLOB:
 -                      p = process_blob(lookup_blob(entry.sha1), p);
 +                      p = process_blob(lookup_blob(entry.oid->hash), p);
                        break;
                default:
                        /* Subproject commit - not in this repository */
@@@ -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 remote-curl.c
index 672b382e5aaf25654f9095e68f45062baed3f397,46a55d28f588e4ee9762b92c94aa3a98ae9d0b75..6b83b7783e9c62fcf623acd0ba034dd1c0b9bd10
@@@ -474,7 -474,7 +474,7 @@@ static int run_slot(struct active_reque
  static int probe_rpc(struct rpc_state *rpc, struct slot_results *results)
  {
        struct active_request_slot *slot;
 -      struct curl_slist *headers = NULL;
 +      struct curl_slist *headers = http_copy_default_headers();
        struct strbuf buf = STRBUF_INIT;
        int err;
  
  static int post_rpc(struct rpc_state *rpc)
  {
        struct active_request_slot *slot;
 -      struct curl_slist *headers = NULL;
 +      struct curl_slist *headers = http_copy_default_headers();
        int use_gzip = rpc->gzip_request;
        char *gzip_body = NULL;
        size_t gzip_size = 0;
@@@ -984,14 -984,11 +984,11 @@@ static void parse_push(struct strbuf *b
        free(specs);
  }
  
- int main(int argc, const char **argv)
+ int cmd_main(int argc, const char **argv)
  {
        struct strbuf buf = STRBUF_INIT;
        int nongit;
  
-       git_setup_gettext();
-       git_extract_argv0_path(argv[0]);
        setup_git_directory_gently(&nongit);
        if (argc < 2) {
                error("remote-curl: usage: git remote-curl <remote> [<url>]");
diff --combined t/helper/test-chmtime.c
index dfe8a83261b3623e64f99ddf8dc775616771ec4d,0000000000000000000000000000000000000000..e760256406fa9c2fe0f9b2cde0ffb97ff11c6cab
mode 100644,000000..100644
--- /dev/null
@@@ -1,119 -1,0 +1,119 @@@
- int main(int argc, char *argv[])
 +/*
 + * This program can either change modification time of the given
 + * file(s) or just print it. The program does not change atime or
 + * ctime (their values are explicitly preserved).
 + *
 + * The mtime can be changed to an absolute value:
 + *
 + *    test-chmtime =<seconds> file...
 + *
 + * Relative to the current time as returned by time(3):
 + *
 + *    test-chmtime =+<seconds> (or =-<seconds>) file...
 + *
 + * Or relative to the current mtime of the file:
 + *
 + *    test-chmtime <seconds> file...
 + *    test-chmtime +<seconds> (or -<seconds>) file...
 + *
 + * Examples:
 + *
 + * To just print the mtime use --verbose and set the file mtime offset to 0:
 + *
 + *    test-chmtime -v +0 file
 + *
 + * To set the mtime to current time:
 + *
 + *    test-chmtime =+0 file
 + *
 + */
 +#include "git-compat-util.h"
 +#include <utime.h>
 +
 +static const char usage_str[] = "-v|--verbose (+|=|=+|=-|-)<seconds> <file>...";
 +
 +static int timespec_arg(const char *arg, long int *set_time, int *set_eq)
 +{
 +      char *test;
 +      const char *timespec = arg;
 +      *set_eq = (*timespec == '=') ? 1 : 0;
 +      if (*set_eq) {
 +              timespec++;
 +              if (*timespec == '+') {
 +                      *set_eq = 2; /* relative "in the future" */
 +                      timespec++;
 +              }
 +      }
 +      *set_time = strtol(timespec, &test, 10);
 +      if (*test) {
 +              fprintf(stderr, "Not a base-10 integer: %s\n", arg + 1);
 +              return 0;
 +      }
 +      if ((*set_eq && *set_time < 0) || *set_eq == 2) {
 +              time_t now = time(NULL);
 +              *set_time += now;
 +      }
 +      return 1;
 +}
 +
++int cmd_main(int argc, const char **argv)
 +{
 +      static int verbose;
 +
 +      int i = 1;
 +      /* no mtime change by default */
 +      int set_eq = 0;
 +      long int set_time = 0;
 +
 +      if (argc < 3)
 +              goto usage;
 +
 +      if (strcmp(argv[i], "--verbose") == 0 || strcmp(argv[i], "-v") == 0) {
 +              verbose = 1;
 +              ++i;
 +      }
 +      if (timespec_arg(argv[i], &set_time, &set_eq))
 +              ++i;
 +      else
 +              goto usage;
 +
 +      for (; i < argc; i++) {
 +              struct stat sb;
 +              struct utimbuf utb;
 +
 +              if (stat(argv[i], &sb) < 0) {
 +                      fprintf(stderr, "Failed to stat %s: %s\n",
 +                              argv[i], strerror(errno));
 +                      return 1;
 +              }
 +
 +#ifdef GIT_WINDOWS_NATIVE
 +              if (!(sb.st_mode & S_IWUSR) &&
 +                              chmod(argv[i], sb.st_mode | S_IWUSR)) {
 +                      fprintf(stderr, "Could not make user-writable %s: %s",
 +                              argv[i], strerror(errno));
 +                      return 1;
 +              }
 +#endif
 +
 +              utb.actime = sb.st_atime;
 +              utb.modtime = set_eq ? set_time : sb.st_mtime + set_time;
 +
 +              if (verbose) {
 +                      uintmax_t mtime = utb.modtime < 0 ? 0: utb.modtime;
 +                      printf("%"PRIuMAX"\t%s\n", mtime, argv[i]);
 +              }
 +
 +              if (utb.modtime != sb.st_mtime && utime(argv[i], &utb) < 0) {
 +                      fprintf(stderr, "Failed to modify time on %s: %s\n",
 +                              argv[i], strerror(errno));
 +                      return 1;
 +              }
 +      }
 +
 +      return 0;
 +
 +usage:
 +      fprintf(stderr, "usage: %s %s\n", argv[0], usage_str);
 +      return 1;
 +}
diff --combined t/helper/test-config.c
index 6a775522105d9bfc5c1c60f36944bc43e64badef,0000000000000000000000000000000000000000..d143cd72223dec9c947fbf84d0f72945745a09c6
mode 100644,000000..100644
--- /dev/null
@@@ -1,152 -1,0 +1,152 @@@
- int main(int argc, char **argv)
 +#include "cache.h"
 +#include "string-list.h"
 +
 +/*
 + * This program exposes the C API of the configuration mechanism
 + * as a set of simple commands in order to facilitate testing.
 + *
 + * Reads stdin and prints result of command to stdout:
 + *
 + * get_value -> prints the value with highest priority for the entered key
 + *
 + * get_value_multi -> prints all values for the entered key in increasing order
 + *                 of priority
 + *
 + * get_int -> print integer value for the entered key or die
 + *
 + * get_bool -> print bool value for the entered key or die
 + *
 + * get_string -> print string value for the entered key or die
 + *
 + * configset_get_value -> returns value with the highest priority for the entered key
 + *                    from a config_set constructed from files entered as arguments.
 + *
 + * configset_get_value_multi -> returns value_list for the entered key sorted in
 + *                            ascending order of priority from a config_set
 + *                            constructed from files entered as arguments.
 + *
 + * Examples:
 + *
 + * To print the value with highest priority for key "foo.bAr Baz.rock":
 + *    test-config get_value "foo.bAr Baz.rock"
 + *
 + */
 +
 +
++int cmd_main(int argc, const char **argv)
 +{
 +      int i, val;
 +      const char *v;
 +      const struct string_list *strptr;
 +      struct config_set cs;
 +      git_configset_init(&cs);
 +
 +      if (argc < 2) {
 +              fprintf(stderr, "Please, provide a command name on the command-line\n");
 +              goto exit1;
 +      } else if (argc == 3 && !strcmp(argv[1], "get_value")) {
 +              if (!git_config_get_value(argv[2], &v)) {
 +                      if (!v)
 +                              printf("(NULL)\n");
 +                      else
 +                              printf("%s\n", v);
 +                      goto exit0;
 +              } else {
 +                      printf("Value not found for \"%s\"\n", argv[2]);
 +                      goto exit1;
 +              }
 +      } else if (argc == 3 && !strcmp(argv[1], "get_value_multi")) {
 +              strptr = git_config_get_value_multi(argv[2]);
 +              if (strptr) {
 +                      for (i = 0; i < strptr->nr; i++) {
 +                              v = strptr->items[i].string;
 +                              if (!v)
 +                                      printf("(NULL)\n");
 +                              else
 +                                      printf("%s\n", v);
 +                      }
 +                      goto exit0;
 +              } else {
 +                      printf("Value not found for \"%s\"\n", argv[2]);
 +                      goto exit1;
 +              }
 +      } else if (argc == 3 && !strcmp(argv[1], "get_int")) {
 +              if (!git_config_get_int(argv[2], &val)) {
 +                      printf("%d\n", val);
 +                      goto exit0;
 +              } else {
 +                      printf("Value not found for \"%s\"\n", argv[2]);
 +                      goto exit1;
 +              }
 +      } else if (argc == 3 && !strcmp(argv[1], "get_bool")) {
 +              if (!git_config_get_bool(argv[2], &val)) {
 +                      printf("%d\n", val);
 +                      goto exit0;
 +              } else {
 +                      printf("Value not found for \"%s\"\n", argv[2]);
 +                      goto exit1;
 +              }
 +      } else if (argc == 3 && !strcmp(argv[1], "get_string")) {
 +              if (!git_config_get_string_const(argv[2], &v)) {
 +                      printf("%s\n", v);
 +                      goto exit0;
 +              } else {
 +                      printf("Value not found for \"%s\"\n", argv[2]);
 +                      goto exit1;
 +              }
 +      } else if (!strcmp(argv[1], "configset_get_value")) {
 +              for (i = 3; i < argc; i++) {
 +                      int err;
 +                      if ((err = git_configset_add_file(&cs, argv[i]))) {
 +                              fprintf(stderr, "Error (%d) reading configuration file %s.\n", err, argv[i]);
 +                              goto exit2;
 +                      }
 +              }
 +              if (!git_configset_get_value(&cs, argv[2], &v)) {
 +                      if (!v)
 +                              printf("(NULL)\n");
 +                      else
 +                              printf("%s\n", v);
 +                      goto exit0;
 +              } else {
 +                      printf("Value not found for \"%s\"\n", argv[2]);
 +                      goto exit1;
 +              }
 +      } else if (!strcmp(argv[1], "configset_get_value_multi")) {
 +              for (i = 3; i < argc; i++) {
 +                      int err;
 +                      if ((err = git_configset_add_file(&cs, argv[i]))) {
 +                              fprintf(stderr, "Error (%d) reading configuration file %s.\n", err, argv[i]);
 +                              goto exit2;
 +                      }
 +              }
 +              strptr = git_configset_get_value_multi(&cs, argv[2]);
 +              if (strptr) {
 +                      for (i = 0; i < strptr->nr; i++) {
 +                              v = strptr->items[i].string;
 +                              if (!v)
 +                                      printf("(NULL)\n");
 +                              else
 +                                      printf("%s\n", v);
 +                      }
 +                      goto exit0;
 +              } else {
 +                      printf("Value not found for \"%s\"\n", argv[2]);
 +                      goto exit1;
 +              }
 +      }
 +
 +      die("%s: Please check the syntax and the function name", argv[0]);
 +
 +exit0:
 +      git_configset_clear(&cs);
 +      return 0;
 +
 +exit1:
 +      git_configset_clear(&cs);
 +      return 1;
 +
 +exit2:
 +      git_configset_clear(&cs);
 +      return 2;
 +}
diff --combined t/helper/test-ctype.c
index 707a821f03d59b1b3685b380fa4f3e83535c5342,0000000000000000000000000000000000000000..bb72c47df570d9c07ae4567fd6d31ea49fe49656
mode 100644,000000..100644
--- /dev/null
@@@ -1,42 -1,0 +1,42 @@@
- int main(int argc, char **argv)
 +#include "cache.h"
 +
 +static int rc;
 +
 +static void report_error(const char *class, int ch)
 +{
 +      printf("%s classifies char %d (0x%02x) wrongly\n", class, ch, ch);
 +      rc = 1;
 +}
 +
 +static int is_in(const char *s, int ch)
 +{
 +      /* We can't find NUL using strchr.  It's classless anyway. */
 +      if (ch == '\0')
 +              return 0;
 +      return !!strchr(s, ch);
 +}
 +
 +#define TEST_CLASS(t,s) {                     \
 +      int i;                                  \
 +      for (i = 0; i < 256; i++) {             \
 +              if (is_in(s, i) != t(i))        \
 +                      report_error(#t, i);    \
 +      }                                       \
 +}
 +
 +#define DIGIT "0123456789"
 +#define LOWER "abcdefghijklmnopqrstuvwxyz"
 +#define UPPER "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
 +
++int cmd_main(int argc, const char **argv)
 +{
 +      TEST_CLASS(isdigit, DIGIT);
 +      TEST_CLASS(isspace, " \n\r\t");
 +      TEST_CLASS(isalpha, LOWER UPPER);
 +      TEST_CLASS(isalnum, LOWER UPPER DIGIT);
 +      TEST_CLASS(is_glob_special, "*?[\\");
 +      TEST_CLASS(is_regex_special, "$()*+.?[\\^{|");
 +      TEST_CLASS(is_pathspec_magic, "!\"#%&',-/:;<=>@_`~");
 +
 +      return rc;
 +}
diff --combined t/helper/test-date.c
index 63f373557e7236d294fb580d38db9e6d331e53d3,0000000000000000000000000000000000000000..0f3cfb1721b641b25267458edce93c9de2f923e2
mode 100644,000000..100644
--- /dev/null
@@@ -1,73 -1,0 +1,73 @@@
- static void show_dates(char **argv, struct timeval *now)
 +#include "cache.h"
 +
 +static const char *usage_msg = "\n"
 +"  test-date show [time_t]...\n"
 +"  test-date parse [date]...\n"
 +"  test-date approxidate [date]...\n";
 +
- static void parse_dates(char **argv, struct timeval *now)
++static void show_dates(const char **argv, struct timeval *now)
 +{
 +      struct strbuf buf = STRBUF_INIT;
 +
 +      for (; *argv; argv++) {
 +              time_t t = atoi(*argv);
 +              show_date_relative(t, 0, now, &buf);
 +              printf("%s -> %s\n", *argv, buf.buf);
 +      }
 +      strbuf_release(&buf);
 +}
 +
- static void parse_approxidate(char **argv, struct timeval *now)
++static void parse_dates(const char **argv, struct timeval *now)
 +{
 +      struct strbuf result = STRBUF_INIT;
 +
 +      for (; *argv; argv++) {
 +              unsigned long t;
 +              int tz;
 +
 +              strbuf_reset(&result);
 +              parse_date(*argv, &result);
 +              if (sscanf(result.buf, "%lu %d", &t, &tz) == 2)
 +                      printf("%s -> %s\n",
 +                             *argv, show_date(t, tz, DATE_MODE(ISO8601)));
 +              else
 +                      printf("%s -> bad\n", *argv);
 +      }
 +      strbuf_release(&result);
 +}
 +
- int main(int argc, char **argv)
++static void parse_approxidate(const char **argv, struct timeval *now)
 +{
 +      for (; *argv; argv++) {
 +              time_t t;
 +              t = approxidate_relative(*argv, now);
 +              printf("%s -> %s\n", *argv, show_date(t, 0, DATE_MODE(ISO8601)));
 +      }
 +}
 +
++int cmd_main(int argc, const char **argv)
 +{
 +      struct timeval now;
 +      const char *x;
 +
 +      x = getenv("TEST_DATE_NOW");
 +      if (x) {
 +              now.tv_sec = atoi(x);
 +              now.tv_usec = 0;
 +      }
 +      else
 +              gettimeofday(&now, NULL);
 +
 +      argv++;
 +      if (!*argv)
 +              usage(usage_msg);
 +      if (!strcmp(*argv, "show"))
 +              show_dates(argv+1, &now);
 +      else if (!strcmp(*argv, "parse"))
 +              parse_dates(argv+1, &now);
 +      else if (!strcmp(*argv, "approxidate"))
 +              parse_approxidate(argv+1, &now);
 +      else
 +              usage(usage_msg);
 +      return 0;
 +}
diff --combined t/helper/test-delta.c
index 4595cd6433f9fd543791ee5a8a59a9112b50c046,0000000000000000000000000000000000000000..59937dc1be1c4f0b3d80e3ef3a86e09bff3703b6
mode 100644,000000..100644
--- /dev/null
@@@ -1,78 -1,0 +1,78 @@@
- int main(int argc, char *argv[])
 +/*
 + * test-delta.c: test code to exercise diff-delta.c and patch-delta.c
 + *
 + * (C) 2005 Nicolas Pitre <nico@fluxnic.net>
 + *
 + * This code is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License version 2 as
 + * published by the Free Software Foundation.
 + */
 +
 +#include "git-compat-util.h"
 +#include "delta.h"
 +#include "cache.h"
 +
 +static const char usage_str[] =
 +      "test-delta (-d|-p) <from_file> <data_file> <out_file>";
 +
++int cmd_main(int argc, const char **argv)
 +{
 +      int fd;
 +      struct stat st;
 +      void *from_buf, *data_buf, *out_buf;
 +      unsigned long from_size, data_size, out_size;
 +
 +      if (argc != 5 || (strcmp(argv[1], "-d") && strcmp(argv[1], "-p"))) {
 +              fprintf(stderr, "usage: %s\n", usage_str);
 +              return 1;
 +      }
 +
 +      fd = open(argv[2], O_RDONLY);
 +      if (fd < 0 || fstat(fd, &st)) {
 +              perror(argv[2]);
 +              return 1;
 +      }
 +      from_size = st.st_size;
 +      from_buf = mmap(NULL, from_size, PROT_READ, MAP_PRIVATE, fd, 0);
 +      if (from_buf == MAP_FAILED) {
 +              perror(argv[2]);
 +              close(fd);
 +              return 1;
 +      }
 +      close(fd);
 +
 +      fd = open(argv[3], O_RDONLY);
 +      if (fd < 0 || fstat(fd, &st)) {
 +              perror(argv[3]);
 +              return 1;
 +      }
 +      data_size = st.st_size;
 +      data_buf = mmap(NULL, data_size, PROT_READ, MAP_PRIVATE, fd, 0);
 +      if (data_buf == MAP_FAILED) {
 +              perror(argv[3]);
 +              close(fd);
 +              return 1;
 +      }
 +      close(fd);
 +
 +      if (argv[1][1] == 'd')
 +              out_buf = diff_delta(from_buf, from_size,
 +                                   data_buf, data_size,
 +                                   &out_size, 0);
 +      else
 +              out_buf = patch_delta(from_buf, from_size,
 +                                    data_buf, data_size,
 +                                    &out_size);
 +      if (!out_buf) {
 +              fprintf(stderr, "delta operation failed (returned NULL)\n");
 +              return 1;
 +      }
 +
 +      fd = open (argv[4], O_WRONLY|O_CREAT|O_TRUNC, 0666);
 +      if (fd < 0 || write_in_full(fd, out_buf, out_size) != out_size) {
 +              perror(argv[4]);
 +              return 1;
 +      }
 +
 +      return 0;
 +}
index bb53c0aa655c7a2df09638024b304a79e8b07fc6,0000000000000000000000000000000000000000..44f3290258a003317e4aad4f90d17ce5529e3b07
mode 100644,000000..100644
--- /dev/null
@@@ -1,67 -1,0 +1,67 @@@
- int main(int ac, char **av)
 +#include "cache.h"
 +#include "tree.h"
 +#include "cache-tree.h"
 +
 +
 +static void dump_one(struct cache_tree *it, const char *pfx, const char *x)
 +{
 +      if (it->entry_count < 0)
 +              printf("%-40s %s%s (%d subtrees)\n",
 +                     "invalid", x, pfx, it->subtree_nr);
 +      else
 +              printf("%s %s%s (%d entries, %d subtrees)\n",
 +                     sha1_to_hex(it->sha1), x, pfx,
 +                     it->entry_count, it->subtree_nr);
 +}
 +
 +static int dump_cache_tree(struct cache_tree *it,
 +                         struct cache_tree *ref,
 +                         const char *pfx)
 +{
 +      int i;
 +      int errs = 0;
 +
 +      if (!it || !ref)
 +              /* missing in either */
 +              return 0;
 +
 +      if (it->entry_count < 0) {
 +              /* invalid */
 +              dump_one(it, pfx, "");
 +              dump_one(ref, pfx, "#(ref) ");
 +      }
 +      else {
 +              dump_one(it, pfx, "");
 +              if (hashcmp(it->sha1, ref->sha1) ||
 +                  ref->entry_count != it->entry_count ||
 +                  ref->subtree_nr != it->subtree_nr) {
 +                      /* claims to be valid but is lying */
 +                      dump_one(ref, pfx, "#(ref) ");
 +                      errs = 1;
 +              }
 +      }
 +
 +      for (i = 0; i < it->subtree_nr; i++) {
 +              char path[PATH_MAX];
 +              struct cache_tree_sub *down = it->down[i];
 +              struct cache_tree_sub *rdwn;
 +
 +              rdwn = cache_tree_sub(ref, down->name);
 +              xsnprintf(path, sizeof(path), "%s%.*s/", pfx, down->namelen, down->name);
 +              if (dump_cache_tree(down->cache_tree, rdwn->cache_tree, path))
 +                      errs = 1;
 +      }
 +      return errs;
 +}
 +
++int cmd_main(int ac, const char **av)
 +{
 +      struct index_state istate;
 +      struct cache_tree *another = cache_tree();
 +      if (read_cache() < 0)
 +              die("unable to read index file");
 +      istate = the_index;
 +      istate.cache_tree = another;
 +      cache_tree_update(&istate, WRITE_TREE_DRY_RUN);
 +      return dump_cache_tree(active_cache_tree, another, "");
 +}
index 861d28c9b6c1b4d95f74ffbd95bc279ea0d377eb,0000000000000000000000000000000000000000..d1689248b4937fbecaf16129c4016814554b983d
mode 100644,000000..100644
--- /dev/null
@@@ -1,36 -1,0 +1,36 @@@
- int main(int ac, char **av)
 +#include "cache.h"
 +#include "split-index.h"
 +#include "ewah/ewok.h"
 +
 +static void show_bit(size_t pos, void *data)
 +{
 +      printf(" %d", (int)pos);
 +}
 +
++int cmd_main(int ac, const char **av)
 +{
 +      struct split_index *si;
 +      int i;
 +
 +      do_read_index(&the_index, av[1], 1);
 +      printf("own %s\n", sha1_to_hex(the_index.sha1));
 +      si = the_index.split_index;
 +      if (!si) {
 +              printf("not a split index\n");
 +              return 0;
 +      }
 +      printf("base %s\n", sha1_to_hex(si->base_sha1));
 +      for (i = 0; i < the_index.cache_nr; i++) {
 +              struct cache_entry *ce = the_index.cache[i];
 +              printf("%06o %s %d\t%s\n", ce->ce_mode,
 +                     sha1_to_hex(ce->sha1), ce_stage(ce), ce->name);
 +      }
 +      printf("replacements:");
 +      if (si->replace_bitmap)
 +              ewah_each_bit(si->replace_bitmap, show_bit, NULL);
 +      printf("\ndeletions:");
 +      if (si->delete_bitmap)
 +              ewah_each_bit(si->delete_bitmap, show_bit, NULL);
 +      printf("\n");
 +      return 0;
 +}
index 0a1c28524668f02d3aa4d073c0c6991652cbf850,0000000000000000000000000000000000000000..50112cc8586c75cf9f9b5fac65ea2f7dbc1a69e2
mode 100644,000000..100644
--- /dev/null
@@@ -1,66 -1,0 +1,66 @@@
- int main(int ac, char **av)
 +#include "cache.h"
 +#include "dir.h"
 +
 +static int compare_untracked(const void *a_, const void *b_)
 +{
 +      const char *const *a = a_;
 +      const char *const *b = b_;
 +      return strcmp(*a, *b);
 +}
 +
 +static int compare_dir(const void *a_, const void *b_)
 +{
 +      const struct untracked_cache_dir *const *a = a_;
 +      const struct untracked_cache_dir *const *b = b_;
 +      return strcmp((*a)->name, (*b)->name);
 +}
 +
 +static void dump(struct untracked_cache_dir *ucd, struct strbuf *base)
 +{
 +      int i, len;
 +      qsort(ucd->untracked, ucd->untracked_nr, sizeof(*ucd->untracked),
 +            compare_untracked);
 +      qsort(ucd->dirs, ucd->dirs_nr, sizeof(*ucd->dirs),
 +            compare_dir);
 +      len = base->len;
 +      strbuf_addf(base, "%s/", ucd->name);
 +      printf("%s %s", base->buf,
 +             sha1_to_hex(ucd->exclude_sha1));
 +      if (ucd->recurse)
 +              fputs(" recurse", stdout);
 +      if (ucd->check_only)
 +              fputs(" check_only", stdout);
 +      if (ucd->valid)
 +              fputs(" valid", stdout);
 +      printf("\n");
 +      for (i = 0; i < ucd->untracked_nr; i++)
 +              printf("%s\n", ucd->untracked[i]);
 +      for (i = 0; i < ucd->dirs_nr; i++)
 +              dump(ucd->dirs[i], base);
 +      strbuf_setlen(base, len);
 +}
 +
++int cmd_main(int ac, const char **av)
 +{
 +      struct untracked_cache *uc;
 +      struct strbuf base = STRBUF_INIT;
 +
 +      /* Hack to avoid modifying the untracked cache when we read it */
 +      ignore_untracked_cache_config = 1;
 +
 +      setup_git_directory();
 +      if (read_cache() < 0)
 +              die("unable to read index file");
 +      uc = the_index.untracked;
 +      if (!uc) {
 +              printf("no untracked cache\n");
 +              return 0;
 +      }
 +      printf("info/exclude %s\n", sha1_to_hex(uc->ss_info_exclude.sha1));
 +      printf("core.excludesfile %s\n", sha1_to_hex(uc->ss_excludes_file.sha1));
 +      printf("exclude_per_dir %s\n", uc->exclude_per_dir);
 +      printf("flags %08x\n", uc->dir_flags);
 +      if (uc->root)
 +              dump(uc->root, &base);
 +      return 0;
 +}
diff --combined t/helper/test-fake-ssh.c
index 980de216e10990a6406cae6e0b023c5fee7de488,0000000000000000000000000000000000000000..12beee99ad2f4e70e804b21895522d6d362929d2
mode 100644,000000..100644
--- /dev/null
@@@ -1,30 -1,0 +1,30 @@@
- int main(int argc, char **argv)
 +#include "git-compat-util.h"
 +#include "run-command.h"
 +#include "strbuf.h"
 +
++int cmd_main(int argc, const char **argv)
 +{
 +      const char *trash_directory = getenv("TRASH_DIRECTORY");
 +      struct strbuf buf = STRBUF_INIT;
 +      FILE *f;
 +      int i;
 +      const char *child_argv[] = { NULL, NULL };
 +
 +      /* First, print all parameters into $TRASH_DIRECTORY/ssh-output */
 +      if (!trash_directory)
 +              die("Need a TRASH_DIRECTORY!");
 +      strbuf_addf(&buf, "%s/ssh-output", trash_directory);
 +      f = fopen(buf.buf, "w");
 +      if (!f)
 +              die("Could not write to %s", buf.buf);
 +      for (i = 0; i < argc; i++)
 +              fprintf(f, "%s%s", i > 0 ? " " : "", i > 0 ? argv[i] : "ssh:");
 +      fprintf(f, "\n");
 +      fclose(f);
 +
 +      /* Now, evaluate the *last* parameter */
 +      if (argc < 2)
 +              return 0;
 +      child_argv[0] = argv[argc - 1];
 +      return run_command_v_opt(child_argv, RUN_USING_SHELL);
 +}
index 54824d075421e792f337beb5cdce170a33b00e68,0000000000000000000000000000000000000000..8d11d22d98649900b6d558cc174e2af1dbff9948
mode 100644,000000..100644
--- /dev/null
@@@ -1,33 -1,0 +1,33 @@@
- int main(int argc, char *argv[])
 +/*
 + * Simple random data generator used to create reproducible test files.
 + * This is inspired from POSIX.1-2001 implementation example for rand().
 + * Copyright (C) 2007 by Nicolas Pitre, licensed under the GPL version 2.
 + */
 +
 +#include "git-compat-util.h"
 +
++int cmd_main(int argc, const char **argv)
 +{
 +      unsigned long count, next = 0;
 +      unsigned char *c;
 +
 +      if (argc < 2 || argc > 3) {
 +              fprintf(stderr, "usage: %s <seed_string> [<size>]\n", argv[0]);
 +              return 1;
 +      }
 +
 +      c = (unsigned char *) argv[1];
 +      do {
 +              next = next * 11 + *c;
 +      } while (*c++);
 +
 +      count = (argc == 3) ? strtoul(argv[2], NULL, 0) : -1L;
 +
 +      while (count--) {
 +              next = next * 1103515245 + 12345;
 +              if (putchar((next >> 16) & 0xff) == EOF)
 +                      return -1;
 +      }
 +
 +      return 0;
 +}
diff --combined t/helper/test-hashmap.c
index cc2891dd971edfa70733eb327d12ccb66fd09f3e,0000000000000000000000000000000000000000..7aa9440e274fb443a30b3f61a241f4fea1601f10
mode 100644,000000..100644
--- /dev/null
@@@ -1,264 -1,0 +1,264 @@@
- int main(int argc, char *argv[])
 +#include "git-compat-util.h"
 +#include "hashmap.h"
 +
 +struct test_entry
 +{
 +      struct hashmap_entry ent;
 +      /* key and value as two \0-terminated strings */
 +      char key[FLEX_ARRAY];
 +};
 +
 +static const char *get_value(const struct test_entry *e)
 +{
 +      return e->key + strlen(e->key) + 1;
 +}
 +
 +static int test_entry_cmp(const struct test_entry *e1,
 +              const struct test_entry *e2, const char* key)
 +{
 +      return strcmp(e1->key, key ? key : e2->key);
 +}
 +
 +static int test_entry_cmp_icase(const struct test_entry *e1,
 +              const struct test_entry *e2, const char* key)
 +{
 +      return strcasecmp(e1->key, key ? key : e2->key);
 +}
 +
 +static struct test_entry *alloc_test_entry(int hash, char *key, int klen,
 +              char *value, int vlen)
 +{
 +      struct test_entry *entry = malloc(sizeof(struct test_entry) + klen
 +                      + vlen + 2);
 +      hashmap_entry_init(entry, hash);
 +      memcpy(entry->key, key, klen + 1);
 +      memcpy(entry->key + klen + 1, value, vlen + 1);
 +      return entry;
 +}
 +
 +#define HASH_METHOD_FNV 0
 +#define HASH_METHOD_I 1
 +#define HASH_METHOD_IDIV10 2
 +#define HASH_METHOD_0 3
 +#define HASH_METHOD_X2 4
 +#define TEST_SPARSE 8
 +#define TEST_ADD 16
 +#define TEST_SIZE 100000
 +
 +static unsigned int hash(unsigned int method, unsigned int i, const char *key)
 +{
 +      unsigned int hash = 0;
 +      switch (method & 3)
 +      {
 +      case HASH_METHOD_FNV:
 +              hash = strhash(key);
 +              break;
 +      case HASH_METHOD_I:
 +              hash = i;
 +              break;
 +      case HASH_METHOD_IDIV10:
 +              hash = i / 10;
 +              break;
 +      case HASH_METHOD_0:
 +              hash = 0;
 +              break;
 +      }
 +
 +      if (method & HASH_METHOD_X2)
 +              hash = 2 * hash;
 +      return hash;
 +}
 +
 +/*
 + * Test performance of hashmap.[ch]
 + * Usage: time echo "perfhashmap method rounds" | test-hashmap
 + */
 +static void perf_hashmap(unsigned int method, unsigned int rounds)
 +{
 +      struct hashmap map;
 +      char buf[16];
 +      struct test_entry **entries;
 +      unsigned int *hashes;
 +      unsigned int i, j;
 +
 +      entries = malloc(TEST_SIZE * sizeof(struct test_entry *));
 +      hashes = malloc(TEST_SIZE * sizeof(int));
 +      for (i = 0; i < TEST_SIZE; i++) {
 +              snprintf(buf, sizeof(buf), "%i", i);
 +              entries[i] = alloc_test_entry(0, buf, strlen(buf), "", 0);
 +              hashes[i] = hash(method, i, entries[i]->key);
 +      }
 +
 +      if (method & TEST_ADD) {
 +              /* test adding to the map */
 +              for (j = 0; j < rounds; j++) {
 +                      hashmap_init(&map, (hashmap_cmp_fn) test_entry_cmp, 0);
 +
 +                      /* add entries */
 +                      for (i = 0; i < TEST_SIZE; i++) {
 +                              hashmap_entry_init(entries[i], hashes[i]);
 +                              hashmap_add(&map, entries[i]);
 +                      }
 +
 +                      hashmap_free(&map, 0);
 +              }
 +      } else {
 +              /* test map lookups */
 +              hashmap_init(&map, (hashmap_cmp_fn) test_entry_cmp, 0);
 +
 +              /* fill the map (sparsely if specified) */
 +              j = (method & TEST_SPARSE) ? TEST_SIZE / 10 : TEST_SIZE;
 +              for (i = 0; i < j; i++) {
 +                      hashmap_entry_init(entries[i], hashes[i]);
 +                      hashmap_add(&map, entries[i]);
 +              }
 +
 +              for (j = 0; j < rounds; j++) {
 +                      for (i = 0; i < TEST_SIZE; i++) {
 +                              hashmap_get_from_hash(&map, hashes[i],
 +                                                    entries[i]->key);
 +                      }
 +              }
 +
 +              hashmap_free(&map, 0);
 +      }
 +}
 +
 +#define DELIM " \t\r\n"
 +
 +/*
 + * Read stdin line by line and print result of commands to stdout:
 + *
 + * hash key -> strhash(key) memhash(key) strihash(key) memihash(key)
 + * put key value -> NULL / old value
 + * get key -> NULL / value
 + * remove key -> NULL / old value
 + * iterate -> key1 value1\nkey2 value2\n...
 + * size -> tablesize numentries
 + *
 + * perfhashmap method rounds -> test hashmap.[ch] performance
 + */
++int cmd_main(int argc, const char **argv)
 +{
 +      char line[1024];
 +      struct hashmap map;
 +      int icase;
 +
 +      /* init hash map */
 +      icase = argc > 1 && !strcmp("ignorecase", argv[1]);
 +      hashmap_init(&map, (hashmap_cmp_fn) (icase ? test_entry_cmp_icase
 +                      : test_entry_cmp), 0);
 +
 +      /* process commands from stdin */
 +      while (fgets(line, sizeof(line), stdin)) {
 +              char *cmd, *p1 = NULL, *p2 = NULL;
 +              int l1 = 0, l2 = 0, hash = 0;
 +              struct test_entry *entry;
 +
 +              /* break line into command and up to two parameters */
 +              cmd = strtok(line, DELIM);
 +              /* ignore empty lines */
 +              if (!cmd || *cmd == '#')
 +                      continue;
 +
 +              p1 = strtok(NULL, DELIM);
 +              if (p1) {
 +                      l1 = strlen(p1);
 +                      hash = icase ? strihash(p1) : strhash(p1);
 +                      p2 = strtok(NULL, DELIM);
 +                      if (p2)
 +                              l2 = strlen(p2);
 +              }
 +
 +              if (!strcmp("hash", cmd) && l1) {
 +
 +                      /* print results of different hash functions */
 +                      printf("%u %u %u %u\n", strhash(p1), memhash(p1, l1),
 +                                      strihash(p1), memihash(p1, l1));
 +
 +              } else if (!strcmp("add", cmd) && l1 && l2) {
 +
 +                      /* create entry with key = p1, value = p2 */
 +                      entry = alloc_test_entry(hash, p1, l1, p2, l2);
 +
 +                      /* add to hashmap */
 +                      hashmap_add(&map, entry);
 +
 +              } else if (!strcmp("put", cmd) && l1 && l2) {
 +
 +                      /* create entry with key = p1, value = p2 */
 +                      entry = alloc_test_entry(hash, p1, l1, p2, l2);
 +
 +                      /* add / replace entry */
 +                      entry = hashmap_put(&map, entry);
 +
 +                      /* print and free replaced entry, if any */
 +                      puts(entry ? get_value(entry) : "NULL");
 +                      free(entry);
 +
 +              } else if (!strcmp("get", cmd) && l1) {
 +
 +                      /* lookup entry in hashmap */
 +                      entry = hashmap_get_from_hash(&map, hash, p1);
 +
 +                      /* print result */
 +                      if (!entry)
 +                              puts("NULL");
 +                      while (entry) {
 +                              puts(get_value(entry));
 +                              entry = hashmap_get_next(&map, entry);
 +                      }
 +
 +              } else if (!strcmp("remove", cmd) && l1) {
 +
 +                      /* setup static key */
 +                      struct hashmap_entry key;
 +                      hashmap_entry_init(&key, hash);
 +
 +                      /* remove entry from hashmap */
 +                      entry = hashmap_remove(&map, &key, p1);
 +
 +                      /* print result and free entry*/
 +                      puts(entry ? get_value(entry) : "NULL");
 +                      free(entry);
 +
 +              } else if (!strcmp("iterate", cmd)) {
 +
 +                      struct hashmap_iter iter;
 +                      hashmap_iter_init(&map, &iter);
 +                      while ((entry = hashmap_iter_next(&iter)))
 +                              printf("%s %s\n", entry->key, get_value(entry));
 +
 +              } else if (!strcmp("size", cmd)) {
 +
 +                      /* print table sizes */
 +                      printf("%u %u\n", map.tablesize, map.size);
 +
 +              } else if (!strcmp("intern", cmd) && l1) {
 +
 +                      /* test that strintern works */
 +                      const char *i1 = strintern(p1);
 +                      const char *i2 = strintern(p1);
 +                      if (strcmp(i1, p1))
 +                              printf("strintern(%s) returns %s\n", p1, i1);
 +                      else if (i1 == p1)
 +                              printf("strintern(%s) returns input pointer\n", p1);
 +                      else if (i1 != i2)
 +                              printf("strintern(%s) != strintern(%s)", i1, i2);
 +                      else
 +                              printf("%s\n", i1);
 +
 +              } else if (!strcmp("perfhashmap", cmd) && l1 && l2) {
 +
 +                      perf_hashmap(atoi(p1), atoi(p2));
 +
 +              } else {
 +
 +                      printf("Unknown command %s\n", cmd);
 +
 +              }
 +      }
 +
 +      hashmap_free(&map, 1);
 +      return 0;
 +}
index 05d4699c4a6cf32b2b6291e275dafa2744fe19d6,0000000000000000000000000000000000000000..f569f6b7eff87227f82dbe6390fd31fb970a5fca
mode 100644,000000..100644
--- /dev/null
@@@ -1,14 -1,0 +1,14 @@@
- int main(int argc, char **argv)
 +#include "cache.h"
 +
++int cmd_main(int argc, const char **argv)
 +{
 +      struct cache_header hdr;
 +      int version;
 +
 +      memset(&hdr,0,sizeof(hdr));
 +      if (read(0, &hdr, sizeof(hdr)) != sizeof(hdr))
 +              return 0;
 +      version = ntohl(hdr.hdr_version);
 +      printf("%d\n", version);
 +      return 0;
 +}
index 1e58f0476f3465f9b8b361cc4776abf5c051430b,0000000000000000000000000000000000000000..81575fe2ab91b550067ce8180650b003bdd939b7
mode 100644,000000..100644
--- /dev/null
@@@ -1,91 -1,0 +1,91 @@@
- int main(int argc, char *argv[])
 +/*
 + * test-line-buffer.c: code to exercise the svn importer's input helper
 + */
 +
 +#include "git-compat-util.h"
 +#include "strbuf.h"
 +#include "vcs-svn/line_buffer.h"
 +
 +static uint32_t strtouint32(const char *s)
 +{
 +      char *end;
 +      uintmax_t n = strtoumax(s, &end, 10);
 +      if (*s == '\0' || *end != '\0')
 +              die("invalid count: %s", s);
 +      return (uint32_t) n;
 +}
 +
 +static void handle_command(const char *command, const char *arg, struct line_buffer *buf)
 +{
 +      switch (*command) {
 +      case 'b':
 +              if (starts_with(command, "binary ")) {
 +                      struct strbuf sb = STRBUF_INIT;
 +                      strbuf_addch(&sb, '>');
 +                      buffer_read_binary(buf, &sb, strtouint32(arg));
 +                      fwrite(sb.buf, 1, sb.len, stdout);
 +                      strbuf_release(&sb);
 +                      return;
 +              }
 +      case 'c':
 +              if (starts_with(command, "copy ")) {
 +                      buffer_copy_bytes(buf, strtouint32(arg));
 +                      return;
 +              }
 +      case 's':
 +              if (starts_with(command, "skip ")) {
 +                      buffer_skip_bytes(buf, strtouint32(arg));
 +                      return;
 +              }
 +      default:
 +              die("unrecognized command: %s", command);
 +      }
 +}
 +
 +static void handle_line(const char *line, struct line_buffer *stdin_buf)
 +{
 +      const char *arg = strchr(line, ' ');
 +      if (!arg)
 +              die("no argument in line: %s", line);
 +      handle_command(line, arg + 1, stdin_buf);
 +}
 +
++int cmd_main(int argc, const char **argv)
 +{
 +      struct line_buffer stdin_buf = LINE_BUFFER_INIT;
 +      struct line_buffer file_buf = LINE_BUFFER_INIT;
 +      struct line_buffer *input = &stdin_buf;
 +      const char *filename;
 +      char *s;
 +
 +      if (argc == 1)
 +              filename = NULL;
 +      else if (argc == 2)
 +              filename = argv[1];
 +      else
 +              usage("test-line-buffer [file | &fd] < script");
 +
 +      if (buffer_init(&stdin_buf, NULL))
 +              die_errno("open error");
 +      if (filename) {
 +              if (*filename == '&') {
 +                      if (buffer_fdinit(&file_buf, strtouint32(filename + 1)))
 +                              die_errno("error opening fd %s", filename + 1);
 +              } else {
 +                      if (buffer_init(&file_buf, filename))
 +                              die_errno("error opening %s", filename);
 +              }
 +              input = &file_buf;
 +      }
 +
 +      while ((s = buffer_read_line(&stdin_buf)))
 +              handle_line(s, input);
 +
 +      if (filename && buffer_deinit(&file_buf))
 +              die("error reading from %s", filename);
 +      if (buffer_deinit(&stdin_buf))
 +              die("input error");
 +      if (ferror(stdout))
 +              die("output error");
 +      return 0;
 +}
index d446b8eaca727dfa9c1b0928f2b8c9af286f2702,0000000000000000000000000000000000000000..e9395028630bf26390366065aa07bc7b2827eb73
mode 100644,000000..100644
--- /dev/null
@@@ -1,26 -1,0 +1,26 @@@
- int main(int ac, char **av)
 +#include "cache.h"
 +#include "tree.h"
 +
++int cmd_main(int ac, const char **av)
 +{
 +      struct object_id hash1, hash2, shifted;
 +      struct tree *one, *two;
 +
 +      setup_git_directory();
 +
 +      if (get_oid(av[1], &hash1))
 +              die("cannot parse %s as an object name", av[1]);
 +      if (get_oid(av[2], &hash2))
 +              die("cannot parse %s as an object name", av[2]);
 +      one = parse_tree_indirect(hash1.hash);
 +      if (!one)
 +              die("not a tree-ish %s", av[1]);
 +      two = parse_tree_indirect(hash2.hash);
 +      if (!two)
 +              die("not a tree-ish %s", av[2]);
 +
 +      shift_tree(&one->object.oid, &two->object.oid, &shifted, -1);
 +      printf("shifted: %s\n", oid_to_hex(&shifted));
 +
 +      exit(0);
 +}
index ea3b959e94ff6f53726d4fce955bca1181a3be07,0000000000000000000000000000000000000000..335cf6b6264cdaf9563736fbcfa40e7a3006a432
mode 100644,000000..100644
--- /dev/null
@@@ -1,52 -1,0 +1,52 @@@
- int main(int argc, char **argv)
 +#include "cache.h"
 +#include "mergesort.h"
 +
 +struct line {
 +      char *text;
 +      struct line *next;
 +};
 +
 +static void *get_next(const void *a)
 +{
 +      return ((const struct line *)a)->next;
 +}
 +
 +static void set_next(void *a, void *b)
 +{
 +      ((struct line *)a)->next = b;
 +}
 +
 +static int compare_strings(const void *a, const void *b)
 +{
 +      const struct line *x = a, *y = b;
 +      return strcmp(x->text, y->text);
 +}
 +
++int cmd_main(int argc, const char **argv)
 +{
 +      struct line *line, *p = NULL, *lines = NULL;
 +      struct strbuf sb = STRBUF_INIT;
 +
 +      for (;;) {
 +              if (strbuf_getwholeline(&sb, stdin, '\n'))
 +                      break;
 +              line = xmalloc(sizeof(struct line));
 +              line->text = strbuf_detach(&sb, NULL);
 +              if (p) {
 +                      line->next = p->next;
 +                      p->next = line;
 +              } else {
 +                      line->next = NULL;
 +                      lines = line;
 +              }
 +              p = line;
 +      }
 +
 +      lines = llist_mergesort(lines, get_next, set_next, compare_strings);
 +
 +      while (lines) {
 +              printf("%s", lines->text);
 +              lines = lines->next;
 +      }
 +      return 0;
 +}
diff --combined t/helper/test-mktemp.c
index c8c54213a3916c4adffd7396a37ed83e88af34fb,0000000000000000000000000000000000000000..89d9b2f7bee05ff5c9fde31ba6798651ccee2947
mode 100644,000000..100644
--- /dev/null
@@@ -1,14 -1,0 +1,14 @@@
- int main(int argc, char *argv[])
 +/*
 + * test-mktemp.c: code to exercise the creation of temporary files
 + */
 +#include "git-compat-util.h"
 +
++int cmd_main(int argc, const char **argv)
 +{
 +      if (argc != 2)
 +              usage("Expected 1 parameter defining the temporary file template");
 +
 +      xmkstemp(xstrdup(argv[1]));
 +
 +      return 0;
 +}
index 8a1235d03e2daab4b9e90d31c5da6708e5c712f2,0000000000000000000000000000000000000000..d51d29251eb2cf5adeba1d4f94ff2ce100421560
mode 100644,000000..100644
--- /dev/null
@@@ -1,179 -1,0 +1,179 @@@
- int main(int argc, char **argv)
 +#include "cache.h"
 +#include "parse-options.h"
 +#include "string-list.h"
 +
 +static int boolean = 0;
 +static int integer = 0;
 +static unsigned long magnitude = 0;
 +static unsigned long timestamp;
 +static int abbrev = 7;
 +static int verbose = -1; /* unspecified */
 +static int dry_run = 0, quiet = 0;
 +static char *string = NULL;
 +static char *file = NULL;
 +static int ambiguous;
 +static struct string_list list;
 +
 +static struct {
 +      int called;
 +      const char *arg;
 +      int unset;
 +} length_cb;
 +
 +static int length_callback(const struct option *opt, const char *arg, int unset)
 +{
 +      length_cb.called = 1;
 +      length_cb.arg = arg;
 +      length_cb.unset = unset;
 +
 +      if (unset)
 +              return 1; /* do not support unset */
 +
 +      *(int *)opt->value = strlen(arg);
 +      return 0;
 +}
 +
 +static int number_callback(const struct option *opt, const char *arg, int unset)
 +{
 +      *(int *)opt->value = strtol(arg, NULL, 10);
 +      return 0;
 +}
 +
 +static int collect_expect(const struct option *opt, const char *arg, int unset)
 +{
 +      struct string_list *expect;
 +      struct string_list_item *item;
 +      struct strbuf label = STRBUF_INIT;
 +      const char *colon;
 +
 +      if (!arg || unset)
 +              die("malformed --expect option");
 +
 +      expect = (struct string_list *)opt->value;
 +      colon = strchr(arg, ':');
 +      if (!colon)
 +              die("malformed --expect option, lacking a colon");
 +      strbuf_add(&label, arg, colon - arg);
 +      item = string_list_insert(expect, strbuf_detach(&label, NULL));
 +      if (item->util)
 +              die("malformed --expect option, duplicate %s", label.buf);
 +      item->util = (void *)arg;
 +      return 0;
 +}
 +
 +__attribute__((format (printf,3,4)))
 +static void show(struct string_list *expect, int *status, const char *fmt, ...)
 +{
 +      struct string_list_item *item;
 +      struct strbuf buf = STRBUF_INIT;
 +      va_list args;
 +
 +      va_start(args, fmt);
 +      strbuf_vaddf(&buf, fmt, args);
 +      va_end(args);
 +
 +      if (!expect->nr)
 +              printf("%s\n", buf.buf);
 +      else {
 +              char *colon = strchr(buf.buf, ':');
 +              if (!colon)
 +                      die("malformed output format, output lacking colon: %s", fmt);
 +              *colon = '\0';
 +              item = string_list_lookup(expect, buf.buf);
 +              *colon = ':';
 +              if (!item)
 +                      ; /* not among entries being checked */
 +              else {
 +                      if (strcmp((const char *)item->util, buf.buf)) {
 +                              printf("-%s\n", (char *)item->util);
 +                              printf("+%s\n", buf.buf);
 +                              *status = 1;
 +                      }
 +              }
 +      }
 +      strbuf_release(&buf);
 +}
 +
++int cmd_main(int argc, const char **argv)
 +{
 +      const char *prefix = "prefix/";
 +      const char *usage[] = {
 +              "test-parse-options <options>",
 +              NULL
 +      };
 +      struct string_list expect = STRING_LIST_INIT_NODUP;
 +      struct option options[] = {
 +              OPT_BOOL(0, "yes", &boolean, "get a boolean"),
 +              OPT_BOOL('D', "no-doubt", &boolean, "begins with 'no-'"),
 +              { OPTION_SET_INT, 'B', "no-fear", &boolean, NULL,
 +                "be brave", PARSE_OPT_NOARG | PARSE_OPT_NONEG, NULL, 1 },
 +              OPT_COUNTUP('b', "boolean", &boolean, "increment by one"),
 +              OPT_BIT('4', "or4", &boolean,
 +                      "bitwise-or boolean with ...0100", 4),
 +              OPT_NEGBIT(0, "neg-or4", &boolean, "same as --no-or4", 4),
 +              OPT_GROUP(""),
 +              OPT_INTEGER('i', "integer", &integer, "get a integer"),
 +              OPT_INTEGER('j', NULL, &integer, "get a integer, too"),
 +              OPT_MAGNITUDE('m', "magnitude", &magnitude, "get a magnitude"),
 +              OPT_SET_INT(0, "set23", &integer, "set integer to 23", 23),
 +              OPT_DATE('t', NULL, &timestamp, "get timestamp of <time>"),
 +              OPT_CALLBACK('L', "length", &integer, "str",
 +                      "get length of <str>", length_callback),
 +              OPT_FILENAME('F', "file", &file, "set file to <file>"),
 +              OPT_GROUP("String options"),
 +              OPT_STRING('s', "string", &string, "string", "get a string"),
 +              OPT_STRING(0, "string2", &string, "str", "get another string"),
 +              OPT_STRING(0, "st", &string, "st", "get another string (pervert ordering)"),
 +              OPT_STRING('o', NULL, &string, "str", "get another string"),
 +              OPT_NOOP_NOARG(0, "obsolete"),
 +              OPT_STRING_LIST(0, "list", &list, "str", "add str to list"),
 +              OPT_GROUP("Magic arguments"),
 +              OPT_ARGUMENT("quux", "means --quux"),
 +              OPT_NUMBER_CALLBACK(&integer, "set integer to NUM",
 +                      number_callback),
 +              { OPTION_COUNTUP, '+', NULL, &boolean, NULL, "same as -b",
 +                PARSE_OPT_NOARG | PARSE_OPT_NONEG | PARSE_OPT_NODASH },
 +              { OPTION_COUNTUP, 0, "ambiguous", &ambiguous, NULL,
 +                "positive ambiguity", PARSE_OPT_NOARG | PARSE_OPT_NONEG },
 +              { OPTION_COUNTUP, 0, "no-ambiguous", &ambiguous, NULL,
 +                "negative ambiguity", PARSE_OPT_NOARG | PARSE_OPT_NONEG },
 +              OPT_GROUP("Standard options"),
 +              OPT__ABBREV(&abbrev),
 +              OPT__VERBOSE(&verbose, "be verbose"),
 +              OPT__DRY_RUN(&dry_run, "dry run"),
 +              OPT__QUIET(&quiet, "be quiet"),
 +              OPT_CALLBACK(0, "expect", &expect, "string",
 +                           "expected output in the variable dump",
 +                           collect_expect),
 +              OPT_END(),
 +      };
 +      int i;
 +      int ret = 0;
 +
 +      argc = parse_options(argc, (const char **)argv, prefix, options, usage, 0);
 +
 +      if (length_cb.called) {
 +              const char *arg = length_cb.arg;
 +              int unset = length_cb.unset;
 +              show(&expect, &ret, "Callback: \"%s\", %d",
 +                   (arg ? arg : "not set"), unset);
 +      }
 +      show(&expect, &ret, "boolean: %d", boolean);
 +      show(&expect, &ret, "integer: %d", integer);
 +      show(&expect, &ret, "magnitude: %lu", magnitude);
 +      show(&expect, &ret, "timestamp: %lu", timestamp);
 +      show(&expect, &ret, "string: %s", string ? string : "(not set)");
 +      show(&expect, &ret, "abbrev: %d", abbrev);
 +      show(&expect, &ret, "verbose: %d", verbose);
 +      show(&expect, &ret, "quiet: %d", quiet);
 +      show(&expect, &ret, "dry run: %s", dry_run ? "yes" : "no");
 +      show(&expect, &ret, "file: %s", file ? file : "(not set)");
 +
 +      for (i = 0; i < list.nr; i++)
 +              show(&expect, &ret, "list: %s", list.items[i].string);
 +
 +      for (i = 0; i < argc; i++)
 +              show(&expect, &ret, "arg %02d: %s", i, argv[i]);
 +
 +      return ret;
 +}
index ba805b374c57a4e5ad2e6e4a4b9071a11c165afa,0000000000000000000000000000000000000000..1ebe0f750c648cd4d92983c11ace9e8a86327dd1
mode 100644,000000..100644
--- /dev/null
@@@ -1,262 -1,0 +1,262 @@@
- int main(int argc, char **argv)
 +#include "cache.h"
 +#include "string-list.h"
 +
 +/*
 + * A "string_list_each_func_t" function that normalizes an entry from
 + * GIT_CEILING_DIRECTORIES.  If the path is unusable for some reason,
 + * die with an explanation.
 + */
 +static int normalize_ceiling_entry(struct string_list_item *item, void *unused)
 +{
 +      char *ceil = item->string;
 +
 +      if (!*ceil)
 +              die("Empty path is not supported");
 +      if (!is_absolute_path(ceil))
 +              die("Path \"%s\" is not absolute", ceil);
 +      if (normalize_path_copy(ceil, ceil) < 0)
 +              die("Path \"%s\" could not be normalized", ceil);
 +      return 1;
 +}
 +
 +static void normalize_argv_string(const char **var, const char *input)
 +{
 +      if (!strcmp(input, "<null>"))
 +              *var = NULL;
 +      else if (!strcmp(input, "<empty>"))
 +              *var = "";
 +      else
 +              *var = input;
 +
 +      if (*var && (**var == '<' || **var == '('))
 +              die("Bad value: %s\n", input);
 +}
 +
 +struct test_data {
 +      const char *from;  /* input:  transform from this ... */
 +      const char *to;    /* output: ... to this.            */
 +      const char *alternative; /* output: ... or this.      */
 +};
 +
 +static int test_function(struct test_data *data, char *(*func)(char *input),
 +      const char *funcname)
 +{
 +      int failed = 0, i;
 +      char buffer[1024];
 +      char *to;
 +
 +      for (i = 0; data[i].to; i++) {
 +              if (!data[i].from)
 +                      to = func(NULL);
 +              else {
 +                      xsnprintf(buffer, sizeof(buffer), "%s", data[i].from);
 +                      to = func(buffer);
 +              }
 +              if (!strcmp(to, data[i].to))
 +                      continue;
 +              if (!data[i].alternative)
 +                      error("FAIL: %s(%s) => '%s' != '%s'\n",
 +                              funcname, data[i].from, to, data[i].to);
 +              else if (!strcmp(to, data[i].alternative))
 +                      continue;
 +              else
 +                      error("FAIL: %s(%s) => '%s' != '%s', '%s'\n",
 +                              funcname, data[i].from, to, data[i].to,
 +                              data[i].alternative);
 +              failed = 1;
 +      }
 +      return failed;
 +}
 +
 +static struct test_data basename_data[] = {
 +      /* --- POSIX type paths --- */
 +      { NULL,              "."    },
 +      { "",                "."    },
 +      { ".",               "."    },
 +      { "..",              ".."   },
 +      { "/",               "/"    },
 +      { "//",              "/", "//" },
 +      { "///",             "/", "//" },
 +      { "////",            "/", "//" },
 +      { "usr",             "usr"  },
 +      { "/usr",            "usr"  },
 +      { "/usr/",           "usr"  },
 +      { "/usr//",          "usr"  },
 +      { "/usr/lib",        "lib"  },
 +      { "usr/lib",         "lib"  },
 +      { "usr/lib///",      "lib"  },
 +
 +#if defined(__MINGW32__) || defined(_MSC_VER)
 +      /* --- win32 type paths --- */
 +      { "\\usr",           "usr"  },
 +      { "\\usr\\",         "usr"  },
 +      { "\\usr\\\\",       "usr"  },
 +      { "\\usr\\lib",      "lib"  },
 +      { "usr\\lib",        "lib"  },
 +      { "usr\\lib\\\\\\",  "lib"  },
 +      { "C:/usr",          "usr"  },
 +      { "C:/usr",          "usr"  },
 +      { "C:/usr/",         "usr"  },
 +      { "C:/usr//",        "usr"  },
 +      { "C:/usr/lib",      "lib"  },
 +      { "C:usr/lib",       "lib"  },
 +      { "C:usr/lib///",    "lib"  },
 +      { "C:",              "."    },
 +      { "C:a",             "a"    },
 +      { "C:/",             "/"    },
 +      { "C:///",           "/"    },
 +      { "\\",              "\\", "/" },
 +      { "\\\\",            "\\", "/" },
 +      { "\\\\\\",          "\\", "/" },
 +#endif
 +      { NULL,              NULL   }
 +};
 +
 +static struct test_data dirname_data[] = {
 +      /* --- POSIX type paths --- */
 +      { NULL,              "."      },
 +      { "",                "."      },
 +      { ".",               "."      },
 +      { "..",              "."      },
 +      { "/",               "/"      },
 +      { "//",              "/", "//" },
 +      { "///",             "/", "//" },
 +      { "////",            "/", "//" },
 +      { "usr",             "."      },
 +      { "/usr",            "/"      },
 +      { "/usr/",           "/"      },
 +      { "/usr//",          "/"      },
 +      { "/usr/lib",        "/usr"   },
 +      { "usr/lib",         "usr"    },
 +      { "usr/lib///",      "usr"    },
 +
 +#if defined(__MINGW32__) || defined(_MSC_VER)
 +      /* --- win32 type paths --- */
 +      { "\\",              "\\"     },
 +      { "\\\\",            "\\\\"   },
 +      { "\\usr",           "\\"     },
 +      { "\\usr\\",         "\\"     },
 +      { "\\usr\\\\",       "\\"     },
 +      { "\\usr\\lib",      "\\usr"  },
 +      { "usr\\lib",        "usr"    },
 +      { "usr\\lib\\\\\\",  "usr"    },
 +      { "C:a",             "C:."    },
 +      { "C:/",             "C:/"    },
 +      { "C:///",           "C:/"    },
 +      { "C:/usr",          "C:/"    },
 +      { "C:/usr/",         "C:/"    },
 +      { "C:/usr//",        "C:/"    },
 +      { "C:/usr/lib",      "C:/usr" },
 +      { "C:usr/lib",       "C:usr"  },
 +      { "C:usr/lib///",    "C:usr"  },
 +      { "\\\\\\",          "\\"     },
 +      { "\\\\\\\\",        "\\"     },
 +      { "C:",              "C:.", "." },
 +#endif
 +      { NULL,              NULL     }
 +};
 +
-               char *prefix = argv[2];
++int cmd_main(int argc, const char **argv)
 +{
 +      if (argc == 3 && !strcmp(argv[1], "normalize_path_copy")) {
 +              char *buf = xmallocz(strlen(argv[2]));
 +              int rv = normalize_path_copy(buf, argv[2]);
 +              if (rv)
 +                      buf = "++failed++";
 +              puts(buf);
 +              return 0;
 +      }
 +
 +      if (argc >= 2 && !strcmp(argv[1], "real_path")) {
 +              while (argc > 2) {
 +                      puts(real_path(argv[2]));
 +                      argc--;
 +                      argv++;
 +              }
 +              return 0;
 +      }
 +
 +      if (argc >= 2 && !strcmp(argv[1], "absolute_path")) {
 +              while (argc > 2) {
 +                      puts(absolute_path(argv[2]));
 +                      argc--;
 +                      argv++;
 +              }
 +              return 0;
 +      }
 +
 +      if (argc == 4 && !strcmp(argv[1], "longest_ancestor_length")) {
 +              int len;
 +              struct string_list ceiling_dirs = STRING_LIST_INIT_DUP;
 +              char *path = xstrdup(argv[2]);
 +
 +              /*
 +               * We have to normalize the arguments because under
 +               * Windows, bash mangles arguments that look like
 +               * absolute POSIX paths or colon-separate lists of
 +               * absolute POSIX paths into DOS paths (e.g.,
 +               * "/foo:/foo/bar" might be converted to
 +               * "D:\Src\msysgit\foo;D:\Src\msysgit\foo\bar"),
 +               * whereas longest_ancestor_length() requires paths
 +               * that use forward slashes.
 +               */
 +              if (normalize_path_copy(path, path))
 +                      die("Path \"%s\" could not be normalized", argv[2]);
 +              string_list_split(&ceiling_dirs, argv[3], PATH_SEP, -1);
 +              filter_string_list(&ceiling_dirs, 0,
 +                                 normalize_ceiling_entry, NULL);
 +              len = longest_ancestor_length(path, &ceiling_dirs);
 +              string_list_clear(&ceiling_dirs, 0);
 +              free(path);
 +              printf("%d\n", len);
 +              return 0;
 +      }
 +
 +      if (argc >= 4 && !strcmp(argv[1], "prefix_path")) {
++              const char *prefix = argv[2];
 +              int prefix_len = strlen(prefix);
 +              int nongit_ok;
 +              setup_git_directory_gently(&nongit_ok);
 +              while (argc > 3) {
 +                      puts(prefix_path(prefix, prefix_len, argv[3]));
 +                      argc--;
 +                      argv++;
 +              }
 +              return 0;
 +      }
 +
 +      if (argc == 4 && !strcmp(argv[1], "strip_path_suffix")) {
 +              char *prefix = strip_path_suffix(argv[2], argv[3]);
 +              printf("%s\n", prefix ? prefix : "(null)");
 +              return 0;
 +      }
 +
 +      if (argc == 3 && !strcmp(argv[1], "print_path")) {
 +              puts(argv[2]);
 +              return 0;
 +      }
 +
 +      if (argc == 4 && !strcmp(argv[1], "relative_path")) {
 +              struct strbuf sb = STRBUF_INIT;
 +              const char *in, *prefix, *rel;
 +              normalize_argv_string(&in, argv[2]);
 +              normalize_argv_string(&prefix, argv[3]);
 +              rel = relative_path(in, prefix, &sb);
 +              if (!rel)
 +                      puts("(null)");
 +              else
 +                      puts(strlen(rel) > 0 ? rel : "(empty)");
 +              strbuf_release(&sb);
 +              return 0;
 +      }
 +
 +      if (argc == 2 && !strcmp(argv[1], "basename"))
 +              return test_function(basename_data, basename, argv[1]);
 +
 +      if (argc == 2 && !strcmp(argv[1], "dirname"))
 +              return test_function(dirname_data, dirname, argv[1]);
 +
 +      fprintf(stderr, "%s: unknown function name: %s\n", argv[0],
 +              argv[1] ? argv[1] : "(there was none)");
 +      return 1;
 +}
index 7be72f0086ba4b80cecf9f324bd5152a8531cdbd,0000000000000000000000000000000000000000..ae58fff35972a09c08a47d2bc0abb67c96ba20eb
mode 100644,000000..100644
--- /dev/null
@@@ -1,39 -1,0 +1,39 @@@
- int main(int argc, char **argv)
 +#include "cache.h"
 +#include "prio-queue.h"
 +
 +static int intcmp(const void *va, const void *vb, void *data)
 +{
 +      const int *a = va, *b = vb;
 +      return *a - *b;
 +}
 +
 +static void show(int *v)
 +{
 +      if (!v)
 +              printf("NULL\n");
 +      else
 +              printf("%d\n", *v);
 +      free(v);
 +}
 +
++int cmd_main(int argc, const char **argv)
 +{
 +      struct prio_queue pq = { intcmp };
 +
 +      while (*++argv) {
 +              if (!strcmp(*argv, "get"))
 +                      show(prio_queue_get(&pq));
 +              else if (!strcmp(*argv, "dump")) {
 +                      int *v;
 +                      while ((v = prio_queue_get(&pq)))
 +                             show(v);
 +              }
 +              else {
 +                      int *v = malloc(sizeof(*v));
 +                      *v = atoi(*argv);
 +                      prio_queue_put(&pq, v);
 +              }
 +      }
 +
 +      return 0;
 +}
index b25bcf139b2bf61292eb9910cb4f92d8ce7763bd,0000000000000000000000000000000000000000..2a7990efc31d042121122a17890c623d7714c128
mode 100644,000000..100644
--- /dev/null
@@@ -1,13 -1,0 +1,13 @@@
- int main (int argc, char **argv)
 +#include "cache.h"
 +
++int cmd_main(int argc, const char **argv)
 +{
 +      int i, cnt = 1;
 +      if (argc == 2)
 +              cnt = strtol(argv[1], NULL, 0);
 +      for (i = 0; i < cnt; i++) {
 +              read_cache();
 +              discard_cache();
 +      }
 +      return 0;
 +}
diff --combined t/helper/test-regex.c
index 0dc598ecdc2696af956b1c517166f9e28b37dc68,0000000000000000000000000000000000000000..37b7f06e552ef51c852f54e70d66c434ca50b6b2
mode 100644,000000..100644
--- /dev/null
@@@ -1,20 -1,0 +1,20 @@@
- int main(int argc, char **argv)
 +#include "git-compat-util.h"
 +
++int cmd_main(int argc, const char **argv)
 +{
 +      char *pat = "[^={} \t]+";
 +      char *str = "={}\nfred";
 +      regex_t r;
 +      regmatch_t m[1];
 +
 +      if (regcomp(&r, pat, REG_EXTENDED | REG_NEWLINE))
 +              die("failed regcomp() for pattern '%s'", pat);
 +      if (regexec(&r, str, 1, m, 0))
 +              die("no match of pattern '%s' to string '%s'", pat, str);
 +
 +      /* http://sourceware.org/bugzilla/show_bug.cgi?id=3957  */
 +      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);
 +}
index 3d0313354b3e100fe3624b58c61af7cc7e0f8e7b,0000000000000000000000000000000000000000..b8e6fe1d007449d30dd30ccd4319b26f151bbf23
mode 100644,000000..100644
--- /dev/null
@@@ -1,68 -1,0 +1,68 @@@
- int main(int argc, char **argv)
 +/*
 + * test-revision-walking.c: test revision walking API.
 + *
 + * (C) 2012 Heiko Voigt <hvoigt@hvoigt.net>
 + *
 + * This code is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License version 2 as
 + * published by the Free Software Foundation.
 + */
 +
 +#include "cache.h"
 +#include "commit.h"
 +#include "diff.h"
 +#include "revision.h"
 +
 +static void print_commit(struct commit *commit)
 +{
 +      struct strbuf sb = STRBUF_INIT;
 +      struct pretty_print_context ctx = {0};
 +      ctx.date_mode.type = DATE_NORMAL;
 +      format_commit_message(commit, " %m %s", &sb, &ctx);
 +      printf("%s\n", sb.buf);
 +      strbuf_release(&sb);
 +}
 +
 +static int run_revision_walk(void)
 +{
 +      struct rev_info rev;
 +      struct commit *commit;
 +      const char *argv[] = {NULL, "--all", NULL};
 +      int argc = ARRAY_SIZE(argv) - 1;
 +      int got_revision = 0;
 +
 +      init_revisions(&rev, NULL);
 +      setup_revisions(argc, argv, &rev, NULL);
 +      if (prepare_revision_walk(&rev))
 +              die("revision walk setup failed");
 +
 +      while ((commit = get_revision(&rev)) != NULL) {
 +              print_commit(commit);
 +              got_revision = 1;
 +      }
 +
 +      reset_revision_walk();
 +      return got_revision;
 +}
 +
++int cmd_main(int argc, const char **argv)
 +{
 +      if (argc < 2)
 +              return 1;
 +
 +      setup_git_directory();
 +
 +      if (!strcmp(argv[1], "run-twice")) {
 +              printf("1st\n");
 +              if (!run_revision_walk())
 +                      return 1;
 +              printf("2nd\n");
 +              if (!run_revision_walk())
 +                      return 1;
 +
 +              return 0;
 +      }
 +
 +      fprintf(stderr, "check usage\n");
 +      return 1;
 +}
index 30a64a98dc8b53a3a2d7edfaa57a8ee51d5d63e7,0000000000000000000000000000000000000000..c71ea4f759bf15253841bda5dd95f0783d0f7ad6
mode 100644,000000..100644
--- /dev/null
@@@ -1,87 -1,0 +1,87 @@@
- int main(int argc, char **argv)
 +/*
 + * test-run-command.c: test run command API.
 + *
 + * (C) 2009 Ilari Liusvaara <ilari.liusvaara@elisanet.fi>
 + *
 + * This code is free software; you can redistribute it and/or modify
 + * it under the terms of the GNU General Public License version 2 as
 + * published by the Free Software Foundation.
 + */
 +
 +#include "git-compat-util.h"
 +#include "run-command.h"
 +#include "argv-array.h"
 +#include "strbuf.h"
 +#include <string.h>
 +#include <errno.h>
 +
 +static int number_callbacks;
 +static int parallel_next(struct child_process *cp,
 +                       struct strbuf *err,
 +                       void *cb,
 +                       void **task_cb)
 +{
 +      struct child_process *d = cb;
 +      if (number_callbacks >= 4)
 +              return 0;
 +
 +      argv_array_pushv(&cp->args, d->argv);
 +      strbuf_addf(err, "preloaded output of a child\n");
 +      number_callbacks++;
 +      return 1;
 +}
 +
 +static int no_job(struct child_process *cp,
 +                struct strbuf *err,
 +                void *cb,
 +                void **task_cb)
 +{
 +      strbuf_addf(err, "no further jobs available\n");
 +      return 0;
 +}
 +
 +static int task_finished(int result,
 +                       struct strbuf *err,
 +                       void *pp_cb,
 +                       void *pp_task_cb)
 +{
 +      strbuf_addf(err, "asking for a quick stop\n");
 +      return 1;
 +}
 +
++int cmd_main(int argc, const char **argv)
 +{
 +      struct child_process proc = CHILD_PROCESS_INIT;
 +      int jobs;
 +
 +      if (argc < 3)
 +              return 1;
 +      proc.argv = (const char **)argv + 2;
 +
 +      if (!strcmp(argv[1], "start-command-ENOENT")) {
 +              if (start_command(&proc) < 0 && errno == ENOENT)
 +                      return 0;
 +              fprintf(stderr, "FAIL %s\n", argv[1]);
 +              return 1;
 +      }
 +      if (!strcmp(argv[1], "run-command"))
 +              exit(run_command(&proc));
 +
 +      jobs = atoi(argv[2]);
 +      proc.argv = (const char **)argv + 3;
 +
 +      if (!strcmp(argv[1], "run-command-parallel"))
 +              exit(run_processes_parallel(jobs, parallel_next,
 +                                          NULL, NULL, &proc));
 +
 +      if (!strcmp(argv[1], "run-command-abort"))
 +              exit(run_processes_parallel(jobs, parallel_next,
 +                                          NULL, task_finished, &proc));
 +
 +      if (!strcmp(argv[1], "run-command-no-jobs"))
 +              exit(run_processes_parallel(jobs, no_job,
 +                                          NULL, task_finished, &proc));
 +
 +      fprintf(stderr, "check usage\n");
 +      return 1;
 +}
index 6efee31a4867b4ff8493161376e5a9cfdd48fe44,0000000000000000000000000000000000000000..5b2fd0990894dd59a074ded5822bbcf215a989aa
mode 100644,000000..100644
--- /dev/null
@@@ -1,17 -1,0 +1,17 @@@
- int main(int ac, char **av)
 +#include "cache.h"
 +#include "lockfile.h"
 +#include "tree.h"
 +#include "cache-tree.h"
 +
 +static struct lock_file index_lock;
 +
++int cmd_main(int ac, const char **av)
 +{
 +      hold_locked_index(&index_lock, 1);
 +      if (read_cache() < 0)
 +              die("unable to read index file");
 +      active_cache_tree = NULL;
 +      if (write_locked_index(&the_index, &index_lock, COMMIT_LOCK))
 +              die("unable to write index file");
 +      return 0;
 +}
index 60ea1d5f14e2572df5716da5815143ed26a5be4b,0000000000000000000000000000000000000000..09f77909716326bdb76a79d3c32d10b74702e1d5
mode 100644,000000..100644
--- /dev/null
@@@ -1,34 -1,0 +1,34 @@@
- int main(int argc, char **argv)
 +#include "cache.h"
 +#include "sha1-array.h"
 +
 +static void print_sha1(const unsigned char sha1[20], void *data)
 +{
 +      puts(sha1_to_hex(sha1));
 +}
 +
++int cmd_main(int argc, const char **argv)
 +{
 +      struct sha1_array array = SHA1_ARRAY_INIT;
 +      struct strbuf line = STRBUF_INIT;
 +
 +      while (strbuf_getline(&line, stdin) != EOF) {
 +              const char *arg;
 +              unsigned char sha1[20];
 +
 +              if (skip_prefix(line.buf, "append ", &arg)) {
 +                      if (get_sha1_hex(arg, sha1))
 +                              die("not a hexadecimal SHA1: %s", arg);
 +                      sha1_array_append(&array, sha1);
 +              } else if (skip_prefix(line.buf, "lookup ", &arg)) {
 +                      if (get_sha1_hex(arg, sha1))
 +                              die("not a hexadecimal SHA1: %s", arg);
 +                      printf("%d\n", sha1_array_lookup(&array, sha1));
 +              } else if (!strcmp(line.buf, "clear"))
 +                      sha1_array_clear(&array);
 +              else if (!strcmp(line.buf, "for_each_unique"))
 +                      sha1_array_for_each_unique(&array, print_sha1, NULL);
 +              else
 +                      die("unknown command: %s", line.buf);
 +      }
 +      return 0;
 +}
diff --combined t/helper/test-sha1.c
index e57eae10bf73baac79fd8b95ddb0ff1b4c8c0cd6,0000000000000000000000000000000000000000..a1c13f54eca0db7d11a5df134d565171d70b8cce
mode 100644,000000..100644
--- /dev/null
@@@ -1,56 -1,0 +1,56 @@@
- int main(int ac, char **av)
 +#include "cache.h"
 +
++int cmd_main(int ac, const char **av)
 +{
 +      git_SHA_CTX ctx;
 +      unsigned char sha1[20];
 +      unsigned bufsz = 8192;
 +      int binary = 0;
 +      char *buffer;
 +
 +      if (ac == 2) {
 +              if (!strcmp(av[1], "-b"))
 +                      binary = 1;
 +              else
 +                      bufsz = strtoul(av[1], NULL, 10) * 1024 * 1024;
 +      }
 +
 +      if (!bufsz)
 +              bufsz = 8192;
 +
 +      while ((buffer = malloc(bufsz)) == NULL) {
 +              fprintf(stderr, "bufsz %u is too big, halving...\n", bufsz);
 +              bufsz /= 2;
 +              if (bufsz < 1024)
 +                      die("OOPS");
 +      }
 +
 +      git_SHA1_Init(&ctx);
 +
 +      while (1) {
 +              ssize_t sz, this_sz;
 +              char *cp = buffer;
 +              unsigned room = bufsz;
 +              this_sz = 0;
 +              while (room) {
 +                      sz = xread(0, cp, room);
 +                      if (sz == 0)
 +                              break;
 +                      if (sz < 0)
 +                              die_errno("test-sha1");
 +                      this_sz += sz;
 +                      cp += sz;
 +                      room -= sz;
 +              }
 +              if (this_sz == 0)
 +                      break;
 +              git_SHA1_Update(&ctx, buffer, this_sz);
 +      }
 +      git_SHA1_Final(sha1, &ctx);
 +
 +      if (binary)
 +              fwrite(sha1, 1, 20, stdout);
 +      else
 +              puts(sha1_to_hex(sha1));
 +      exit(0);
 +}
diff --combined t/helper/test-sigchain.c
index e499fce60ff50069ace6174ef9fa3ca4aff0cdc8,0000000000000000000000000000000000000000..b71edbd4429184b59b4bd1355d5cfb53970a1876
mode 100644,000000..100644
--- /dev/null
@@@ -1,22 -1,0 +1,22 @@@
- int main(int argc, char **argv) {
 +#include "cache.h"
 +#include "sigchain.h"
 +
 +#define X(f) \
 +static void f(int sig) { \
 +      puts(#f); \
 +      fflush(stdout); \
 +      sigchain_pop(sig); \
 +      raise(sig); \
 +}
 +X(one)
 +X(two)
 +X(three)
 +#undef X
 +
++int cmd_main(int argc, const char **argv) {
 +      sigchain_push(SIGTERM, one);
 +      sigchain_push(SIGTERM, two);
 +      sigchain_push(SIGTERM, three);
 +      raise(SIGTERM);
 +      return 0;
 +}
index 14bdf9d2153a98d0b2a5d03395c1adcc166f8a07,0000000000000000000000000000000000000000..4a68967bd126e5ab74ec2b39113cce58e7c021bf
mode 100644,000000..100644
--- /dev/null
@@@ -1,103 -1,0 +1,103 @@@
- int main(int argc, char **argv)
 +#include "cache.h"
 +#include "string-list.h"
 +
 +/*
 + * Parse an argument into a string list.  arg should either be a
 + * ':'-separated list of strings, or "-" to indicate an empty string
 + * list (as opposed to "", which indicates a string list containing a
 + * single empty string).  list->strdup_strings must be set.
 + */
 +static void parse_string_list(struct string_list *list, const char *arg)
 +{
 +      if (!strcmp(arg, "-"))
 +              return;
 +
 +      (void)string_list_split(list, arg, ':', -1);
 +}
 +
 +static void write_list(const struct string_list *list)
 +{
 +      int i;
 +      for (i = 0; i < list->nr; i++)
 +              printf("[%d]: \"%s\"\n", i, list->items[i].string);
 +}
 +
 +static void write_list_compact(const struct string_list *list)
 +{
 +      int i;
 +      if (!list->nr)
 +              printf("-\n");
 +      else {
 +              printf("%s", list->items[0].string);
 +              for (i = 1; i < list->nr; i++)
 +                      printf(":%s", list->items[i].string);
 +              printf("\n");
 +      }
 +}
 +
 +static int prefix_cb(struct string_list_item *item, void *cb_data)
 +{
 +      const char *prefix = (const char *)cb_data;
 +      return starts_with(item->string, prefix);
 +}
 +
++int cmd_main(int argc, const char **argv)
 +{
 +      if (argc == 5 && !strcmp(argv[1], "split")) {
 +              struct string_list list = STRING_LIST_INIT_DUP;
 +              int i;
 +              const char *s = argv[2];
 +              int delim = *argv[3];
 +              int maxsplit = atoi(argv[4]);
 +
 +              i = string_list_split(&list, s, delim, maxsplit);
 +              printf("%d\n", i);
 +              write_list(&list);
 +              string_list_clear(&list, 0);
 +              return 0;
 +      }
 +
 +      if (argc == 5 && !strcmp(argv[1], "split_in_place")) {
 +              struct string_list list = STRING_LIST_INIT_NODUP;
 +              int i;
 +              char *s = xstrdup(argv[2]);
 +              int delim = *argv[3];
 +              int maxsplit = atoi(argv[4]);
 +
 +              i = string_list_split_in_place(&list, s, delim, maxsplit);
 +              printf("%d\n", i);
 +              write_list(&list);
 +              string_list_clear(&list, 0);
 +              free(s);
 +              return 0;
 +      }
 +
 +      if (argc == 4 && !strcmp(argv[1], "filter")) {
 +              /*
 +               * Retain only the items that have the specified prefix.
 +               * Arguments: list|- prefix
 +               */
 +              struct string_list list = STRING_LIST_INIT_DUP;
 +              const char *prefix = argv[3];
 +
 +              parse_string_list(&list, argv[2]);
 +              filter_string_list(&list, 0, prefix_cb, (void *)prefix);
 +              write_list_compact(&list);
 +              string_list_clear(&list, 0);
 +              return 0;
 +      }
 +
 +      if (argc == 3 && !strcmp(argv[1], "remove_duplicates")) {
 +              struct string_list list = STRING_LIST_INIT_DUP;
 +
 +              parse_string_list(&list, argv[2]);
 +              string_list_remove_duplicates(&list, 0);
 +              write_list_compact(&list);
 +              string_list_clear(&list, 0);
 +              return 0;
 +      }
 +
 +      fprintf(stderr, "%s: unknown function name: %s\n", argv[0],
 +              argv[1] ? argv[1] : "(there was none)");
 +      return 1;
 +}
index dab8c27768160d4cfa61c41a95004eb7a8a336b6,0000000000000000000000000000000000000000..2cffded116f77d7c62ee718fa08558b52574a205
mode 100644,000000..100644
--- /dev/null
@@@ -1,76 -1,0 +1,76 @@@
- static void die_usage(int argc, char **argv, const char *msg)
 +#include "cache.h"
 +#include "submodule-config.h"
 +#include "submodule.h"
 +
- int main(int argc, char **argv)
++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]);
 +      exit(1);
 +}
 +
 +static int git_test_config(const char *var, const char *value, void *cb)
 +{
 +      return parse_submodule_config_option(var, value);
 +}
 +
-       char **arg = argv;
++int cmd_main(int argc, const char **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], "--")) {
 +              if (!strcmp(arg[0], "--url"))
 +                      output_url = 1;
 +              if (!strcmp(arg[0], "--name"))
 +                      lookup_name = 1;
 +              arg++;
 +              my_argc--;
 +      }
 +
 +      if (my_argc % 2 != 0)
 +              die_usage(argc, argv, "Wrong number of arguments.");
 +
 +      setup_git_directory();
 +      gitmodules_config();
 +      git_config(git_test_config, NULL);
 +
 +      while (*arg) {
 +              unsigned char commit_sha1[20];
 +              const struct submodule *submodule;
 +              const char *commit;
 +              const char *path_or_name;
 +
 +              commit = arg[0];
 +              path_or_name = arg[1];
 +
 +              if (commit[0] == '\0')
 +                      hashcpy(commit_sha1, null_sha1);
 +              else if (get_sha1(commit, commit_sha1) < 0)
 +                      die_usage(argc, argv, "Commit not found.");
 +
 +              if (lookup_name) {
 +                      submodule = submodule_from_name(commit_sha1, path_or_name);
 +              } else
 +                      submodule = submodule_from_path(commit_sha1, path_or_name);
 +              if (!submodule)
 +                      die_usage(argc, argv, "Submodule not found.");
 +
 +              if (output_url)
 +                      printf("Submodule url: '%s' for path '%s'\n",
 +                                      submodule->url, submodule->path);
 +              else
 +                      printf("Submodule name: '%s' for path '%s'\n",
 +                                      submodule->name, submodule->path);
 +
 +              arg += 2;
 +      }
 +
 +      submodule_free();
 +
 +      return 0;
 +}
index 56881a032471752ca16880d98ea1510e16d38eed,0000000000000000000000000000000000000000..30c5765bfc3590421c21bc2350eed882752de3a0
mode 100644,000000..100644
--- /dev/null
@@@ -1,19 -1,0 +1,19 @@@
- int main(int argc, char **argv)
 +#include "cache.h"
 +#include "run-command.h"
 +
++int cmd_main(int argc, const char **argv)
 +{
 +      struct child_process cp = CHILD_PROCESS_INIT;
 +      int nogit = 0;
 +
 +      setup_git_directory_gently(&nogit);
 +      if (nogit)
 +              die("No git repo found");
 +      if (argc > 1 && !strcmp(argv[1], "--setup-work-tree")) {
 +              setup_work_tree();
 +              argv++;
 +      }
 +      cp.git_cmd = 1;
 +      cp.argv = (const char **)argv + 1;
 +      return run_command(&cp);
 +}
diff --combined t/helper/test-svn-fe.c
index 120ec96b0dbd94e7be9ffc81d0fb87ccbd30a7df,0000000000000000000000000000000000000000..7667c0803f1231152190a1a5b4c61a2fb2677048
mode 100644,000000..100644
--- /dev/null
@@@ -1,52 -1,0 +1,52 @@@
- static int apply_delta(int argc, char *argv[])
 +/*
 + * test-svn-fe: Code to exercise the svn import lib
 + */
 +
 +#include "git-compat-util.h"
 +#include "vcs-svn/svndump.h"
 +#include "vcs-svn/svndiff.h"
 +#include "vcs-svn/sliding_window.h"
 +#include "vcs-svn/line_buffer.h"
 +
 +static const char test_svnfe_usage[] =
 +      "test-svn-fe (<dumpfile> | [-d] <preimage> <delta> <len>)";
 +
- int main(int argc, char *argv[])
++static int apply_delta(int argc, const char **argv)
 +{
 +      struct line_buffer preimage = LINE_BUFFER_INIT;
 +      struct line_buffer delta = LINE_BUFFER_INIT;
 +      struct sliding_view preimage_view = SLIDING_VIEW_INIT(&preimage, -1);
 +
 +      if (argc != 5)
 +              usage(test_svnfe_usage);
 +
 +      if (buffer_init(&preimage, argv[2]))
 +              die_errno("cannot open preimage");
 +      if (buffer_init(&delta, argv[3]))
 +              die_errno("cannot open delta");
 +      if (svndiff0_apply(&delta, (off_t) strtoumax(argv[4], NULL, 0),
 +                                      &preimage_view, stdout))
 +              return 1;
 +      if (buffer_deinit(&preimage))
 +              die_errno("cannot close preimage");
 +      if (buffer_deinit(&delta))
 +              die_errno("cannot close delta");
 +      strbuf_release(&preimage_view.buf);
 +      return 0;
 +}
 +
++int cmd_main(int argc, const char **argv)
 +{
 +      if (argc == 2) {
 +              if (svndump_init(argv[1]))
 +                      return 1;
 +              svndump_read(NULL, "refs/heads/master", "refs/notes/svn/revs");
 +              svndump_deinit();
 +              svndump_reset();
 +              return 0;
 +      }
 +
 +      if (argc >= 2 && !strcmp(argv[1], "-d"))
 +              return apply_delta(argc, argv);
 +      usage(test_svnfe_usage);
 +}
index 090bf219a7d499ae246f80c0d478eb37fdef8f8f,0000000000000000000000000000000000000000..49b6e836be257c0689601bf17138439cff0d61a0
mode 100644,000000..100644
--- /dev/null
@@@ -1,50 -1,0 +1,50 @@@
- int main(int argc, char **argv)
 +#include "git-compat-util.h"
 +#include "urlmatch.h"
 +
++int cmd_main(int argc, const char **argv)
 +{
 +      const char usage[] = "test-urlmatch-normalization [-p | -l] <url1> | <url1> <url2>";
 +      char *url1, *url2;
 +      int opt_p = 0, opt_l = 0;
 +
 +      /*
 +       * For one url, succeed if url_normalize succeeds on it, fail otherwise.
 +       * For two urls, succeed only if url_normalize succeeds on both and
 +       * the results compare equal with strcmp.  If -p is given (one url only)
 +       * and url_normalize succeeds, print the result followed by "\n".  If
 +       * -l is given (one url only) and url_normalize succeeds, print the
 +       * returned length in decimal followed by "\n".
 +       */
 +
 +      if (argc > 1 && !strcmp(argv[1], "-p")) {
 +              opt_p = 1;
 +              argc--;
 +              argv++;
 +      } else if (argc > 1 && !strcmp(argv[1], "-l")) {
 +              opt_l = 1;
 +              argc--;
 +              argv++;
 +      }
 +
 +      if (argc < 2 || argc > 3)
 +              die("%s", usage);
 +
 +      if (argc == 2) {
 +              struct url_info info;
 +              url1 = url_normalize(argv[1], &info);
 +              if (!url1)
 +                      return 1;
 +              if (opt_p)
 +                      printf("%s\n", url1);
 +              if (opt_l)
 +                      printf("%u\n", (unsigned)info.url_len);
 +              return 0;
 +      }
 +
 +      if (opt_p || opt_l)
 +              die("%s", usage);
 +
 +      url1 = url_normalize(argv[1], NULL);
 +      url2 = url_normalize(argv[2], NULL);
 +      return (url1 && url2 && !strcmp(url1, url2)) ? 0 : 1;
 +}
index 578b164fe603f11dfe67e25be36a6ab38aa6d645,0000000000000000000000000000000000000000..52be876fed3bcc3bb5a1def5de8febe8b29c0ec4
mode 100644,000000..100644
--- /dev/null
@@@ -1,21 -1,0 +1,21 @@@
- int main(int argc, char **argv)
 +#include "cache.h"
 +
++int cmd_main(int argc, const char **argv)
 +{
 +      int i;
 +      for (i = 2; i < argc; i++) {
 +              if (argv[i][0] == '/')
 +                      die("Forward slash is not allowed at the beginning of the\n"
 +                          "pattern because Windows does not like it. Use `XXX/' instead.");
 +              else if (!strncmp(argv[i], "XXX/", 4))
 +                      argv[i] += 3;
 +      }
 +      if (!strcmp(argv[1], "wildmatch"))
 +              return !!wildmatch(argv[3], argv[2], WM_PATHNAME, NULL);
 +      else if (!strcmp(argv[1], "iwildmatch"))
 +              return !!wildmatch(argv[3], argv[2], WM_PATHNAME | WM_CASEFOLD, NULL);
 +      else if (!strcmp(argv[1], "pathmatch"))
 +              return !!wildmatch(argv[3], argv[2], 0, NULL);
 +      else
 +              return 1;
 +}
diff --combined upload-pack.c
index f19444df7bc9c19da4d2f3bf831525f7a5d6034d,f0a0fdaf71f69043323b237ae6acc9be87cb7fdf..b97a7659d1f2ffeb8e63fa46a17ca1501db983ab
@@@ -174,7 -174,8 +174,7 @@@ static void create_pack_file(void
  
                if (ret < 0) {
                        if (errno != EINTR) {
 -                              error("poll failed, resuming: %s",
 -                                    strerror(errno));
 +                              error_errno("poll failed, resuming");
                                sleep(1);
                        }
                        continue;
@@@ -816,20 -817,17 +816,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;