refs.c 15.4 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 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
	entry->next = *p;
	*p = entry;
	return list;
}

static struct ref_list *get_packed_refs(void)
{
	static int did_refs = 0;
	static struct ref_list *refs = NULL;

	if (!did_refs) {
		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;
84
				list = add_ref(name, sha1, REF_ISPACKED, list);
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100
			}
			fclose(f);
			refs = list;
		}
		did_refs = 1;
	}
	return refs;
}

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

L
Linus Torvalds 已提交
103
		memcpy(ref, base, baselen);
104
		if (baselen && base[baselen-1] != '/')
L
Linus Torvalds 已提交
105
			ref[baselen++] = '/';
106 107 108 109

		while ((de = readdir(dir)) != NULL) {
			unsigned char sha1[20];
			struct stat st;
110
			int flag;
111 112 113 114 115 116 117 118 119
			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 已提交
120 121
			memcpy(ref + baselen, de->d_name, namelen+1);
			if (stat(git_path("%s", ref), &st) < 0)
122 123
				continue;
			if (S_ISDIR(st.st_mode)) {
L
Linus Torvalds 已提交
124
				list = get_ref_dir(ref, list);
125 126
				continue;
			}
127
			if (!resolve_ref(ref, sha1, 1, &flag)) {
L
Linus Torvalds 已提交
128
				error("%s points nowhere!", ref);
129 130
				continue;
			}
131
			list = add_ref(ref, sha1, flag, list);
132
		}
L
Linus Torvalds 已提交
133
		free(ref);
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150
		closedir(dir);
	}
	return list;
}

static struct ref_list *get_loose_refs(void)
{
	static int did_refs = 0;
	static struct ref_list *refs = NULL;

	if (!did_refs) {
		refs = get_ref_dir("refs", NULL);
		did_refs = 1;
	}
	return refs;
}

151 152 153
/* We allow "recursive" symbolic refs. Only within reason, though */
#define MAXDEPTH 5

