update-cache.c 6.3 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5
/*
 * GIT - The information manager from hell
 *
 * Copyright (C) Linus Torvalds, 2005
 */
6 7
#include "cache.h"

8 9 10 11 12 13 14 15 16
/*
 * Default to not allowing changes to the list of files. The
 * tool doesn't actually care, but this makes it harder to add
 * files to the revision control by mistake by doing something
 * like "update-cache *" and suddenly having all the object
 * files be revision controlled.
 */
static int allow_add = 0, allow_remove = 0;

17 18 19
static int index_fd(const char *path, int namelen, struct cache_entry *ce, int fd, struct stat *st)
{
	z_stream stream;
20 21
	unsigned long size = st->st_size;
	int max_out_bytes = namelen + size + 200;
22 23
	void *out = malloc(max_out_bytes);
	void *metadata = malloc(namelen + 200);
24
	void *in;
25 26
	SHA_CTX c;

27 28 29
	in = "";
	if (size)
		in = mmap(NULL, size, PROT_READ, MAP_PRIVATE, fd, 0);
30 31 32 33 34 35 36 37 38 39 40
	close(fd);
	if (!out || (int)(long)in == -1)
		return -1;

	memset(&stream, 0, sizeof(stream));
	deflateInit(&stream, Z_BEST_COMPRESSION);

	/*
	 * ASCII size + nul byte
	 */	
	stream.next_in = metadata;
41
	stream.avail_in = 1+sprintf(metadata, "blob %lu", size);
42 43 44 45 46 47 48 49 50
	stream.next_out = out;
	stream.avail_out = max_out_bytes;
	while (deflate(&stream, 0) == Z_OK)
		/* nothing */;

	/*
	 * File content
	 */
	stream.next_in = in;
51
	stream.avail_in = size;
52 53 54 55 56 57 58 59 60 61 62 63
	while (deflate(&stream, Z_FINISH) == Z_OK)
		/*nothing */;

	deflateEnd(&stream);
	
	SHA1_Init(&c);
	SHA1_Update(&c, out, stream.total_out);
	SHA1_Final(ce->sha1, &c);

	return write_sha1_buffer(ce->sha1, out, stream.total_out);
}

64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
/*
 * This only updates the "non-critical" parts of the directory
 * cache, ie the parts that aren't tracked by GIT, and only used
 * to validate the cache.
 */
static void fill_stat_cache_info(struct cache_entry *ce, struct stat *st)
{
	ce->ctime.sec = st->st_ctime;
	ce->ctime.nsec = st->st_ctim.tv_nsec;
	ce->mtime.sec = st->st_mtime;
	ce->mtime.nsec = st->st_mtim.tv_nsec;
	ce->st_dev = st->st_dev;
	ce->st_ino = st->st_ino;
	ce->st_uid = st->st_uid;
	ce->st_gid = st->st_gid;
}

81 82 83 84 85 86 87 88 89
static int add_file_to_cache(char *path)
{
	int size, namelen;
	struct cache_entry *ce;
	struct stat st;
	int fd;

	fd = open(path, O_RDONLY);
	if (fd < 0) {
90 91 92 93
		if (errno == ENOENT) {
			if (allow_remove)
				return remove_file_from_cache(path);
		}
94 95 96 97 98 99 100 101 102 103 104
		return -1;
	}
	if (fstat(fd, &st) < 0) {
		close(fd);
		return -1;
	}
	namelen = strlen(path);
	size = cache_entry_size(namelen);
	ce = malloc(size);
	memset(ce, 0, size);
	memcpy(ce->name, path, namelen);
105
	fill_stat_cache_info(ce, &st);
106 107 108 109 110 111 112
	ce->st_mode = st.st_mode;
	ce->st_size = st.st_size;
	ce->namelen = namelen;

	if (index_fd(path, namelen, ce, fd, &st) < 0)
		return -1;

113 114 115
	return add_cache_entry(ce, allow_add);
}

116 117 118 119 120 121 122 123 124 125 126 127 128 129
static int match_data(int fd, void *buffer, unsigned long size)
{
	while (size) {
		char compare[1024];
		int ret = read(fd, compare, sizeof(compare));

		if (ret <= 0 || ret > size || memcmp(buffer, compare, ret))
			return -1;
		size -= ret;
		buffer += ret;
	}
	return 0;
}

