refs.c 22.5 KB
Newer Older
D
Daniel Barkalow 已提交
1 2
#include "refs.h"
#include "cache.h"
3 4
#include "object.h"
#include "tag.h"
D
Daniel Barkalow 已提交
5 6 7

#include <errno.h>

8 9 10
/* ISSYMREF=01 and ISPACKED=02 are public interfaces */
#define REF_KNOWS_PEELED 04

11 12
struct ref_list {
	struct ref_list *next;
13
	unsigned char flag; /* ISSYMREF? ISPACKED? */
14
	unsigned char sha1[20];
15
	unsigned char peeled[20];
16 17 18
	char name[FLEX_ARRAY];
};

19
static const char *parse_ref_line(char *line, unsigned char *sha1)
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37
{
	/*
	 * 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;
38 39
	if (isspace(*line))
		return NULL;
40 41 42
	if (line[len] != '\n')
		return NULL;
	line[len] = 0;
43

44 45 46
	return line;
}

47
static struct ref_list *add_ref(const char *name, const unsigned char *sha1,
48 49
				int flag, struct ref_list *list,
				struct ref_list **new_entry)
50 51 52 53 54 55 56 57 58 59 60
{
	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? */
61 62 63
		if (!cmp) {
			if (new_entry)
				*new_entry = entry;
64
			return list;
65
		}
66 67 68 69 70 71 72
		p = &entry->next;
	}

	/* Allocate it and add it in.. */
	len = strlen(name) + 1;
	entry = xmalloc(sizeof(struct ref_list) + len);
	hashcpy(entry->sha1, sha1);
73
	hashclr(entry->peeled);
74
	memcpy(entry->name, name, len);
75
	entry->flag = flag;
76 77
	entry->next = *p;
	*p = entry;
78 79
	if (new_entry)
		*new_entry = entry;
80 81 82
	return list;
}

83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
/*
 * 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)
104
{
105 106 107 108 109 110 111 112 113
	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;
}
114

115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
static void read_packed_refs(FILE *f, struct cached_refs *cached_refs)
{
	struct ref_list *list = NULL;
	struct ref_list *last = NULL;
	char refline[PATH_MAX];
	int flag = REF_ISPACKED;

	while (fgets(refline, sizeof(refline), f)) {
		unsigned char sha1[20];
		const char *name;
		static const char header[] = "# pack-refs with:";

		if (!strncmp(refline, header, sizeof(header)-1)) {
			const char *traits = refline + sizeof(header) - 1;
			if (strstr(traits, " peeled "))
				flag |= REF_KNOWS_PEELED;
			/* perhaps other traits later as well */
			continue;
		}

		name = parse_ref_line(refline, sha1);
		if (name) {
			list = add_ref(name, sha1, flag, list, &last);
			continue;
		}
		if (last &&
		    refline[0] == '^' &&
		    strlen(refline) == 42 &&
		    refline[41] == '\n' &&
		    !get_sha1_hex(refline + 1, sha1))
			hashcpy(last->peeled, sha1);
	}
	cached_refs->packed = list;
}

150 151 152
static struct ref_list *get_packed_refs(void)
{
	if (!cached_refs.did_packed) {
153
		FILE *f = fopen(git_path("packed-refs"), "r");
154
		cached_refs.packed = NULL;
155
		if (f) {
156
			read_packed_refs(f, &cached_refs);
157 158
			fclose(f);
		}
159
		cached_refs.did_packed = 1;
160
	}
161
	return cached_refs.packed;
162 163 164 165 166 167 168 169 170
}

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 已提交
171
		char *ref = xmalloc(baselen + 257);
172

L
Linus Torvalds 已提交
173
		memcpy(ref, base, baselen);
174
		if (baselen && base[baselen-1] != '/')
L
Linus Torvalds 已提交
175
			ref[baselen++] = '/';
176 177 178 179

		while ((de = readdir(dir)) != NULL) {
			unsigned char sha1[20];
			struct stat st;
180
			int flag;
181 182 183 184 185 186 187 188 189
			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 已提交
190 191
			memcpy(ref + baselen, de->d_name, namelen+1);
			if (stat(git_path("%s", ref), &st) < 0)
192 193
				continue;
			if (S_ISDIR(st.st_mode)) {
L
Linus Torvalds 已提交
194
				list = get_ref_dir(ref, list);
195 196
				continue;
			}
197
			if (!resolve_ref(ref, sha1, 1, &flag)) {
L
Linus Torvalds 已提交
198
				error("%s points nowhere!", ref);
199 200
				continue;
			}
201
			list = add_ref(ref, sha1, flag, list, NULL);
202
		}
