[PATCH] git-tar-tree: add a test case
[git.git] / checkout-cache.c
1 /*
2  * Check-out files from the "current cache directory"
3  *
4  * Copyright (C) 2005 Linus Torvalds
5  *
6  * Careful: order of argument flags does matter. For example,
7  *
8  *      git-checkout-cache -a -f file.c
9  *
10  * Will first check out all files listed in the cache (but not
11  * overwrite any old ones), and then force-checkout "file.c" a
12  * second time (ie that one _will_ overwrite any old contents
13  * with the same filename).
14  *
15  * Also, just doing "git-checkout-cache" does nothing. You probably
16  * meant "git-checkout-cache -a". And if you want to force it, you
17  * want "git-checkout-cache -f -a".
18  *
19  * Intuitiveness is not the goal here. Repeatability is. The
20  * reason for the "no arguments means no work" thing is that
21  * from scripts you are supposed to be able to do things like
22  *
23  *      find . -name '*.h' -print0 | xargs -0 git-checkout-cache -f --
24  *
25  * which will force all existing *.h files to be replaced with
26  * their cached copies. If an empty command line implied "all",
27  * then this would force-refresh everything in the cache, which
28  * was not the point.
29  *
30  * Oh, and the "--" is just a good idea when you know the rest
31  * will be filenames. Just so that you wouldn't have a filename
32  * of "-a" causing problems (not possible in the above example,
33  * but get used to it in scripting!).
34  */
35 #include <sys/types.h>
36 #include <dirent.h>
37 #include "cache.h"
38
39 static int force = 0, quiet = 0, not_new = 0, refresh_cache = 0;
40 static const char *base_dir = "";
41 static int base_dir_len = 0;
42
43 static void create_directories(const char *path)
44 {
45         int len = strlen(path);
46         char *buf = xmalloc(len + 1);
47         const char *slash = path;
48
49         while ((slash = strchr(slash+1, '/')) != NULL) {
50                 len = slash - path;
51                 memcpy(buf, path, len);
52                 buf[len] = 0;
53                 if (mkdir(buf, 0755)) {
54                         if (errno == EEXIST) {
55                                 struct stat st;
56                                 if (len > base_dir_len && force && !unlink(buf) && !mkdir(buf, 0755))
57                                         continue;
58                                 if (!stat(buf, &st) && S_ISDIR(st.st_mode))
59                                         continue; /* ok */
60                         }
61                         die("cannot create directory at %s", buf);
62                 }
63         }
64         free(buf);
65 }
66
67 static void remove_subtree(const char *path)
68 {
69         DIR *dir = opendir(path);
70         struct dirent *de;
71         char pathbuf[PATH_MAX];
72         char *name;
73         
74         if (!dir)
75                 die("cannot opendir %s", path);
76         strcpy(pathbuf, path);
77         name = pathbuf + strlen(path);
78         *name++ = '/';
79         while ((de = readdir(dir)) != NULL) {
80                 struct stat st;
81                 if ((de->d_name[0] == '.') &&
82                     ((de->d_name[1] == 0) ||
83                      ((de->d_name[1] == '.') && de->d_name[2] == 0)))
84                         continue;
85                 strcpy(name, de->d_name);
86                 if (lstat(pathbuf, &st))
87                         die("cannot lstat %s", pathbuf);
88                 if (S_ISDIR(st.st_mode))
89                         remove_subtree(pathbuf);
90                 else if (unlink(pathbuf))
91                         die("cannot unlink %s", pathbuf);
92         }
93         closedir(dir);
94         if (rmdir(path))
95                 die("cannot rmdir %s", path);
96 }
97
98 static int create_file(const char *path, unsigned int mode)
99 {
100         int fd;
101
102         mode = (mode & 0100) ? 0777 : 0666;
103         create_directories(path);
104         fd = open(path, O_WRONLY | O_TRUNC | O_CREAT, mode);
105         if (fd < 0) {
106                 if (errno == EISDIR && force) {
107                         remove_subtree(path);
108                         fd = open(path, O_WRONLY | O_TRUNC | O_CREAT, mode);
109                 }
110         }
111         return fd;
112 }
113
114 static int write_entry(struct cache_entry *ce, const char *path)
115 {
116         int fd;
117         void *new;
118         unsigned long size;
119         long wrote;
120         char type[20];
121         char target[1024];
122
123         new = read_sha1_file(ce->sha1, type, &size);
124         if (!new || strcmp(type, "blob")) {
125                 if (new)
126                         free(new);
127                 return error("git-checkout-cache: unable to read sha1 file of %s (%s)",
128                         path, sha1_to_hex(ce->sha1));
129         }
130         switch (ntohl(ce->ce_mode) & S_IFMT) {
131         case S_IFREG:
132                 fd = create_file(path, ntohl(ce->ce_mode));
133                 if (fd < 0) {
134                         free(new);
135                         return error("git-checkout-cache: unable to create file %s (%s)",
136                                 path, strerror(errno));
137                 }
138                 wrote = write(fd, new, size);
139                 close(fd);
140                 free(new);
141                 if (wrote != size)
142                         return error("git-checkout-cache: unable to write file %s", path);
143                 break;
144         case S_IFLNK:
145                 memcpy(target, new, size);
146                 target[size] = '\0';
147                 create_directories(path);
148                 if (symlink(target, path)) {
149                         free(new);
150                         return error("git-checkout-cache: unable to create symlink %s (%s)",
151                                 path, strerror(errno));
152                 }
153                 free(new);
154                 break;
155         default:
156                 free(new);
157                 return error("git-checkout-cache: unknown file mode for %s", path);
158         }
159
160         if (refresh_cache) {
161                 struct stat st;
162                 lstat(ce->name, &st);
163                 fill_stat_cache_info(ce, &st);
164         }
165         return 0;
166 }
167
168 static int checkout_entry(struct cache_entry *ce)
169 {
170         struct stat st;
171         static char path[MAXPATHLEN+1];
172         int len = base_dir_len;
173
174         memcpy(path, base_dir, len);
175         strcpy(path + len, ce->name);
176
177         if (!lstat(path, &st)) {
178                 unsigned changed = ce_match_stat(ce, &st);
179                 if (!changed)
180                         return 0;
181                 if (!force) {
182                         if (!quiet)
183                                 fprintf(stderr, "git-checkout-cache: %s already exists\n", path);
184                         return 0;
185                 }
186
187                 /*
188                  * We unlink the old file, to get the new one with the
189                  * right permissions (including umask, which is nasty
190                  * to emulate by hand - much easier to let the system
191                  * just do the right thing)
192                  */
193                 unlink(path);
194         } else if (not_new) 
195                 return 0;
196         return write_entry(ce, path);
197 }
198
199 static int checkout_file(const char *name)
200 {
201         int pos = cache_name_pos(name, strlen(name));
202         if (pos < 0) {
203                 if (!quiet) {
204                         pos = -pos - 1;
205                         fprintf(stderr,
206                                 "git-checkout-cache: %s is %s.\n",
207                                 name,
208                                 (pos < active_nr &&
209                                  !strcmp(active_cache[pos]->name, name)) ?
210                                 "unmerged" : "not in the cache");
211                 }
212                 return -1;
213         }
214         return checkout_entry(active_cache[pos]);
215 }
216
217 static int checkout_all(void)
218 {
219         int i;
220
221         for (i = 0; i < active_nr ; i++) {
222                 struct cache_entry *ce = active_cache[i];
223                 if (ce_stage(ce))
224                         continue;
225                 if (checkout_entry(ce) < 0)
226                         return -1;
227         }
228         return 0;
229 }
230
231 int main(int argc, char **argv)
232 {
233         int i, force_filename = 0;
234         struct cache_file cache_file;
235         int newfd = -1;
236
237         if (read_cache() < 0) {
238                 die("invalid cache");
239         }
240
241         for (i = 1; i < argc; i++) {
242                 const char *arg = argv[i];
243                 if (!force_filename) {
244                         if (!strcmp(arg, "-a")) {
245                                 checkout_all();
246                                 continue;
247                         }
248                         if (!strcmp(arg, "--")) {
249                                 force_filename = 1;
250                                 continue;
251                         }
252                         if (!strcmp(arg, "-f")) {
253                                 force = 1;
254                                 continue;
255                         }
256                         if (!strcmp(arg, "-q")) {
257                                 quiet = 1;
258                                 continue;
259                         }
260                         if (!strcmp(arg, "-n")) {
261                                 not_new = 1;
262                                 continue;
263                         }
264                         if (!strcmp(arg, "-u")) {
265                                 refresh_cache = 1;
266                                 if (newfd < 0)
267                                         newfd = hold_index_file_for_update
268                                                 (&cache_file,
269                                                  get_index_file());
270                                 if (newfd < 0)
271                                         die("cannot open index.lock file.");
272                                 continue;
273                         }
274                         if (!memcmp(arg, "--prefix=", 9)) {
275                                 base_dir = arg+9;
276                                 base_dir_len = strlen(base_dir);
277                                 continue;
278                         }
279                 }
280                 if (base_dir_len) {
281                         /* when --prefix is specified we do not
282                          * want to update cache.
283                          */
284                         if (refresh_cache) {
285                                 close(newfd); newfd = -1;
286                                 rollback_index_file(&cache_file);
287                         }
288                         refresh_cache = 0;
289                 }
290                 checkout_file(arg);
291         }
292
293         if (0 <= newfd &&
294             (write_cache(newfd, active_cache, active_nr) ||
295              commit_index_file(&cache_file)))
296                 die("Unable to write new cachefile");
297         return 0;
298 }