refs.c 20.9 KB
Newer Older
D
Daniel Barkalow 已提交
1 2 3 4 5
#include "refs.h"
#include "cache.h"

#include <errno.h>

6 7
struct ref_list {
	struct ref_list *next;
8
	unsigned char flag; /* ISSYMREF? ISPACKED? */
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
	unsigned char sha1[20];
	char name[FLEX_ARRAY];
};

static const char *parse_ref_line(char *line, unsigned char *sha1)
{
	/*
	 * 42: the answer to everything.
	 *
	 * In this case, it happens to be the answer to
	 *  40 (length of sha1 hex representation)
	 *  +1 (space in between hex and name)
	 *  +1 (newline at the end of the line)
	 */
	int len = strlen(line) - 42;

	if (len <= 0)
		return NULL;
	if (get_sha1_hex(line, sha1) < 0)
		return NULL;
	if (!isspace(line[40]))
		return NULL;
	line += 41;
32 33
	if (isspace(*line))
		return NULL;
34 35 36 37 38 39
	if (line[len] != '\n')
		return NULL;
	line[len] = 0;
	return line;
}

40 41
static struct ref_list *add_ref(const char *name, const unsigned char *sha1,
				int flag, struct ref_list *list)
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
{
	int len;
	struct ref_list **p = &list, *entry;

	/* Find the place to insert the ref into.. */
	while ((entry = *p) != NULL) {
		int cmp = strcmp(entry->name, name);
		if (cmp > 0)
			break;

		/* Same as existing entry? */
		if (!cmp)
			return list;
		p = &entry->next;
	}

	/* Allocate it and add it in.. */
	len = strlen(name) + 1;
	entry = xmalloc(sizeof(struct ref_list) + len);
	hashcpy(entry->sha1, sha1);
	memcpy(entry->name, name, len);
63
	entry->flag = flag;
64 65 66 67 68
	entry->next = *p;
	*p = entry;
	return list;
}

69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
/*
 * Future: need to be in "struct repository"
 * when doing a full libification.
 */
struct cached_refs {
	char did_loose;
	char did_packed;
	struct ref_list *loose;
	struct ref_list *packed;
} cached_refs;

static void free_ref_list(struct ref_list *list)
{
	struct ref_list *next;
	for ( ; list; list = next) {
		next = list->next;
		free(list);
	}
}

static void invalidate_cached_refs(void)
90
{
91 92 93 94 95 96 97 98 99
	struct cached_refs *ca = &cached_refs;

	if (ca->did_loose && ca->loose)
		free_ref_list(ca->loose);
	if (ca->did_packed && ca->packed)
		free_ref_list(ca->packed);
	ca->loose = ca->packed = NULL;
	ca->did_loose = ca->did_packed = 0;
}
100

101 102 103 104
static struct ref_list *get_packed_refs(void)
{
	if (!cached_refs.did_packed) {
		struct ref_list *refs = NULL;
105 106 107 108 109 110 111 112 113
		FILE *f = fopen(git_path("packed-refs"), "r");
		if (f) {
			struct ref_list *list = NULL;
			char refline[PATH_MAX];
			while (fgets(refline, sizeof(refline), f)) {
				unsigned char sha1[20];
				const char *name = parse_ref_line(refline, sha1);
				if (!name)
					continue;
114
				list = add_ref(name, sha1, REF_ISPACKED, list);
115 116 117 118
			}
			fclose(f);
			refs = list;
		}
119 120
		cached_refs.packed = refs;
		cached_refs.did_packed = 1;
121
	}
122
	return cached_refs.packed;
123 124 125 126 127 128 129 130 131
}

static struct ref_list *get_ref_dir(const char *base, struct ref_list *list)
{
	DIR *dir = opendir(git_path("%s", base));

