[PATCH] Change diff-tree output format
[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         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 #ifdef NSEC
73         ce->ctime.nsec = st->st_ctim.tv_nsec;
74 #endif
75         ce->mtime.sec = st->st_mtime;
76 #ifdef NSEC
77         ce->mtime.nsec = st->st_mtim.tv_nsec;
78 #endif
79         ce->st_dev = st->st_dev;
80         ce->st_ino = st->st_ino;
81         ce->st_uid = st->st_uid;
82         ce->st_gid = st->st_gid;
83 }
84
85 static int add_file_to_cache(char *path)
86 {
87         int size, namelen;
88         struct cache_entry *ce;
89         struct stat st;
90         int fd;
91
92         fd = open(path, O_RDONLY);
93         if (fd < 0) {
94                 if (errno == ENOENT) {
95                         if (allow_remove)
96                                 return remove_file_from_cache(path);
97                 }
98                 return -1;
99         }
100         if (fstat(fd, &st) < 0) {
101                 close(fd);
102                 return -1;
103         }
104         namelen = strlen(path);
105         size = cache_entry_size(namelen);
106         ce = malloc(size);
107         memset(ce, 0, size);
108         memcpy(ce->name, path, namelen);
109         fill_stat_cache_info(ce, &st);
110         ce->st_mode = st.st_mode;
111         ce->st_size = st.st_size;
112         ce->namelen = namelen;
113
114         if (index_fd(path, namelen, ce, fd, &st) < 0)
115                 return -1;
116
117         return add_cache_entry(ce, allow_add);
118 }
119
120 static int match_data(int fd, void *buffer, unsigned long size)
121 {
122         while (size) {
123                 char compare[1024];
124                 int ret = read(fd, compare, sizeof(compare));
125
126                 if (ret <= 0 || ret > size || memcmp(buffer, compare, ret))
127                         return -1;
128                 size -= ret;
129                 buffer += ret;
130         }
131         return 0;
132 }
133
134 static int compare_data(struct cache_entry *ce, unsigned long expected_size)
135 {
136         int match = -1;
137         int fd = open(ce->name, O_RDONLY);
138
139         if (fd >= 0) {
140                 void *buffer;
141                 unsigned long size;
142                 char type[10];
143
144                 buffer = read_sha1_file(ce->sha1, type, &size);
145                 if (buffer) {
146                         if (size == expected_size && !strcmp(type, "blob"))
147                                 match = match_data(fd, buffer, size);
148                         free(buffer);
149                 }
150                 close(fd);
151         }
152         return match;
153 }
154
155 /*
156  * "refresh" does not calculate a new sha1 file or bring the
157  * cache up-to-date for mode/content changes. But what it
158  * _does_ do is to "re-match" the stat information of a file
159  * with the cache, so that you can refresh the cache for a
160  * file that hasn't been changed but where the stat entry is
161  * out of date.
162  *
163  * For example, you'd want to do this after doing a "read-tree",
164  * to link up the stat cache details with the proper files.
165  */
166 static struct cache_entry *refresh_entry(struct cache_entry *ce)
167 {
168         struct stat st;
169         struct cache_entry *updated;
170         int changed, size;
171
172         if (stat(ce->name, &st) < 0)
173                 return NULL;
174
175         changed = cache_match_stat(ce, &st);
176         if (!changed)
177                 return ce;
178
179         /*
180          * If the mode has changed, there's no point in trying
181          * to refresh the entry - it's not going to match
182          */
183         if (changed & MODE_CHANGED)
184                 return NULL;
185
186         if (compare_data(ce, st.st_size))
187                 return NULL;
188
189         size = ce_size(ce);
190         updated = malloc(size);
191         memcpy(updated, ce, size);
192         fill_stat_cache_info(updated, &st);
193         updated->st_size = st.st_size;
194         return updated;
195 }
196
197 static void refresh_cache(void)
198 {
199         int i;
200
201         for (i = 0; i < active_nr; i++) {
202                 struct cache_entry *ce = active_cache[i];
203                 struct cache_entry *new = refresh_entry(ce);
204
205                 if (!new) {
206                         printf("%s: needs update\n", ce->name);
207                         continue;
208                 }
209                 active_cache[i] = new;
210         }
211 }
212
213 /*
214  * We fundamentally don't like some paths: we don't want
215  * dot or dot-dot anywhere, and in fact, we don't even want
216  * any other dot-files (.git or anything else). They
217  * are hidden, for chist sake.
218  *
219  * Also, we don't want double slashes or slashes at the
220  * end that can make pathnames ambiguous.
221  */
222 static int verify_path(char *path)
223 {
224         char c;
225
226         goto inside;
227         for (;;) {
228                 if (!c)
229                         return 1;
230                 if (c == '/') {
231 inside:
232                         c = *path++;
233                         if (c != '/' && c != '.' && c != '\0')
234                                 continue;
235                         return 0;
236                 }
237                 c = *path++;
238         }
239 }
240
241 static int remove_lock = 0;
242
243 static void remove_lock_file(void)
244 {
245         if (remove_lock)
246                 unlink(".git/index.lock");
247 }
248
249 int main(int argc, char **argv)
250 {
251         int i, newfd, entries;
252         int allow_options = 1;
253
254         newfd = open(".git/index.lock", O_RDWR | O_CREAT | O_EXCL, 0600);
255         if (newfd < 0)
256                 die("unable to create new cachefile");
257
258         atexit(remove_lock_file);
259         remove_lock = 1;
260
261         entries = read_cache();
262         if (entries < 0)
263                 die("cache corrupted");
264
265         for (i = 1 ; i < argc; i++) {
266                 char *path = argv[i];
267
268                 if (allow_options && *path == '-') {
269                         if (!strcmp(path, "--")) {
270                                 allow_options = 0;
271                                 continue;
272                         }
273                         if (!strcmp(path, "--add")) {
274                                 allow_add = 1;
275                                 continue;
276                         }
277                         if (!strcmp(path, "--remove")) {
278                                 allow_remove = 1;
279                                 continue;
280                         }
281                         if (!strcmp(path, "--refresh")) {
282                                 refresh_cache();
283                                 continue;
284                         }
285                         die("unknown option %s", path);
286                 }
287                 if (!verify_path(path)) {
288                         fprintf(stderr, "Ignoring path %s\n", argv[i]);
289                         continue;
290                 }
291                 if (add_file_to_cache(path))
292                         die("Unable to add %s to database", path);
293         }
294         if (write_cache(newfd, active_cache, active_nr) ||
295             rename(".git/index.lock", ".git/index"))
296                 die("Unable to write new cachefile");
297
298         remove_lock = 0;
299         return 0;
300 }