L
Linus Torvalds 已提交
203
		free(ref);
204 205 206 207 208 209 210
		closedir(dir);
	}
	return list;
}

static struct ref_list *get_loose_refs(void)
{
211 212 213
	if (!cached_refs.did_loose) {
		cached_refs.loose = get_ref_dir("refs", NULL);
		cached_refs.did_loose = 1;
214
	}
215
	return cached_refs.loose;
216 217
}

218 219 220
/* We allow "recursive" symbolic refs. Only within reason, though */
#define MAXDEPTH 5

221
const char *resolve_ref(const char *ref, unsigned char *sha1, int reading, int *flag)
222
{
223 224
	int depth = MAXDEPTH, len;
	char buffer[256];
L
Linus Torvalds 已提交
225
	static char ref_buffer[256];
226

227 228 229
	if (flag)
		*flag = 0;

230
	for (;;) {
L
Linus Torvalds 已提交
231
		const char *path = git_path("%s", ref);
232 233 234
		struct stat st;
		char *buf;
		int fd;
235

236 237
		if (--depth < 0)
			return NULL;
238

239 240 241 242 243 244 245 246
		/* 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) {
247 248
			struct ref_list *list = get_packed_refs();
			while (list) {
249
				if (!strcmp(ref, list->name)) {
250
					hashcpy(sha1, list->sha1);
251 252
					if (flag)
						*flag |= REF_ISPACKED;
253 254 255 256
					return ref;
				}
				list = list->next;
			}
257 258
			if (reading || errno != ENOENT)
				return NULL;
259
			hashclr(sha1);
L
Linus Torvalds 已提交
260
			return ref;
261
		}
262

263 264 265 266
		/* 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 已提交
267 268 269
				buffer[len] = 0;
				strcpy(ref_buffer, buffer);
				ref = ref_buffer;
270 271
				if (flag)
					*flag |= REF_ISSYMREF;
272 273
				continue;
			}
274
		}
275

276 277 278 279 280 281
		/* Is it a directory? */
		if (S_ISDIR(st.st_mode)) {
			errno = EISDIR;
			return NULL;
		}

282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301
		/*
		 * 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 已提交
302 303 304 305
			len--;
		buf[len] = 0;
		memcpy(ref_buffer, buf, len + 1);
		ref = ref_buffer;
306 307
		if (flag)
			*flag |= REF_ISSYMREF;
308
	}
309 310
	if (len < 40 || get_sha1_hex(buffer, sha1))
		return NULL;
L
Linus Torvalds 已提交
311
	return ref;
312 313
}

L
Linus Torvalds 已提交
314
int create_symref(const char *ref_target, const char *refs_heads_master)
J
Junio C Hamano 已提交
315 316 317 318
{
	const char *lockpath;
	char ref[1000];
	int fd, len, written;
L
Linus Torvalds 已提交
319
	const char *git_HEAD = git_path("%s", ref_target);
J
Junio C Hamano 已提交
320

321 322
#ifndef NO_SYMLINK_HEAD
	if (prefer_symlink_refs) {
323 324 325 326 327
		unlink(git_HEAD);
		if (!symlink(refs_heads_master, git_HEAD))
			return 0;
		fprintf(stderr, "no symlink - falling back to symbolic ref\n");
	}
328 329
#endif

J
Junio C Hamano 已提交
330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348
	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;
	}
349 350 351 352 353
	if (adjust_shared_perm(git_HEAD)) {
		unlink(lockpath);
		error("Unable to fix permissions on %s", lockpath);
		return -4;
	}
J
Junio C Hamano 已提交
354 355 356
	return 0;
}

L
Linus Torvalds 已提交
357
int read_ref(const char *ref, unsigned char *sha1)
358
{
359
	if (resolve_ref(ref, sha1, 1, NULL))
360 361
		return 0;
	return -1;
362 363
}

364 365 366 367 368 369 370 371 372 373 374 375 376 377
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);
}

378 379 380 381 382 383 384 385 386 387 388 389 390
int peel_ref(const char *ref, unsigned char *sha1)
{
	int flag;
	unsigned char base[20];
	struct object *o;

	if (!resolve_ref(ref, base, 1, &flag))
		return -1;

	if ((flag & REF_ISPACKED)) {
		struct ref_list *list = get_packed_refs();

		while (list) {
391 392 393 394 395 396 397
			if (!strcmp(list->name, ref)) {
				if (list->flag & REF_KNOWS_PEELED) {
					hashcpy(sha1, list->peeled);
					return 0;
				}
				/* older pack-refs did not leave peeled ones */
				break;
398 399 400 401 402
			}
			list = list->next;
		}
	}