	if (dir) {
		struct dirent *de;
		int baselen = strlen(base);
L
Linus Torvalds 已提交
132
		char *ref = xmalloc(baselen + 257);
133

L
Linus Torvalds 已提交
134
		memcpy(ref, base, baselen);
135
		if (baselen && base[baselen-1] != '/')
L
Linus Torvalds 已提交
136
			ref[baselen++] = '/';
137 138 139 140

		while ((de = readdir(dir)) != NULL) {
			unsigned char sha1[20];
			struct stat st;
141
			int flag;
142 143 144 145 146 147 148 149 150
			int namelen;

			if (de->d_name[0] == '.')
				continue;
			namelen = strlen(de->d_name);
			if (namelen > 255)
				continue;
			if (has_extension(de->d_name, ".lock"))
				continue;
L
Linus Torvalds 已提交
151 152
			memcpy(ref + baselen, de->d_name, namelen+1);
			if (stat(git_path("%s", ref), &st) < 0)
153 154
				continue;
			if (S_ISDIR(st.st_mode)) {
L
Linus Torvalds 已提交
155
				list = get_ref_dir(ref, list);
156 157
				continue;
			}
158
			if (!resolve_ref(ref, sha1, 1, &flag)) {
L
Linus Torvalds 已提交
159
				error("%s points nowhere!", ref);
160 161
				continue;
			}
162
			list = add_ref(ref, sha1, flag, list);
163
		}
L
Linus Torvalds 已提交
164
		free(ref);
165 166 167 168 169 170 171
		closedir(dir);
	}
	return list;
}

static struct ref_list *get_loose_refs(void)
{
172 173 174
	if (!cached_refs.did_loose) {
		cached_refs.loose = get_ref_dir("refs", NULL);
		cached_refs.did_loose = 1;
175
	}
176
	return cached_refs.loose;
177 178
}

179 180 181
/* We allow "recursive" symbolic refs. Only within reason, though */
#define MAXDEPTH 5

182
const char *resolve_ref(const char *ref, unsigned char *sha1, int reading, int *flag)
183
{
184 185
	int depth = MAXDEPTH, len;
	char buffer[256];
L
Linus Torvalds 已提交
186
	static char ref_buffer[256];
187

188 189 190
	if (flag)
		*flag = 0;

191
	for (;;) {
L
Linus Torvalds 已提交
192
		const char *path = git_path("%s", ref);
193 194 195
		struct stat st;
		char *buf;
		int fd;
196

197 198
		if (--depth < 0)
			return NULL;
199

200 201 202 203 204 205 206 207
		/* Special case: non-existing file.
		 * Not having the refs/heads/new-branch is OK
		 * if we are writing into it, so is .git/HEAD
		 * that points at refs/heads/master still to be
		 * born.  It is NOT OK if we are resolving for
		 * reading.
		 */
		if (lstat(path, &st) < 0) {
208 209 210 211
			struct ref_list *list = get_packed_refs();
			while (list) {
				if (!strcmp(ref, list->name)) {
					hashcpy(sha1, list->sha1);
212 213
					if (flag)
						*flag |= REF_ISPACKED;
214 215 216 217
					return ref;
				}
				list = list->next;
			}
218 219
			if (reading || errno != ENOENT)
				return NULL;
220
			hashclr(sha1);
L
Linus Torvalds 已提交
221
			return ref;
222
		}
223

224 225 226 227
		/* Follow "normalized" - ie "refs/.." symlinks by hand */
		if (S_ISLNK(st.st_mode)) {
			len = readlink(path, buffer, sizeof(buffer)-1);
			if (len >= 5 && !memcmp("refs/", buffer, 5)) {
L
Linus Torvalds 已提交
228 229 230
				buffer[len] = 0;
				strcpy(ref_buffer, buffer);
				ref = ref_buffer;
231 232
				if (flag)
					*flag |= REF_ISSYMREF;
233 234
				continue;
			}
235
		}
236

237 238 239 240 241 242
		/* Is it a directory? */
		if (S_ISDIR(st.st_mode)) {
			errno = EISDIR;
			return NULL;
		}

243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262
		/*
		 * Anything else, just open it and try to use it as
		 * a ref
		 */
		fd = open(path, O_RDONLY);
		if (fd < 0)
			return NULL;
		len = read(fd, buffer, sizeof(buffer)-1);
		close(fd);

		/*
		 * Is it a symbolic ref?
		 */
		if (len < 4 || memcmp("ref:", buffer, 4))
			break;
		buf = buffer + 4;
		len -= 4;
		while (len && isspace(*buf))
			buf++, len--;
		while (len && isspace(buf[len-1]))
L
Linus Torvalds 已提交
263 264 265 266
			len--;
		buf[len] = 0;
		memcpy(ref_buffer, buf, len + 1);
		ref = ref_buffer;
267 268
		if (flag)
			*flag |= REF_ISSYMREF;
269
	}
270 271
	if (len < 40 || get_sha1_hex(buffer, sha1))
		return NULL;
L
Linus Torvalds 已提交
272
	return ref;
273 274
}

