Merge branch 'pw/convert-pathname-substitution'
* pw/convert-pathname-substitution: t0021: avoid getting filter killed with SIGPIPE convert filter: supply path to external driver
This commit is contained in:
commit
9e98354ab9
@ -335,6 +335,16 @@ input that is already correctly indented. In this case, the lack of a
|
|||||||
smudge filter means that the clean filter _must_ accept its own output
|
smudge filter means that the clean filter _must_ accept its own output
|
||||||
without modifying it.
|
without modifying it.
|
||||||
|
|
||||||
|
Sequence "%f" on the filter command line is replaced with the name of
|
||||||
|
the file the filter is working on. A filter might use this in keyword
|
||||||
|
substitution. For example:
|
||||||
|
|
||||||
|
------------------------
|
||||||
|
[filter "p4"]
|
||||||
|
clean = git-p4-filter --clean %f
|
||||||
|
smudge = git-p4-filter --smudge %f
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
|
||||||
Interaction between checkin/checkout attributes
|
Interaction between checkin/checkout attributes
|
||||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
23
convert.c
23
convert.c
@ -1,6 +1,7 @@
|
|||||||
#include "cache.h"
|
#include "cache.h"
|
||||||
#include "attr.h"
|
#include "attr.h"
|
||||||
#include "run-command.h"
|
#include "run-command.h"
|
||||||
|
#include "quote.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* convert.c - convert a file when checking it out and checking it in.
|
* convert.c - convert a file when checking it out and checking it in.
|
||||||
@ -318,6 +319,7 @@ struct filter_params {
|
|||||||
const char *src;
|
const char *src;
|
||||||
unsigned long size;
|
unsigned long size;
|
||||||
const char *cmd;
|
const char *cmd;
|
||||||
|
const char *path;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int filter_buffer(int in, int out, void *data)
|
static int filter_buffer(int in, int out, void *data)
|
||||||
@ -330,7 +332,23 @@ static int filter_buffer(int in, int out, void *data)
|
|||||||
int write_err, status;
|
int write_err, status;
|
||||||
const char *argv[] = { NULL, NULL };
|
const char *argv[] = { NULL, NULL };
|
||||||
|
|
||||||
argv[0] = params->cmd;
|
/* apply % substitution to cmd */
|
||||||
|
struct strbuf cmd = STRBUF_INIT;
|
||||||
|
struct strbuf path = STRBUF_INIT;
|
||||||
|
struct strbuf_expand_dict_entry dict[] = {
|
||||||
|
{ "f", NULL, },
|
||||||
|
{ NULL, NULL, },
|
||||||
|
};
|
||||||
|
|
||||||
|
/* quote the path to preserve spaces, etc. */
|
||||||
|
sq_quote_buf(&path, params->path);
|
||||||
|
dict[0].value = path.buf;
|
||||||
|
|
||||||
|
/* expand all %f with the quoted path */
|
||||||
|
strbuf_expand(&cmd, params->cmd, strbuf_expand_dict_cb, &dict);
|
||||||
|
strbuf_release(&path);
|
||||||
|
|
||||||
|
argv[0] = cmd.buf;
|
||||||
|
|
||||||
memset(&child_process, 0, sizeof(child_process));
|
memset(&child_process, 0, sizeof(child_process));
|
||||||
child_process.argv = argv;
|
child_process.argv = argv;
|
||||||
@ -350,6 +368,8 @@ static int filter_buffer(int in, int out, void *data)
|
|||||||
status = finish_command(&child_process);
|
status = finish_command(&child_process);
|
||||||
if (status)
|
if (status)
|
||||||
error("external filter %s failed %d", params->cmd, status);
|
error("external filter %s failed %d", params->cmd, status);
|
||||||
|
|
||||||
|
strbuf_release(&cmd);
|
||||||
return (write_err || status);
|
return (write_err || status);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -377,6 +397,7 @@ static int apply_filter(const char *path, const char *src, size_t len,
|
|||||||
params.src = src;
|
params.src = src;
|
||||||
params.size = len;
|
params.size = len;
|
||||||
params.cmd = cmd;
|
params.cmd = cmd;
|
||||||
|
params.path = path;
|
||||||
|
|
||||||
fflush(NULL);
|
fflush(NULL);
|
||||||
if (start_async(&async))
|
if (start_async(&async))
|
||||||
|
@ -93,4 +93,47 @@ test_expect_success expanded_in_repo '
|
|||||||
cmp expanded-keywords expected-output
|
cmp expanded-keywords expected-output
|
||||||
'
|
'
|
||||||
|
|
||||||
|
# The use of %f in a filter definition is expanded to the path to
|
||||||
|
# the filename being smudged or cleaned. It must be shell escaped.
|
||||||
|
# First, set up some interesting file names and pet them in
|
||||||
|
# .gitattributes.
|
||||||
|
test_expect_success 'filter shell-escaped filenames' '
|
||||||
|
cat >argc.sh <<-EOF &&
|
||||||
|
#!$SHELL_PATH
|
||||||
|
cat >/dev/null
|
||||||
|
echo argc: \$# "\$@"
|
||||||
|
EOF
|
||||||
|
normal=name-no-magic &&
|
||||||
|
special="name with '\''sq'\'' and \$x" &&
|
||||||
|
echo some test text >"$normal" &&
|
||||||
|
echo some test text >"$special" &&
|
||||||
|
git add "$normal" "$special" &&
|
||||||
|
git commit -q -m "add files" &&
|
||||||
|
echo "name* filter=argc" >.gitattributes &&
|
||||||
|
|
||||||
|
# delete the files and check them out again, using a smudge filter
|
||||||
|
# that will count the args and echo the command-line back to us
|
||||||
|
git config filter.argc.smudge "sh ./argc.sh %f" &&
|
||||||
|
rm "$normal" "$special" &&
|
||||||
|
git checkout -- "$normal" "$special" &&
|
||||||
|
|
||||||
|
# make sure argc.sh counted the right number of args
|
||||||
|
echo "argc: 1 $normal" >expect &&
|
||||||
|
test_cmp expect "$normal" &&
|
||||||
|
echo "argc: 1 $special" >expect &&
|
||||||
|
test_cmp expect "$special" &&
|
||||||
|
|
||||||
|
# do the same thing, but with more args in the filter expression
|
||||||
|
git config filter.argc.smudge "sh ./argc.sh %f --my-extra-arg" &&
|
||||||
|
rm "$normal" "$special" &&
|
||||||
|
git checkout -- "$normal" "$special" &&
|
||||||
|
|
||||||
|
# make sure argc.sh counted the right number of args
|
||||||
|
echo "argc: 2 $normal --my-extra-arg" >expect &&
|
||||||
|
test_cmp expect "$normal" &&
|
||||||
|
echo "argc: 2 $special --my-extra-arg" >expect &&
|
||||||
|
test_cmp expect "$special" &&
|
||||||
|
:
|
||||||
|
'
|
||||||
|
|
||||||
test_done
|
test_done
|
||||||
|
Loading…
Reference in New Issue
Block a user