403
	/* fallback - callers should not call this for unpacked refs */
404 405 406 407 408 409 410 411 412 413 414
	o = parse_object(base);
	if (o->type == OBJ_TAG) {
		o = deref_tag(o, ref, 0);
		if (o) {
			hashcpy(sha1, o->sha1);
			return 0;
		}
	}
	return -1;
}

415 416
static int do_for_each_ref(const char *base, each_ref_fn fn, int trim,
			   void *cb_data)
417
{
418 419 420
	int retval;
	struct ref_list *packed = get_packed_refs();
	struct ref_list *loose = get_loose_refs();
421

422 423 424 425 426 427
	while (packed && loose) {
		struct ref_list *entry;
		int cmp = strcmp(packed->name, loose->name);
		if (!cmp) {
			packed = packed->next;
			continue;
428
		}
429 430 431 432 433 434 435
		if (cmp > 0) {
			entry = loose;
			loose = loose->next;
		} else {
			entry = packed;
			packed = packed->next;
		}
436
		retval = do_one_ref(base, fn, trim, cb_data, entry);
437 438 439
		if (retval)
			return retval;
	}
440

441 442 443 444
	for (packed = packed ? packed : loose; packed; packed = packed->next) {
		retval = do_one_ref(base, fn, trim, cb_data, packed);
		if (retval)
			return retval;
445
	}
446
	return 0;
447 448
}

449
int head_ref(each_ref_fn fn, void *cb_data)
450 451
{
	unsigned char sha1[20];
452 453 454 455
	int flag;

	if (resolve_ref("HEAD", sha1, 1, &flag))
		return fn("HEAD", sha1, flag, cb_data);
456
	return 0;
457 458
}

459
int for_each_ref(each_ref_fn fn, void *cb_data)
460
{
461
	return do_for_each_ref("refs/", fn, 0, cb_data);
462 463
}

464
int for_each_tag_ref(each_ref_fn fn, void *cb_data)
465
{
466
	return do_for_each_ref("refs/tags/", fn, 10, cb_data);
467 468
}

469
int for_each_branch_ref(each_ref_fn fn, void *cb_data)
470
{
471
	return do_for_each_ref("refs/heads/", fn, 11, cb_data);
472 473
}

474
int for_each_remote_ref(each_ref_fn fn, void *cb_data)
475
{
476
	return do_for_each_ref("refs/remotes/", fn, 13, cb_data);
477 478
}

479 480 481 482 483
/* 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 已提交
484 485 486 487
int get_ref_sha1(const char *ref, unsigned char *sha1)
{
	if (check_ref_format(ref))
		return -1;
L
Linus Torvalds 已提交
488
	return read_ref(mkpath("refs/%s", ref), sha1);
D
Daniel Barkalow 已提交
489 490
}

491 492 493 494 495 496 497 498 499 500 501 502 503
/*
 * 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) <= ' ' ||
504 505 506
		ch == '~' || ch == '^' || ch == ':' ||
		/* 2.13 Pattern Matching Notation */
		ch == '?' || ch == '*' || ch == '[');
507 508
}

D
Daniel Barkalow 已提交
509 510
int check_ref_format(const char *ref)
{
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 537 538 539 540
	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 已提交
541 542
}

J
Junio C Hamano 已提交
543
static struct ref_lock *verify_lock(struct ref_lock *lock,
544 545
	const unsigned char *old_sha1, int mustexist)
{
546
	if (!resolve_ref(lock->ref_name, lock->old_sha1, mustexist, NULL)) {
547
		error("Can't verify ref %s", lock->ref_name);
548 549 550
		unlock_ref(lock);
		return NULL;
	}
551
	if (hashcmp(lock->old_sha1, old_sha1)) {
552
		error("Ref %s is at %s but expected %s", lock->ref_name,
553 554 555 556 557 558 559
			sha1_to_hex(lock->old_sha1), sha1_to_hex(old_sha1));
		unlock_ref(lock);
		return NULL;
	}
	return lock;
}