154
const char *resolve_ref(const char *ref, unsigned char *sha1, int reading, int *flag)
155
{
156 157
	int depth = MAXDEPTH, len;
	char buffer[256];
L
Linus Torvalds 已提交
158
	static char ref_buffer[256];
159

160 161 162
	if (flag)
		*flag = 0;

163
	for (;;) {
L
Linus Torvalds 已提交
164
		const char *path = git_path("%s", ref);
165 166 167
		struct stat st;
		char *buf;
		int fd;
168

169 170
		if (--depth < 0)
			return NULL;
171

172 173 174 175 176 177 178 179
		/* 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) {
180 181 182 183
			struct ref_list *list = get_packed_refs();
			while (list) {
				if (!strcmp(ref, list->name)) {
					hashcpy(sha1, list->sha1);
184 185
					if (flag)
						*flag |= REF_ISPACKED;
186 187 188 189
					return ref;
				}
				list = list->next;
			}
190 191
			if (reading || errno != ENOENT)
				return NULL;
192
			hashclr(sha1);
L
Linus Torvalds 已提交
193
			return ref;
194
		}
195

196 197 198 199
		/* 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 已提交
200 201 202
				buffer[len] = 0;
				strcpy(ref_buffer, buffer);
				ref = ref_buffer;
203 204
				if (flag)
					*flag |= REF_ISSYMREF;
205 206
				continue;
			}
207
		}
208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228

		/*
		 * 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 已提交
229 230 231 232
			len--;
		buf[len] = 0;
		memcpy(ref_buffer, buf, len + 1);
		ref = ref_buffer;
233 234
		if (flag)
			*flag |= REF_ISSYMREF;
235
	}
236 237
	if (len < 40 || get_sha1_hex(buffer, sha1))
		return NULL;
L
Linus Torvalds 已提交
238
	return ref;
239 240
}

L
Linus Torvalds 已提交
241
int create_symref(const char *ref_target, const char *refs_heads_master)
J
Junio C Hamano 已提交
242 243 244 245
{
	const char *lockpath;
	char ref[1000];
	int fd, len, written;
L
Linus Torvalds 已提交
246
	const char *git_HEAD = git_path("%s", ref_target);
J
Junio C Hamano 已提交
247

248 249
#ifndef NO_SYMLINK_HEAD
	if (prefer_symlink_refs) {
250 251 252 253 254
		unlink(git_HEAD);
		if (!symlink(refs_heads_master, git_HEAD))
			return 0;
		fprintf(stderr, "no symlink - falling back to symbolic ref\n");
	}
255 256
#endif

J
Junio C Hamano 已提交
257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275
	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;
	}
276 277 278 279 280
	if (adjust_shared_perm(git_HEAD)) {
		unlink(lockpath);
		error("Unable to fix permissions on %s", lockpath);
		return -4;
	}
J
Junio C Hamano 已提交
281 282 283
	return 0;
}

L
Linus Torvalds 已提交
284
int read_ref(const char *ref, unsigned char *sha1)
285
{
286
	if (resolve_ref(ref, sha1, 1, NULL))
287 288
		return 0;
	return -1;
289 290
}

291 292
static int do_for_each_ref(const char *base, each_ref_fn fn, int trim,
			   void *cb_data)
293
{
294 295 296
	int retval;
	struct ref_list *packed = get_packed_refs();
	struct ref_list *loose = get_loose_refs();
297

298 299 300 301 302 303
	while (packed && loose) {
		struct ref_list *entry;
		int cmp = strcmp(packed->name, loose->name);
		if (!cmp) {
			packed = packed->next;
			continue;
304
		}
305 306 307 308 309 310 311 312 313
		if (cmp > 0) {
			entry = loose;
			loose = loose->next;
		} else {
			entry = packed;
			packed = packed->next;
		}
		if (strncmp(base, entry->name, trim))
			continue;
L
Linus Torvalds 已提交
314 315 316 317 318 319
		if (is_null_sha1(entry->sha1))
			continue;
		if (!has_sha1_file(entry->sha1)) {
			error("%s does not point to a valid object!", entry->name);
			continue;
		}
320 321
		retval = fn(entry->name + trim, entry->sha1,
			    entry->flag, cb_data);
322 323 324
		if (retval)
			return retval;
	}
325

326 327 328
	packed = packed ? packed : loose;
	while (packed) {
		if (!strncmp(base, packed->name, trim)) {
329 330
			retval = fn(packed->name + trim, packed->sha1,
				    packed->flag, cb_data);
331
			if (retval)
332
				return retval;
333
		}
334
		packed = packed->next;
335
	}
336
	return 0;
337 338
}

339
int head_ref(each_ref_fn fn, void *cb_data)
340 341
{
	unsigned char sha1[20];
342 343 344 345
	int flag;

	if (resolve_ref("HEAD", sha1, 1, &flag))
		return fn("HEAD", sha1, flag, cb_data);
346
	return 0;
347 348
}

349
int for_each_ref(each_ref_fn fn, void *cb_data)
350
{
351
	return do_for_each_ref("refs/", fn, 0, cb_data);
352 353
}

354
int for_each_tag_ref(each_ref_fn fn, void *cb_data)
355
{
356
	return do_for_each_ref("refs/tags/", fn, 10, cb_data);
357 358
}

359
int for_each_branch_ref(each_ref_fn fn, void *cb_data)
360
{
361
	return do_for_each_ref("refs/heads/", fn, 11, cb_data);
362 363
}

364
int for_each_remote_ref(each_ref_fn fn, void *cb_data)
365
{
366
	return do_for_each_ref("refs/remotes/", fn, 13, cb_data);
367 368
}

369 370 371 372 373
/* 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 已提交
374 375 376 377
int get_ref_sha1(const char *ref, unsigned char *sha1)
{
	if (check_ref_format(ref))
		return -1;
L
Linus Torvalds 已提交
378
	return read_ref(mkpath("refs/%s", ref), sha1);
D
Daniel Barkalow 已提交
379 380
}

381 382 383 384 385 386 387 388 389 390 391 392 393
/*
 * 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) <= ' ' ||
394 395 396
		ch == '~' || ch == '^' || ch == ':' ||
		/* 2.13 Pattern Matching Notation */
		ch == '?' || ch == '*' || ch == '[');
397 398
}

D
Daniel Barkalow 已提交
399 400
int check_ref_format(const char *ref)
{
401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430
	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 已提交
431 432
}

