sha1_name.c 19.6 KB
Newer Older
1
#include "cache.h"
J
Junio C Hamano 已提交
2
#include "tag.h"
3
#include "commit.h"
J
Junio C Hamano 已提交
4 5
#include "tree.h"
#include "blob.h"
6
#include "tree-walk.h"
7
#include "refs.h"
8 9 10

static int find_short_object_filename(int len, const char *name, unsigned char *sha1)
{
11
	struct alternate_object_database *alt;
12
	char hex[40];
13 14 15 16 17 18 19 20 21 22 23 24 25
	int found = 0;
	static struct alternate_object_database *fakeent;

	if (!fakeent) {
		const char *objdir = get_object_directory();
		int objdir_len = strlen(objdir);
		int entlen = objdir_len + 43;
		fakeent = xmalloc(sizeof(*fakeent) + entlen);
		memcpy(fakeent->base, objdir, objdir_len);
		fakeent->name = fakeent->base + objdir_len + 1;
		fakeent->name[-1] = '/';
	}
	fakeent->next = alt_odb_list;
26 27

	sprintf(hex, "%.2s", name);
28
	for (alt = fakeent; alt && found < 2; alt = alt->next) {
29
		struct dirent *de;
30 31 32 33 34
		DIR *dir;
		sprintf(alt->name, "%.2s/", name);
		dir = opendir(alt->base);
		if (!dir)
			continue;
35 36 37
		while ((de = readdir(dir)) != NULL) {
			if (strlen(de->d_name) != 38)
				continue;
38
			if (memcmp(de->d_name, name + 2, len - 2))
39
				continue;
40 41 42 43 44 45
			if (!found) {
				memcpy(hex + 2, de->d_name, 38);
				found++;
			}
			else if (memcmp(hex + 2, de->d_name, 38)) {
				found = 2;
46
				break;
47
			}
48 49 50 51 52
		}
		closedir(dir);
	}
	if (found == 1)
		return get_sha1_hex(hex, sha1) == 0;
53
	return found;
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
}

static int match_sha(unsigned len, const unsigned char *a, const unsigned char *b)
{
	do {
		if (*a != *b)
			return 0;
		a++;
		b++;
		len -= 2;
	} while (len > 1);
	if (len)
		if ((*a ^ *b) & 0xf0)
			return 0;
	return 1;
}

static int find_short_packed_object(int len, const unsigned char *match, unsigned char *sha1)
{
	struct packed_git *p;
74
	const unsigned char *found_sha1 = NULL;
75
	int found = 0;
76 77

	prepare_packed_git();
78
	for (p = packed_git; p && found < 2; p = p->next) {
79 80 81 82 83
		uint32_t num, last;
		uint32_t first = 0;
		open_pack_index(p);
		num = p->num_objects;
		last = num;
84
		while (first < last) {
85
			uint32_t mid = (first + last) / 2;
86
			const unsigned char *now;
87 88
			int cmp;

89
			now = nth_packed_object_sha1(p, mid);
90
			cmp = hashcmp(match, now);
91 92 93 94 95 96 97 98 99 100 101
			if (!cmp) {
				first = mid;
				break;
			}
			if (cmp > 0) {
				first = mid+1;
				continue;
			}
			last = mid;
		}
		if (first < num) {
102 103
			const unsigned char *now, *next;
		       now = nth_packed_object_sha1(p, first);
104
			if (match_sha(len, match, now)) {
105 106
				next = nth_packed_object_sha1(p, first+1);
			       if (!next|| !match_sha(len, match, next)) {
107 108
					/* unique within this pack */
					if (!found) {
109
						found_sha1 = now;
110 111
						found++;
					}
112
					else if (hashcmp(found_sha1, now)) {
113 114 115
						found = 2;
						break;
					}
116
				}
117 118
				else {
					/* not even unique within this pack */
119 120
					found = 2;
					break;
121 122 123 124
				}
			}
		}
	}
125
	if (found == 1)
126
		hashcpy(sha1, found_sha1);
127 128 129
	return found;
}

130 131 132
#define SHORT_NAME_NOT_FOUND (-1)
#define SHORT_NAME_AMBIGUOUS (-2)

