Use the spawn workhorse instead of a fork()/exec() pair.
[git/mingw.git] / merge-index.c
blob6c2e00842e3cea39b22a21d71e8ca763ecce98b5
1 #include "cache.h"
2 #include "spawn-pipe.h"
4 static const char *pgm;
5 static const char *arguments[9]; /* last one is always NULL */
6 static int one_shot, quiet;
7 static int err;
9 static void run_program(void)
11 pid_t pid = spawnvpe_pipe(pgm, arguments, environ, NULL, NULL);
12 int status;
14 if (waitpid(pid, &status, 0) < 0 || !WIFEXITED(status) || WEXITSTATUS(status)) {
15 if (one_shot) {
16 err++;
17 } else {
18 if (!quiet)
19 die("merge program failed");
20 exit(1);
25 static int merge_entry(int pos, const char *path)
27 int found;
29 if (pos >= active_nr)
30 die("git-merge-index: %s not in the cache", path);
31 arguments[1] = "";
32 arguments[2] = "";
33 arguments[3] = "";
34 arguments[4] = path;
35 arguments[5] = "";
36 arguments[6] = "";
37 arguments[7] = "";
38 found = 0;
39 do {
40 static char hexbuf[4][60];
41 static char ownbuf[4][60];
42 struct cache_entry *ce = active_cache[pos];
43 int stage = ce_stage(ce);
45 if (strcmp(ce->name, path))
46 break;
47 found++;
48 strcpy(hexbuf[stage], sha1_to_hex(ce->sha1));
49 sprintf(ownbuf[stage], "%o", ntohl(ce->ce_mode) & (~S_IFMT));
50 arguments[stage] = hexbuf[stage];
51 arguments[stage + 4] = ownbuf[stage];
52 } while (++pos < active_nr);
53 if (!found)
54 die("git-merge-index: %s not in the cache", path);
55 run_program();
56 return found;
59 static void merge_file(const char *path)
61 int pos = cache_name_pos(path, strlen(path));
64 * If it already exists in the cache as stage0, it's
65 * already merged and there is nothing to do.
67 if (pos < 0)
68 merge_entry(-pos-1, path);
71 static void merge_all(void)
73 int i;
74 for (i = 0; i < active_nr; i++) {
75 struct cache_entry *ce = active_cache[i];
76 if (!ce_stage(ce))
77 continue;
78 i += merge_entry(i, ce->name)-1;
82 int main(int argc, char **argv)
84 int i, force_file = 0;
86 /* Without this we cannot rely on waitpid() to tell
87 * what happened to our children.
89 signal(SIGCHLD, SIG_DFL);
91 if (argc < 3)
92 usage("git-merge-index [-o] [-q] <merge-program> (-a | <filename>*)");
94 setup_git_directory();
95 read_cache();
97 i = 1;
98 if (!strcmp(argv[i], "-o")) {
99 one_shot = 1;
100 i++;
102 if (!strcmp(argv[i], "-q")) {
103 quiet = 1;
104 i++;
106 pgm = argv[i++];
107 for (; i < argc; i++) {
108 char *arg = argv[i];
109 if (!force_file && *arg == '-') {
110 if (!strcmp(arg, "--")) {
111 force_file = 1;
112 continue;
114 if (!strcmp(arg, "-a")) {
115 merge_all();
116 continue;
118 die("git-merge-index: unknown option %s", arg);
120 merge_file(arg);
122 if (err && !quiet)
123 die("merge program failed");
124 return err;