J
Junio C Hamano 已提交
433
static struct ref_lock *verify_lock(struct ref_lock *lock,
434 435
	const unsigned char *old_sha1, int mustexist)
{
436
	if (!resolve_ref(lock->ref_name, lock->old_sha1, mustexist, NULL)) {
437
		error("Can't verify ref %s", lock->ref_name);
438 439 440
		unlock_ref(lock);
		return NULL;
	}
441
	if (hashcmp(lock->old_sha1, old_sha1)) {
442
		error("Ref %s is at %s but expected %s", lock->ref_name,
443 444 445 446 447 448 449
			sha1_to_hex(lock->old_sha1), sha1_to_hex(old_sha1));
		unlock_ref(lock);
		return NULL;
	}
	return lock;
}

450
static struct ref_lock *lock_ref_sha1_basic(const char *ref, const unsigned char *old_sha1, int mustexist)
451
{
452
	char *ref_file;
L
Linus Torvalds 已提交
453
	const char *orig_ref = ref;
454
	struct ref_lock *lock;
455
	struct stat st;
456 457 458 459

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

460
	ref = resolve_ref(ref, lock->old_sha1, mustexist, NULL);
L
Linus Torvalds 已提交
461
	if (!ref) {
462 463
		int last_errno = errno;
		error("unable to resolve reference %s: %s",
L
Linus Torvalds 已提交
464
			orig_ref, strerror(errno));
465
		unlock_ref(lock);
466
		errno = last_errno;
467 468
		return NULL;
	}
469
	lock->lk = xcalloc(1, sizeof(struct lock_file));
470

471
	lock->ref_name = xstrdup(ref);
L
Linus Torvalds 已提交
472
	lock->log_file = xstrdup(git_path("logs/%s", ref));
P
Petr Baudis 已提交
473
	ref_file = git_path("%s", ref);
474
	lock->force_write = lstat(ref_file, &st) && errno == ENOENT;
475

476 477 478
	if (safe_create_leading_directories(ref_file))
		die("unable to create directory for %s", ref_file);
	lock->lock_fd = hold_lock_file_for_update(lock->lk, ref_file, 1);
479 480 481 482

	return old_sha1 ? verify_lock(lock, old_sha1, mustexist) : lock;
}

J
Junio C Hamano 已提交
483
struct ref_lock *lock_ref_sha1(const char *ref,
484
	const unsigned char *old_sha1, int mustexist)
D
Daniel Barkalow 已提交
485
{
P
Petr Baudis 已提交
486
	char refpath[PATH_MAX];
D
Daniel Barkalow 已提交
487
	if (check_ref_format(ref))
488
		return NULL;
P
Petr Baudis 已提交
489
	strcpy(refpath, mkpath("refs/%s", ref));
490
	return lock_ref_sha1_basic(refpath, old_sha1, mustexist);
491 492
}

J
Junio C Hamano 已提交
493
struct ref_lock *lock_any_ref_for_update(const char *ref,
494 495
	const unsigned char *old_sha1, int mustexist)
{
496
	return lock_ref_sha1_basic(ref, old_sha1, mustexist);
497 498
}

J
Junio C Hamano 已提交
499
void unlock_ref(struct ref_lock *lock)
500 501 502
{
	if (lock->lock_fd >= 0) {
		close(lock->lock_fd);
503 504 505
		/* Do not free lock->lk -- atexit() still looks at them */
		if (lock->lk)
			rollback_lock_file(lock->lk);
506
	}
507
	free(lock->ref_name);
J
Junio C Hamano 已提交
508
	free(lock->log_file);
509 510 511
	free(lock);
}

512 513 514 515 516 517
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;
518
	const char *committer;
519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534

	if (log_all_ref_updates) {
		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) {
		if (!log_all_ref_updates && errno == ENOENT)
			return 0;
		return error("Unable to append to %s: %s",
			lock->log_file, strerror(errno));
	}

535
	committer = git_committer_info(1);
