diffcore-rename.c 18.6 KB
Newer Older
1 2 3 4 5 6
/*
 * Copyright (C) 2005 Junio C Hamano
 */
#include "cache.h"
#include "diff.h"
#include "diffcore.h"
7
#include "hash.h"
8
#include "progress.h"
9

10 11 12 13 14 15 16
/* Table of rename/copy destinations */

static struct diff_rename_dst {
	struct diff_filespec *two;
	struct diff_filepair *pair;
} *rename_dst;
static int rename_dst_nr, rename_dst_alloc;
17

18 19
static struct diff_rename_dst *locate_rename_dst(struct diff_filespec *two,
						 int insert_ok)
20
{
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49
	int first, last;

	first = 0;
	last = rename_dst_nr;
	while (last > first) {
		int next = (last + first) >> 1;
		struct diff_rename_dst *dst = &(rename_dst[next]);
		int cmp = strcmp(two->path, dst->two->path);
		if (!cmp)
			return dst;
		if (cmp < 0) {
			last = next;
			continue;
		}
		first = next+1;
	}
	/* not found */
	if (!insert_ok)
		return NULL;
	/* insert to make it at "first" */
	if (rename_dst_alloc <= rename_dst_nr) {
		rename_dst_alloc = alloc_nr(rename_dst_alloc);
		rename_dst = xrealloc(rename_dst,
				      rename_dst_alloc * sizeof(*rename_dst));
	}
	rename_dst_nr++;
	if (first < rename_dst_nr)
		memmove(rename_dst + first + 1, rename_dst + first,
			(rename_dst_nr - first - 1) * sizeof(*rename_dst));
J
Junio C Hamano 已提交
50
	rename_dst[first].two = alloc_filespec(two->path);
51
	fill_filespec(rename_dst[first].two, two->sha1, two->sha1_valid, two->mode);
52 53
	rename_dst[first].pair = NULL;
	return &(rename_dst[first]);
54 55
}

56
/* Table of rename/copy src files */
57
static struct diff_rename_src {
58
	struct diff_filepair *p;
59
	unsigned short score; /* to remember the break score */
60 61
} *rename_src;
static int rename_src_nr, rename_src_alloc;
62

63
static struct diff_rename_src *register_rename_src(struct diff_filepair *p)
64 65
{
	int first, last;
66 67
	struct diff_filespec *one = p->one;
	unsigned short score = p->score;
68 69 70 71 72 73

	first = 0;
	last = rename_src_nr;
	while (last > first) {
		int next = (last + first) >> 1;
		struct diff_rename_src *src = &(rename_src[next]);
74
		int cmp = strcmp(one->path, src->p->one->path);
75 76 77 78 79 80 81 82
		if (!cmp)
			return src;
		if (cmp < 0) {
			last = next;
			continue;
		}
		first = next+1;
	}
83

84 85 86 87 88
	/* insert to make it at "first" */
	if (rename_src_alloc <= rename_src_nr) {
		rename_src_alloc = alloc_nr(rename_src_alloc);
		rename_src = xrealloc(rename_src,
				      rename_src_alloc * sizeof(*rename_src));
89
	}
90 91 92 93
	rename_src_nr++;
	if (first < rename_src_nr)
		memmove(rename_src + first + 1, rename_src + first,
			(rename_src_nr - first - 1) * sizeof(*rename_src));
94
	rename_src[first].p = p;
95
	rename_src[first].score = score;
96
	return &(rename_src[first]);
97 98
}

99 100 101 102 103 104 105 106 107 108 109 110 111 112 113
static int basename_same(struct diff_filespec *src, struct diff_filespec *dst)
{
	int src_len = strlen(src->path), dst_len = strlen(dst->path);
	while (src_len && dst_len) {
		char c1 = src->path[--src_len];
		char c2 = dst->path[--dst_len];
		if (c1 != c2)
			return 0;
		if (c1 == '/')
			return 1;
	}
	return (!src_len || src->path[src_len - 1] == '/') &&
		(!dst_len || dst->path[dst_len - 1] == '/');
}

114
struct diff_score {
115 116
	int src; /* index in rename_src */
	int dst; /* index in rename_dst */
117 118
	unsigned short score;
	short name_score;
119 120 121 122 123 124 125 126 127 128 129 130 131
};

