merge-index.con commit Merge branch 'maint' (7a6a5e4)
   1#include <sys/types.h>
   2#include <sys/wait.h>
   3#include <signal.h>
   4
   5#include "cache.h"
   6
   7static const char *pgm;
   8static const char *arguments[8];
   9static int one_shot, quiet;
  10static int err;
  11
  12static void run_program(void)
  13{
  14        pid_t pid = fork();
  15        int status;
  16
  17        if (pid < 0)
  18                die("unable to fork");
  19        if (!pid) {
  20                execlp(pgm, arguments[0],
  21                            arguments[1],
  22                            arguments[2],
  23                            arguments[3],
  24                            arguments[4],
  25                            arguments[5],
  26                            arguments[6],
  27                            arguments[7],
  28                            NULL);
  29                die("unable to execute '%s'", pgm);
  30        }
  31        if (waitpid(pid, &status, 0) < 0 || !WIFEXITED(status) || WEXITSTATUS(status)) {
  32                if (one_shot) {
  33                        err++;
  34                } else {
  35                        if (!quiet)
  36                                die("merge program failed");
  37                        exit(1);
  38                }
  39        }
  40}
  41
  42static int merge_entry(int pos, const char *path)
  43{
  44        int found;
  45        
  46        if (pos >= active_nr)
  47                die("git-merge-index: %s not in the cache", path);
  48        arguments[0] = pgm;
  49        arguments[1] = "";
  50        arguments[2] = "";
  51        arguments[3] = "";
  52        arguments[4] = path;
  53        arguments[5] = "";
  54        arguments[6] = "";
  55        arguments[7] = "";
  56        found = 0;
  57        do {
  58                static char hexbuf[4][60];
  59                static char ownbuf[4][60];
  60                struct cache_entry *ce = active_cache[pos];
  61                int stage = ce_stage(ce);
  62
  63                if (strcmp(ce->name, path))
  64                        break;
  65                found++;
  66                strcpy(hexbuf[stage], sha1_to_hex(ce->sha1));
  67                sprintf(ownbuf[stage], "%o", ntohl(ce->ce_mode) & (~S_IFMT));
  68                arguments[stage] = hexbuf[stage];
  69                arguments[stage + 4] = ownbuf[stage];
  70        } while (++pos < active_nr);
  71        if (!found)
  72                die("git-merge-index: %s not in the cache", path);
  73        run_program();
  74        return found;
  75}
  76
  77static void merge_file(const char *path)
  78{
  79        int pos = cache_name_pos(path, strlen(path));
  80
  81        /*
  82         * If it already exists in the cache as stage0, it's
  83         * already merged and there is nothing to do.
  84         */
  85        if (pos < 0)
  86                merge_entry(-pos-1, path);
  87}
  88
  89static void merge_all(void)
  90{
  91        int i;
  92        for (i = 0; i < active_nr; i++) {
  93                struct cache_entry *ce = active_cache[i];
  94                if (!ce_stage(ce))
  95                        continue;
  96                i += merge_entry(i, ce->name)-1;
  97        }
  98}
  99
 100int main(int argc, char **argv)
 101{
 102        int i, force_file = 0;
 103
 104        /* Without this we cannot rely on waitpid() to tell
 105         * what happened to our children.
 106         */
 107        signal(SIGCHLD, SIG_DFL);
 108
 109        if (argc < 3)
 110                usage("git-merge-index [-o] [-q] <merge-program> (-a | <filename>*)");
 111
 112        setup_git_directory();
 113        read_cache();
 114
 115        i = 1;
 116        if (!strcmp(argv[i], "-o")) {
 117                one_shot = 1;
 118                i++;
 119        }
 120        if (!strcmp(argv[i], "-q")) {
 121                quiet = 1;
 122                i++;
 123        }
 124        pgm = argv[i++];
 125        for (; i < argc; i++) {
 126                char *arg = argv[i];
 127                if (!force_file && *arg == '-') {
 128                        if (!strcmp(arg, "--")) {
 129                                force_file = 1;
 130                                continue;
 131                        }
 132                        if (!strcmp(arg, "-a")) {
 133                                merge_all();
 134                                continue;
 135                        }
 136                        die("git-merge-index: unknown option %s", arg);
 137                }
 138                merge_file(arg);
 139        }
 140        if (err && !quiet)
 141                die("merge program failed");
 142        return err;
 143}