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