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