builtin / merge-index.con commit rev-parse: let some options run outside repository (fc7d47f)
   1#include "builtin.h"
   2#include "run-command.h"
   3
   4static const char *pgm;
   5static int one_shot, quiet;
   6static int err;
   7
   8static int merge_entry(int pos, const char *path)
   9{
  10        int found;
  11        const char *arguments[] = { pgm, "", "", "", path, "", "", "", NULL };
  12        char hexbuf[4][GIT_SHA1_HEXSZ + 1];
  13        char ownbuf[4][60];
  14
  15        if (pos >= active_nr)
  16                die("git merge-index: %s not in the cache", path);
  17        found = 0;
  18        do {
  19                const struct cache_entry *ce = active_cache[pos];
  20                int stage = ce_stage(ce);
  21
  22                if (strcmp(ce->name, path))
  23                        break;
  24                found++;
  25                sha1_to_hex_r(hexbuf[stage], ce->sha1);
  26                xsnprintf(ownbuf[stage], sizeof(ownbuf[stage]), "%o", ce->ce_mode);
  27                arguments[stage] = hexbuf[stage];
  28                arguments[stage + 4] = ownbuf[stage];
  29        } while (++pos < active_nr);
  30        if (!found)
  31                die("git merge-index: %s not in the cache", path);
  32
  33        if (run_command_v_opt(arguments, 0)) {
  34                if (one_shot)
  35                        err++;
  36                else {
  37                        if (!quiet)
  38                                die("merge program failed");
  39                        exit(1);
  40                }
  41        }
  42        return found;
  43}
  44
  45static void merge_one_path(const char *path)
  46{
  47        int pos = cache_name_pos(path, strlen(path));
  48
  49        /*
  50         * If it already exists in the cache as stage0, it's
  51         * already merged and there is nothing to do.
  52         */
  53        if (pos < 0)
  54                merge_entry(-pos-1, path);
  55}
  56
  57static void merge_all(void)
  58{
  59        int i;
  60        for (i = 0; i < active_nr; i++) {
  61                const struct cache_entry *ce = active_cache[i];
  62                if (!ce_stage(ce))
  63                        continue;
  64                i += merge_entry(i, ce->name)-1;
  65        }
  66}
  67
  68int cmd_merge_index(int argc, const char **argv, const char *prefix)
  69{
  70        int i, force_file = 0;
  71
  72        /* Without this we cannot rely on waitpid() to tell
  73         * what happened to our children.
  74         */
  75        signal(SIGCHLD, SIG_DFL);
  76
  77        if (argc < 3)
  78                usage("git merge-index [-o] [-q] <merge-program> (-a | [--] [<filename>...])");
  79
  80        read_cache();
  81
  82        i = 1;
  83        if (!strcmp(argv[i], "-o")) {
  84                one_shot = 1;
  85                i++;
  86        }
  87        if (!strcmp(argv[i], "-q")) {
  88                quiet = 1;
  89                i++;
  90        }
  91        pgm = argv[i++];
  92        for (; i < argc; i++) {
  93                const char *arg = argv[i];
  94                if (!force_file && *arg == '-') {
  95                        if (!strcmp(arg, "--")) {
  96                                force_file = 1;
  97                                continue;
  98                        }
  99                        if (!strcmp(arg, "-a")) {
 100                                merge_all();
 101                                continue;
 102                        }
 103                        die("git merge-index: unknown option %s", arg);
 104                }
 105                merge_one_path(arg);
 106        }
 107        if (err && !quiet)
 108                die("merge program failed");
 109        return err;
 110}