133 134 135 136 137 138
static int find_unique_short_object(int len, char *canonical,
				    unsigned char *res, unsigned char *sha1)
{
	int has_unpacked, has_packed;
	unsigned char unpacked_sha1[20], packed_sha1[20];

139
	prepare_alt_odb();
140 141 142
	has_unpacked = find_short_object_filename(len, canonical, unpacked_sha1);
	has_packed = find_short_packed_object(len, res, packed_sha1);
	if (!has_unpacked && !has_packed)
143
		return SHORT_NAME_NOT_FOUND;
144
	if (1 < has_unpacked || 1 < has_packed)
145
		return SHORT_NAME_AMBIGUOUS;
146
	if (has_unpacked != has_packed) {
147
		hashcpy(sha1, (has_packed ? packed_sha1 : unpacked_sha1));
148 149 150
		return 0;
	}
	/* Both have unique ones -- do they match? */
151
	if (hashcmp(packed_sha1, unpacked_sha1))
152
		return SHORT_NAME_AMBIGUOUS;
153
	hashcpy(sha1, packed_sha1);
154 155 156
	return 0;
}

157 158
static int get_short_sha1(const char *name, int len, unsigned char *sha1,
			  int quietly)
159
{
160
	int i, status;
161 162 163
	char canonical[40];
	unsigned char res[20];

164
	if (len < MINIMUM_ABBREV || len > 40)
165
		return -1;
166
	hashclr(res);
167
	memset(canonical, 'x', 40);
168
	for (i = 0; i < len ;i++) {
169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185
		unsigned char c = name[i];
		unsigned char val;
		if (c >= '0' && c <= '9')
			val = c - '0';
		else if (c >= 'a' && c <= 'f')
			val = c - 'a' + 10;
		else if (c >= 'A' && c <='F') {
			val = c - 'A' + 10;
			c -= 'A' - 'a';
		}
		else
			return -1;
		canonical[i] = c;
		if (!(i & 1))
			val <<= 4;
		res[i >> 1] |= val;
	}
186

187 188 189 190 191 192 193 194
	status = find_unique_short_object(i, canonical, res, sha1);
	if (!quietly && (status == SHORT_NAME_AMBIGUOUS))
		return error("short SHA1 %.*s is ambiguous.", len, canonical);
	return status;
}

const char *find_unique_abbrev(const unsigned char *sha1, int len)
{
195
	int status, exists;
196
	static char hex[41];
J
Junio C Hamano 已提交
197

198
	exists = has_sha1_file(sha1);
199
	memcpy(hex, sha1_to_hex(sha1), 40);
200
	if (len == 40 || !len)
J
Junio C Hamano 已提交
201
		return hex;
202 203 204
	while (len < 40) {
		unsigned char sha1_ret[20];
		status = get_short_sha1(hex, len, sha1_ret, 1);
205 206 207
		if (exists
		    ? !status
		    : status == SHORT_NAME_NOT_FOUND) {
208 209 210 211 212
			hex[len] = 0;
			return hex;
		}
		len++;
	}
213
	return hex;
214 215
}

216
static int ambiguous_path(const char *path, int len)
217 218
{
	int slash = 1;
219
	int cnt;
220

221
	for (cnt = 0; cnt < len; cnt++) {
222 223 224 225 226 227 228 229 230 231 232 233 234 235
		switch (*path++) {
		case '\0':
			break;
		case '/':
			if (slash)
				break;
			slash = 1;
			continue;
		case '.':
			continue;
		default:
			slash = 0;
			continue;
		}
236
		break;
237
	}
238
	return slash;
239 240
}

J
Johannes Schindelin 已提交
241 242 243 244
/*
 * *string and *len will only be substituted, and *string returned (for
 * later free()ing) if the string passed in is of the form @{-<n>}.
 */
245
static char *substitute_branch_name(const char **string, int *len)
J
Johannes Schindelin 已提交
246 247
{
	struct strbuf buf = STRBUF_INIT;
248
	int ret = interpret_branch_name(*string, &buf);
J
Johannes Schindelin 已提交
249 250 251 252 253 254 255 256 257 258 259

	if (ret == *len) {
		size_t size;
		*string = strbuf_detach(&buf, &size);
		*len = size;
		return (char *)*string;
	}

	return NULL;
}

