@@ -3,3 +3,10 @@ attr.tree:
linkgit:gitattributes[5]. This is equivalent to setting the
`GIT_ATTR_SOURCE` environment variable, or passing in --attr-source to
the Git command.
+
+attr.allowInvalidSource::
+ If `attr.tree` cannot resolve to a valid tree object, ignore
+ `attr.tree` instead of erroring out, and fall back to looking for
+ attributes in the default locations. Useful when passing `HEAD` into
+ `attr-source` since it allows `HEAD` to point to an unborn branch in
+ cases like an empty repository.
@@ -1202,21 +1202,31 @@ void set_git_attr_source(const char *tree_object_name)
static void compute_default_attr_source(struct object_id *attr_source)
{
+ int attr_source_from_config = 0;
+
if (!default_attr_source_tree_object_name)
default_attr_source_tree_object_name = getenv(GIT_ATTR_SOURCE_ENVIRONMENT);
if (!default_attr_source_tree_object_name) {
char *attr_tree;
- if (!git_config_get_string("attr.tree", &attr_tree))
+ if (!git_config_get_string("attr.tree", &attr_tree)) {
+ attr_source_from_config = 1;
default_attr_source_tree_object_name = attr_tree;
+ }
}
if (!default_attr_source_tree_object_name || !is_null_oid(attr_source))
return;
- if (repo_get_oid_treeish(the_repository, default_attr_source_tree_object_name, attr_source))
- die(_("bad --attr-source or GIT_ATTR_SOURCE"));
+ if (repo_get_oid_treeish(the_repository, default_attr_source_tree_object_name, attr_source)) {
+ int allow_invalid_attr_source = 0;
+
+ git_config_get_bool("attr.allowinvalidsource", &allow_invalid_attr_source);
+
+ if (!(allow_invalid_attr_source && attr_source_from_config))
+ die(_("bad --attr-source or GIT_ATTR_SOURCE"));
+ }
}
static struct object_id *default_attr_source(void)
@@ -346,6 +346,51 @@ test_expect_success 'bare repository: check that .gitattribute is ignored' '
)
'
+bad_attr_source_err="fatal: bad --attr-source or GIT_ATTR_SOURCE"
+
+test_expect_success 'attr.allowInvalidSource when HEAD is unborn' '
+ test_when_finished rm -rf empty &&
+ echo $bad_attr_source_err >expect_err &&
+ echo "f/path: test: unspecified" >expect &&
+ git init empty &&
+ test_must_fail git -C empty --attr-source=HEAD check-attr test -- f/path 2>err &&
+ test_cmp expect_err err &&
+ git -C empty -c attr.tree=HEAD -c attr.allowInvalidSource=true check-attr test -- f/path >actual 2>err &&
+ test_must_be_empty err &&
+ test_cmp expect actual
+'
+
+test_expect_success 'attr.allowInvalidSource when --attr-source points to non-existing ref' '
+ test_when_finished rm -rf empty &&
+ echo $bad_attr_source_err >expect_err &&
+ echo "f/path: test: unspecified" >expect &&
+ git init empty &&
+ test_must_fail git -C empty --attr-source=refs/does/not/exist check-attr test -- f/path 2>err &&
+ test_cmp expect_err err &&
+ git -C empty -c attr.tree=refs/does/not/exist -c attr.allowInvalidSource=true check-attr test -- f/path >actual 2>err &&
+ test_must_be_empty err &&
+ test_cmp expect actual
+'
+
+test_expect_success 'bad attr source defaults to reading .gitattributes file' '
+ test_when_finished rm -rf empty &&
+ git init empty &&
+ echo "f/path test=val" >empty/.gitattributes &&
+ echo "f/path: test: val" >expect &&
+ git -C empty -c attr.tree=HEAD -c attr.allowInvalidSource=true check-attr test -- f/path >actual 2>err &&
+ test_must_be_empty err &&
+ test_cmp expect actual
+'
+
+test_expect_success 'attr.allowInvalidSource has no effect on --attr-source' '
+ test_when_finished rm -rf empty &&
+ echo $bad_attr_source_err >expect_err &&
+ echo "f/path: test: unspecified" >expect &&
+ git init empty &&
+ test_must_fail git -C empty -c attr.allowInvalidSource=true --attr-source=HEAD check-attr test -- f/path 2>err &&
+ test_cmp expect_err err
+'
+
test_expect_success 'bare repository: with --source' '
(
cd bare.git &&