Skip to content

Commit 263eee2

Browse files
author
Junio C Hamano
committed
combine-diff: extend --cc logic to Octopus.
Santi Bejar points out that a hunk that changes from all the same common parents except one is uninteresting. The earlier round marked changes from only one parent uninteresting, but this also marks hunks that have the same change from all but one parent uninteresting, which is a natural extension of the original idea to Octopus merges. Signed-off-by: Junio C Hamano <junkio@cox.net>
1 parent e228340 commit 263eee2

File tree

1 file changed

+63
-26
lines changed

1 file changed

+63
-26
lines changed

combine-diff.c

Lines changed: 63 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -271,21 +271,56 @@ static int interesting(struct sline *sline, unsigned long all_mask)
271271
return ((sline->flag & all_mask) != all_mask || sline->lost_head);
272272
}
273273

274-
static unsigned long line_diff_parents(struct sline *sline, unsigned long all_mask)
274+
static unsigned long line_common_diff(struct sline *sline, unsigned long all_mask)
275275
{
276276
/*
277-
* Look at the line and see from which parents we have difference.
278-
* Lower bits of sline->flag records if the parent had this line,
279-
* so XOR with all_mask gives us on-bits for parents we have
280-
* differences with.
277+
* Look at the line and see from which parents we have the
278+
* same difference.
281279
*/
282-
unsigned long parents = (sline->flag ^ all_mask);
280+
281+
/* Lower bits of sline->flag records if the parent had this
282+
* line, so XOR with all_mask gives us on-bits for parents we
283+
* have differences with.
284+
*/
285+
unsigned long common_adds = (sline->flag ^ all_mask) & all_mask;
286+
unsigned long common_removes = all_mask;
287+
288+
/* If all the parents have this line, that also counts as
289+
* having the same difference.
290+
*/
291+
if (!common_adds)
292+
common_adds = all_mask;
293+
294+
if (sline->lost_head) {
295+
/* Lost head list records the lines removed from
296+
* the parents, and parent_map records from which
297+
* parent the line was removed.
298+
*/
299+
struct lline *ll;
300+
for (ll = sline->lost_head; ll; ll = ll->next) {
301+
common_removes &= ll->parent_map;
302+
}
303+
}
304+
return common_adds & common_removes;
305+
}
306+
307+
static unsigned long line_all_diff(struct sline *sline, unsigned long all_mask)
308+
{
309+
/*
310+
* Look at the line and see from which parents we have some difference.
311+
*/
312+
unsigned long different = (sline->flag ^ all_mask) & all_mask;
283313
if (sline->lost_head) {
314+
/* Lost head list records the lines removed from
315+
* the parents, and parent_map records from which
316+
* parent the line was removed.
317+
*/
284318
struct lline *ll;
285-
for (ll = sline->lost_head; ll; ll = ll->next)
286-
parents |= ll->parent_map;
319+
for (ll = sline->lost_head; ll; ll = ll->next) {
320+
different |= ll->parent_map;
321+
}
287322
}
288-
return parents & all_mask;
323+
return different;
289324
}
290325

291326
static void make_hunks(struct sline *sline, unsigned long cnt,
@@ -316,36 +351,38 @@ static void make_hunks(struct sline *sline, unsigned long cnt,
316351
if (!dense)
317352
return;
318353

319-
/* Look at each hunk, and if it contains changes from only
320-
* one parent, mark that uninteresting.
354+
/* Look at each hunk, and if we have changes from only one
355+
* parent, or the changes are the same from all but one
356+
* parent, mark that uninteresting.
321357
*/
322358
i = 0;
323359
while (i < cnt) {
324-
int j, hunk_end, diffs;
325-
unsigned long parents;
360+
int j, hunk_end, same, diff;
361+
unsigned long same_diff, all_diff, this_diff;
326362
while (i < cnt && !(sline[i].flag & mark))
327363
i++;
328364
if (cnt <= i)
329365
break; /* No more interesting hunks */
330366
for (hunk_end = i + 1; hunk_end < cnt; hunk_end++)
331367
if (!(sline[hunk_end].flag & mark))
332368
break;
333-
/* [i..hunk_end) are interesting. Now is it from
334-
* only one parent?
335-
* If lost lines are only from one parent and
336-
* remaining lines existed in parents other than
337-
* that parent, then the hunk is not that interesting.
369+
/* [i..hunk_end) are interesting. Now does it have
370+
* the same change with all but one parent?
338371
*/
339-
parents = 0;
340-
diffs = 0;
341-
for (j = i; j < hunk_end; j++)
342-
parents |= line_diff_parents(sline + j, all_mask);
343-
/* Now, how many bits from [0..num_parent) are on? */
372+
same_diff = all_mask;
373+
all_diff = 0;
374+
for (j = i; j < hunk_end; j++) {
375+
same_diff &= line_common_diff(sline + j, all_mask);
376+
all_diff |= line_all_diff(sline + j, all_mask);
377+
}
378+
diff = same = 0;
344379
for (j = 0; j < num_parent; j++) {
345-
if (parents & (1UL<<j))
346-
diffs++;
380+
if (same_diff & (1UL<<j))
381+
same++;
382+
if (all_diff & (1UL<<j))
383+
diff++;
347384
}
348-
if (diffs < 2) {
385+
if ((num_parent - 1 <= same) || (diff == 1)) {
349386
/* This hunk is not that interesting after all */
350387
for (j = i; j < hunk_end; j++)
351388
sline[j].flag &= ~mark;

0 commit comments

Comments
 (0)