260
int dwim_ref(const char *str, int len, unsigned char *sha1, char **ref)
261
{
262
	char *last_branch = substitute_branch_name(&str, &len);
263 264 265 266
	const char **p, *r;
	int refs_found = 0;

	*ref = NULL;
S
Steffen Prohaska 已提交
267
	for (p = ref_rev_parse_rules; *p; p++) {
268
		char fullref[PATH_MAX];
269 270
		unsigned char sha1_from_ref[20];
		unsigned char *this_result;
271
		int flag;
272 273

		this_result = refs_found ? sha1_from_ref : sha1;
274
		mksnpath(fullref, sizeof(fullref), *p, len, str);
275
		r = resolve_ref(fullref, this_result, 1, &flag);
276 277 278 279 280
		if (r) {
			if (!refs_found++)
				*ref = xstrdup(r);
			if (!warn_ambiguous_refs)
				break;
281 282
		} else if ((flag & REF_ISSYMREF) &&
			   (len != 4 || strcmp(str, "HEAD")))
283
			warning("ignoring dangling symref %s.", fullref);
284
	}
J
Johannes Schindelin 已提交
285
	free(last_branch);
286 287 288
	return refs_found;
}

J
Johannes Schindelin 已提交
289
int dwim_log(const char *str, int len, unsigned char *sha1, char **log)
290
{
291
	char *last_branch = substitute_branch_name(&str, &len);
292 293 294 295
	const char **p;
	int logs_found = 0;

	*log = NULL;
S
Steffen Prohaska 已提交
296
	for (p = ref_rev_parse_rules; *p; p++) {
297
		struct stat st;
298 299 300 301
		unsigned char hash[20];
		char path[PATH_MAX];
		const char *ref, *it;

302
		mksnpath(path, sizeof(path), *p, len, str);
303
		ref = resolve_ref(path, hash, 1, NULL);
304 305
		if (!ref)
			continue;
306
		if (!stat(git_path("logs/%s", path), &st) &&
307 308 309 310 311 312 313 314 315 316 317
		    S_ISREG(st.st_mode))
			it = path;
		else if (strcmp(ref, path) &&
			 !stat(git_path("logs/%s", ref), &st) &&
			 S_ISREG(st.st_mode))
			it = ref;
		else
			continue;
		if (!logs_found++) {
			*log = xstrdup(it);
			hashcpy(sha1, hash);
318
		}
319 320
		if (!warn_ambiguous_refs)
			break;
321
	}
J
Johannes Schindelin 已提交
322
	free(last_branch);
323 324 325
	return logs_found;
}

326 327
static int get_sha1_1(const char *name, int len, unsigned char *sha1);

328 329
static int get_sha1_basic(const char *str, int len, unsigned char *sha1)
{
330
	static const char *warning = "warning: refname '%.*s' is ambiguous.\n";
L
Linus Torvalds 已提交
331
	char *real_ref = NULL;
332 333
	int refs_found = 0;
	int at, reflog_len;
334

335
	if (len == 40 && !get_sha1_hex(str, sha1))
336 337
		return 0;

338
	/* basic@{time or number or -number} format to query ref-log */
339
	reflog_len = at = 0;
340
	if (len && str[len-1] == '}') {
J
Johannes Schindelin 已提交
341
		for (at = len-2; at >= 0; at--) {
342 343 344 345 346
			if (str[at] == '@' && str[at+1] == '{') {
				reflog_len = (len-1) - (at+2);
				len = at;
				break;
			}
347 348 349
		}
	}

350
	/* Accept only unambiguous ref paths. */
351
	if (len && ambiguous_path(str, len))
352 353
		return -1;

354
	if (!len && reflog_len) {
355 356 357
		struct strbuf buf = STRBUF_INIT;
		int ret;
		/* try the @{-N} syntax for n-th checkout */
358
		ret = interpret_branch_name(str+at, &buf);
359 360 361 362 363 364
		if (ret > 0) {
			/* substitute this branch name and restart */
			return get_sha1_1(buf.buf, buf.len, sha1);
		} else if (ret == 0) {
			return -1;
		}
365 366
		/* allow "@{...}" to mean the current branch reflog */
		refs_found = dwim_ref("HEAD", 4, sha1, &real_ref);
367 368 369
	} else if (reflog_len)
		refs_found = dwim_log(str, len, sha1, &real_ref);
	else
370
		refs_found = dwim_ref(str, len, sha1, &real_ref);
371 372 373 374 375 376 377

	if (!refs_found)
		return -1;

	if (warn_ambiguous_refs && refs_found > 1)
		fprintf(stderr, warning, len, str);

378 379 380
	if (reflog_len) {
		int nth, i;
		unsigned long at_time;
381 382 383
		unsigned long co_time;
		int co_tz, co_cnt;

384
		/* Is it asking for N-th entry, or approxidate? */
385 386 387 388 389 390 391
		for (i = nth = 0; 0 <= nth && i < reflog_len; i++) {
			char ch = str[at+2+i];
			if ('0' <= ch && ch <= '9')
				nth = nth * 10 + ch - '0';
			else
				nth = -1;
		}
392 393 394 395
		if (100000000 <= nth) {
			at_time = nth;
			nth = -1;
		} else if (0 <= nth)
396
			at_time = 0;
J
Jeff King 已提交
397 398 399 400 401
		else {
			char *tmp = xstrndup(str + at + 2, reflog_len);
			at_time = approxidate(tmp);
			free(tmp);
		}
402 403 404 405 406 407
		if (read_ref_at(real_ref, at_time, nth, sha1, NULL,
				&co_time, &co_tz, &co_cnt)) {
			if (at_time)
				fprintf(stderr,
					"warning: Log for '%.*s' only goes "
					"back to %s.\n", len, str,
408
					show_date(co_time, co_tz, DATE_RFC2822));
409 410 411 412 413
			else
				fprintf(stderr,
					"warning: Log for '%.*s' only has "
					"%d entries.\n", len, str, co_cnt);
		}
414 415
	}

L
Linus Torvalds 已提交
416
	free(real_ref);
417
	return 0;
418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435
}

