forked from git/git
-
Notifications
You must be signed in to change notification settings - Fork 133
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add range-diff
, a tbdiff
lookalike
#1
Closed
Closed
Changes from 3 commits
Commits
Show all changes
21 commits
Select commit
Hold shift + click to select a range
f168da3
linear-assignment: a function to solve least-cost assignment problems
dscho 33758f3
Introduce `range-diff` to compare iterations of a topic branch
dscho 08b8c3f
range-diff: first rudimentary implementation
dscho 7b90919
range-diff: improve the order of the shown commits
dscho 8515d2f
range-diff: also show the diff between patches
dscho a10ca01
range-diff: right-trim commit messages
dscho f81cbef
range-diff: indent the diffs just like tbdiff
dscho 458090f
range-diff: suppress the diff headers
dscho d3be03a
range-diff: adjust the output of the commit pairs
dscho 94b44df
range-diff: do not show "function names" in hunk headers
dscho 1477c58
range-diff: add tests
trast 32492c1
range-diff: use color for the commit pairs
dscho 969a196
color: add the meta color GIT_COLOR_REVERSE
dscho f1c86f6
diff: add an internal option to dual-color diffs of diffs
dscho 3c7b9f3
range-diff: offer to dual-color the diffs
dscho c56c51c
range-diff --dual-color: skip white-space warnings
dscho 8c5543a
range-diff: populate the man page
dscho 16e3cf2
completion: support `git range-diff`
dscho d9b09ab
range-diff: left-pad patch numbers
dscho f6fd395
range-diff: make --dual-color the default mode
dscho 699cd71
range-diff: use dim/bold cues to improve dual color mode
dscho File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -113,6 +113,7 @@ | |
/git-pull | ||
/git-push | ||
/git-quiltimport | ||
/git-range-diff | ||
/git-read-tree | ||
/git-rebase | ||
/git-rebase--am | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
git-range-diff(1) | ||
================= | ||
|
||
NAME | ||
---- | ||
git-range-diff - Compare two commit ranges (e.g. two versions of a branch) | ||
|
||
GIT | ||
--- | ||
Part of the linkgit:git[1] suite |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
#include "cache.h" | ||
#include "builtin.h" | ||
#include "parse-options.h" | ||
#include "range-diff.h" | ||
|
||
static const char * const builtin_range_diff_usage[] = { | ||
N_("git range-diff [<options>] <old-base>..<old-tip> <new-base>..<new-tip>"), | ||
N_("git range-diff [<options>] <old-tip>...<new-tip>"), | ||
N_("git range-diff [<options>] <base> <old-tip> <new-tip>"), | ||
NULL | ||
}; | ||
|
||
int cmd_range_diff(int argc, const char **argv, const char *prefix) | ||
{ | ||
int creation_factor = 60; | ||
struct option options[] = { | ||
OPT_INTEGER(0, "creation-factor", &creation_factor, | ||
N_("Percentage by which creation is weighted")), | ||
OPT_END() | ||
}; | ||
int res = 0; | ||
struct strbuf range1 = STRBUF_INIT, range2 = STRBUF_INIT; | ||
|
||
argc = parse_options(argc, argv, NULL, options, | ||
builtin_range_diff_usage, 0); | ||
|
||
if (argc == 2) { | ||
if (!strstr(argv[0], "..")) | ||
die(_("no .. in range: '%s'"), argv[0]); | ||
strbuf_addstr(&range1, argv[0]); | ||
|
||
if (!strstr(argv[1], "..")) | ||
die(_("no .. in range: '%s'"), argv[1]); | ||
strbuf_addstr(&range2, argv[1]); | ||
} else if (argc == 3) { | ||
strbuf_addf(&range1, "%s..%s", argv[0], argv[1]); | ||
strbuf_addf(&range2, "%s..%s", argv[0], argv[2]); | ||
} else if (argc == 1) { | ||
const char *b = strstr(argv[0], "..."), *a = argv[0]; | ||
int a_len; | ||
|
||
if (!b) { | ||
error(_("single arg format must be symmetric range")); | ||
usage_with_options(builtin_range_diff_usage, options); | ||
} | ||
|
||
a_len = (int)(b - a); | ||
if (!a_len) { | ||
a = "HEAD"; | ||
a_len = strlen(a); | ||
} | ||
b += 3; | ||
if (!*b) | ||
b = "HEAD"; | ||
strbuf_addf(&range1, "%s..%.*s", b, a_len, a); | ||
strbuf_addf(&range2, "%.*s..%s", a_len, a, b); | ||
} else { | ||
error(_("need two commit ranges")); | ||
usage_with_options(builtin_range_diff_usage, options); | ||
} | ||
|
||
res = show_range_diff(range1.buf, range2.buf, creation_factor); | ||
|
||
strbuf_release(&range1); | ||
strbuf_release(&range2); | ||
|
||
return res; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,201 @@ | ||
/* | ||
* Based on: Jonker, R., & Volgenant, A. (1987). <i>A shortest augmenting path | ||
* algorithm for dense and sparse linear assignment problems</i>. Computing, | ||
* 38(4), 325-340. | ||
*/ | ||
#include "cache.h" | ||
#include "linear-assignment.h" | ||
|
||
#define COST(column, row) cost[(column) + column_count * (row)] | ||
|
||
/* | ||
* The parameter `cost` is the cost matrix: the cost to assign column j to row | ||
* i is `cost[j + column_count * i]. | ||
*/ | ||
void compute_assignment(int column_count, int row_count, int *cost, | ||
int *column2row, int *row2column) | ||
{ | ||
int *v, *d; | ||
int *free_row, free_count = 0, saved_free_count, *pred, *col; | ||
int i, j, phase; | ||
|
||
memset(column2row, -1, sizeof(int) * column_count); | ||
memset(row2column, -1, sizeof(int) * row_count); | ||
ALLOC_ARRAY(v, column_count); | ||
|
||
/* column reduction */ | ||
for (j = column_count - 1; j >= 0; j--) { | ||
int i1 = 0; | ||
|
||
for (i = 1; i < row_count; i++) | ||
if (COST(j, i1) > COST(j, i)) | ||
i1 = i; | ||
v[j] = COST(j, i1); | ||
if (row2column[i1] == -1) { | ||
/* row i1 unassigned */ | ||
row2column[i1] = j; | ||
column2row[j] = i1; | ||
} else { | ||
if (row2column[i1] >= 0) | ||
row2column[i1] = -2 - row2column[i1]; | ||
column2row[j] = -1; | ||
} | ||
} | ||
|
||
/* reduction transfer */ | ||
ALLOC_ARRAY(free_row, row_count); | ||
for (i = 0; i < row_count; i++) { | ||
int j1 = row2column[i]; | ||
if (j1 == -1) | ||
free_row[free_count++] = i; | ||
else if (j1 < -1) | ||
row2column[i] = -2 - j1; | ||
else { | ||
int min = COST(!j1, i) - v[!j1]; | ||
for (j = 1; j < column_count; j++) | ||
if (j != j1 && min > COST(j, i) - v[j]) | ||
min = COST(j, i) - v[j]; | ||
v[j1] -= min; | ||
} | ||
} | ||
|
||
if (free_count == | ||
(column_count < row_count ? row_count - column_count : 0)) { | ||
free(v); | ||
free(free_row); | ||
return; | ||
} | ||
|
||
/* augmenting row reduction */ | ||
for (phase = 0; phase < 2; phase++) { | ||
int k = 0; | ||
|
||
saved_free_count = free_count; | ||
free_count = 0; | ||
while (k < saved_free_count) { | ||
int u1, u2; | ||
int j1 = 0, j2, i0; | ||
|
||
i = free_row[k++]; | ||
u1 = COST(j1, i) - v[j1]; | ||
j2 = -1; | ||
u2 = INT_MAX; | ||
for (j = 1; j < column_count; j++) { | ||
int c = COST(j, i) - v[j]; | ||
if (u2 > c) { | ||
if (u1 < c) { | ||
u2 = c; | ||
j2 = j; | ||
} else { | ||
u2 = u1; | ||
u1 = c; | ||
j2 = j1; | ||
j1 = j; | ||
} | ||
} | ||
} | ||
if (j2 < 0) { | ||
j2 = j1; | ||
u2 = u1; | ||
} | ||
|
||
i0 = column2row[j1]; | ||
if (u1 < u2) | ||
v[j1] -= u2 - u1; | ||
else if (i0 >= 0) { | ||
j1 = j2; | ||
i0 = column2row[j1]; | ||
} | ||
|
||
if (i0 >= 0) { | ||
if (u1 < u2) | ||
free_row[--k] = i0; | ||
else | ||
free_row[free_count++] = i0; | ||
} | ||
row2column[i] = j1; | ||
column2row[j1] = i; | ||
} | ||
} | ||
|
||
/* augmentation */ | ||
saved_free_count = free_count; | ||
ALLOC_ARRAY(d, column_count); | ||
ALLOC_ARRAY(pred, column_count); | ||
ALLOC_ARRAY(col, column_count); | ||
for (free_count = 0; free_count < saved_free_count; free_count++) { | ||
int i1 = free_row[free_count], low = 0, up = 0, last, k; | ||
int min, c, u1; | ||
|
||
for (j = 0; j < column_count; j++) { | ||
d[j] = COST(j, i1) - v[j]; | ||
pred[j] = i1; | ||
col[j] = j; | ||
} | ||
|
||
j = -1; | ||
do { | ||
last = low; | ||
min = d[col[up++]]; | ||
for (k = up; k < column_count; k++) { | ||
j = col[k]; | ||
c = d[j]; | ||
if (c <= min) { | ||
if (c < min) { | ||
up = low; | ||
min = c; | ||
} | ||
col[k] = col[up]; | ||
col[up++] = j; | ||
} | ||
} | ||
for (k = low; k < up; k++) | ||
if (column2row[col[k]] == -1) | ||
goto update; | ||
|
||
/* scan a row */ | ||
do { | ||
int j1 = col[low++]; | ||
|
||
i = column2row[j1]; | ||
u1 = COST(j1, i) - v[j1] - min; | ||
for (k = up; k < column_count; k++) { | ||
j = col[k]; | ||
c = COST(j, i) - v[j] - u1; | ||
if (c < d[j]) { | ||
d[j] = c; | ||
pred[j] = i; | ||
if (c == min) { | ||
if (column2row[j] == -1) | ||
goto update; | ||
col[k] = col[up]; | ||
col[up++] = j; | ||
} | ||
} | ||
} | ||
} while (low != up); | ||
} while (low == up); | ||
|
||
update: | ||
/* updating of the column pieces */ | ||
for (k = 0; k < last; k++) { | ||
int j1 = col[k]; | ||
v[j1] += d[j1] - min; | ||
} | ||
|
||
/* augmentation */ | ||
do { | ||
if (j < 0) | ||
BUG("negative j: %d", j); | ||
i = pred[j]; | ||
column2row[j] = i; | ||
SWAP(j, row2column[i]); | ||
} while (i1 != i); | ||
} | ||
|
||
free(col); | ||
free(pred); | ||
free(d); | ||
free(v); | ||
free(free_row); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
#ifndef LINEAR_ASSIGNMENT_H | ||
#define LINEAR_ASSIGNMENT_H | ||
|
||
/* | ||
* Compute an assignment of columns -> rows (and vice versa) such that every | ||
* column is assigned to at most one row (and vice versa) minimizing the | ||
* overall cost. | ||
* | ||
* The parameter `cost` is the cost matrix: the cost to assign column j to row | ||
* i is `cost[j + column_count * i]. | ||
* | ||
* The arrays column2row and row2column will be populated with the respective | ||
* assignments (-1 for unassigned, which can happen only if column_count != | ||
* row_count). | ||
*/ | ||
void compute_assignment(int column_count, int row_count, int *cost, | ||
int *column2row, int *row2column); | ||
|
||
/* The maximal cost in the cost matrix (to prevent integer overflows). */ | ||
#define COST_MAX (1<<16) | ||
|
||
#endif |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On the Git mailing list, Junio C Hamano wrote (reply to this):