static int estimate_similarity(struct diff_filespec *src,
			       struct diff_filespec *dst,
			       int minimum_score)
{
	/* src points at a file that existed in the original tree (or
	 * optionally a file in the destination tree) and dst points
	 * at a newly created file.  They may be quite similar, in which
	 * case we want to say src is renamed to dst or src is copied into
	 * dst, and then some edit has been applied to dst.
	 *
	 * Compare them and return how similar they are, representing
132 133 134 135 136
	 * the score as an integer between 0 and MAX_SCORE.
	 *
	 * When there is an exact match, it is considered a better
	 * match than anything else; the destination does not even
	 * call into this function in that case.
137
	 */
L
Linus Torvalds 已提交
138
	unsigned long max_size, delta_size, base_size, src_copied, literal_added;
139
	unsigned long delta_limit;
140 141
	int score;

142 143 144 145 146 147 148
	/* We deal only with regular files.  Symlink renames are handled
	 * only when they are exact matches --- in other words, no edits
	 * after renaming.
	 */
	if (!S_ISREG(src->mode) || !S_ISREG(dst->mode))
		return 0;

149 150 151 152 153 154 155 156 157
	/*
	 * Need to check that source and destination sizes are
	 * filled in before comparing them.
	 *
	 * If we already have "cnt_data" filled in, we know it's
	 * all good (avoid checking the size for zero, as that
	 * is a possible size - we really should have a flag to
	 * say whether the size is valid or not!)
	 */
158
	if (!src->cnt_data && diff_populate_filespec(src, 1))
159
		return 0;
160
	if (!dst->cnt_data && diff_populate_filespec(dst, 1))
161 162
		return 0;

L
Linus Torvalds 已提交
163
	max_size = ((src->size > dst->size) ? src->size : dst->size);
164
	base_size = ((src->size < dst->size) ? src->size : dst->size);
L
Linus Torvalds 已提交
165
	delta_size = max_size - base_size;
166

167 168
	/* We would not consider edits that change the file size so
	 * drastically.  delta_size must be smaller than
169
	 * (MAX_SCORE-minimum_score)/MAX_SCORE * min(src->size, dst->size).
170
	 *
171 172 173
	 * Note that base_size == 0 case is handled here already
	 * and the final score computation below would not have a
	 * divide-by-zero issue.
174
	 */
175
	if (max_size * (MAX_SCORE-minimum_score) < delta_size * MAX_SCORE)
176 177
		return 0;

178 179 180 181 182
	if (!src->cnt_data && diff_populate_filespec(src, 0))
		return 0;
	if (!dst->cnt_data && diff_populate_filespec(dst, 0))
		return 0;

183 184
	delta_limit = (unsigned long)
		(base_size * (MAX_SCORE-minimum_score) / MAX_SCORE);
185
	if (diffcore_count_changes(src, dst,
186
				   &src->cnt_data, &dst->cnt_data,
187 188
				   delta_limit,
				   &src_copied, &literal_added))
189
		return 0;
190

191 192
	/* How similar are they?
	 * what percentage of material in dst are from source?
193
	 */
L
Linus Torvalds 已提交
194
	if (!dst->size)
195
		score = 0; /* should not happen */
196
	else
197
		score = (int)(src_copied * MAX_SCORE / max_size);
198 199 200
	return score;
}

J
Junio C Hamano 已提交
201
static void record_rename_pair(int dst_index, int src_index, int score)
202
{
203
	struct diff_filespec *src, *dst;
204
	struct diff_filepair *dp;
205

206 207
	if (rename_dst[dst_index].pair)
		die("internal error: dst already matched.");
208

209
	src = rename_src[src_index].p->one;
210
	src->rename_used++;
211
	src->count++;
212

213
	dst = rename_dst[dst_index].two;
214
	dst->count++;
215

216
	dp = diff_queue(NULL, src, dst);
217
	dp->renamed_pair = 1;
218 219 220 221
	if (!strcmp(src->path, dst->path))
		dp->score = rename_src[src_index].score;
	else
		dp->score = score;
222
	rename_dst[dst_index].pair = dp;
223 224 225 226
}

/*
 * We sort the rename similarity matrix with the score, in descending
227
 * order (the most similar first).
228 229 230 231
 */
