Merge branch 'jb/required-filter'
* jb/required-filter: Add a setting to require a filter to be successful Conflicts: convert.c
This commit is contained in:
commit
524ee675a3
@ -294,16 +294,27 @@ output is used to update the worktree file. Similarly, the
|
||||
`clean` command is used to convert the contents of worktree file
|
||||
upon checkin.
|
||||
|
||||
A missing filter driver definition in the config is not an error
|
||||
but makes the filter a no-op passthru.
|
||||
One use of the content filtering is to massage the content into a shape
|
||||
that is more convenient for the platform, filesystem, and the user to use.
|
||||
For this mode of operation, the key phrase here is "more convenient" and
|
||||
not "turning something unusable into usable". In other words, the intent
|
||||
is that if someone unsets the filter driver definition, or does not have
|
||||
the appropriate filter program, the project should still be usable.
|
||||
|
||||
The content filtering is done to massage the content into a
|
||||
shape that is more convenient for the platform, filesystem, and
|
||||
the user to use. The key phrase here is "more convenient" and not
|
||||
"turning something unusable into usable". In other words, the
|
||||
intent is that if someone unsets the filter driver definition,
|
||||
or does not have the appropriate filter program, the project
|
||||
should still be usable.
|
||||
Another use of the content filtering is to store the content that cannot
|
||||
be directly used in the repository (e.g. a UUID that refers to the true
|
||||
content stored outside git, or an encrypted content) and turn it into a
|
||||
usable form upon checkout (e.g. download the external content, or decrypt
|
||||
the encrypted content).
|
||||
|
||||
These two filters behave differently, and by default, a filter is taken as
|
||||
the former, massaging the contents into more convenient shape. A missing
|
||||
filter driver definition in the config, or a filter driver that exits with
|
||||
a non-zero status, is not an error but makes the filter a no-op passthru.
|
||||
|
||||
You can declare that a filter turns a content that by itself is unusable
|
||||
into a usable content by setting the filter.<driver>.required configuration
|
||||
variable to `true`.
|
||||
|
||||
For example, in .gitattributes, you would assign the `filter`
|
||||
attribute for paths.
|
||||
@ -335,6 +346,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
|
||||
without modifying it.
|
||||
|
||||
If a filter _must_ succeed in order to make the stored contents usable,
|
||||
you can declare that the filter is `required`, in the configuration:
|
||||
|
||||
------------------------
|
||||
[filter "crypt"]
|
||||
clean = openssl enc ...
|
||||
smudge = openssl enc -d ...
|
||||
required
|
||||
------------------------
|
||||
|
||||
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:
|
||||
|
28
convert.c
28
convert.c
@ -452,6 +452,7 @@ static struct convert_driver {
|
||||
struct convert_driver *next;
|
||||
const char *smudge;
|
||||
const char *clean;
|
||||
int required;
|
||||
} *user_convert, **user_convert_tail;
|
||||
|
||||
static int read_convert_config(const char *var, const char *value, void *cb)
|
||||
@ -495,6 +496,11 @@ static int read_convert_config(const char *var, const char *value, void *cb)
|
||||
if (!strcmp("clean", ep))
|
||||
return git_config_string(&drv->clean, var, value);
|
||||
|
||||
if (!strcmp("required", ep)) {
|
||||
drv->required = git_config_bool(var, value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -773,13 +779,19 @@ int convert_to_git(const char *path, const char *src, size_t len,
|
||||
{
|
||||
int ret = 0;
|
||||
const char *filter = NULL;
|
||||
int required = 0;
|
||||
struct conv_attrs ca;
|
||||
|
||||
convert_attrs(&ca, path);
|
||||
if (ca.drv)
|
||||
if (ca.drv) {
|
||||
filter = ca.drv->clean;
|
||||
required = ca.drv->required;
|
||||
}
|
||||
|
||||
ret |= apply_filter(path, src, len, dst, filter);
|
||||
if (!ret && required)
|
||||
die("%s: clean filter '%s' failed", path, ca.drv->name);
|
||||
|
||||
if (ret && dst) {
|
||||
src = dst->buf;
|
||||
len = dst->len;
|
||||
@ -797,13 +809,16 @@ static int convert_to_working_tree_internal(const char *path, const char *src,
|
||||
size_t len, struct strbuf *dst,
|
||||
int normalizing)
|
||||
{
|
||||
int ret = 0;
|
||||
int ret = 0, ret_filter = 0;
|
||||
const char *filter = NULL;
|
||||
int required = 0;
|
||||
struct conv_attrs ca;
|
||||
|
||||
convert_attrs(&ca, path);
|
||||
if (ca.drv)
|
||||
if (ca.drv) {
|
||||
filter = ca.drv->smudge;
|
||||
required = ca.drv->required;
|
||||
}
|
||||
|
||||
ret |= ident_to_worktree(path, src, len, dst, ca.ident);
|
||||
if (ret) {
|
||||
@ -822,7 +837,12 @@ static int convert_to_working_tree_internal(const char *path, const char *src,
|
||||
len = dst->len;
|
||||
}
|
||||
}
|
||||
return ret | apply_filter(path, src, len, dst, filter);
|
||||
|
||||
ret_filter = apply_filter(path, src, len, dst, filter);
|
||||
if (!ret_filter && required)
|
||||
die("%s: smudge filter %s failed", path, ca.drv->name);
|
||||
|
||||
return ret | ret_filter;
|
||||
}
|
||||
|
||||
int convert_to_working_tree(const char *path, const char *src, size_t len, struct strbuf *dst)
|
||||
|
@ -153,4 +153,41 @@ test_expect_success 'filter shell-escaped filenames' '
|
||||
:
|
||||
'
|
||||
|
||||
test_expect_success 'required filter success' '
|
||||
git config filter.required.smudge cat &&
|
||||
git config filter.required.clean cat &&
|
||||
git config filter.required.required true &&
|
||||
|
||||
echo "*.r filter=required" >.gitattributes &&
|
||||
|
||||
echo test >test.r &&
|
||||
git add test.r &&
|
||||
rm -f test.r &&
|
||||
git checkout -- test.r
|
||||
'
|
||||
|
||||
test_expect_success 'required filter smudge failure' '
|
||||
git config filter.failsmudge.smudge false &&
|
||||
git config filter.failsmudge.clean cat &&
|
||||
git config filter.failsmudge.required true &&
|
||||
|
||||
echo "*.fs filter=failsmudge" >.gitattributes &&
|
||||
|
||||
echo test >test.fs &&
|
||||
git add test.fs &&
|
||||
rm -f test.fs &&
|
||||
test_must_fail git checkout -- test.fs
|
||||
'
|
||||
|
||||
test_expect_success 'required filter clean failure' '
|
||||
git config filter.failclean.smudge cat &&
|
||||
git config filter.failclean.clean false &&
|
||||
git config filter.failclean.required true &&
|
||||
|
||||
echo "*.fc filter=failclean" >.gitattributes &&
|
||||
|
||||
echo test >test.fc &&
|
||||
test_must_fail git add test.fc
|
||||
'
|
||||
|
||||
test_done
|
||||
|
Loading…
Reference in New Issue
Block a user