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:
commit
49ac7358da
@ -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`
|
||||||
^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
10
ll-merge.c
10
ll-merge.c
@ -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
|
||||||
|
@ -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
|
||||||
'
|
'
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user