static int score_compare(const void *a_, const void *b_)
{
	const struct diff_score *a = a_, *b = b_;
232

233 234 235 236 237 238
	/* sink the unused ones to the bottom */
	if (a->dst < 0)
		return (0 <= b->dst);
	else if (b->dst < 0)
		return -1;

239 240 241
	if (a->score == b->score)
		return b->name_score - a->name_score;

242 243 244
	return b->score - a->score;
}

245 246 247 248 249 250 251
struct file_similarity {
	int src_dst, index;
	struct diff_filespec *filespec;
	struct file_similarity *next;
};

static int find_identical_files(struct file_similarity *src,
252 253
				struct file_similarity *dst,
				struct diff_options *options)
254 255 256 257 258 259 260
{
	int renames = 0;

	/*
	 * Walk over all the destinations ...
	 */
	do {
261
		struct diff_filespec *target = dst->filespec;
262
		struct file_similarity *p, *best;
263
		int i = 100, best_score = -1;
264 265 266 267 268 269

		/*
		 * .. to find the best source match
		 */
		best = NULL;
		for (p = src; p; p = p->next) {
270 271
			int score;
			struct diff_filespec *source = p->filespec;
272

M
Mike Ralphson 已提交
273
			/* False hash collision? */
274
			if (hashcmp(source->sha1, target->sha1))
275 276
				continue;
			/* Non-regular files? If so, the modes must match! */
277 278
			if (!S_ISREG(source->mode) || !S_ISREG(target->mode)) {
				if (source->mode != target->mode)
279 280
					continue;
			}
281 282
			/* Give higher scores to sources that haven't been used already */
			score = !source->rename_used;
283 284
			if (source->rename_used && options->detect_rename != DIFF_DETECT_COPY)
				continue;
285 286 287 288 289 290 291
			score += basename_same(source, target);
			if (score > best_score) {
				best = p;
				best_score = score;
				if (score == 2)
					break;
			}
292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313

			/* Too many identical alternatives? Pick one */
			if (!--i)
				break;
		}
		if (best) {
			record_rename_pair(dst->index, best->index, MAX_SCORE);
			renames++;
		}
	} while ((dst = dst->next) != NULL);
	return renames;
}

static void free_similarity_list(struct file_similarity *p)
{
	while (p) {
		struct file_similarity *entry = p;
		p = p->next;
		free(entry);
	}
}

314
static int find_same_files(void *ptr, void *data)
315 316 317 318
{
	int ret;
	struct file_similarity *p = ptr;
	struct file_similarity *src = NULL, *dst = NULL;
319
	struct diff_options *options = data;
320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337

	/* Split the hash list up into sources and destinations */
	do {
		struct file_similarity *entry = p;
		p = p->next;
		if (entry->src_dst < 0) {
			entry->next = src;
			src = entry;
		} else {
			entry->next = dst;
			dst = entry;
		}
	} while (p);

	/*
	 * If we have both sources *and* destinations, see if
	 * we can match them up
	 */
338
	ret = (src && dst) ? find_identical_files(src, dst, options) : 0;
339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378

	/* Free the hashes and return the number of renames found */
	free_similarity_list(src);
	free_similarity_list(dst);
	return ret;
}

static unsigned int hash_filespec(struct diff_filespec *filespec)
{
	unsigned int hash;
	if (!filespec->sha1_valid) {
		if (diff_populate_filespec(filespec, 0))
			return 0;
		hash_sha1_file(filespec->data, filespec->size, "blob", filespec->sha1);
	}
	memcpy(&hash, filespec->sha1, sizeof(hash));
	return hash;
}

static void insert_file_table(struct hash_table *table, int src_dst, int index, struct diff_filespec *filespec)
{
	void **pos;
	unsigned int hash;
	struct file_similarity *entry = xmalloc(sizeof(*entry));

	entry->src_dst = src_dst;
	entry->index = index;
	entry->filespec = filespec;
	entry->next = NULL;

	hash = hash_filespec(filespec);
	pos = insert_hash(hash, entry, table);

	/* We already had an entry there? */
	if (pos) {
		entry->next = *pos;
		*pos = entry;
	}
}