130
static int compare_data(struct cache_entry *ce, unsigned long expected_size)
131
{
132 133 134 135 136 137 138 139 140 141
	int match = -1;
	int fd = open(ce->name, O_RDONLY);

	if (fd >= 0) {
		void *buffer;
		unsigned long size;
		char type[10];

		buffer = read_sha1_file(ce->sha1, type, &size);
		if (buffer) {
142
			if (size == expected_size && !strcmp(type, "blob"))
143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174
				match = match_data(fd, buffer, size);
			free(buffer);
		}
		close(fd);
	}
	return match;
}

/*
 * "refresh" does not calculate a new sha1 file or bring the
 * cache up-to-date for mode/content changes. But what it
 * _does_ do is to "re-match" the stat information of a file
 * with the cache, so that you can refresh the cache for a
 * file that hasn't been changed but where the stat entry is
 * out of date.
 *
 * For example, you'd want to do this after doing a "read-tree",
 * to link up the stat cache details with the proper files.
 */
static struct cache_entry *refresh_entry(struct cache_entry *ce)
{
	struct stat st;
	struct cache_entry *updated;
	int changed, size;

	if (stat(ce->name, &st) < 0)
		return NULL;

	changed = cache_match_stat(ce, &st);
	if (!changed)
		return ce;

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 181
		return NULL;

182
	if (compare_data(ce, st.st_size))
183 184 185 186 187 188
		return NULL;

	size = ce_size(ce);
	updated = malloc(size);
	memcpy(updated, ce, size);
	fill_stat_cache_info(updated, &st);
189
	updated->st_size = st.st_size;
190
	return updated;
191 192 193 194 195 196
}

static void refresh_cache(void)
{
	int i;

197 198 199 200 201 202 203 204 205 206
	for (i = 0; i < active_nr; i++) {
		struct cache_entry *ce = active_cache[i];
		struct cache_entry *new = refresh_entry(ce);

		if (!new) {
			printf("%s: needs update\n", ce->name);
			continue;
		}
		active_cache[i] = new;
	}
207 208 209 210 211
}

/*
 * We fundamentally don't like some paths: we don't want
 * dot or dot-dot anywhere, and in fact, we don't even want
212
 * any other dot-files (.git or anything else). They
213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236
 * are hidden, for chist sake.
 *
 * Also, we don't want double slashes or slashes at the
 * end that can make pathnames ambiguous. 
 */
static int verify_path(char *path)
{
	char c;

	goto inside;
	for (;;) {
		if (!c)
			return 1;
		if (c == '/') {
inside:
			c = *path++;
			if (c != '/' && c != '.' && c != '\0')
				continue;
			return 0;
		}
		c = *path++;
	}
}

237 238 239 240 241
static int remove_lock = 0;

static void remove_lock_file(void)
{
	if (remove_lock)
242
		unlink(".git/index.lock");
243 244
}

245 246 247
int main(int argc, char **argv)
{
	int i, newfd, entries;
248
	int allow_options = 1;
249

250
	newfd = open(".git/index.lock", O_RDWR | O_CREAT | O_EXCL, 0600);
251 252 253 254 255 256
	if (newfd < 0)
		usage("unable to create new cachefile");

	atexit(remove_lock_file);
	remove_lock = 1;

257
	entries = read_cache();
258 259
	if (entries < 0)
		usage("cache corrupted");
260 261 262

	for (i = 1 ; i < argc; i++) {
		char *path = argv[i];
263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282

		if (allow_options && *path == '-') {
			if (!strcmp(path, "--")) {
				allow_options = 0;
				continue;
			}
			if (!strcmp(path, "--add")) {
				allow_add = 1;
				continue;
			}
			if (!strcmp(path, "--remove")) {
				allow_remove = 1;
				continue;
			}
			if (!strcmp(path, "--refresh")) {
				refresh_cache();
				continue;
			}
			usage("unknown option %s", path);
		}
283 284 285 286
		if (!verify_path(path)) {
			fprintf(stderr, "Ignoring path %s\n", argv[i]);
			continue;
		}
287 288
		if (add_file_to_cache(path))
			usage("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 293 294
		usage("Unable to write new cachefile");

	remove_lock = 0;
295
	return 0;
296
}