static int get_parent(const char *name, int len,
		      unsigned char *result, int idx)
{
	unsigned char sha1[20];
	int ret = get_sha1_1(name, len, sha1);
	struct commit *commit;
	struct commit_list *p;

	if (ret)
		return ret;
	commit = lookup_commit_reference(sha1);
	if (!commit)
		return -1;
	if (parse_commit(commit))
		return -1;
	if (!idx) {
436
		hashcpy(result, commit->object.sha1);
437 438 439 440 441
		return 0;
	}
	p = commit->parents;
	while (p) {
		if (!--idx) {
442
			hashcpy(result, p->item->object.sha1);
443 444 445 446 447 448 449
			return 0;
		}
		p = p->next;
	}
	return -1;
}

450 451 452 453
static int get_nth_ancestor(const char *name, int len,
			    unsigned char *result, int generation)
{
	unsigned char sha1[20];
454 455 456 457
	struct commit *commit;
	int ret;

	ret = get_sha1_1(name, len, sha1);
458 459
	if (ret)
		return ret;
460 461 462
	commit = lookup_commit_reference(sha1);
	if (!commit)
		return -1;
463 464

	while (generation--) {
465
		if (parse_commit(commit) || !commit->parents)
466
			return -1;
467
		commit = commit->parents->item;
468
	}
469
	hashcpy(result, commit->object.sha1);
470 471 472
	return 0;
}

473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503
struct object *peel_to_type(const char *name, int namelen,
			    struct object *o, enum object_type expected_type)
{
	if (name && !namelen)
		namelen = strlen(name);
	if (!o) {
		unsigned char sha1[20];
		if (get_sha1_1(name, namelen, sha1))
			return NULL;
		o = parse_object(sha1);
	}
	while (1) {
		if (!o || (!o->parsed && !parse_object(o->sha1)))
			return NULL;
		if (o->type == expected_type)
			return o;
		if (o->type == OBJ_TAG)
			o = ((struct tag*) o)->tagged;
		else if (o->type == OBJ_COMMIT)
			o = &(((struct commit *) o)->tree->object);
		else {
			if (name)
				error("%.*s: expected %s type, but the object "
				      "dereferences to %s type",
				      namelen, name, typename(expected_type),
				      typename(o->type));
			return NULL;
		}
	}
}