379 380 381 382 383 384 385
/*
 * Find exact renames first.
 *
 * The first round matches up the up-to-date entries,
 * and then during the second round we try to match
 * cache-dirty entries as well.
 */
386
static int find_exact_renames(struct diff_options *options)
387
{
388 389
	int i;
	struct hash_table file_table;
390

391
	init_hash(&file_table);
392
	preallocate_hash(&file_table, rename_src_nr + rename_dst_nr);
393
	for (i = 0; i < rename_src_nr; i++)
394
		insert_file_table(&file_table, -1, i, rename_src[i].p->one);
395 396 397 398 399

	for (i = 0; i < rename_dst_nr; i++)
		insert_file_table(&file_table, 1, i, rename_dst[i].two);

	/* Find the renames */
400
	i = for_each_hash(&file_table, find_same_files, options);
401 402 403 404 405

	/* .. and free the hash data structure */
	free_hash(&file_table);

	return i;
406 407
}

408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423
#define NUM_CANDIDATE_PER_DST 4
static void record_if_better(struct diff_score m[], struct diff_score *o)
{
	int i, worst;

	/* find the worst one */
	worst = 0;
	for (i = 1; i < NUM_CANDIDATE_PER_DST; i++)
		if (score_compare(&m[i], &m[worst]) > 0)
			worst = i;

	/* is it better than the worst one? */
	if (score_compare(&m[worst], o) > 0)
		m[worst] = *o;
}

424 425 426 427 428 429
/*
 * Returns:
 * 0 if we are under the limit;
 * 1 if we need to disable inexact rename detection;
 * 2 if we would be under the limit if we were given -C instead of -C -C.
 */
430 431 432 433 434
static int too_many_rename_candidates(int num_create,
				      struct diff_options *options)
{
	int rename_limit = options->rename_limit;
	int num_src = rename_src_nr;
435
	int i;
436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455

	options->needed_rename_limit = 0;

	/*
	 * This basically does a test for the rename matrix not
	 * growing larger than a "rename_limit" square matrix, ie:
	 *
	 *    num_create * num_src > rename_limit * rename_limit
	 *
	 * but handles the potential overflow case specially (and we
	 * assume at least 32-bit integers)
	 */
	if (rename_limit <= 0 || rename_limit > 32767)
		rename_limit = 32767;
	if ((num_create <= rename_limit || num_src <= rename_limit) &&
	    (num_create * num_src <= rename_limit * rename_limit))
		return 0;

	options->needed_rename_limit =
		num_src > num_create ? num_src : num_create;
456 457 458 459 460 461 462 463 464 465 466 467 468 469

	/* Are we running under -C -C? */
	if (!DIFF_OPT_TST(options, FIND_COPIES_HARDER))
		return 1;

	/* Would we bust the limit if we were running under -C? */
	for (num_src = i = 0; i < rename_src_nr; i++) {
		if (diff_unmodified_pair(rename_src[i].p))
			continue;
		num_src++;
	}
	if ((num_create <= rename_limit || num_src <= rename_limit) &&
	    (num_create * num_src <= rename_limit * rename_limit))
		return 2;
470 471 472
	return 1;
}

473 474 475 476 477 478 479 480 481 482 483 484 485
static int find_renames(struct diff_score *mx, int dst_cnt, int minimum_score, int copies)
{
	int count = 0, i;

	for (i = 0; i < dst_cnt * NUM_CANDIDATE_PER_DST; i++) {
		struct diff_rename_dst *dst;

		if ((mx[i].dst < 0) ||
		    (mx[i].score < minimum_score))
			break; /* there is no more usable pair. */
		dst = &rename_dst[mx[i].dst];
		if (dst->pair)
			continue; /* already done, either exact or fuzzy. */
486
		if (!copies && rename_src[mx[i].src].p->one->rename_used)
487 488 489 490 491 492 493
			continue;
		record_rename_pair(mx[i].dst, mx[i].src, mx[i].score);
		count++;
	}
	return count;
}

