Git fork
1#define USE_THE_REPOSITORY_VARIABLE
2#define DISABLE_SIGN_COMPARE_WARNINGS
3
4#include "builtin.h"
5#include "hex.h"
6#include "read-cache-ll.h"
7#include "run-command.h"
8#include "sparse-index.h"
9
10static const char *pgm;
11static int one_shot, quiet;
12static int err;
13
14static int merge_entry(int pos, const char *path)
15{
16 int found;
17 const char *arguments[] = { pgm, "", "", "", path, "", "", "", NULL };
18 char hexbuf[4][GIT_MAX_HEXSZ + 1];
19 char ownbuf[4][60];
20 struct child_process cmd = CHILD_PROCESS_INIT;
21
22 if (pos >= the_repository->index->cache_nr)
23 die("git merge-index: %s not in the cache", path);
24 found = 0;
25 do {
26 const struct cache_entry *ce = the_repository->index->cache[pos];
27 int stage = ce_stage(ce);
28
29 if (strcmp(ce->name, path))
30 break;
31 found++;
32 oid_to_hex_r(hexbuf[stage], &ce->oid);
33 xsnprintf(ownbuf[stage], sizeof(ownbuf[stage]), "%o", ce->ce_mode);
34 arguments[stage] = hexbuf[stage];
35 arguments[stage + 4] = ownbuf[stage];
36 } while (++pos < the_repository->index->cache_nr);
37 if (!found)
38 die("git merge-index: %s not in the cache", path);
39
40 strvec_pushv(&cmd.args, arguments);
41 if (run_command(&cmd)) {
42 if (one_shot)
43 err++;
44 else {
45 if (!quiet)
46 die("merge program failed");
47 exit(1);
48 }
49 }
50 return found;
51}
52
53static void merge_one_path(const char *path)
54{
55 int pos = index_name_pos(the_repository->index, path, strlen(path));
56
57 /*
58 * If it already exists in the cache as stage0, it's
59 * already merged and there is nothing to do.
60 */
61 if (pos < 0)
62 merge_entry(-pos-1, path);
63}
64
65static void merge_all(void)
66{
67 int i;
68 /* TODO: audit for interaction with sparse-index. */
69 ensure_full_index(the_repository->index);
70 for (i = 0; i < the_repository->index->cache_nr; i++) {
71 const struct cache_entry *ce = the_repository->index->cache[i];
72 if (!ce_stage(ce))
73 continue;
74 i += merge_entry(i, ce->name)-1;
75 }
76}
77
78static const char usage_string[] =
79"git merge-index [-o] [-q] <merge-program> (-a | [--] [<filename>...])";
80
81int cmd_merge_index(int argc,
82 const char **argv,
83 const char *prefix UNUSED,
84 struct repository *repo UNUSED)
85{
86 int i, force_file = 0;
87
88 /* Without this we cannot rely on waitpid() to tell
89 * what happened to our children.
90 */
91 signal(SIGCHLD, SIG_DFL);
92
93 show_usage_if_asked(argc, argv, usage_string);
94
95 if (argc < 3)
96 usage(usage_string);
97
98 repo_read_index(the_repository);
99
100 /* TODO: audit for interaction with sparse-index. */
101 ensure_full_index(the_repository->index);
102
103 i = 1;
104 if (!strcmp(argv[i], "-o")) {
105 one_shot = 1;
106 i++;
107 }
108 if (!strcmp(argv[i], "-q")) {
109 quiet = 1;
110 i++;
111 }
112 pgm = argv[i++];
113 for (; i < argc; i++) {
114 const char *arg = argv[i];
115 if (!force_file && *arg == '-') {
116 if (!strcmp(arg, "--")) {
117 force_file = 1;
118 continue;
119 }
120 if (!strcmp(arg, "-a")) {
121 merge_all();
122 continue;
123 }
124 die("git merge-index: unknown option %s", arg);
125 }
126 merge_one_path(arg);
127 }
128 if (err && !quiet)
129 die("merge program failed");
130 return err;
131}