L
Linus Torvalds 已提交
275
int create_symref(const char *ref_target, const char *refs_heads_master)
J
Junio C Hamano 已提交
276 277 278 279
{
	const char *lockpath;
	char ref[1000];
	int fd, len, written;
L
Linus Torvalds 已提交
280
	const char *git_HEAD = git_path("%s", ref_target);
J
Junio C Hamano 已提交
281

282 283
#ifndef NO_SYMLINK_HEAD
	if (prefer_symlink_refs) {
284 285 286 287 288
		unlink(git_HEAD);
		if (!symlink(refs_heads_master, git_HEAD))
			return 0;
		fprintf(stderr, "no symlink - falling back to symbolic ref\n");
	}
289 290
#endif

J
Junio C Hamano 已提交
291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309
	len = snprintf(ref, sizeof(ref), "ref: %s\n", refs_heads_master);
	if (sizeof(ref) <= len) {
		error("refname too long: %s", refs_heads_master);
		return -1;
	}
	lockpath = mkpath("%s.lock", git_HEAD);
	fd = open(lockpath, O_CREAT | O_EXCL | O_WRONLY, 0666);	
	written = write(fd, ref, len);
	close(fd);
	if (written != len) {
		unlink(lockpath);
		error("Unable to write to %s", lockpath);
		return -2;
	}
	if (rename(lockpath, git_HEAD) < 0) {
		unlink(lockpath);
		error("Unable to create %s", git_HEAD);
		return -3;
	}
310 311 312 313 314
	if (adjust_shared_perm(git_HEAD)) {
		unlink(lockpath);
		error("Unable to fix permissions on %s", lockpath);
		return -4;
	}
J
Junio C Hamano 已提交
315 316 317
	return 0;
}

L
Linus Torvalds 已提交
318
int read_ref(const char *ref, unsigned char *sha1)
319
{
320
	if (resolve_ref(ref, sha1, 1, NULL))
321 322
		return 0;
	return -1;
323 324
}

325 326 327 328 329 330 331 332 333 334 335 336 337 338
static int do_one_ref(const char *base, each_ref_fn fn, int trim,
		      void *cb_data, struct ref_list *entry)
{
	if (strncmp(base, entry->name, trim))
		return 0;
	if (is_null_sha1(entry->sha1))
		return 0;
	if (!has_sha1_file(entry->sha1)) {
		error("%s does not point to a valid object!", entry->name);
		return 0;
	}
	return fn(entry->name + trim, entry->sha1, entry->flag, cb_data);
}

339 340
static int do_for_each_ref(const char *base, each_ref_fn fn, int trim,
			   void *cb_data)
341
{
342 343 344
	int retval;
	struct ref_list *packed = get_packed_refs();
	struct ref_list *loose = get_loose_refs();
345

346 347 348 349 350 351
	while (packed && loose) {
		struct ref_list *entry;
		int cmp = strcmp(packed->name, loose->name);
		if (!cmp) {
			packed = packed->next;
			continue;
352
		}
353 354 355 356 357 358 359
		if (cmp > 0) {
			entry = loose;
			loose = loose->next;
		} else {
			entry = packed;
			packed = packed->next;
		}
360
		retval = do_one_ref(base, fn, trim, cb_data, entry);
361 362 363
		if (retval)
			return retval;
	}
364

365 366 367 368
	for (packed = packed ? packed : loose; packed; packed = packed->next) {
		retval = do_one_ref(base, fn, trim, cb_data, packed);
		if (retval)
			return retval;
369
	}
370
	return 0;
371 372
}

