1#include "cache.h"
2#include "run-command.h"
34
static const char *pgm;
5static const char *arguments[9];
6static int one_shot, quiet;
7static int err;
89
static void run_program(void)
10{
11struct child_process child;
12memset(&child, 0, sizeof(child));
13child.argv = arguments;
14if (run_command(&child)) {
15if (one_shot) {
16err++;
17} else {
18if (!quiet)
19die("merge program failed");
20exit(1);
21}
22}
23}
2425
static int merge_entry(int pos, const char *path)
26{
27int found;
2829
if (pos >= active_nr)
30die("git-merge-index: %s not in the cache", path);
31arguments[0] = pgm;
32arguments[1] = "";
33arguments[2] = "";
34arguments[3] = "";
35arguments[4] = path;
36arguments[5] = "";
37arguments[6] = "";
38arguments[7] = "";
39arguments[8] = NULL;
40found = 0;
41do {
42static char hexbuf[4][60];
43static char ownbuf[4][60];
44struct cache_entry *ce = active_cache[pos];
45int stage = ce_stage(ce);
4647
if (strcmp(ce->name, path))
48break;
49found++;
50strcpy(hexbuf[stage], sha1_to_hex(ce->sha1));
51sprintf(ownbuf[stage], "%o", ce->ce_mode);
52arguments[stage] = hexbuf[stage];
53arguments[stage + 4] = ownbuf[stage];
54} while (++pos < active_nr);
55if (!found)
56die("git-merge-index: %s not in the cache", path);
57run_program();
58return found;
59}
6061
static void merge_file(const char *path)
62{
63int pos = cache_name_pos(path, strlen(path));
6465
/*
66* If it already exists in the cache as stage0, it's
67* already merged and there is nothing to do.
68*/
69if (pos < 0)
70merge_entry(-pos-1, path);
71}
7273
static void merge_all(void)
74{
75int i;
76for (i = 0; i < active_nr; i++) {
77struct cache_entry *ce = active_cache[i];
78if (!ce_stage(ce))
79continue;
80i += merge_entry(i, ce->name)-1;
81}
82}
8384
int main(int argc, char **argv)
85{
86int i, force_file = 0;
8788
/* Without this we cannot rely on waitpid() to tell
89* what happened to our children.
90*/
91signal(SIGCHLD, SIG_DFL);
9293
if (argc < 3)
94usage("git-merge-index [-o] [-q] <merge-program> (-a | <filename>*)");
9596
setup_git_directory();
97read_cache();
9899
i = 1;
100if (!strcmp(argv[i], "-o")) {
101one_shot = 1;
102i++;
103}
104if (!strcmp(argv[i], "-q")) {
105quiet = 1;
106i++;
107}
108pgm = argv[i++];
109for (; i < argc; i++) {
110char *arg = argv[i];
111if (!force_file && *arg == '-') {
112if (!strcmp(arg, "--")) {
113force_file = 1;
114continue;
115}
116if (!strcmp(arg, "-a")) {
117merge_all();
118continue;
119}
120die("git-merge-index: unknown option %s", arg);
121}
122merge_file(arg);
123}
124if (err && !quiet)
125die("merge program failed");
126return err;
127}