J
Junio C Hamano 已提交
504 505 506 507
static int peel_onion(const char *name, int len, unsigned char *sha1)
{
	unsigned char outer[20];
	const char *sp;
L
Linus Torvalds 已提交
508
	unsigned int expected_type = 0;
J
Junio C Hamano 已提交
509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531
	struct object *o;

	/*
	 * "ref^{type}" dereferences ref repeatedly until you cannot
	 * dereference anymore, or you get an object of given type,
	 * whichever comes first.  "ref^{}" means just dereference
	 * tags until you get a non-tag.  "ref^0" is a shorthand for
	 * "ref^{commit}".  "commit^{tree}" could be used to find the
	 * top-level tree of the given commit.
	 */
	if (len < 4 || name[len-1] != '}')
		return -1;

	for (sp = name + len - 1; name <= sp; sp--) {
		int ch = *sp;
		if (ch == '{' && name < sp && sp[-1] == '^')
			break;
	}
	if (sp <= name)
		return -1;

	sp++; /* beginning of type name, or closing brace for empty */
	if (!strncmp(commit_type, sp, 6) && sp[6] == '}')
532
		expected_type = OBJ_COMMIT;
J
Junio C Hamano 已提交
533
	else if (!strncmp(tree_type, sp, 4) && sp[4] == '}')
534
		expected_type = OBJ_TREE;
J
Junio C Hamano 已提交
535
	else if (!strncmp(blob_type, sp, 4) && sp[4] == '}')
536
		expected_type = OBJ_BLOB;
J
Junio C Hamano 已提交
537
	else if (sp[0] == '}')
538
		expected_type = OBJ_NONE;
J
Junio C Hamano 已提交
539 540 541 542 543 544 545 546 547
	else
		return -1;

	if (get_sha1_1(name, sp - name - 2, outer))
		return -1;

	o = parse_object(outer);
	if (!o)
		return -1;
L
Linus Torvalds 已提交
548
	if (!expected_type) {
549
		o = deref_tag(o, name, sp - name - 2);
550 551
		if (!o || (!o->parsed && !parse_object(o->sha1)))
			return -1;
552
		hashcpy(sha1, o->sha1);
J
Junio C Hamano 已提交
553 554
	}
	else {
555 556
		/*
		 * At this point, the syntax look correct, so
J
Junio C Hamano 已提交
557 558 559
		 * if we do not get the needed object, we should
		 * barf.
		 */
560 561 562 563
		o = peel_to_type(name, len, o, expected_type);
		if (o) {
			hashcpy(sha1, o->sha1);
			return 0;
J
Junio C Hamano 已提交
564
		}
565
		return -1;
J
Junio C Hamano 已提交
566 567 568 569
	}
	return 0;
}

570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589
static int get_describe_name(const char *name, int len, unsigned char *sha1)
{
	const char *cp;

	for (cp = name + len - 1; name + 2 <= cp; cp--) {
		char ch = *cp;
		if (hexval(ch) & ~0377) {
			/* We must be looking at g in "SOMETHING-g"
			 * for it to be describe output.
			 */
			if (ch == 'g' && cp[-1] == '-') {
				cp++;
				len -= cp - name;
				return get_short_sha1(cp, len, sha1, 1);
			}
		}
	}
	return -1;
}

590 591
static int get_sha1_1(const char *name, int len, unsigned char *sha1)
{
592
	int ret, has_suffix;
593
	const char *cp;
594

595 596
	/*
	 * "name~3" is "name^^^", "name~" is "name~1", and "name^" is "name^1".
597
	 */
598
	has_suffix = 0;
599 600 601 602
	for (cp = name + len - 1; name <= cp; cp--) {
		int ch = *cp;
		if ('0' <= ch && ch <= '9')
			continue;
603 604
		if (ch == '~' || ch == '^')
			has_suffix = ch;
605 606
		break;
	}
607 608 609

	if (has_suffix) {
		int num = 0;
610 611 612
		int len1 = cp - name;
		cp++;
		while (cp < name + len)
613
			num = num * 10 + *cp++ - '0';
614 615 616
		if (!num && len1 == len - 1)
			num = 1;
		if (has_suffix == '^')
617 618 619
			return get_parent(name, len1, sha1, num);
		/* else if (has_suffix == '~') -- goes without saying */
		return get_nth_ancestor(name, len1, sha1, num);
620 621
	}

J
Junio C Hamano 已提交
622 623 624 625
	ret = peel_onion(name, len, sha1);
	if (!ret)
		return 0;

626 627 628
	ret = get_sha1_basic(name, len, sha1);
	if (!ret)
		return 0;
629 630 631 632 633 634

	/* It could be describe output that is "SOMETHING-gXXXX" */
	ret = get_describe_name(name, len, sha1);
	if (!ret)
		return 0;

635
	return get_short_sha1(name, len, sha1, 0);
636 637
}

