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
|
#define USE_THE_REPOSITORY_VARIABLE
#define DISABLE_SIGN_COMPARE_WARNINGS
#include "builtin.h"
#include "hex.h"
#include "read-cache-ll.h"
#include "run-command.h"
#include "sparse-index.h"
static const char *pgm;
static int one_shot, quiet;
static int err;
static int merge_entry(int pos, const char *path)
{
int found;
const char *arguments[] = { pgm, "", "", "", path, "", "", "", NULL };
char hexbuf[4][GIT_MAX_HEXSZ + 1];
char ownbuf[4][60];
struct child_process cmd = CHILD_PROCESS_INIT;
if (pos >= the_repository->index->cache_nr)
die("git merge-index: %s not in the cache", path);
found = 0;
do {
const struct cache_entry *ce = the_repository->index->cache[pos];
int stage = ce_stage(ce);
if (strcmp(ce->name, path))
break;
found++;
oid_to_hex_r(hexbuf[stage], &ce->oid);
xsnprintf(ownbuf[stage], sizeof(ownbuf[stage]), "%o", ce->ce_mode);
arguments[stage] = hexbuf[stage];
arguments[stage + 4] = ownbuf[stage];
} while (++pos < the_repository->index->cache_nr);
if (!found)
die("git merge-index: %s not in the cache", path);
strvec_pushv(&cmd.args, arguments);
if (run_command(&cmd)) {
if (one_shot)
err++;
else {
if (!quiet)
die("merge program failed");
exit(1);
}
}
return found;
}
static void merge_one_path(const char *path)
{
int pos = index_name_pos(the_repository->index, 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;
/* TODO: audit for interaction with sparse-index. */
ensure_full_index(the_repository->index);
for (i = 0; i < the_repository->index->cache_nr; i++) {
const struct cache_entry *ce = the_repository->index->cache[i];
if (!ce_stage(ce))
continue;
i += merge_entry(i, ce->name)-1;
}
}
static const char usage_string[] =
"git merge-index [-o] [-q] <merge-program> (-a | [--] [<filename>...])";
int cmd_merge_index(int argc,
const char **argv,
const char *prefix UNUSED,
struct repository *repo UNUSED)
{
int i, force_file = 0;
/* Without this we cannot rely on waitpid() to tell
* what happened to our children.
*/
signal(SIGCHLD, SIG_DFL);
show_usage_if_asked(argc, argv, usage_string);
if (argc < 3)
usage(usage_string);
repo_read_index(the_repository);
/* TODO: audit for interaction with sparse-index. */
ensure_full_index(the_repository->index);
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++) {
const 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_one_path(arg);
}
if (err && !quiet)
die("merge program failed");
return err;
}
|