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