[PATCH] convert filter: supply path to external driver
- From
- Pete Wyckoff <pw@padd.com>
- Date
- Dec 19, 2010, 21:29 UTC
- Message-ID
- <20101219212925.GA7393@arf.padd.com>
- In-Reply-To
- <20101218223822.GA18902@arf.padd.com>
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@padd.com> ---
pw@padd.com wrote on Sat, 18 Dec 2010 17:38 -0500:
Show 7 quoted lines
> 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