[PATCH] Typofix in git/show-files.
[git] / update-cache.c
1 /*
2  * GIT - The information manager from hell
3  *
4  * Copyright (C) Linus Torvalds, 2005
5  */
6 #include "cache.h"
7
8 /*
9  * Default to not allowing changes to the list of files. The
10  * tool doesn't actually care, but this makes it harder to add
11  * files to the revision control by mistake by doing something
12  * like "update-cache *" and suddenly having all the object
13  * files be revision controlled.
14  */
15 static int allow_add = 0, allow_remove = 0;
16
17 static int index_fd(const char *path, int namelen, struct cache_entry *ce, int fd, struct stat *st)
18 {
19         z_stream stream;
20         unsigned long size = st->st_size;
21         int max_out_bytes = namelen + size + 200;
22         void *out = malloc(max_out_bytes);
23         void *metadata = malloc(namelen + 200);
24         void *in;
25         SHA_CTX c;
26
27         in = "";
28         if (size)
29                 in = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
30         close(fd);
31         if (!out || (int)(long)in == -1)
32                 return -1;
33
34         memset(&stream, 0, sizeof(stream));
35         deflateInit(&stream, Z_BEST_COMPRESSION);
36
37         /*
38          * ASCII size + nul byte
39          */     
40         stream.next_in = metadata;
41         stream.avail_in = 1+sprintf(metadata, "blob %lu", size);
42         stream.next_out = out;
43         stream.avail_out = max_out_bytes;
44         while (deflate(&stream, 0) == Z_OK)
45                 /* nothing */;
46
47         /*
48          * File content
49          */
50         stream.next_in = in;
51         stream.avail_in = size;
52         while (deflate(&stream, Z_FINISH) == Z_OK)
53                 /*nothing */;
54
55         deflateEnd(&stream);
56         
57         SHA1_Init(&c);
58         SHA1_Update(&c, out, stream.total_out);
59         SHA1_Final(ce->sha1, &c);
60
61         return write_sha1_buffer(ce->sha1, out, stream.total_out);
62 }
63
64 /*
65  * This only updates the "non-critical" parts of the directory
66  * cache, ie the parts that aren't tracked by GIT, and only used
67  * to validate the cache.
68  */
69 static void fill_stat_cache_info(struct cache_entry *ce, struct stat *st)
70 {
71         ce->ctime.sec = st->st_ctime;
72         ce->ctime.nsec = st->st_ctim.tv_nsec;
73         ce->mtime.sec = st->st_mtime;
74         ce->mtime.nsec = st->st_mtim.tv_nsec;
75         ce->st_dev = st->st_dev;
76         ce->st_ino = st->st_ino;
77         ce->st_uid = st->st_uid;
78         ce->st_gid = st->st_gid;
79 }
80
81 static int add_file_to_cache(char *path)
82 {
83         int size, namelen;
84         struct cache_entry *ce;
85         struct stat st;
86         int fd;
87
88         fd = open(path, O_RDONLY);
89         if (fd < 0) {
90                 if (errno == ENOENT) {
91                         if (allow_remove)
92                                 return remove_file_from_cache(path);
93                 }
94                 return -1;
95         }
96         if (fstat(fd, &st) < 0) {
97                 close(fd);
98                 return -1;
99         }
100         namelen = strlen(path);
101         size = cache_entry_size(namelen);
102         ce = malloc(size);
103         memset(ce, 0, size);
104         memcpy(ce->name, path, namelen);
105         fill_stat_cache_info(ce, &st);
106         ce->st_mode = st.st_mode;
107         ce->st_size = st.st_size;
108         ce->namelen = namelen;
109
110         if (index_fd(path, namelen, ce, fd, &st) < 0)
111                 return -1;
112
113         return add_cache_entry(ce, allow_add);
114 }
115
116 static int match_data(int fd, void *buffer, unsigned long size)
117 {
118         while (size) {
119                 char compare[1024];
120                 int ret = read(fd, compare, sizeof(compare));
121
122                 if (ret <= 0 || ret > size || memcmp(buffer, compare, ret))
123                         return -1;
124                 size -= ret;
125                 buffer += ret;
126         }
127         return 0;
128 }
129
130 static int compare_data(struct cache_entry *ce, unsigned long expected_size)
131 {
132         int match = -1;
133         int fd = open(ce->name, O_RDONLY);
134
135         if (fd >= 0) {
136                 void *buffer;
137                 unsigned long size;
138                 char type[10];
139
140                 buffer = read_sha1_file(ce->sha1, type, &size);
141                 if (buffer) {
142                         if (size == expected_size && !strcmp(type, "blob"))
143                                 match = match_data(fd, buffer, size);
144                         free(buffer);
145                 }
146                 close(fd);
147         }
148         return match;
149 }
150
151 /*
152  * "refresh" does not calculate a new sha1 file or bring the
153  * cache up-to-date for mode/content changes. But what it
154  * _does_ do is to "re-match" the stat information of a file
155  * with the cache, so that you can refresh the cache for a
156  * file that hasn't been changed but where the stat entry is
157  * out of date.
158  *
159  * For example, you'd want to do this after doing a "read-tree",
160  * to link up the stat cache details with the proper files.
161  */
162 static struct cache_entry *refresh_entry(struct cache_entry *ce)
163 {
164         struct stat st;
165         struct cache_entry *updated;
166         int changed, size;
167
168         if (stat(ce->name, &st) < 0)
169                 return NULL;
170
171         changed = cache_match_stat(ce, &st);
172         if (!changed)
173                 return ce;
174
175         /*
176          * If the mode has changed, there's no point in trying
177          * to refresh the entry - it's not going to match
178          */
179         if (changed & MODE_CHANGED)
180                 return NULL;
181
182         if (compare_data(ce, st.st_size))
183                 return NULL;
184
185         size = ce_size(ce);
186         updated = malloc(size);
187         memcpy(updated, ce, size);
188         fill_stat_cache_info(updated, &st);
189         updated->st_size = st.st_size;
190         return updated;
191 }
192
193 static void refresh_cache(void)
194 {
195         int i;
196
197         for (i = 0; i < active_nr; i++) {
198                 struct cache_entry *ce = active_cache[i];
199                 struct cache_entry *new = refresh_entry(ce);
200
201                 if (!new) {
202                         printf("%s: needs update\n", ce->name);
203                         continue;
204                 }
205                 active_cache[i] = new;
206         }
207 }
208
209 /*
210  * We fundamentally don't like some paths: we don't want
211  * dot or dot-dot anywhere, and in fact, we don't even want
212  * any other dot-files (.git or anything else). They
213  * are hidden, for chist sake.
214  *
215  * Also, we don't want double slashes or slashes at the
216  * end that can make pathnames ambiguous. 
217  */
218 static int verify_path(char *path)
219 {
220         char c;
221
222         goto inside;
223         for (;;) {
224                 if (!c)
225                         return 1;
226                 if (c == '/') {
227 inside:
228                         c = *path++;
229                         if (c != '/' && c != '.' && c != '\0')
230                                 continue;
231                         return 0;
232                 }
233                 c = *path++;
234         }
235 }
236
237 static int remove_lock = 0;
238
239 static void remove_lock_file(void)
240 {
241         if (remove_lock)
242                 unlink(".git/index.lock");
243 }
244
245 int main(int argc, char **argv)
246 {
247         int i, newfd, entries;
248         int allow_options = 1;
249
250         newfd = open(".git/index.lock", O_RDWR | O_CREAT | O_EXCL, 0600);
251         if (newfd < 0)
252                 die("unable to create new cachefile");
253
254         atexit(remove_lock_file);
255         remove_lock = 1;
256
257         entries = read_cache();
258         if (entries < 0)
259                 die("cache corrupted");
260
261         for (i = 1 ; i < argc; i++) {
262                 char *path = argv[i];
263
264                 if (allow_options && *path == '-') {
265                         if (!strcmp(path, "--")) {
266                                 allow_options = 0;
267                                 continue;
268                         }
269                         if (!strcmp(path, "--add")) {
270                                 allow_add = 1;
271                                 continue;
272                         }
273                         if (!strcmp(path, "--remove")) {
274                                 allow_remove = 1;
275                                 continue;
276                         }
277                         if (!strcmp(path, "--refresh")) {
278                                 refresh_cache();
279                                 continue;
280                         }
281                         die("unknown option %s", path);
282                 }
283                 if (!verify_path(path)) {
284                         fprintf(stderr, "Ignoring path %s\n", argv[i]);
285                         continue;
286                 }
287                 if (add_file_to_cache(path))
288                         die("Unable to add %s to database", path);
289         }
290         if (write_cache(newfd, active_cache, active_nr) ||
291             rename(".git/index.lock", ".git/index"))
292                 die("Unable to write new cachefile");
293
294         remove_lock = 0;
295         return 0;
296 }