[PATCH] Fix diff-pruning logic which was running prune too early.
For later stages to reorder patches, pruning logic and rename detection
logic should not decide which delete to discard (because another entry
said it will take over the file as a rename) until the very end.
Also fix some tests that were assuming the earlier "last one is rename
or keep everything else is copy" semantics of diff-raw format, which no
longer is true.
Signed-off-by: Junio C Hamano <junkio@cox.net>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
maint
Junio C Hamano20 years agocommitted byLinus Torvalds
@ -630,105 +625,82 @@ int diff_needs_to_stay(struct diff_queue_struct *q, int i,
@@ -630,105 +625,82 @@ int diff_needs_to_stay(struct diff_queue_struct *q, int i,
return 0;
}
static int diff_used_as_source(struct diff_queue_struct *q, int lim,
struct diff_filespec *it)
int diff_queue_is_empty(void)
{
int i;
for (i = 0; i < lim; i++) {
struct diff_filepair *p = q->queue[i++];
if (!strcmp(p->one->path, it->path))
return 1;
}
return 0;
struct diff_queue_struct *q = &diff_queued_diff;
return q->nr == 0;
}
void diffcore_prune(void)
static void diff_resolve_rename_copy(void)
{
/*
* Although rename/copy detection wants to have "no-change"
* entries fed into them, the downstream do not need to see
* them, unless we had rename/copy for the same path earlier.
* This function removes such entries.
*
* The applications that use rename/copy should:
*
* (1) feed change and "no-change" entries via diff_queue().
* (2) call diffcore_rename, and any other future diffcore_xxx
* that would benefit by still having "no-change" entries.
* (3) call diffcore_prune
* (4) call other diffcore_xxx that do not need to see
* "no-change" entries.
* (5) call diff_flush().
*/
struct diff_queue_struct *q = &diff_queued_diff;
struct diff_queue_struct outq;
int i;
outq.queue = NULL;
outq.nr = outq.alloc = 0;
struct diff_queue_struct *q = &diff_queued_diff;
for (i = 0; i < q->nr; i++) {
struct diff_filepair *p = q->queue[i];
if (!diff_unmodified_pair(p) ||
diff_used_as_source(q, i, p->one))
diff_q(&outq, p);
else
free(p);
p->status = 0;
if (DIFF_PAIR_UNMERGED(p))
p->status = 'U';
else if (!DIFF_FILE_VALID((p)->one))
p->status = 'N';
else if (!DIFF_FILE_VALID((p)->two)) {
/* maybe earlier one said 'R', meaning
* it will take it, in which case we do
* not need to keep 'D'.
*/
int j;
for (j = 0; j < i; j++) {
struct diff_filepair *pp = q->queue[j];
if (pp->status == 'R' &&
!strcmp(pp->one->path, p->one->path))
break;
}
if (j < i)
continue;
p->status = 'D';
}
else if (strcmp(p->one->path, p->two->path)) {
/* This is rename or copy. Which one is it? */
if (diff_needs_to_stay(q, i+1, p->one))
p->status = 'C';
else
p->status = 'R';
}
else if (memcmp(p->one->sha1, p->two->sha1, 20))
p->status = 'M';
else {
/* we do not need this one */
p->status = 0;
}
}
free(q->queue);
*q = outq;
return;
}
int diff_queue_is_empty(void)
{
struct diff_queue_struct *q = &diff_queued_diff;
return q->nr == 0;
}
void diff_flush(int diff_output_style, int resolve_rename_copy)