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