560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582
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) &&
583
		    !remove_empty_dir_recursive(path, len + namlen))
584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612
			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 已提交
613
static struct ref_lock *lock_ref_sha1_basic(const char *ref, const unsigned char *old_sha1, int *flag)
614
{
615
	char *ref_file;
L
Linus Torvalds 已提交
616
	const char *orig_ref = ref;
617
	struct ref_lock *lock;
618
	struct stat st;
619
	int last_errno = 0;
620
	int mustexist = (old_sha1 && !is_null_sha1(old_sha1));
621 622 623 624

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

J
Junio C Hamano 已提交
625
	ref = resolve_ref(ref, lock->old_sha1, mustexist, flag);
626 627 628 629 630 631 632
	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);
633 634 635 636 637
		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 已提交
638
		ref = resolve_ref(orig_ref, lock->old_sha1, mustexist, flag);
639
	}
L
Linus Torvalds 已提交
640
	if (!ref) {
641
		last_errno = errno;
642
		error("unable to resolve reference %s: %s",
L
Linus Torvalds 已提交
643
			orig_ref, strerror(errno));
644
		goto error_return;
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
	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;
		}
	}

670
	lock->lk = xcalloc(1, sizeof(struct lock_file));
671

672
	lock->ref_name = xstrdup(ref);
L
Linus Torvalds 已提交
673
	lock->log_file = xstrdup(git_path("logs/%s", ref));
P
Petr Baudis 已提交
674
	ref_file = git_path("%s", ref);
675
	lock->force_write = lstat(ref_file, &st) && errno == ENOENT;
676

677 678 679 680 681
	if (safe_create_leading_directories(ref_file)) {
		last_errno = errno;
		error("unable to create directory for %s", ref_file);
		goto error_return;
	}
682
	lock->lock_fd = hold_lock_file_for_update(lock->lk, ref_file, 1);
683 684

	return old_sha1 ? verify_lock(lock, old_sha1, mustexist) : lock;
685 686 687 688 689

 error_return:
	unlock_ref(lock);
	errno = last_errno;
	return NULL;
690 691
}

692
struct ref_lock *lock_ref_sha1(const char *ref, const unsigned char *old_sha1)
D
Daniel Barkalow 已提交
693
{
P
Petr Baudis 已提交
694
	char refpath[PATH_MAX];
D
Daniel Barkalow 已提交
695
	if (check_ref_format(ref))
696
		return NULL;
P
Petr Baudis 已提交
697
	strcpy(refpath, mkpath("refs/%s", ref));
J
Junio C Hamano 已提交
698
	return lock_ref_sha1_basic(refpath, old_sha1, NULL);
699 700
}

701
struct ref_lock *lock_any_ref_for_update(const char *ref, const unsigned char *old_sha1)
702
{
J
Junio C Hamano 已提交
703 704 705
	return lock_ref_sha1_basic(ref, old_sha1, NULL);
}

706 707
static struct lock_file packlock;

J
Junio C Hamano 已提交
708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776
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;
	memset(&packlock, 0, sizeof(packlock));
	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;
777 778
}

J
Junio C Hamano 已提交
779
void unlock_ref(struct ref_lock *lock)
780 781 782
{
	if (lock->lock_fd >= 0) {
		close(lock->lock_fd);
783 784 785
		/* Do not free lock->lk -- atexit() still looks at them */
		if (lock->lk)
			rollback_lock_file(lock->lk);
786
	}
787
	free(lock->ref_name);
J
Junio C Hamano 已提交
788
	free(lock->log_file);
789 790 791
	free(lock);
}

792 793 794 795 796 797
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;
798
	const char *committer;
799

800 801
	if (log_all_ref_updates &&
	    !strncmp(lock->ref_name, "refs/heads/", 11)) {
802 803 804 805 806 807 808 809
		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 已提交
810
		if (!(oflags & O_CREAT) && errno == ENOENT)
811
			return 0;
812 813 814 815 816 817 818 819 820 821 822 823

		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));
824 825
	}

826
	committer = git_committer_info(1);
