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