373
int head_ref(each_ref_fn fn, void *cb_data)
374 375
{
	unsigned char sha1[20];
376 377 378 379
	int flag;

	if (resolve_ref("HEAD", sha1, 1, &flag))
		return fn("HEAD", sha1, flag, cb_data);
380
	return 0;
381 382
}

383
int for_each_ref(each_ref_fn fn, void *cb_data)
384
{
385
	return do_for_each_ref("refs/", fn, 0, cb_data);
386 387
}

388
int for_each_tag_ref(each_ref_fn fn, void *cb_data)
389
{
390
	return do_for_each_ref("refs/tags/", fn, 10, cb_data);
391 392
}

393
int for_each_branch_ref(each_ref_fn fn, void *cb_data)
394
{
395
	return do_for_each_ref("refs/heads/", fn, 11, cb_data);
396 397
}

398
int for_each_remote_ref(each_ref_fn fn, void *cb_data)
399
{
400
	return do_for_each_ref("refs/remotes/", fn, 13, cb_data);
401 402
}

403 404 405 406 407
/* NEEDSWORK: This is only used by ssh-upload and it should go; the
 * caller should do resolve_ref or read_ref like everybody else.  Or
 * maybe everybody else should use get_ref_sha1() instead of doing
 * read_ref().
 */
D
Daniel Barkalow 已提交
408 409 410 411
int get_ref_sha1(const char *ref, unsigned char *sha1)
{
	if (check_ref_format(ref))
		return -1;
L
Linus Torvalds 已提交
412
	return read_ref(mkpath("refs/%s", ref), sha1);
D
Daniel Barkalow 已提交
413 414
}

415 416 417 418 419 420 421 422 423 424 425 426 427
/*
 * Make sure "ref" is something reasonable to have under ".git/refs/";
 * We do not like it if:
 *
 * - any path component of it begins with ".", or
 * - it has double dots "..", or
 * - it has ASCII control character, "~", "^", ":" or SP, anywhere, or
 * - it ends with a "/".
 */

static inline int bad_ref_char(int ch)
{
	return (((unsigned) ch) <= ' ' ||
428 429 430
		ch == '~' || ch == '^' || ch == ':' ||
		/* 2.13 Pattern Matching Notation */
		ch == '?' || ch == '*' || ch == '[');
431 432
}

D
Daniel Barkalow 已提交
433 434
int check_ref_format(const char *ref)
{
435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464
	int ch, level;
	const char *cp = ref;

	level = 0;
	while (1) {
		while ((ch = *cp++) == '/')
			; /* tolerate duplicated slashes */
		if (!ch)
			return -1; /* should not end with slashes */

		/* we are at the beginning of the path component */
		if (ch == '.' || bad_ref_char(ch))
			return -1;

		/* scan the rest of the path component */
		while ((ch = *cp++) != 0) {
			if (bad_ref_char(ch))
				return -1;
			if (ch == '/')
				break;
			if (ch == '.' && *cp == '.')
				return -1;
		}
		level++;
		if (!ch) {
			if (level < 2)
				return -1; /* at least of form "heads/blah" */
			return 0;
		}
	}
D
Daniel Barkalow 已提交
465 466
}

J
Junio C Hamano 已提交
467
static struct ref_lock *verify_lock(struct ref_lock *lock,
468 469
	const unsigned char *old_sha1, int mustexist)
{
470
	if (!resolve_ref(lock->ref_name, lock->old_sha1, mustexist, NULL)) {
471
		error("Can't verify ref %s", lock->ref_name);
472 473 474
		unlock_ref(lock);
		return NULL;
	}
475
	if (hashcmp(lock->old_sha1, old_sha1)) {
476
		error("Ref %s is at %s but expected %s", lock->ref_name,
477 478 479 480 481 482 483
			sha1_to_hex(lock->old_sha1), sha1_to_hex(old_sha1));
		unlock_ref(lock);
		return NULL;
	}
	return lock;
}