827
	if (msg) {
828
		maxlen = strlen(committer) + strlen(msg) + 2*40 + 5;
829 830 831 832
		logrec = xmalloc(maxlen);
		len = snprintf(logrec, maxlen, "%s %s %s\t%s\n",
			sha1_to_hex(lock->old_sha1),
			sha1_to_hex(sha1),
833
			committer,
834
			msg);
J
Junio C Hamano 已提交
835 836
	}
	else {
837
		maxlen = strlen(committer) + 2*40 + 4;
838 839 840 841
		logrec = xmalloc(maxlen);
		len = snprintf(logrec, maxlen, "%s %s %s\n",
			sha1_to_hex(lock->old_sha1),
			sha1_to_hex(sha1),
842
			committer);
843 844 845 846 847 848 849 850 851
	}
	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;
}

852 853 854 855 856 857
int write_ref_sha1(struct ref_lock *lock,
	const unsigned char *sha1, const char *logmsg)
{
	static char term = '\n';

	if (!lock)
D
Daniel Barkalow 已提交
858
		return -1;
859
	if (!lock->force_write && !hashcmp(lock->old_sha1, sha1)) {
860 861
		unlock_ref(lock);
		return 0;
D
Daniel Barkalow 已提交
862
	}
863 864 865
	if (write(lock->lock_fd, sha1_to_hex(sha1), 40) != 40 ||
	    write(lock->lock_fd, &term, 1) != 1
		|| close(lock->lock_fd) < 0) {
866
		error("Couldn't write %s", lock->lk->filename);
867 868 869
		unlock_ref(lock);
		return -1;
	}
870
	invalidate_cached_refs();
871 872 873 874
	if (log_ref_write(lock, sha1, logmsg) < 0) {
		unlock_ref(lock);
		return -1;
	}
875
	if (commit_lock_file(lock->lk)) {
876
		error("Couldn't set %s", lock->ref_name);
877 878 879 880 881 882
		unlock_ref(lock);
		return -1;
	}
	lock->lock_fd = -1;
	unlock_ref(lock);
	return 0;
D
Daniel Barkalow 已提交
883
}
884

885
int read_ref_at(const char *ref, unsigned long at_time, int cnt, unsigned char *sha1)
886
{
887
	const char *logfile, *logdata, *logend, *rec, *lastgt, *lastrec;
888 889 890 891
	char *tz_c;
	int logfd, tz;
	struct stat st;
	unsigned long date;
892
	unsigned char logged_sha1[20];
893 894 895 896 897 898 899 900 901 902 903

	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);

904
	lastrec = NULL;
905 906 907 908
	rec = logend = logdata + st.st_size;
	while (logdata < rec) {
		if (logdata < rec && *(rec-1) == '\n')
			rec--;
909 910
		lastgt = NULL;
		while (logdata < rec && *(rec-1) != '\n') {
911
			rec--;
912 913 914 915
			if (*rec == '>')
				lastgt = rec;
		}
		if (!lastgt)
916
			die("Log %s is corrupt.", logfile);
917
		date = strtoul(lastgt + 1, &tz_c, 10);
918
		if (date <= at_time || cnt == 0) {
919 920 921 922 923
			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);
924
				if (hashcmp(logged_sha1, sha1)) {
925 926 927 928 929
					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 已提交
930 931
			}
			else if (date == at_time) {
932 933
				if (get_sha1_hex(rec + 41, sha1))
					die("Log %s is corrupt.", logfile);
J
Junio C Hamano 已提交
934 935
			}
			else {
936 937
				if (get_sha1_hex(rec + 41, logged_sha1))
					die("Log %s is corrupt.", logfile);
938
				if (hashcmp(logged_sha1, sha1)) {
939 940 941 942 943 944
					tz = strtoul(tz_c, NULL, 10);
					fprintf(stderr,
						"warning: Log %s unexpectedly ended on %s.\n",
						logfile, show_rfc2822_date(date, tz));
				}
			}
945 946 947
			munmap((void*)logdata, st.st_size);
			return 0;
		}
948
		lastrec = rec;
949 950
		if (cnt > 0)
			cnt--;
951 952
	}

953 954 955 956
	rec = logdata;
	while (rec < logend && *rec != '>' && *rec != '\n')
		rec++;
	if (rec == logend || *rec == '\n')
957
		die("Log %s is corrupt.", logfile);
958
	date = strtoul(rec + 1, &tz_c, 10);
959 960 961 962 963 964 965 966
	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;
}