mirror of
https://github.com/git/git
synced 2024-08-27 11:39:22 +00:00
Merge branch 'jc/maint-split-diff-metainfo'
* jc/maint-split-diff-metainfo: diff.c: output correct index lines for a split diff
This commit is contained in:
commit
bdf6442b48
146
diff.c
146
diff.c
|
@ -2087,16 +2087,86 @@ static void run_external_diff(const char *pgm,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int similarity_index(struct diff_filepair *p)
|
||||||
|
{
|
||||||
|
return p->score * 100 / MAX_SCORE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void fill_metainfo(struct strbuf *msg,
|
||||||
|
const char *name,
|
||||||
|
const char *other,
|
||||||
|
struct diff_filespec *one,
|
||||||
|
struct diff_filespec *two,
|
||||||
|
struct diff_options *o,
|
||||||
|
struct diff_filepair *p)
|
||||||
|
{
|
||||||
|
strbuf_init(msg, PATH_MAX * 2 + 300);
|
||||||
|
switch (p->status) {
|
||||||
|
case DIFF_STATUS_COPIED:
|
||||||
|
strbuf_addf(msg, "similarity index %d%%", similarity_index(p));
|
||||||
|
strbuf_addstr(msg, "\ncopy from ");
|
||||||
|
quote_c_style(name, msg, NULL, 0);
|
||||||
|
strbuf_addstr(msg, "\ncopy to ");
|
||||||
|
quote_c_style(other, msg, NULL, 0);
|
||||||
|
strbuf_addch(msg, '\n');
|
||||||
|
break;
|
||||||
|
case DIFF_STATUS_RENAMED:
|
||||||
|
strbuf_addf(msg, "similarity index %d%%", similarity_index(p));
|
||||||
|
strbuf_addstr(msg, "\nrename from ");
|
||||||
|
quote_c_style(name, msg, NULL, 0);
|
||||||
|
strbuf_addstr(msg, "\nrename to ");
|
||||||
|
quote_c_style(other, msg, NULL, 0);
|
||||||
|
strbuf_addch(msg, '\n');
|
||||||
|
break;
|
||||||
|
case DIFF_STATUS_MODIFIED:
|
||||||
|
if (p->score) {
|
||||||
|
strbuf_addf(msg, "dissimilarity index %d%%\n",
|
||||||
|
similarity_index(p));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/* fallthru */
|
||||||
|
default:
|
||||||
|
/* nothing */
|
||||||
|
;
|
||||||
|
}
|
||||||
|
if (one && two && hashcmp(one->sha1, two->sha1)) {
|
||||||
|
int abbrev = DIFF_OPT_TST(o, FULL_INDEX) ? 40 : DEFAULT_ABBREV;
|
||||||
|
|
||||||
|
if (DIFF_OPT_TST(o, BINARY)) {
|
||||||
|
mmfile_t mf;
|
||||||
|
if ((!fill_mmfile(&mf, one) && diff_filespec_is_binary(one)) ||
|
||||||
|
(!fill_mmfile(&mf, two) && diff_filespec_is_binary(two)))
|
||||||
|
abbrev = 40;
|
||||||
|
}
|
||||||
|
strbuf_addf(msg, "index %.*s..%.*s",
|
||||||
|
abbrev, sha1_to_hex(one->sha1),
|
||||||
|
abbrev, sha1_to_hex(two->sha1));
|
||||||
|
if (one->mode == two->mode)
|
||||||
|
strbuf_addf(msg, " %06o", one->mode);
|
||||||
|
strbuf_addch(msg, '\n');
|
||||||
|
}
|
||||||
|
if (msg->len)
|
||||||
|
strbuf_setlen(msg, msg->len - 1);
|
||||||
|
}
|
||||||
|
|
||||||
static void run_diff_cmd(const char *pgm,
|
static void run_diff_cmd(const char *pgm,
|
||||||
const char *name,
|
const char *name,
|
||||||
const char *other,
|
const char *other,
|
||||||
const char *attr_path,
|
const char *attr_path,
|
||||||
struct diff_filespec *one,
|
struct diff_filespec *one,
|
||||||
struct diff_filespec *two,
|
struct diff_filespec *two,
|
||||||
const char *xfrm_msg,
|
struct strbuf *msg,
|
||||||
struct diff_options *o,
|
struct diff_options *o,
|
||||||
int complete_rewrite)
|
struct diff_filepair *p)
|
||||||
{
|
{
|
||||||
|
const char *xfrm_msg = NULL;
|
||||||
|
int complete_rewrite = (p->status == DIFF_STATUS_MODIFIED) && p->score;
|
||||||
|
|
||||||
|
if (msg) {
|
||||||
|
fill_metainfo(msg, name, other, one, two, o, p);
|
||||||
|
xfrm_msg = msg->len ? msg->buf : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
if (!DIFF_OPT_TST(o, ALLOW_EXTERNAL))
|
if (!DIFF_OPT_TST(o, ALLOW_EXTERNAL))
|
||||||
pgm = NULL;
|
pgm = NULL;
|
||||||
else {
|
else {
|
||||||
|
@ -2136,11 +2206,6 @@ static void diff_fill_sha1_info(struct diff_filespec *one)
|
||||||
hashclr(one->sha1);
|
hashclr(one->sha1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int similarity_index(struct diff_filepair *p)
|
|
||||||
{
|
|
||||||
return p->score * 100 / MAX_SCORE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void strip_prefix(int prefix_length, const char **namep, const char **otherp)
|
static void strip_prefix(int prefix_length, const char **namep, const char **otherp)
|
||||||
{
|
{
|
||||||
/* Strip the prefix but do not molest /dev/null and absolute paths */
|
/* Strip the prefix but do not molest /dev/null and absolute paths */
|
||||||
|
@ -2154,13 +2219,11 @@ static void run_diff(struct diff_filepair *p, struct diff_options *o)
|
||||||
{
|
{
|
||||||
const char *pgm = external_diff();
|
const char *pgm = external_diff();
|
||||||
struct strbuf msg;
|
struct strbuf msg;
|
||||||
char *xfrm_msg;
|
|
||||||
struct diff_filespec *one = p->one;
|
struct diff_filespec *one = p->one;
|
||||||
struct diff_filespec *two = p->two;
|
struct diff_filespec *two = p->two;
|
||||||
const char *name;
|
const char *name;
|
||||||
const char *other;
|
const char *other;
|
||||||
const char *attr_path;
|
const char *attr_path;
|
||||||
int complete_rewrite = 0;
|
|
||||||
|
|
||||||
name = p->one->path;
|
name = p->one->path;
|
||||||
other = (strcmp(name, p->two->path) ? p->two->path : NULL);
|
other = (strcmp(name, p->two->path) ? p->two->path : NULL);
|
||||||
|
@ -2170,83 +2233,34 @@ static void run_diff(struct diff_filepair *p, struct diff_options *o)
|
||||||
|
|
||||||
if (DIFF_PAIR_UNMERGED(p)) {
|
if (DIFF_PAIR_UNMERGED(p)) {
|
||||||
run_diff_cmd(pgm, name, NULL, attr_path,
|
run_diff_cmd(pgm, name, NULL, attr_path,
|
||||||
NULL, NULL, NULL, o, 0);
|
NULL, NULL, NULL, o, p);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
diff_fill_sha1_info(one);
|
diff_fill_sha1_info(one);
|
||||||
diff_fill_sha1_info(two);
|
diff_fill_sha1_info(two);
|
||||||
|
|
||||||
strbuf_init(&msg, PATH_MAX * 2 + 300);
|
|
||||||
switch (p->status) {
|
|
||||||
case DIFF_STATUS_COPIED:
|
|
||||||
strbuf_addf(&msg, "similarity index %d%%", similarity_index(p));
|
|
||||||
strbuf_addstr(&msg, "\ncopy from ");
|
|
||||||
quote_c_style(name, &msg, NULL, 0);
|
|
||||||
strbuf_addstr(&msg, "\ncopy to ");
|
|
||||||
quote_c_style(other, &msg, NULL, 0);
|
|
||||||
strbuf_addch(&msg, '\n');
|
|
||||||
break;
|
|
||||||
case DIFF_STATUS_RENAMED:
|
|
||||||
strbuf_addf(&msg, "similarity index %d%%", similarity_index(p));
|
|
||||||
strbuf_addstr(&msg, "\nrename from ");
|
|
||||||
quote_c_style(name, &msg, NULL, 0);
|
|
||||||
strbuf_addstr(&msg, "\nrename to ");
|
|
||||||
quote_c_style(other, &msg, NULL, 0);
|
|
||||||
strbuf_addch(&msg, '\n');
|
|
||||||
break;
|
|
||||||
case DIFF_STATUS_MODIFIED:
|
|
||||||
if (p->score) {
|
|
||||||
strbuf_addf(&msg, "dissimilarity index %d%%\n",
|
|
||||||
similarity_index(p));
|
|
||||||
complete_rewrite = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
/* fallthru */
|
|
||||||
default:
|
|
||||||
/* nothing */
|
|
||||||
;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hashcmp(one->sha1, two->sha1)) {
|
|
||||||
int abbrev = DIFF_OPT_TST(o, FULL_INDEX) ? 40 : DEFAULT_ABBREV;
|
|
||||||
|
|
||||||
if (DIFF_OPT_TST(o, BINARY)) {
|
|
||||||
mmfile_t mf;
|
|
||||||
if ((!fill_mmfile(&mf, one) && diff_filespec_is_binary(one)) ||
|
|
||||||
(!fill_mmfile(&mf, two) && diff_filespec_is_binary(two)))
|
|
||||||
abbrev = 40;
|
|
||||||
}
|
|
||||||
strbuf_addf(&msg, "index %.*s..%.*s",
|
|
||||||
abbrev, sha1_to_hex(one->sha1),
|
|
||||||
abbrev, sha1_to_hex(two->sha1));
|
|
||||||
if (one->mode == two->mode)
|
|
||||||
strbuf_addf(&msg, " %06o", one->mode);
|
|
||||||
strbuf_addch(&msg, '\n');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (msg.len)
|
|
||||||
strbuf_setlen(&msg, msg.len - 1);
|
|
||||||
xfrm_msg = msg.len ? msg.buf : NULL;
|
|
||||||
|
|
||||||
if (!pgm &&
|
if (!pgm &&
|
||||||
DIFF_FILE_VALID(one) && DIFF_FILE_VALID(two) &&
|
DIFF_FILE_VALID(one) && DIFF_FILE_VALID(two) &&
|
||||||
(S_IFMT & one->mode) != (S_IFMT & two->mode)) {
|
(S_IFMT & one->mode) != (S_IFMT & two->mode)) {
|
||||||
/* a filepair that changes between file and symlink
|
/*
|
||||||
|
* a filepair that changes between file and symlink
|
||||||
* needs to be split into deletion and creation.
|
* needs to be split into deletion and creation.
|
||||||
*/
|
*/
|
||||||
struct diff_filespec *null = alloc_filespec(two->path);
|
struct diff_filespec *null = alloc_filespec(two->path);
|
||||||
run_diff_cmd(NULL, name, other, attr_path,
|
run_diff_cmd(NULL, name, other, attr_path,
|
||||||
one, null, xfrm_msg, o, 0);
|
one, null, &msg, o, p);
|
||||||
free(null);
|
free(null);
|
||||||
|
strbuf_release(&msg);
|
||||||
|
|
||||||
null = alloc_filespec(one->path);
|
null = alloc_filespec(one->path);
|
||||||
run_diff_cmd(NULL, name, other, attr_path,
|
run_diff_cmd(NULL, name, other, attr_path,
|
||||||
null, two, xfrm_msg, o, 0);
|
null, two, &msg, o, p);
|
||||||
free(null);
|
free(null);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
run_diff_cmd(pgm, name, other, attr_path,
|
run_diff_cmd(pgm, name, other, attr_path,
|
||||||
one, two, xfrm_msg, o, complete_rewrite);
|
one, two, &msg, o, p);
|
||||||
|
|
||||||
strbuf_release(&msg);
|
strbuf_release(&msg);
|
||||||
}
|
}
|
||||||
|
|
|
@ -104,7 +104,7 @@ cat >expect.typechange <<'EOF'
|
||||||
-1
|
-1
|
||||||
diff --git a/file b/file
|
diff --git a/file b/file
|
||||||
new file mode 120000
|
new file mode 120000
|
||||||
index ad8b3d2..67be421
|
index 0000000..67be421
|
||||||
--- /dev/null
|
--- /dev/null
|
||||||
+++ b/file
|
+++ b/file
|
||||||
@@ -0,0 +1 @@
|
@@ -0,0 +1 @@
|
||||||
|
|
|
@ -25,6 +25,10 @@ test_expect_success 'setup repository and commits' '
|
||||||
git update-index foo &&
|
git update-index foo &&
|
||||||
git commit -m "foo back to file" &&
|
git commit -m "foo back to file" &&
|
||||||
git branch foo-back-to-file &&
|
git branch foo-back-to-file &&
|
||||||
|
printf "\0" > foo &&
|
||||||
|
git update-index foo &&
|
||||||
|
git commit -m "foo becomes binary" &&
|
||||||
|
git branch foo-becomes-binary &&
|
||||||
rm -f foo &&
|
rm -f foo &&
|
||||||
git update-index --remove foo &&
|
git update-index --remove foo &&
|
||||||
mkdir foo &&
|
mkdir foo &&
|
||||||
|
@ -85,6 +89,20 @@ test_expect_success 'symlink becomes file' '
|
||||||
'
|
'
|
||||||
test_debug 'cat patch'
|
test_debug 'cat patch'
|
||||||
|
|
||||||
|
test_expect_success 'binary file becomes symlink' '
|
||||||
|
git checkout -f foo-becomes-binary &&
|
||||||
|
git diff-tree -p --binary HEAD foo-symlinked-to-bar > patch &&
|
||||||
|
git apply --index < patch
|
||||||
|
'
|
||||||
|
test_debug 'cat patch'
|
||||||
|
|
||||||
|
test_expect_success 'symlink becomes binary file' '
|
||||||
|
git checkout -f foo-symlinked-to-bar &&
|
||||||
|
git diff-tree -p --binary HEAD foo-becomes-binary > patch &&
|
||||||
|
git apply --index < patch
|
||||||
|
'
|
||||||
|
test_debug 'cat patch'
|
||||||
|
|
||||||
|
|
||||||
test_expect_success 'symlink becomes directory' '
|
test_expect_success 'symlink becomes directory' '
|
||||||
git checkout -f foo-symlinked-to-bar &&
|
git checkout -f foo-symlinked-to-bar &&
|
||||||
|
|
Loading…
Reference in a new issue