[PATCH 1/6] Reworked external diff interface.
From: Junio C Hamano <hidden>
Date: 2016-06-15 22:41:54
This patch introduces three public functions for diff-cache and
friends can use to call out to the GIT_EXTERNAL_DIFF program
when they wish to. A normal "add/remove/change" entry is turned
into 7-parameter process invocation of GIT_EXTERNAL_DIFF program
as before. In addition, the program can now be called with a
single parameter when diff-cache and friends want to report an
unmerged path.
Signed-off-by: Junio C Hamano <redacted>
---
diff.c | 93 ++++++++++++++++++++++++++++++++++++++++-------------------------
diff.h | 19 +++++++++----
2 files changed, 72 insertions(+), 40 deletions(-)
To be tested with the following:
GIT_INDEX_FILE=junk
export GIT_INDEX_FILE
read-tree $(cat .git/HEAD)
t1=$(write-tree)
date >trash ; update-cache --add trash
t2=$(write-tree)
read-tree -m $(cat .git/HEAD) $t1 $t2
update-cache --refresh
./show-diff | GIT_EXTERNAL_DIFF=echo ./diff-tree-helper
--- k/diff.c
+++ l/diff.c@@ -194,13 +194,15 @@ void run_external_diff(const char *name, int pid, status; static int atexit_asked = 0; - prepare_temp_file(name, &temp[0], one); - prepare_temp_file(name, &temp[1], two); - if (! atexit_asked && - (temp[0].name == temp[0].tmp_path || - temp[1].name == temp[1].tmp_path)) { - atexit_asked = 1; - atexit(remove_tempfile); + if (one && two) { + prepare_temp_file(name, &temp[0], one); + prepare_temp_file(name, &temp[1], two); + if (! atexit_asked && + (temp[0].name == temp[0].tmp_path || + temp[1].name == temp[1].tmp_path)) { + atexit_asked = 1; + atexit(remove_tempfile); + } } fflush(NULL);
@@ -209,16 +211,23 @@ void run_external_diff(const char *name, die("unable to fork"); if (!pid) { const char *pgm = external_diff(); - if (pgm) - execlp(pgm, pgm, - name, - temp[0].name, temp[0].hex, temp[0].mode, - temp[1].name, temp[1].hex, temp[1].mode, - NULL); + if (pgm) { + if (one && two) + execlp(pgm, pgm, + name, + temp[0].name, temp[0].hex, temp[0].mode, + temp[1].name, temp[1].hex, temp[1].mode, + NULL); + else + execlp(pgm, pgm, name, NULL); + } /* * otherwise we use the built-in one. */ - builtin_diff(name, temp); + if (one && two) + builtin_diff(name, temp); + else + printf("* Unmerged path %s\n", name); exit(0); } if (waitpid(pid, &status, 0) < 0 || !WIFEXITED(status))
@@ -227,41 +236,55 @@ void run_external_diff(const char *name, remove_tempfile(); } -void show_diff_empty(const struct cache_entry *ce, int reverse) +void diff_addremove(int addremove, unsigned mode, + const unsigned char *sha1, + const char *base, const char *path) { + char concatpath[PATH_MAX]; struct diff_spec spec[2], *one, *two; - memcpy(spec[0].u.sha1, ce->sha1, 20); - spec[0].mode = ntohl(ce->ce_mode); + memcpy(spec[0].u.sha1, sha1, 20); + spec[0].mode = mode; spec[0].sha1_valid = spec[0].file_valid = 1; spec[1].file_valid = 0; - if (reverse) { + if (addremove == '+') { one = spec + 1; two = spec; } else { one = spec; two = one + 1; } - - run_external_diff(ce->name, one, two); + + if (path) { + strcpy(concatpath, base); + strcat(concatpath, "/"); + strcat(concatpath, path); + } + run_external_diff(path ? concatpath : base, one, two); } -void show_differences(const struct cache_entry *ce, int reverse) -{ - struct diff_spec spec[2], *one, *two; - - memcpy(spec[0].u.sha1, ce->sha1, 20); - spec[0].mode = ntohl(ce->ce_mode); +void diff_change(unsigned old_mode, unsigned new_mode, + const unsigned char *old_sha1, + const unsigned char *new_sha1, + const char *base, const char *path) { + char concatpath[PATH_MAX]; + struct diff_spec spec[2]; + + memcpy(spec[0].u.sha1, old_sha1, 20); + spec[0].mode = old_mode; + memcpy(spec[1].u.sha1, new_sha1, 20); + spec[1].mode = new_mode; spec[0].sha1_valid = spec[0].file_valid = 1; + spec[1].sha1_valid = spec[1].file_valid = 1; - spec[1].u.name = ce->name; /* the name we stated */ - spec[1].sha1_valid = 0; - spec[1].file_valid = 1; - - if (reverse) { - one = spec + 1; two = spec; - } else { - one = spec; two = one + 1; + if (path) { + strcpy(concatpath, base); + strcat(concatpath, "/"); + strcat(concatpath, path); } + run_external_diff(path ? concatpath : base, &spec[0], &spec[1]); +} - run_external_diff(ce->name, one, two); +void diff_unmerge(const char *path) +{ + run_external_diff(path, NULL, NULL); } --- k/diff.h +++ l/diff.h
@@ -4,11 +4,20 @@ #ifndef DIFF_H #define DIFF_H -/* These two are for backward compatibility with show-diff; - * new users should not use them. - */ -extern void show_differences(const struct cache_entry *ce, int reverse); -extern void show_diff_empty(const struct cache_entry *ce, int reverse); +extern void diff_addremove(int addremove, + unsigned mode, + const unsigned char *sha1, + const char *base, + const char *path); + +extern void diff_change(unsigned mode1, unsigned mode2, + const unsigned char *sha1, + const unsigned char *sha2, + const char *base, const char *path); + +extern void diff_unmerge(const char *path); + +/* These are for diff-tree-helper */ struct diff_spec { union {