536
	if (msg) {
537
		maxlen = strlen(committer) + strlen(msg) + 2*40 + 5;
538 539 540 541
		logrec = xmalloc(maxlen);
		len = snprintf(logrec, maxlen, "%s %s %s\t%s\n",
			sha1_to_hex(lock->old_sha1),
			sha1_to_hex(sha1),
542
			committer,
543
			msg);
J
Junio C Hamano 已提交
544 545
	}
	else {
546
		maxlen = strlen(committer) + 2*40 + 4;
547 548 549 550
		logrec = xmalloc(maxlen);
		len = snprintf(logrec, maxlen, "%s %s %s\n",
			sha1_to_hex(lock->old_sha1),
			sha1_to_hex(sha1),
551
			committer);
552 553 554 555 556 557 558 559 560
	}
	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;
}

561 562 563 564 565 566
int write_ref_sha1(struct ref_lock *lock,
	const unsigned char *sha1, const char *logmsg)
{
	static char term = '\n';

	if (!lock)
D
Daniel Barkalow 已提交
567
		return -1;
568
	if (!lock->force_write && !hashcmp(lock->old_sha1, sha1)) {
569 570
		unlock_ref(lock);
		return 0;
D
Daniel Barkalow 已提交
571
	}
572 573 574
	if (write(lock->lock_fd, sha1_to_hex(sha1), 40) != 40 ||
	    write(lock->lock_fd, &term, 1) != 1
		|| close(lock->lock_fd) < 0) {
575
		error("Couldn't write %s", lock->lk->filename);
576 577 578
		unlock_ref(lock);
		return -1;
	}
579 580 581 582
	if (log_ref_write(lock, sha1, logmsg) < 0) {
		unlock_ref(lock);
		return -1;
	}
583
	if (commit_lock_file(lock->lk)) {
584
		error("Couldn't set %s", lock->ref_name);
585 586 587 588 589 590
		unlock_ref(lock);
		return -1;
	}
	lock->lock_fd = -1;
	unlock_ref(lock);
	return 0;
D
Daniel Barkalow 已提交
591
}
592 593 594

int read_ref_at(const char *ref, unsigned long at_time, unsigned char *sha1)
{
595
	const char *logfile, *logdata, *logend, *rec, *lastgt, *lastrec;
596 597 598 599
	char *tz_c;
	int logfd, tz;
	struct stat st;
	unsigned long date;
600
	unsigned char logged_sha1[20];
601 602 603 604 605 606 607 608 609 610 611

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

612
	lastrec = NULL;
613 614 615 616
	rec = logend = logdata + st.st_size;
	while (logdata < rec) {
		if (logdata < rec && *(rec-1) == '\n')
			rec--;
617 618
		lastgt = NULL;
		while (logdata < rec && *(rec-1) != '\n') {
619
			rec--;
620 621 622 623
			if (*rec == '>')
				lastgt = rec;
		}
		if (!lastgt)
624
			die("Log %s is corrupt.", logfile);
625
		date = strtoul(lastgt + 1, &tz_c, 10);
626
		if (date <= at_time) {
627 628 629 630 631
			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);
632
				if (hashcmp(logged_sha1, sha1)) {
633 634 635 636 637
					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 已提交
638 639
			}
			else if (date == at_time) {
640 641
				if (get_sha1_hex(rec + 41, sha1))
					die("Log %s is corrupt.", logfile);
J
Junio C Hamano 已提交
642 643
			}
			else {
644 645
				if (get_sha1_hex(rec + 41, logged_sha1))
					die("Log %s is corrupt.", logfile);
646
				if (hashcmp(logged_sha1, sha1)) {
647 648 649 650 651 652
					tz = strtoul(tz_c, NULL, 10);
					fprintf(stderr,
						"warning: Log %s unexpectedly ended on %s.\n",
						logfile, show_rfc2822_date(date, tz));
				}
			}
653 654 655
			munmap((void*)logdata, st.st_size);
			return 0;
		}
656
		lastrec = rec;
657 658
	}

659 660 661 662
	rec = logdata;
	while (rec < logend && *rec != '>' && *rec != '\n')
		rec++;
	if (rec == logend || *rec == '\n')
663
		die("Log %s is corrupt.", logfile);
664
	date = strtoul(rec + 1, &tz_c, 10);
665 666 667 668 669 670 671 672
	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;
}