638 639 640 641 642 643 644
static int handle_one_ref(const char *path,
		const unsigned char *sha1, int flag, void *cb_data)
{
	struct commit_list **list = cb_data;
	struct object *object = parse_object(sha1);
	if (!object)
		return 0;
645
	if (object->type == OBJ_TAG) {
646
		object = deref_tag(object, path, strlen(path));
647 648 649
		if (!object)
			return 0;
	}
650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665
	if (object->type != OBJ_COMMIT)
		return 0;
	insert_by_date((struct commit *)object, list);
	return 0;
}

/*
 * This interprets names like ':/Initial revision of "git"' by searching
 * through history and returning the first commit whose message starts
 * with the given string.
 *
 * For future extension, ':/!' is reserved. If you want to match a message
 * beginning with a '!', you have to repeat the exclamation mark.
 */

#define ONELINE_SEEN (1u<<20)
L
Linus Torvalds 已提交
666
static int get_sha1_oneline(const char *prefix, unsigned char *sha1)
667 668
{
	struct commit_list *list = NULL, *backup = NULL, *l;
L
Linus Torvalds 已提交
669
	int retval = -1;
670
	char *temp_commit_buffer = NULL;
671 672 673 674 675 676 677 678 679

	if (prefix[0] == '!') {
		if (prefix[1] != '!')
			die ("Invalid search pattern: %s", prefix);
		prefix++;
	}
	for_each_ref(handle_one_ref, &list);
	for (l = list; l; l = l->next)
		commit_list_insert(l->item, &backup);
680
	while (list) {
681
		char *p;
L
Linus Torvalds 已提交
682
		struct commit *commit;
683 684
		enum object_type type;
		unsigned long size;
685 686

		commit = pop_most_recent_commit(&list, ONELINE_SEEN);
687 688
		if (!parse_object(commit->object.sha1))
			continue;
689
		free(temp_commit_buffer);
690 691 692 693 694 695 696 697 698
		if (commit->buffer)
			p = commit->buffer;
		else {
			p = read_sha1_file(commit->object.sha1, &type, &size);
			if (!p)
				continue;
			temp_commit_buffer = p;
		}
		if (!(p = strstr(p, "\n\n")))
699 700 701
			continue;
		if (!prefixcmp(p + 2, prefix)) {
			hashcpy(sha1, commit->object.sha1);
L
Linus Torvalds 已提交
702
			retval = 0;
703 704 705
			break;
		}
	}
706
	free(temp_commit_buffer);
707 708 709
	free_commit_list(list);
	for (l = backup; l; l = l->next)
		clear_commit_marks(l->item, ONELINE_SEEN);
L
Linus Torvalds 已提交
710
	return retval;
711 712
}

713
struct grab_nth_branch_switch_cbdata {
714
	long cnt, alloc;
715 716 717 718 719 720 721 722
	struct strbuf *buf;
};

static int grab_nth_branch_switch(unsigned char *osha1, unsigned char *nsha1,
				  const char *email, unsigned long timestamp, int tz,
				  const char *message, void *cb_data)
{
	struct grab_nth_branch_switch_cbdata *cb = cb_data;
T
Thomas Rast 已提交
723 724
	const char *match = NULL, *target = NULL;
	size_t len;
725
	int nth;
T
Thomas Rast 已提交
726 727 728

	if (!prefixcmp(message, "checkout: moving from ")) {
		match = message + strlen("checkout: moving from ");
729
		target = strstr(match, " to ");
730 731
	}

732
	if (!match || !target)
733 734
		return 0;

735
	len = target - match;
736 737 738
	nth = cb->cnt++ % cb->alloc;
	strbuf_reset(&cb->buf[nth]);
	strbuf_add(&cb->buf[nth], match, len);
739 740 741 742 743 744
	return 0;
}

/*
 * This reads "@{-N}" syntax, finds the name of the Nth previous
 * branch we were on, and places the name of the branch in the given
T
Thomas Rast 已提交
745
 * buf and returns the number of characters parsed if successful.
746 747 748
 *
 * If the input is not of the accepted format, it returns a negative
 * number to signal an error.
T
Thomas Rast 已提交
749 750 751
 *
 * If the input was ok but there are not N branch switches in the
 * reflog, it returns 0.
752
 */