484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506
static int remove_empty_dir_recursive(char *path, int len)
{
	DIR *dir = opendir(path);
	struct dirent *e;
	int ret = 0;

	if (!dir)
		return -1;
	if (path[len-1] != '/')
		path[len++] = '/';
	while ((e = readdir(dir)) != NULL) {
		struct stat st;
		int namlen;
		if ((e->d_name[0] == '.') &&
		    ((e->d_name[1] == 0) ||
		     ((e->d_name[1] == '.') && e->d_name[2] == 0)))
			continue; /* "." and ".." */

		namlen = strlen(e->d_name);
		if ((len + namlen < PATH_MAX) &&
		    strcpy(path + len, e->d_name) &&
		    !lstat(path, &st) &&
		    S_ISDIR(st.st_mode) &&
507
		    !remove_empty_dir_recursive(path, len + namlen))
508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536
			continue; /* happy */

		/* path too long, stat fails, or non-directory still exists */
		ret = -1;
		break;
	}
	closedir(dir);
	if (!ret) {
		path[len] = 0;
		ret = rmdir(path);
	}
	return ret;
}

static int remove_empty_directories(char *file)
{
	/* we want to create a file but there is a directory there;
	 * if that is an empty directory (or a directory that contains
	 * only empty directories), remove them.
	 */
	char path[PATH_MAX];
	int len = strlen(file);

	if (len >= PATH_MAX) /* path too long ;-) */
		return -1;
	strcpy(path, file);
	return remove_empty_dir_recursive(path, len);
}

J
Junio C Hamano 已提交
537
static struct ref_lock *lock_ref_sha1_basic(const char *ref, const unsigned char *old_sha1, int *flag)
538
{
539
	char *ref_file;
L
Linus Torvalds 已提交
540
	const char *orig_ref = ref;
541
	struct ref_lock *lock;
542
	struct stat st;
543
	int last_errno = 0;
544
	int mustexist = (old_sha1 && !is_null_sha1(old_sha1));
545 546 547 548

	lock = xcalloc(1, sizeof(struct ref_lock));
	lock->lock_fd = -1;

J
Junio C Hamano 已提交
549
	ref = resolve_ref(ref, lock->old_sha1, mustexist, flag);
550 551 552 553 554 555 556
	if (!ref && errno == EISDIR) {
		/* we are trying to lock foo but we used to
		 * have foo/bar which now does not exist;
		 * it is normal for the empty directory 'foo'
		 * to remain.
		 */
		ref_file = git_path("%s", orig_ref);
557 558 559 560 561
		if (remove_empty_directories(ref_file)) {
			last_errno = errno;
			error("there are still refs under '%s'", orig_ref);
			goto error_return;
		}
J
Junio C Hamano 已提交
562
		ref = resolve_ref(orig_ref, lock->old_sha1, mustexist, flag);
563
	}
L
Linus Torvalds 已提交
564
	if (!ref) {
565
		last_errno = errno;
566
		error("unable to resolve reference %s: %s",
L
Linus Torvalds 已提交
567
			orig_ref, strerror(errno));
568
		goto error_return;
569
	}
570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593
	if (is_null_sha1(lock->old_sha1)) {
		/* The ref did not exist and we are creating it.
		 * Make sure there is no existing ref that is packed
		 * whose name begins with our refname, nor a ref whose
		 * name is a proper prefix of our refname.
		 */
		int namlen = strlen(ref); /* e.g. 'foo/bar' */
		struct ref_list *list = get_packed_refs();
		while (list) {
			/* list->name could be 'foo' or 'foo/bar/baz' */
			int len = strlen(list->name);
			int cmplen = (namlen < len) ? namlen : len;
			const char *lead = (namlen < len) ? list->name : ref;

			if (!strncmp(ref, list->name, cmplen) &&
			    lead[cmplen] == '/') {
				error("'%s' exists; cannot create '%s'",
				      list->name, ref);
				goto error_return;
			}
			list = list->next;
		}
	}

594
	lock->lk = xcalloc(1, sizeof(struct lock_file));
595

596
	lock->ref_name = xstrdup(ref);
L
Linus Torvalds 已提交
597
	lock->log_file = xstrdup(git_path("logs/%s", ref));
P
Petr Baudis 已提交
598
	ref_file = git_path("%s", ref);
599
	lock->force_write = lstat(ref_file, &st) && errno == ENOENT;
600

601 602 603 604 605
	if (safe_create_leading_directories(ref_file)) {
		last_errno = errno;
		error("unable to create directory for %s", ref_file);
		goto error_return;
	}
606
	lock->lock_fd = hold_lock_file_for_update(lock->lk, ref_file, 1);
607 608

	return old_sha1 ? verify_lock(lock, old_sha1, mustexist) : lock;
609 610 611 612 613

 error_return:
	unlock_ref(lock);
	errno = last_errno;
	return NULL;
614 615
}

