Merge branch 'bw/attr'

The gitattributes machinery is being taught to work better in a
multi-threaded environment.

* bw/attr: (27 commits)
  attr: reformat git_attr_set_direction() function
  attr: push the bare repo check into read_attr()
  attr: store attribute stack in attr_check structure
  attr: tighten const correctness with git_attr and match_attr
  attr: remove maybe-real, maybe-macro from git_attr
  attr: eliminate global check_all_attr array
  attr: use hashmap for attribute dictionary
  attr: change validity check for attribute names to use positive logic
  attr: pass struct attr_check to collect_some_attrs
  attr: retire git_check_attrs() API
  attr: convert git_check_attrs() callers to use the new API
  attr: convert git_all_attrs() to use "struct attr_check"
  attr: (re)introduce git_check_attr() and struct attr_check
  attr: rename function and struct related to checking attributes
  attr.c: outline the future plans by heavily commenting
  Documentation: fix a typo
  attr.c: add push_stack() helper
  attr: support quoting pathname patterns in C style
  attr.c: plug small leak in parse_attr_line()
  attr.c: tighten constness around "git_attr" structure
  ...
This commit is contained in:
Junio C Hamano
2017-02-27 13:57:14 -08:00
14 changed files with 830 additions and 458 deletions

View File

@ -21,9 +21,11 @@ Each line in `gitattributes` file is of form:
pattern attr1 attr2 ...
That is, a pattern followed by an attributes list,
separated by whitespaces. When the pattern matches the
path in question, the attributes listed on the line are given to
the path.
separated by whitespaces. Leading and trailing whitespaces are
ignored. Lines that begin with '#' are ignored. Patterns
that begin with a double quote are quoted in C style.
When the pattern matches the path in question, the attributes
listed on the line are given to the path.
Each attribute can be in one of these states for a given path:
@ -86,7 +88,7 @@ is either not set or empty, $HOME/.config/git/attributes is used instead.
Attributes for all users on a system should be placed in the
`$(prefix)/etc/gitattributes` file.
Sometimes you would need to override an setting of an attribute
Sometimes you would need to override a setting of an attribute
for a path to `Unspecified` state. This can be done by listing
the name of the attribute prefixed with an exclamation point `!`.

View File

@ -16,10 +16,15 @@ Data Structure
of no interest to the calling programs. The name of the
attribute can be retrieved by calling `git_attr_name()`.
`struct git_attr_check`::
`struct attr_check_item`::
This structure represents a set of attributes to check in a call
to `git_check_attr()` function, and receives the results.
This structure represents one attribute and its value.
`struct attr_check`::
This structure represents a collection of `attr_check_item`.
It is passed to `git_check_attr()` function, specifying the
attributes to check, and receives their values.
Attribute Values
@ -27,7 +32,7 @@ Attribute Values
An attribute for a path can be in one of four states: Set, Unset,
Unspecified or set to a string, and `.value` member of `struct
git_attr_check` records it. There are three macros to check these:
attr_check_item` records it. There are three macros to check these:
`ATTR_TRUE()`::
@ -48,49 +53,51 @@ value of the attribute for the path.
Querying Specific Attributes
----------------------------
* Prepare an array of `struct git_attr_check` to define the list of
attributes you would want to check. To populate this array, you would
need to define necessary attributes by calling `git_attr()` function.
* Prepare `struct attr_check` using attr_check_initl()
function, enumerating the names of attributes whose values you are
interested in, terminated with a NULL pointer. Alternatively, an
empty `struct attr_check` can be prepared by calling
`attr_check_alloc()` function and then attributes you want to
ask about can be added to it with `attr_check_append()`
function.
* Call `git_check_attr()` to check the attributes for the path.
* Inspect `git_attr_check` structure to see how each of the attribute in
the array is defined for the path.
* Inspect `attr_check` structure to see how each of the
attribute in the array is defined for the path.
Example
-------
To see how attributes "crlf" and "indent" are set for different paths.
To see how attributes "crlf" and "ident" are set for different paths.
. Prepare an array of `struct git_attr_check` with two elements (because
we are checking two attributes). Initialize their `attr` member with
pointers to `struct git_attr` obtained by calling `git_attr()`:
. Prepare a `struct attr_check` with two elements (because
we are checking two attributes):
------------
static struct git_attr_check check[2];
static struct attr_check *check;
static void setup_check(void)
{
if (check[0].attr)
if (check)
return; /* already done */
check[0].attr = git_attr("crlf");
check[1].attr = git_attr("ident");
check = attr_check_initl("crlf", "ident", NULL);
}
------------
. Call `git_check_attr()` with the prepared array of `struct git_attr_check`:
. Call `git_check_attr()` with the prepared `struct attr_check`:
------------
const char *path;
setup_check();
git_check_attr(path, ARRAY_SIZE(check), check);
git_check_attr(path, check);
------------
. Act on `.value` member of the result, left in `check[]`:
. Act on `.value` member of the result, left in `check->items[]`:
------------
const char *value = check[0].value;
const char *value = check->items[0].value;
if (ATTR_TRUE(value)) {
The attribute is Set, by listing only the name of the
@ -109,20 +116,39 @@ static void setup_check(void)
}
------------
To see how attributes in argv[] are set for different paths, only
the first step in the above would be different.
------------
static struct attr_check *check;
static void setup_check(const char **argv)
{
check = attr_check_alloc();
while (*argv) {
struct git_attr *attr = git_attr(*argv);
attr_check_append(check, attr);
argv++;
}
}
------------
Querying All Attributes
-----------------------
To get the values of all attributes associated with a file:
* Call `git_all_attrs()`, which returns an array of `git_attr_check`
structures.
* Prepare an empty `attr_check` structure by calling
`attr_check_alloc()`.
* Iterate over the `git_attr_check` array to examine the attribute
names and values. The name of the attribute described by a
`git_attr_check` object can be retrieved via
`git_attr_name(check[i].attr)`. (Please note that no items will be
returned for unset attributes, so `ATTR_UNSET()` will return false
for all returned `git_array_check` objects.)
* Call `git_all_attrs()`, which populates the `attr_check`
with the attributes attached to the path.
* Free the `git_array_check` array.
* Iterate over the `attr_check.items[]` array to examine
the attribute names and values. The name of the attribute
described by a `attr_check.items[]` object can be retrieved via
`git_attr_name(check->items[i].attr)`. (Please note that no items
will be returned for unset attributes, so `ATTR_UNSET()` will return
false for all returned `attr_check.items[]` objects.)
* Free the `attr_check` struct by calling `attr_check_free()`.