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