616
struct ref_lock *lock_ref_sha1(const char *ref, const unsigned char *old_sha1)
D
Daniel Barkalow 已提交
617
{
P
Petr Baudis 已提交
618
	char refpath[PATH_MAX];
D
Daniel Barkalow 已提交
619
	if (check_ref_format(ref))
620
		return NULL;
P
Petr Baudis 已提交
621
	strcpy(refpath, mkpath("refs/%s", ref));
J
Junio C Hamano 已提交
622
	return lock_ref_sha1_basic(refpath, old_sha1, NULL);
623 624
}

625
struct ref_lock *lock_any_ref_for_update(const char *ref, const unsigned char *old_sha1)
626
{
J
Junio C Hamano 已提交
627 628 629
	return lock_ref_sha1_basic(ref, old_sha1, NULL);
}

630 631
static struct lock_file packlock;

J
Junio C Hamano 已提交
632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699
static int repack_without_ref(const char *refname)
{
	struct ref_list *list, *packed_ref_list;
	int fd;
	int found = 0;

	packed_ref_list = get_packed_refs();
	for (list = packed_ref_list; list; list = list->next) {
		if (!strcmp(refname, list->name)) {
			found = 1;
			break;
		}
	}
	if (!found)
		return 0;
	fd = hold_lock_file_for_update(&packlock, git_path("packed-refs"), 0);
	if (fd < 0)
		return error("cannot delete '%s' from packed refs", refname);

	for (list = packed_ref_list; list; list = list->next) {
		char line[PATH_MAX + 100];
		int len;

		if (!strcmp(refname, list->name))
			continue;
		len = snprintf(line, sizeof(line), "%s %s\n",
			       sha1_to_hex(list->sha1), list->name);
		/* this should not happen but just being defensive */
		if (len > sizeof(line))
			die("too long a refname '%s'", list->name);
		write_or_die(fd, line, len);
	}
	return commit_lock_file(&packlock);
}

int delete_ref(const char *refname, unsigned char *sha1)
{
	struct ref_lock *lock;
	int err, i, ret = 0, flag = 0;

	lock = lock_ref_sha1_basic(refname, sha1, &flag);
	if (!lock)
		return 1;
	if (!(flag & REF_ISPACKED)) {
		/* loose */
		i = strlen(lock->lk->filename) - 5; /* .lock */
		lock->lk->filename[i] = 0;
		err = unlink(lock->lk->filename);
		if (err) {
			ret = 1;
			error("unlink(%s) failed: %s",
			      lock->lk->filename, strerror(errno));
		}
		lock->lk->filename[i] = '.';
	}
	/* removing the loose one could have resurrected an earlier
	 * packed one.  Also, if it was not loose we need to repack
	 * without it.
	 */
	ret |= repack_without_ref(refname);

	err = unlink(lock->log_file);
	if (err && errno != ENOENT)
		fprintf(stderr, "warning: unlink(%s) failed: %s",
			lock->log_file, strerror(errno));
	invalidate_cached_refs();
	unlock_ref(lock);
	return ret;
700 701
}

