Filtering to support keyword expansion may need the name of the file being filtered. In particular, to support p4 keywords like $File: //depot/product/dir/script.sh $ the smudge filter needs to know the name of the file it is smudging. Add a "%s" conversion specifier to the gitattribute for filter. It will be expanded with the path name to the file when invoking the external filter command. Signed-off-by: Pete Wyckoff <pw@xxxxxxxx> --- pw@xxxxxxxx wrote on Sat, 18 Dec 2010 17:38 -0500: > I'm using git-p4 to import and work with upstream p4 > repositories. Some of the files are ktext, meaning they expect > expansion of $Id$ and similar identifiers. > > Using the filter driver for this file, I can do the "clean" part > easily, but to calculate the "smudge" correctly, I need to know > the filename inside the filter driver. This works fine for me. It is backward compatible, and leaves open the possibility of adding other % modifiers if we find a need later. I have a filter that handles all the p4 $Keyword$ expansions, now, using this patch. It can go into contrib if others would find it useful. This seriously reduces many hassles associated with my git-p4 workflow, where a plethora of ancillary systems rely on keyword expansion in the source. Cc Junio for comments as the original author of convert filter code. -- Pete Documentation/gitattributes.txt | 12 ++++++++++++ convert.c | 15 ++++++++++++++- 2 files changed, 26 insertions(+), 1 deletions(-) diff --git a/Documentation/gitattributes.txt b/Documentation/gitattributes.txt index 564586b..9ac2138 100644 --- a/Documentation/gitattributes.txt +++ b/Documentation/gitattributes.txt @@ -317,6 +317,18 @@ command is "cat"). smudge = cat ------------------------ +If your filter needs the path of the file it is working on, +you can use the "%s" conversion specification. It will be +replaced with the relative path to the file. This is important +for keyword substitution that depends on the name of the +file. Like this: + +------------------------ +[filter "p4"] + clean = git-p4-filter --clean %s + smudge = git-p4-filter --smudge %s +------------------------ + Interaction between checkin/checkout attributes ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/convert.c b/convert.c index e41a31e..d4c6ed1 100644 --- a/convert.c +++ b/convert.c @@ -317,6 +317,7 @@ struct filter_params { const char *src; unsigned long size; const char *cmd; + const char *path; }; static int filter_buffer(int in, int out, void *data) @@ -329,7 +330,16 @@ static int filter_buffer(int in, int out, void *data) int write_err, status; const char *argv[] = { NULL, NULL }; - argv[0] = params->cmd; + /* replace optional %s with path */ + struct strbuf cmd = STRBUF_INIT; + struct strbuf_expand_dict_entry dict[] = { + "s", params->path, + NULL, NULL, + }; + + strbuf_expand(&cmd, params->cmd, strbuf_expand_dict_cb, &dict); + + argv[0] = cmd.buf; memset(&child_process, 0, sizeof(child_process)); child_process.argv = argv; @@ -349,6 +359,8 @@ static int filter_buffer(int in, int out, void *data) status = finish_command(&child_process); if (status) error("external filter %s failed %d", params->cmd, status); + + strbuf_release(&cmd); return (write_err || status); } @@ -376,6 +388,7 @@ static int apply_filter(const char *path, const char *src, size_t len, params.src = src; params.size = len; params.cmd = cmd; + params.path = path; fflush(NULL); if (start_async(&async)) -- 1.7.2.3 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html