Merge branch 'jc/ll-merge-expose-path'

Traditionally, external low-level 3-way merge drivers are expected
to produce their results based solely on the contents of the three
variants given in temporary files named by %O, %A and %B on their
command line.  Additionally allow them to look at the final path
(given by %P).

* jc/ll-merge-expose-path:
  ll-merge: pass the original path to external drivers
This commit is contained in:
Junio C Hamano 2015-06-24 12:21:45 -07:00
commit 49ac7358da
3 changed files with 21 additions and 8 deletions

View File

@ -774,7 +774,7 @@ To define a custom merge driver `filfre`, add a section to your
---------------------------------------------------------------- ----------------------------------------------------------------
[merge "filfre"] [merge "filfre"]
name = feel-free merge driver name = feel-free merge driver
driver = filfre %O %A %B driver = filfre %O %A %B %L %P
recursive = binary recursive = binary
---------------------------------------------------------------- ----------------------------------------------------------------
@ -800,6 +800,9 @@ merge between common ancestors, when there are more than one.
When left unspecified, the driver itself is used for both When left unspecified, the driver itself is used for both
internal merge and the final merge. internal merge and the final merge.
The merge driver can learn the pathname in which the merged result
will be stored via placeholder `%P`.
`conflict-marker-size` `conflict-marker-size`
^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^

View File

@ -9,6 +9,7 @@
#include "xdiff-interface.h" #include "xdiff-interface.h"
#include "run-command.h" #include "run-command.h"
#include "ll-merge.h" #include "ll-merge.h"
#include "quote.h"
struct ll_merge_driver; struct ll_merge_driver;
@ -166,17 +167,20 @@ static int ll_ext_merge(const struct ll_merge_driver *fn,
{ {
char temp[4][50]; char temp[4][50];
struct strbuf cmd = STRBUF_INIT; struct strbuf cmd = STRBUF_INIT;
struct strbuf_expand_dict_entry dict[5]; struct strbuf_expand_dict_entry dict[6];
struct strbuf path_sq = STRBUF_INIT;
const char *args[] = { NULL, NULL }; const char *args[] = { NULL, NULL };
int status, fd, i; int status, fd, i;
struct stat st; struct stat st;
assert(opts); assert(opts);
sq_quote_buf(&path_sq, path);
dict[0].placeholder = "O"; dict[0].value = temp[0]; dict[0].placeholder = "O"; dict[0].value = temp[0];
dict[1].placeholder = "A"; dict[1].value = temp[1]; dict[1].placeholder = "A"; dict[1].value = temp[1];
dict[2].placeholder = "B"; dict[2].value = temp[2]; dict[2].placeholder = "B"; dict[2].value = temp[2];
dict[3].placeholder = "L"; dict[3].value = temp[3]; dict[3].placeholder = "L"; dict[3].value = temp[3];
dict[4].placeholder = NULL; dict[4].value = NULL; dict[4].placeholder = "P"; dict[4].value = path_sq.buf;
dict[5].placeholder = NULL; dict[5].value = NULL;
if (fn->cmdline == NULL) if (fn->cmdline == NULL)
die("custom merge driver %s lacks command line.", fn->name); die("custom merge driver %s lacks command line.", fn->name);
@ -210,6 +214,7 @@ static int ll_ext_merge(const struct ll_merge_driver *fn,
for (i = 0; i < 3; i++) for (i = 0; i < 3; i++)
unlink_or_warn(temp[i]); unlink_or_warn(temp[i]);
strbuf_release(&cmd); strbuf_release(&cmd);
strbuf_release(&path_sq);
return status; return status;
} }
@ -269,6 +274,7 @@ static int read_merge_config(const char *var, const char *value, void *cb)
* %A - temporary file name for our version. * %A - temporary file name for our version.
* %B - temporary file name for the other branches' version. * %B - temporary file name for the other branches' version.
* %L - conflict marker length * %L - conflict marker length
* %P - the original path (safely quoted for the shell)
* *
* The external merge driver should write the results in the * The external merge driver should write the results in the
* file named by %A, and signal that it has done with zero exit * file named by %A, and signal that it has done with zero exit

View File

@ -85,11 +85,12 @@ test_expect_success 'retry the merge with longer context' '
cat >./custom-merge <<\EOF cat >./custom-merge <<\EOF
#!/bin/sh #!/bin/sh
orig="$1" ours="$2" theirs="$3" exit="$4" orig="$1" ours="$2" theirs="$3" exit="$4" path=$5
( (
echo "orig is $orig" echo "orig is $orig"
echo "ours is $ours" echo "ours is $ours"
echo "theirs is $theirs" echo "theirs is $theirs"
echo "path is $path"
echo "=== orig ===" echo "=== orig ==="
cat "$orig" cat "$orig"
echo "=== ours ===" echo "=== ours ==="
@ -110,7 +111,7 @@ test_expect_success 'custom merge backend' '
git reset --hard anchor && git reset --hard anchor &&
git config --replace-all \ git config --replace-all \
merge.custom.driver "./custom-merge %O %A %B 0" && merge.custom.driver "./custom-merge %O %A %B 0 %P" &&
git config --replace-all \ git config --replace-all \
merge.custom.name "custom merge driver for testing" && merge.custom.name "custom merge driver for testing" &&
@ -121,7 +122,7 @@ test_expect_success 'custom merge backend' '
o=$(git unpack-file master^:text) && o=$(git unpack-file master^:text) &&
a=$(git unpack-file side^:text) && a=$(git unpack-file side^:text) &&
b=$(git unpack-file master:text) && b=$(git unpack-file master:text) &&
sh -c "./custom-merge $o $a $b 0" && sh -c "./custom-merge $o $a $b 0 'text'" &&
sed -e 1,3d $a >check-2 && sed -e 1,3d $a >check-2 &&
cmp check-1 check-2 && cmp check-1 check-2 &&
rm -f $o $a $b rm -f $o $a $b
@ -131,7 +132,7 @@ test_expect_success 'custom merge backend' '
git reset --hard anchor && git reset --hard anchor &&
git config --replace-all \ git config --replace-all \
merge.custom.driver "./custom-merge %O %A %B 1" && merge.custom.driver "./custom-merge %O %A %B 1 %P" &&
git config --replace-all \ git config --replace-all \
merge.custom.name "custom merge driver for testing" && merge.custom.name "custom merge driver for testing" &&
@ -148,9 +149,12 @@ test_expect_success 'custom merge backend' '
o=$(git unpack-file master^:text) && o=$(git unpack-file master^:text) &&
a=$(git unpack-file anchor:text) && a=$(git unpack-file anchor:text) &&
b=$(git unpack-file master:text) && b=$(git unpack-file master:text) &&
sh -c "./custom-merge $o $a $b 0" && sh -c "./custom-merge $o $a $b 0 'text'" &&
sed -e 1,3d $a >check-2 && sed -e 1,3d $a >check-2 &&
cmp check-1 check-2 && cmp check-1 check-2 &&
sed -e 1,3d -e 4q $a >check-3 &&
echo "path is text" >expect &&
cmp expect check-3 &&
rm -f $o $a $b rm -f $o $a $b
' '