J
Junio C Hamano 已提交
702
void unlock_ref(struct ref_lock *lock)
703 704 705
{
	if (lock->lock_fd >= 0) {
		close(lock->lock_fd);
706 707 708
		/* Do not free lock->lk -- atexit() still looks at them */
		if (lock->lk)
			rollback_lock_file(lock->lk);
709
	}
710
	free(lock->ref_name);
J
Junio C Hamano 已提交
711
	free(lock->log_file);
712 713 714
	free(lock);
}

715 716 717 718 719 720
static int log_ref_write(struct ref_lock *lock,
	const unsigned char *sha1, const char *msg)
{
	int logfd, written, oflags = O_APPEND | O_WRONLY;
	unsigned maxlen, len;
	char *logrec;
721
	const char *committer;
722

723 724
	if (log_all_ref_updates &&
	    !strncmp(lock->ref_name, "refs/heads/", 11)) {
725 726 727 728 729 730 731 732
		if (safe_create_leading_directories(lock->log_file) < 0)
			return error("unable to create directory for %s",
				lock->log_file);
		oflags |= O_CREAT;
	}

	logfd = open(lock->log_file, oflags, 0666);
	if (logfd < 0) {
J
Junio C Hamano 已提交
733
		if (!(oflags & O_CREAT) && errno == ENOENT)
734
			return 0;
735 736 737 738 739 740 741 742 743 744 745 746

		if ((oflags & O_CREAT) && errno == EISDIR) {
			if (remove_empty_directories(lock->log_file)) {
				return error("There are still logs under '%s'",
					     lock->log_file);
			}
			logfd = open(lock->log_file, oflags, 0666);
		}

		if (logfd < 0)
			return error("Unable to append to %s: %s",
				     lock->log_file, strerror(errno));
747 748
	}

749
	committer = git_committer_info(1);
750
	if (msg) {
751
		maxlen = strlen(committer) + strlen(msg) + 2*40 + 5;
752 753 754 755
		logrec = xmalloc(maxlen);
		len = snprintf(logrec, maxlen, "%s %s %s\t%s\n",
			sha1_to_hex(lock->old_sha1),
			sha1_to_hex(sha1),
756
			committer,
757
			msg);
J
Junio C Hamano 已提交
758 759
	}
	else {
760
		maxlen = strlen(committer) + 2*40 + 4;
761 762 763 764
		logrec = xmalloc(maxlen);
		len = snprintf(logrec, maxlen, "%s %s %s\n",
			sha1_to_hex(lock->old_sha1),
			sha1_to_hex(sha1),
765
			committer);
766 767 768 769 770 771 772 773 774
	}
	written = len <= maxlen ? write(logfd, logrec, len) : -1;
	free(logrec);
	close(logfd);
	if (written != len)
		return error("Unable to append to %s", lock->log_file);
	return 0;
}

775 776 777 778 779 780
int write_ref_sha1(struct ref_lock *lock,
	const unsigned char *sha1, const char *logmsg)
{
	static char term = '\n';

	if (!lock)
D
Daniel Barkalow 已提交
781
		return -1;
782
	if (!lock->force_write && !hashcmp(lock->old_sha1, sha1)) {
783 784
		unlock_ref(lock);
		return 0;
D
Daniel Barkalow 已提交
785
	}
786 787 788
	if (write(lock->lock_fd, sha1_to_hex(sha1), 40) != 40 ||
	    write(lock->lock_fd, &term, 1) != 1
		|| close(lock->lock_fd) < 0) {
789
		error("Couldn't write %s", lock->lk->filename);
790 791 792
		unlock_ref(lock);
		return -1;
	}
793
	invalidate_cached_refs();
794 795 796 797
	if (log_ref_write(lock, sha1, logmsg) < 0) {
		unlock_ref(lock);
		return -1;
	}
798
	if (commit_lock_file(lock->lk)) {
799
		error("Couldn't set %s", lock->ref_name);
800 801 802 803 804 805
		unlock_ref(lock);
		return -1;
	}
	lock->lock_fd = -1;
	unlock_ref(lock);
	return 0;
D
Daniel Barkalow 已提交
806
}
807