753
int interpret_branch_name(const char *name, struct strbuf *buf)
754
{
755
	long nth;
756
	int i, retval;
757
	struct grab_nth_branch_switch_cbdata cb;
T
Thomas Rast 已提交
758 759
	const char *brace;
	char *num_end;
760 761 762

	if (name[0] != '@' || name[1] != '{' || name[2] != '-')
		return -1;
T
Thomas Rast 已提交
763 764 765 766 767
	brace = strchr(name, '}');
	if (!brace)
		return -1;
	nth = strtol(name+3, &num_end, 10);
	if (num_end != brace)
768
		return -1;
769 770 771 772 773 774 775
	if (nth <= 0)
		return -1;
	cb.alloc = nth;
	cb.buf = xmalloc(nth * sizeof(struct strbuf));
	for (i = 0; i < nth; i++)
		strbuf_init(&cb.buf[i], 20);
	cb.cnt = 0;
776
	retval = 0;
777 778 779 780 781
	for_each_recent_reflog_ent("HEAD", grab_nth_branch_switch, 40960, &cb);
	if (cb.cnt < nth) {
		cb.cnt = 0;
		for_each_reflog_ent("HEAD", grab_nth_branch_switch, &cb);
	}
782
	if (cb.cnt < nth)
783
		goto release_return;
784 785 786
	i = cb.cnt % nth;
	strbuf_reset(buf);
	strbuf_add(buf, cb.buf[i].buf, cb.buf[i].len);
787 788 789
	retval = brace-name+1;

release_return:
790 791 792
	for (i = 0; i < nth; i++)
		strbuf_release(&cb.buf[i]);
	free(cb.buf);
T
Thomas Rast 已提交
793

794
	return retval;
795 796
}

797 798 799 800 801 802
/*
 * This is like "get_sha1_basic()", except it allows "sha1 expressions",
 * notably "xyz^" for "parent of xyz"
 */
int get_sha1(const char *name, unsigned char *sha1)
{
803
	unsigned unused;
M
Martin Koegler 已提交
804 805 806 807 808 809
	return get_sha1_with_mode(name, sha1, &unused);
}

int get_sha1_with_mode(const char *name, unsigned char *sha1, unsigned *mode)
{
	int ret, bracket_depth;
810 811
	int namelen = strlen(name);
	const char *cp;
812

M
Martin Koegler 已提交
813
	*mode = S_IFINVALID;
814 815 816 817 818 819 820 821 822 823 824
	ret = get_sha1_1(name, namelen, sha1);
	if (!ret)
		return ret;
	/* sha1:path --> object name of path in ent sha1
	 * :path -> object name of path in index
	 * :[0-3]:path -> object name of path in index at stage
	 */
	if (name[0] == ':') {
		int stage = 0;
		struct cache_entry *ce;
		int pos;
825 826
		if (namelen > 2 && name[1] == '/')
			return get_sha1_oneline(name + 2, sha1);
827 828 829 830 831 832 833
		if (namelen < 3 ||
		    name[2] != ':' ||
		    name[1] < '0' || '3' < name[1])
			cp = name + 1;
		else {
			stage = name[1] - '0';
			cp = name + 3;
834
		}
835 836 837 838 839 840 841 842 843 844 845 846
		namelen = namelen - (cp - name);
		if (!active_cache)
			read_cache();
		pos = cache_name_pos(cp, namelen);
		if (pos < 0)
			pos = -pos - 1;
		while (pos < active_nr) {
			ce = active_cache[pos];
			if (ce_namelen(ce) != namelen ||
			    memcmp(ce->name, cp, namelen))
				break;
			if (ce_stage(ce) == stage) {
847
				hashcpy(sha1, ce->sha1);
848
				*mode = ce->ce_mode;
849 850
				return 0;
			}
851
			pos++;
852 853 854
		}
		return -1;
	}
855 856 857 858 859 860 861 862 863
	for (cp = name, bracket_depth = 0; *cp; cp++) {
		if (*cp == '{')
			bracket_depth++;
		else if (bracket_depth && *cp == '}')
			bracket_depth--;
		else if (!bracket_depth && *cp == ':')
			break;
	}
	if (*cp == ':') {
864 865 866
		unsigned char tree_sha1[20];
		if (!get_sha1_1(name, cp-name, tree_sha1))
			return get_tree_entry(tree_sha1, cp+1, sha1,
M
Martin Koegler 已提交
867
					      mode);
868 869
	}
	return ret;
870
}