494
void diffcore_rename(struct diff_options *options)
495
{
496 497
	int detect_rename = options->detect_rename;
	int minimum_score = options->rename_score;
498
	struct diff_queue_struct *q = &diff_queued_diff;
J
Junio C Hamano 已提交
499
	struct diff_queue_struct outq;
500
	struct diff_score *mx;
501
	int i, j, rename_count, skip_unmodified = 0;
502
	int num_create, dst_cnt;
503
	struct progress *progress = NULL;
504

505
	if (!minimum_score)
506
		minimum_score = DEFAULT_RENAME_SCORE;
507 508

	for (i = 0; i < q->nr; i++) {
509
		struct diff_filepair *p = q->queue[i];
510
		if (!DIFF_FILE_VALID(p->one)) {
511
			if (!DIFF_FILE_VALID(p->two))
512
				continue; /* unmerged */
513 514 515
			else if (options->single_follow &&
				 strcmp(options->single_follow, p->two->path))
				continue; /* not interested */
516 517 518
			else if (!DIFF_OPT_TST(options, RENAME_EMPTY) &&
				 is_empty_blob_sha1(p->two->sha1))
				continue;
519
			else
520
				locate_rename_dst(p->two, 1);
521
		}
522 523 524
		else if (!DIFF_OPT_TST(options, RENAME_EMPTY) &&
			 is_empty_blob_sha1(p->one->sha1))
			continue;
525
		else if (!DIFF_PAIR_UNMERGED(p) && !DIFF_FILE_VALID(p->two)) {
526 527
			/*
			 * If the source is a broken "delete", and
528 529
			 * they did not really want to get broken,
			 * that means the source actually stays.
530 531 532 533 534
			 * So we increment the "rename_used" score
			 * by one, to indicate ourselves as a user
			 */
			if (p->broken_pair && !p->score)
				p->one->rename_used++;
535
			register_rename_src(p);
536 537 538 539 540
		}
		else if (detect_rename == DIFF_DETECT_COPY) {
			/*
			 * Increment the "rename_used" score by
			 * one, to indicate ourselves as a user.
541
			 */
542
			p->one->rename_used++;
543
			register_rename_src(p);
544
		}
545
	}
546
	if (rename_dst_nr == 0 || rename_src_nr == 0)
547 548
		goto cleanup; /* nothing to do */

549 550 551 552
	/*
	 * We really want to cull the candidates list early
	 * with cheap tests in order to avoid doing deltas.
	 */
553
	rename_count = find_exact_renames(options);
554

555 556 557 558 559 560 561 562 563 564 565 566 567 568
	/* Did we only want exact renames? */
	if (minimum_score == MAX_SCORE)
		goto cleanup;

	/*
	 * Calculate how many renames are left (but all the source
	 * files still remain as options for rename/copies!)
	 */
	num_create = (rename_dst_nr - rename_count);

	/* All done? */
	if (!num_create)
		goto cleanup;

569 570
	switch (too_many_rename_candidates(num_create, options)) {
	case 1:
571
		goto cleanup;
572 573 574 575 576 577 578
	case 2:
		options->degraded_cc_to_c = 1;
		skip_unmodified = 1;
		break;
	default:
		break;
	}
579

580 581 582 583 584 585
	if (options->show_rename_progress) {
		progress = start_progress_delay(
				"Performing inexact rename detection",
				rename_dst_nr * rename_src_nr, 50, 1);
	}

586
	mx = xcalloc(num_create * NUM_CANDIDATE_PER_DST, sizeof(*mx));
587 588
	for (dst_cnt = i = 0; i < rename_dst_nr; i++) {
		struct diff_filespec *two = rename_dst[i].two;
589 590
		struct diff_score *m;

591
		if (rename_dst[i].pair)
592
			continue; /* dealt with exact match already. */
593 594 595 596 597

		m = &mx[dst_cnt * NUM_CANDIDATE_PER_DST];
		for (j = 0; j < NUM_CANDIDATE_PER_DST; j++)
			m[j].dst = -1;

598
		for (j = 0; j < rename_src_nr; j++) {
599
			struct diff_filespec *one = rename_src[j].p->one;
600
			struct diff_score this_src;
601 602 603 604 605

			if (skip_unmodified &&
			    diff_unmodified_pair(rename_src[j].p))
				continue;

606 607 608 609 610 611
			this_src.score = estimate_similarity(one, two,
							     minimum_score);
			this_src.name_score = basename_same(one, two);
			this_src.dst = i;
			this_src.src = j;
			record_if_better(m, &this_src);
612 613 614 615
			/*
			 * Once we run estimate_similarity,
			 * We do not need the text anymore.
			 */
616
			diff_free_filespec_blob(one);
617
			diff_free_filespec_blob(two);
618 619
		}
		dst_cnt++;
620
		display_progress(progress, (i+1)*rename_src_nr);
621
	}
622
	stop_progress(&progress);
623

624
	/* cost matrix sorted by most to least similar pair */
625 626
	qsort(mx, dst_cnt * NUM_CANDIDATE_PER_DST, sizeof(*mx), score_compare);

627 628 629
	rename_count += find_renames(mx, dst_cnt, minimum_score, 0);
	if (detect_rename == DIFF_DETECT_COPY)
		rename_count += find_renames(mx, dst_cnt, minimum_score, 1);
630 631
	free(mx);

632
 cleanup:
633
	/* At this point, we have found some renames and copies and they
J
Junio C Hamano 已提交
634
	 * are recorded in rename_dst.  The original list is still in *q.
635
	 */
B
Bo Yang 已提交
636
	DIFF_QUEUE_CLEAR(&outq);
637
	for (i = 0; i < q->nr; i++) {
638 639 640
		struct diff_filepair *p = q->queue[i];
		struct diff_filepair *pair_to_free = NULL;

641 642 643 644
		if (DIFF_PAIR_UNMERGED(p)) {
			diff_q(&outq, p);
		}
		else if (!DIFF_FILE_VALID(p->one) && DIFF_FILE_VALID(p->two)) {
645 646 647 648 649 650 651 652 653
			/*
			 * Creation
			 *
			 * We would output this create record if it has
			 * not been turned into a rename/copy already.
			 */
			struct diff_rename_dst *dst =
				locate_rename_dst(p->two, 0);
			if (dst && dst->pair) {
654 655 656 657
				diff_q(&outq, dst->pair);
				pair_to_free = p;
			}
			else
658 659
				/* no matching rename/copy source, so
				 * record this as a creation.
660 661
				 */
				diff_q(&outq, p);
662
		}
663 664 665 666
		else if (DIFF_FILE_VALID(p->one) && !DIFF_FILE_VALID(p->two)) {
			/*
			 * Deletion
			 *
667 668 669 670
			 * We would output this delete record if:
			 *
			 * (1) this is a broken delete and the counterpart
			 *     broken create remains in the output; or
J
Junio C Hamano 已提交
671 672 673
			 * (2) this is not a broken delete, and rename_dst
			 *     does not have a rename/copy to move p->one->path
			 *     out of existence.
674 675 676 677 678
			 *
			 * Otherwise, the counterpart broken create
			 * has been turned into a rename-edit; or
			 * delete did not have a matching create to
			 * begin with.
679
			 */
680 681 682 683 684 685 686 687 688
			if (DIFF_PAIR_BROKEN(p)) {
				/* broken delete */
				struct diff_rename_dst *dst =
					locate_rename_dst(p->one, 0);
				if (dst && dst->pair)
					/* counterpart is now rename/copy */
					pair_to_free = p;
			}
			else {
689
				if (p->one->rename_used)
690 691 692
					/* this path remains */
					pair_to_free = p;
			}
693 694 695 696 697 698

			if (pair_to_free)
				;
			else
				diff_q(&outq, p);
		}
699
		else if (!diff_unmodified_pair(p))
700
			/* all the usual ones need to be kept */
701
			diff_q(&outq, p);
702 703 704 705
		else
			/* no need to keep unmodified pairs */
			pair_to_free = p;

706 707
		if (pair_to_free)
			diff_free_filepair(pair_to_free);
708
	}
709
	diff_debug_queue("done copying original", &outq);
710

711 712 713
	free(q->queue);
	*q = outq;
	diff_debug_queue("done collapsing", q);
714

715 716
	for (i = 0; i < rename_dst_nr; i++)
		free_filespec(rename_dst[i].two);
J
Junio C Hamano 已提交
717

718 719 720 721 722 723
	free(rename_dst);
	rename_dst = NULL;
	rename_dst_nr = rename_dst_alloc = 0;
	free(rename_src);
	rename_src = NULL;
	rename_src_nr = rename_src_alloc = 0;
724 725
	return;
}