808
int read_ref_at(const char *ref, unsigned long at_time, int cnt, unsigned char *sha1)
809
{
810
	const char *logfile, *logdata, *logend, *rec, *lastgt, *lastrec;
811 812 813 814
	char *tz_c;
	int logfd, tz;
	struct stat st;
	unsigned long date;
815
	unsigned char logged_sha1[20];
816 817 818 819 820 821 822 823 824 825 826

	logfile = git_path("logs/%s", ref);
	logfd = open(logfile, O_RDONLY, 0);
	if (logfd < 0)
		die("Unable to read log %s: %s", logfile, strerror(errno));
	fstat(logfd, &st);
	if (!st.st_size)
		die("Log %s is empty.", logfile);
	logdata = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, logfd, 0);
	close(logfd);

827
	lastrec = NULL;
828 829 830 831
	rec = logend = logdata + st.st_size;
	while (logdata < rec) {
		if (logdata < rec && *(rec-1) == '\n')
			rec--;
832 833
		lastgt = NULL;
		while (logdata < rec && *(rec-1) != '\n') {
834
			rec--;
835 836 837 838
			if (*rec == '>')
				lastgt = rec;
		}
		if (!lastgt)
839
			die("Log %s is corrupt.", logfile);
840
		date = strtoul(lastgt + 1, &tz_c, 10);
841
		if (date <= at_time || cnt == 0) {
842 843 844 845 846
			if (lastrec) {
				if (get_sha1_hex(lastrec, logged_sha1))
					die("Log %s is corrupt.", logfile);
				if (get_sha1_hex(rec + 41, sha1))
					die("Log %s is corrupt.", logfile);
847
				if (hashcmp(logged_sha1, sha1)) {
848 849 850 851 852
					tz = strtoul(tz_c, NULL, 10);
					fprintf(stderr,
						"warning: Log %s has gap after %s.\n",
						logfile, show_rfc2822_date(date, tz));
				}
J
Junio C Hamano 已提交
853 854
			}
			else if (date == at_time) {
855 856
				if (get_sha1_hex(rec + 41, sha1))
					die("Log %s is corrupt.", logfile);
J
Junio C Hamano 已提交
857 858
			}
			else {
859 860
				if (get_sha1_hex(rec + 41, logged_sha1))
					die("Log %s is corrupt.", logfile);
861
				if (hashcmp(logged_sha1, sha1)) {
862 863 864 865 866 867
					tz = strtoul(tz_c, NULL, 10);
					fprintf(stderr,
						"warning: Log %s unexpectedly ended on %s.\n",
						logfile, show_rfc2822_date(date, tz));
				}
			}
868 869 870
			munmap((void*)logdata, st.st_size);
			return 0;
		}
871
		lastrec = rec;
872 873
		if (cnt > 0)
			cnt--;
874 875
	}

876 877 878 879
	rec = logdata;
	while (rec < logend && *rec != '>' && *rec != '\n')
		rec++;
	if (rec == logend || *rec == '\n')
880
		die("Log %s is corrupt.", logfile);
881
	date = strtoul(rec + 1, &tz_c, 10);
882 883 884 885 886 887 888 889
	tz = strtoul(tz_c, NULL, 10);
	if (get_sha1_hex(logdata, sha1))
		die("Log %s is corrupt.", logfile);
	munmap((void*)logdata, st.st_size);
	fprintf(stderr, "warning: Log %s only goes back to %s.\n",
		logfile, show_rfc2822_date(date, tz));
	return 0;
}