mirror of
https://github.com/git/git.git
synced 2024-11-24 18:33:43 +08:00
Merge branch 'mh/check-attr-relative'
* mh/check-attr-relative: (29 commits) test-path-utils: Add subcommand "prefix_path" test-path-utils: Add subcommand "absolute_path" git-check-attr: Normalize paths git-check-attr: Demonstrate problems with relative paths git-check-attr: Demonstrate problems with unnormalized paths git-check-attr: test that no output is written to stderr Rename git_checkattr() to git_check_attr() git-check-attr: Fix command-line handling to match docs git-check-attr: Drive two tests using the same raw data git-check-attr: Add an --all option to show all attributes git-check-attr: Error out if no pathnames are specified git-check-attr: Process command-line args more systematically git-check-attr: Handle each error separately git-check-attr: Extract a function error_with_usage() git-check-attr: Introduce a new variable git-check-attr: Extract a function output_attr() Allow querying all attributes on a file Remove redundant check Remove redundant call to bootstrap_attr_stack() Extract a function collect_all_attrs() ...
This commit is contained in:
commit
324b6b1678
@ -9,8 +9,8 @@ git-check-attr - Display gitattributes information
|
||||
SYNOPSIS
|
||||
--------
|
||||
[verse]
|
||||
'git check-attr' attr... [--] pathname...
|
||||
'git check-attr' --stdin [-z] attr... < <list-of-paths>
|
||||
'git check-attr' [-a | --all | attr...] [--] pathname...
|
||||
'git check-attr' --stdin [-z] [-a | --all | attr...] < <list-of-paths>
|
||||
|
||||
DESCRIPTION
|
||||
-----------
|
||||
@ -19,6 +19,11 @@ For every pathname, this command will list if each attribute is 'unspecified',
|
||||
|
||||
OPTIONS
|
||||
-------
|
||||
-a, --all::
|
||||
List all attributes that are associated with the specified
|
||||
paths. If this option is used, then 'unspecified' attributes
|
||||
will not be included in the output.
|
||||
|
||||
--stdin::
|
||||
Read file names from stdin instead of from the command-line.
|
||||
|
||||
@ -28,8 +33,11 @@ OPTIONS
|
||||
|
||||
\--::
|
||||
Interpret all preceding arguments as attributes and all following
|
||||
arguments as path names. If not supplied, only the first argument will
|
||||
be treated as an attribute.
|
||||
arguments as path names.
|
||||
|
||||
If none of `--stdin`, `--all`, or `--` is used, the first argument
|
||||
will be treated as an attribute and the rest of the arguments as
|
||||
pathnames.
|
||||
|
||||
OUTPUT
|
||||
------
|
||||
@ -69,6 +77,13 @@ org/example/MyClass.java: diff: java
|
||||
org/example/MyClass.java: myAttr: set
|
||||
---------------
|
||||
|
||||
* Listing all attributes for a file:
|
||||
---------------
|
||||
$ git check-attr --all -- org/example/MyClass.java
|
||||
org/example/MyClass.java: diff: java
|
||||
org/example/MyClass.java: myAttr: set
|
||||
---------------
|
||||
|
||||
* Listing an attribute for multiple files:
|
||||
---------------
|
||||
$ git check-attr myAttr -- org/example/MyClass.java org/example/NoMyAttr.java
|
||||
|
@ -955,6 +955,9 @@ frotz unspecified
|
||||
----------------------------------------------------------------
|
||||
|
||||
|
||||
SEE ALSO
|
||||
--------
|
||||
linkgit:git-check-attr[1].
|
||||
|
||||
GIT
|
||||
---
|
||||
|
@ -11,27 +11,15 @@ Data Structure
|
||||
`struct git_attr`::
|
||||
|
||||
An attribute is an opaque object that is identified by its name.
|
||||
Pass the name and its length to `git_attr()` function to obtain
|
||||
the object of this type. The internal representation of this
|
||||
structure is of no interest to the calling programs.
|
||||
Pass the name to `git_attr()` function to obtain the object of
|
||||
this type. The internal representation of this structure is
|
||||
of no interest to the calling programs. The name of the
|
||||
attribute can be retrieved by calling `git_attr_name()`.
|
||||
|
||||
`struct git_attr_check`::
|
||||
|
||||
This structure represents a set of attributes to check in a call
|
||||
to `git_checkattr()` function, and receives the results.
|
||||
|
||||
|
||||
Calling Sequence
|
||||
----------------
|
||||
|
||||
* 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.
|
||||
|
||||
* Call git_checkattr() 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.
|
||||
to `git_check_attr()` function, and receives the results.
|
||||
|
||||
|
||||
Attribute Values
|
||||
@ -57,6 +45,19 @@ If none of the above returns true, `.value` member points at a string
|
||||
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.
|
||||
|
||||
* 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.
|
||||
|
||||
|
||||
Example
|
||||
-------
|
||||
|
||||
@ -72,18 +73,18 @@ static void setup_check(void)
|
||||
{
|
||||
if (check[0].attr)
|
||||
return; /* already done */
|
||||
check[0].attr = git_attr("crlf", 4);
|
||||
check[1].attr = git_attr("ident", 5);
|
||||
check[0].attr = git_attr("crlf");
|
||||
check[1].attr = git_attr("ident");
|
||||
}
|
||||
------------
|
||||
|
||||
. Call `git_checkattr()` with the prepared array of `struct git_attr_check`:
|
||||
. Call `git_check_attr()` with the prepared array of `struct git_attr_check`:
|
||||
|
||||
------------
|
||||
const char *path;
|
||||
|
||||
setup_check();
|
||||
git_checkattr(path, ARRAY_SIZE(check), check);
|
||||
git_check_attr(path, ARRAY_SIZE(check), check);
|
||||
------------
|
||||
|
||||
. Act on `.value` member of the result, left in `check[]`:
|
||||
@ -108,4 +109,20 @@ static void setup_check(void)
|
||||
}
|
||||
------------
|
||||
|
||||
(JC)
|
||||
|
||||
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.
|
||||
|
||||
* 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.)
|
||||
|
||||
* Free the `git_array_check` array.
|
||||
|
@ -123,7 +123,7 @@ static int write_archive_entry(const unsigned char *sha1, const char *base,
|
||||
path_without_prefix = path.buf + args->baselen;
|
||||
|
||||
setup_archive_check(check);
|
||||
if (!git_checkattr(path_without_prefix, ARRAY_SIZE(check), check)) {
|
||||
if (!git_check_attr(path_without_prefix, ARRAY_SIZE(check), check)) {
|
||||
if (ATTR_TRUE(check[0].value))
|
||||
return 0;
|
||||
convert = ATTR_TRUE(check[1].value);
|
||||
|
79
attr.c
79
attr.c
@ -36,6 +36,11 @@ static int attr_nr;
|
||||
static struct git_attr_check *check_all_attr;
|
||||
static struct git_attr *(git_attr_hash[HASHSIZE]);
|
||||
|
||||
char *git_attr_name(struct git_attr *attr)
|
||||
{
|
||||
return attr->name;
|
||||
}
|
||||
|
||||
static unsigned hash_name(const char *name, int namelen)
|
||||
{
|
||||
unsigned val = 0, c;
|
||||
@ -50,12 +55,10 @@ static unsigned hash_name(const char *name, int namelen)
|
||||
static int invalid_attr_name(const char *name, int namelen)
|
||||
{
|
||||
/*
|
||||
* Attribute name cannot begin with '-' and from
|
||||
* [-A-Za-z0-9_.]. We'd specifically exclude '=' for now,
|
||||
* as we might later want to allow non-binary value for
|
||||
* attributes, e.g. "*.svg merge=special-merge-program-for-svg"
|
||||
* Attribute name cannot begin with '-' and must consist of
|
||||
* characters from [-A-Za-z0-9_.].
|
||||
*/
|
||||
if (*name == '-')
|
||||
if (namelen <= 0 || *name == '-')
|
||||
return -1;
|
||||
while (namelen--) {
|
||||
char ch = *name++;
|
||||
@ -532,11 +535,18 @@ static void bootstrap_attr_stack(void)
|
||||
}
|
||||
}
|
||||
|
||||
static void prepare_attr_stack(const char *path, int dirlen)
|
||||
static void prepare_attr_stack(const char *path)
|
||||
{
|
||||
struct attr_stack *elem, *info;
|
||||
int len;
|
||||
int dirlen, len;
|
||||
struct strbuf pathbuf;
|
||||
const char *cp;
|
||||
|
||||
cp = strrchr(path, '/');
|
||||
if (!cp)
|
||||
dirlen = 0;
|
||||
else
|
||||
dirlen = cp - path;
|
||||
|
||||
strbuf_init(&pathbuf, dirlen+2+strlen(GITATTRIBUTES_FILE));
|
||||
|
||||
@ -555,8 +565,7 @@ static void prepare_attr_stack(const char *path, int dirlen)
|
||||
* .gitattributes in deeper directories to shallower ones,
|
||||
* and finally use the built-in set as the default.
|
||||
*/
|
||||
if (!attr_stack)
|
||||
bootstrap_attr_stack();
|
||||
bootstrap_attr_stack();
|
||||
|
||||
/*
|
||||
* Pop the "info" one that is always at the top of the stack.
|
||||
@ -703,26 +712,30 @@ static int macroexpand_one(int attr_nr, int rem)
|
||||
return rem;
|
||||
}
|
||||
|
||||
int git_checkattr(const char *path, int num, struct git_attr_check *check)
|
||||
/*
|
||||
* Collect all attributes for path into the array pointed to by
|
||||
* check_all_attr.
|
||||
*/
|
||||
static void collect_all_attrs(const char *path)
|
||||
{
|
||||
struct attr_stack *stk;
|
||||
const char *cp;
|
||||
int dirlen, pathlen, i, rem;
|
||||
int i, pathlen, rem;
|
||||
|
||||
bootstrap_attr_stack();
|
||||
prepare_attr_stack(path);
|
||||
for (i = 0; i < attr_nr; i++)
|
||||
check_all_attr[i].value = ATTR__UNKNOWN;
|
||||
|
||||
pathlen = strlen(path);
|
||||
cp = strrchr(path, '/');
|
||||
if (!cp)
|
||||
dirlen = 0;
|
||||
else
|
||||
dirlen = cp - path;
|
||||
prepare_attr_stack(path, dirlen);
|
||||
rem = attr_nr;
|
||||
for (stk = attr_stack; 0 < rem && stk; stk = stk->prev)
|
||||
rem = fill(path, pathlen, stk, rem);
|
||||
}
|
||||
|
||||
int git_check_attr(const char *path, int num, struct git_attr_check *check)
|
||||
{
|
||||
int i;
|
||||
|
||||
collect_all_attrs(path);
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
const char *value = check_all_attr[check[i].attr->attr_nr].value;
|
||||
@ -734,6 +747,34 @@ int git_checkattr(const char *path, int num, struct git_attr_check *check)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int git_all_attrs(const char *path, int *num, struct git_attr_check **check)
|
||||
{
|
||||
int i, count, j;
|
||||
|
||||
collect_all_attrs(path);
|
||||
|
||||
/* Count the number of attributes that are set. */
|
||||
count = 0;
|
||||
for (i = 0; i < attr_nr; i++) {
|
||||
const char *value = check_all_attr[i].value;
|
||||
if (value != ATTR__UNSET && value != ATTR__UNKNOWN)
|
||||
++count;
|
||||
}
|
||||
*num = count;
|
||||
*check = xmalloc(sizeof(**check) * count);
|
||||
j = 0;
|
||||
for (i = 0; i < attr_nr; i++) {
|
||||
const char *value = check_all_attr[i].value;
|
||||
if (value != ATTR__UNSET && value != ATTR__UNKNOWN) {
|
||||
(*check)[j].attr = check_all_attr[i].attr;
|
||||
(*check)[j].value = value;
|
||||
++j;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void git_attr_set_direction(enum git_attr_direction new, struct index_state *istate)
|
||||
{
|
||||
enum git_attr_direction old = direction;
|
||||
|
20
attr.h
20
attr.h
@ -20,7 +20,7 @@ extern const char git_attr__false[];
|
||||
#define ATTR_UNSET(v) ((v) == NULL)
|
||||
|
||||
/*
|
||||
* Send one or more git_attr_check to git_checkattr(), and
|
||||
* Send one or more git_attr_check to git_check_attr(), and
|
||||
* each 'value' member tells what its value is.
|
||||
* Unset one is returned as NULL.
|
||||
*/
|
||||
@ -29,7 +29,23 @@ struct git_attr_check {
|
||||
const char *value;
|
||||
};
|
||||
|
||||
int git_checkattr(const char *path, int, struct git_attr_check *);
|
||||
/*
|
||||
* Return the name of the attribute represented by the argument. The
|
||||
* return value is a pointer to a null-delimited string that is part
|
||||
* of the internal data structure; it should not be modified or freed.
|
||||
*/
|
||||
char *git_attr_name(struct git_attr *);
|
||||
|
||||
int git_check_attr(const char *path, int, struct git_attr_check *);
|
||||
|
||||
/*
|
||||
* Retrieve all attributes that apply to the specified path. *num
|
||||
* will be set the the number of attributes on the path; **check will
|
||||
* be set to point at a newly-allocated array of git_attr_check
|
||||
* objects describing the attributes and their values. *check must be
|
||||
* free()ed by the caller.
|
||||
*/
|
||||
int git_all_attrs(const char *path, int *num, struct git_attr_check **check);
|
||||
|
||||
enum git_attr_direction {
|
||||
GIT_ATTR_CHECKIN,
|
||||
|
@ -4,28 +4,28 @@
|
||||
#include "quote.h"
|
||||
#include "parse-options.h"
|
||||
|
||||
static int all_attrs;
|
||||
static int stdin_paths;
|
||||
static const char * const check_attr_usage[] = {
|
||||
"git check-attr attr... [--] pathname...",
|
||||
"git check-attr --stdin attr... < <list-of-paths>",
|
||||
"git check-attr [-a | --all | attr...] [--] pathname...",
|
||||
"git check-attr --stdin [-a | --all | attr...] < <list-of-paths>",
|
||||
NULL
|
||||
};
|
||||
|
||||
static int null_term_line;
|
||||
|
||||
static const struct option check_attr_options[] = {
|
||||
OPT_BOOLEAN('a', "all", &all_attrs, "report all attributes set on file"),
|
||||
OPT_BOOLEAN(0 , "stdin", &stdin_paths, "read file names from stdin"),
|
||||
OPT_BOOLEAN('z', NULL, &null_term_line,
|
||||
"input paths are terminated by a null character"),
|
||||
OPT_END()
|
||||
};
|
||||
|
||||
static void check_attr(int cnt, struct git_attr_check *check,
|
||||
const char** name, const char *file)
|
||||
static void output_attr(int cnt, struct git_attr_check *check,
|
||||
const char *file)
|
||||
{
|
||||
int j;
|
||||
if (git_checkattr(file, cnt, check))
|
||||
die("git_checkattr died");
|
||||
for (j = 0; j < cnt; j++) {
|
||||
const char *value = check[j].value;
|
||||
|
||||
@ -37,12 +37,30 @@ static void check_attr(int cnt, struct git_attr_check *check,
|
||||
value = "unspecified";
|
||||
|
||||
quote_c_style(file, NULL, stdout, 0);
|
||||
printf(": %s: %s\n", name[j], value);
|
||||
printf(": %s: %s\n", git_attr_name(check[j].attr), value);
|
||||
}
|
||||
}
|
||||
|
||||
static void check_attr_stdin_paths(int cnt, struct git_attr_check *check,
|
||||
const char** name)
|
||||
static void check_attr(const char *prefix, int cnt,
|
||||
struct git_attr_check *check, const char *file)
|
||||
{
|
||||
char *full_path =
|
||||
prefix_path(prefix, prefix ? strlen(prefix) : 0, file);
|
||||
if (check != NULL) {
|
||||
if (git_check_attr(full_path, cnt, check))
|
||||
die("git_check_attr died");
|
||||
output_attr(cnt, check, file);
|
||||
} else {
|
||||
if (git_all_attrs(full_path, &cnt, &check))
|
||||
die("git_all_attrs died");
|
||||
output_attr(cnt, check, file);
|
||||
free(check);
|
||||
}
|
||||
free(full_path);
|
||||
}
|
||||
|
||||
static void check_attr_stdin_paths(const char *prefix, int cnt,
|
||||
struct git_attr_check *check)
|
||||
{
|
||||
struct strbuf buf, nbuf;
|
||||
int line_termination = null_term_line ? 0 : '\n';
|
||||
@ -56,23 +74,26 @@ static void check_attr_stdin_paths(int cnt, struct git_attr_check *check,
|
||||
die("line is badly quoted");
|
||||
strbuf_swap(&buf, &nbuf);
|
||||
}
|
||||
check_attr(cnt, check, name, buf.buf);
|
||||
check_attr(prefix, cnt, check, buf.buf);
|
||||
maybe_flush_or_die(stdout, "attribute to stdout");
|
||||
}
|
||||
strbuf_release(&buf);
|
||||
strbuf_release(&nbuf);
|
||||
}
|
||||
|
||||
static NORETURN void error_with_usage(const char *msg)
|
||||
{
|
||||
error("%s", msg);
|
||||
usage_with_options(check_attr_usage, check_attr_options);
|
||||
}
|
||||
|
||||
int cmd_check_attr(int argc, const char **argv, const char *prefix)
|
||||
{
|
||||
struct git_attr_check *check;
|
||||
int cnt, i, doubledash;
|
||||
const char *errstr = NULL;
|
||||
int cnt, i, doubledash, filei;
|
||||
|
||||
argc = parse_options(argc, argv, prefix, check_attr_options,
|
||||
check_attr_usage, PARSE_OPT_KEEP_DASHDASH);
|
||||
if (!argc)
|
||||
usage_with_options(check_attr_usage, check_attr_options);
|
||||
|
||||
if (read_cache() < 0) {
|
||||
die("invalid cache");
|
||||
@ -84,39 +105,63 @@ int cmd_check_attr(int argc, const char **argv, const char *prefix)
|
||||
doubledash = i;
|
||||
}
|
||||
|
||||
/* If there is no double dash, we handle only one attribute */
|
||||
if (doubledash < 0) {
|
||||
cnt = 1;
|
||||
doubledash = 0;
|
||||
} else
|
||||
cnt = doubledash;
|
||||
doubledash++;
|
||||
/* Process --all and/or attribute arguments: */
|
||||
if (all_attrs) {
|
||||
if (doubledash >= 1)
|
||||
error_with_usage("Attributes and --all both specified");
|
||||
|
||||
if (cnt <= 0)
|
||||
errstr = "No attribute specified";
|
||||
else if (stdin_paths && doubledash < argc)
|
||||
errstr = "Can't specify files with --stdin";
|
||||
if (errstr) {
|
||||
error("%s", errstr);
|
||||
usage_with_options(check_attr_usage, check_attr_options);
|
||||
cnt = 0;
|
||||
filei = doubledash + 1;
|
||||
} else if (doubledash == 0) {
|
||||
error_with_usage("No attribute specified");
|
||||
} else if (doubledash < 0) {
|
||||
if (!argc)
|
||||
error_with_usage("No attribute specified");
|
||||
|
||||
if (stdin_paths) {
|
||||
/* Treat all arguments as attribute names. */
|
||||
cnt = argc;
|
||||
filei = argc;
|
||||
} else {
|
||||
/* Treat exactly one argument as an attribute name. */
|
||||
cnt = 1;
|
||||
filei = 1;
|
||||
}
|
||||
} else {
|
||||
cnt = doubledash;
|
||||
filei = doubledash + 1;
|
||||
}
|
||||
|
||||
check = xcalloc(cnt, sizeof(*check));
|
||||
for (i = 0; i < cnt; i++) {
|
||||
const char *name;
|
||||
struct git_attr *a;
|
||||
name = argv[i];
|
||||
a = git_attr(name);
|
||||
if (!a)
|
||||
return error("%s: not a valid attribute name", name);
|
||||
check[i].attr = a;
|
||||
/* Check file argument(s): */
|
||||
if (stdin_paths) {
|
||||
if (filei < argc)
|
||||
error_with_usage("Can't specify files with --stdin");
|
||||
} else {
|
||||
if (filei >= argc)
|
||||
error_with_usage("No file specified");
|
||||
}
|
||||
|
||||
if (all_attrs) {
|
||||
check = NULL;
|
||||
} else {
|
||||
check = xcalloc(cnt, sizeof(*check));
|
||||
for (i = 0; i < cnt; i++) {
|
||||
const char *name;
|
||||
struct git_attr *a;
|
||||
name = argv[i];
|
||||
a = git_attr(name);
|
||||
if (!a)
|
||||
return error("%s: not a valid attribute name",
|
||||
name);
|
||||
check[i].attr = a;
|
||||
}
|
||||
}
|
||||
|
||||
if (stdin_paths)
|
||||
check_attr_stdin_paths(cnt, check, argv);
|
||||
check_attr_stdin_paths(prefix, cnt, check);
|
||||
else {
|
||||
for (i = doubledash; i < argc; i++)
|
||||
check_attr(cnt, check, argv, argv[i]);
|
||||
for (i = filei; i < argc; i++)
|
||||
check_attr(prefix, cnt, check, argv[i]);
|
||||
maybe_flush_or_die(stdout, "attribute to stdout");
|
||||
}
|
||||
return 0;
|
||||
|
@ -770,7 +770,7 @@ static int no_try_delta(const char *path)
|
||||
struct git_attr_check check[1];
|
||||
|
||||
setup_delta_attr_check(check);
|
||||
if (git_checkattr(path, ARRAY_SIZE(check), check))
|
||||
if (git_check_attr(path, ARRAY_SIZE(check), check))
|
||||
return 0;
|
||||
if (ATTR_FALSE(check->value))
|
||||
return 1;
|
||||
|
@ -727,7 +727,7 @@ static void convert_attrs(struct conv_attrs *ca, const char *path)
|
||||
git_config(read_convert_config, NULL);
|
||||
}
|
||||
|
||||
if (!git_checkattr(path, NUM_CONV_ATTRS, ccheck)) {
|
||||
if (!git_check_attr(path, NUM_CONV_ATTRS, ccheck)) {
|
||||
ca->crlf_action = git_path_check_crlf(path, ccheck + 4);
|
||||
if (ca->crlf_action == CRLF_GUESS)
|
||||
ca->crlf_action = git_path_check_crlf(path, ccheck + 0);
|
||||
|
@ -330,7 +330,7 @@ static int git_path_check_merge(const char *path, struct git_attr_check check[2]
|
||||
check[0].attr = git_attr("merge");
|
||||
check[1].attr = git_attr("conflict-marker-size");
|
||||
}
|
||||
return git_checkattr(path, 2, check);
|
||||
return git_check_attr(path, 2, check);
|
||||
}
|
||||
|
||||
static void normalize_file(mmfile_t *mm, const char *path)
|
||||
@ -387,7 +387,7 @@ int ll_merge_marker_size(const char *path)
|
||||
|
||||
if (!check.attr)
|
||||
check.attr = git_attr("conflict-marker-size");
|
||||
if (!git_checkattr(path, 1, &check) && check.value) {
|
||||
if (!git_check_attr(path, 1, &check) && check.value) {
|
||||
marker_size = atoi(check.value);
|
||||
if (marker_size <= 0)
|
||||
marker_size = DEFAULT_CONFLICT_MARKER_SIZE;
|
||||
|
@ -9,16 +9,17 @@ attr_check () {
|
||||
path="$1"
|
||||
expect="$2"
|
||||
|
||||
git check-attr test -- "$path" >actual &&
|
||||
git check-attr test -- "$path" >actual 2>err &&
|
||||
echo "$path: test: $2" >expect &&
|
||||
test_cmp expect actual
|
||||
test_cmp expect actual &&
|
||||
test_line_count = 0 err
|
||||
|
||||
}
|
||||
|
||||
|
||||
test_expect_success 'setup' '
|
||||
|
||||
mkdir -p a/b/d a/c &&
|
||||
mkdir -p a/b/d a/c b &&
|
||||
(
|
||||
echo "[attr]notest !test"
|
||||
echo "f test=f"
|
||||
@ -35,10 +36,42 @@ test_expect_success 'setup' '
|
||||
echo "h test=a/b/h" &&
|
||||
echo "d/* test=a/b/d/*"
|
||||
echo "d/yes notest"
|
||||
) >a/b/.gitattributes
|
||||
) >a/b/.gitattributes &&
|
||||
(
|
||||
echo "global test=global"
|
||||
) >"$HOME"/global-gitattributes
|
||||
) >"$HOME"/global-gitattributes &&
|
||||
cat <<EOF >expect-all
|
||||
f: test: f
|
||||
a/f: test: f
|
||||
a/c/f: test: f
|
||||
a/g: test: a/g
|
||||
a/b/g: test: a/b/g
|
||||
b/g: test: unspecified
|
||||
a/b/h: test: a/b/h
|
||||
a/b/d/g: test: a/b/d/*
|
||||
onoff: test: unset
|
||||
offon: test: set
|
||||
no: notest: set
|
||||
no: test: unspecified
|
||||
a/b/d/no: notest: set
|
||||
a/b/d/no: test: a/b/d/*
|
||||
a/b/d/yes: notest: set
|
||||
a/b/d/yes: test: unspecified
|
||||
EOF
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'command line checks' '
|
||||
|
||||
test_must_fail git check-attr &&
|
||||
test_must_fail git check-attr -- &&
|
||||
test_must_fail git check-attr test &&
|
||||
test_must_fail git check-attr test -- &&
|
||||
test_must_fail git check-attr -- f &&
|
||||
echo "f" | test_must_fail git check-attr --stdin &&
|
||||
echo "f" | test_must_fail git check-attr --stdin -- f &&
|
||||
echo "f" | test_must_fail git check-attr --stdin test -- f &&
|
||||
test_must_fail git check-attr "" -- f
|
||||
|
||||
'
|
||||
|
||||
@ -60,6 +93,28 @@ test_expect_success 'attribute test' '
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'unnormalized paths' '
|
||||
|
||||
attr_check ./f f &&
|
||||
attr_check ./a/g a/g &&
|
||||
attr_check a/./g a/g &&
|
||||
attr_check a/c/../b/g a/b/g
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'relative paths' '
|
||||
|
||||
(cd a && attr_check ../f f) &&
|
||||
(cd a && attr_check f f) &&
|
||||
(cd a && attr_check i a/i) &&
|
||||
(cd a && attr_check g a/g) &&
|
||||
(cd a && attr_check b/g a/b/g) &&
|
||||
(cd b && attr_check ../a/f f) &&
|
||||
(cd b && attr_check ../a/g a/g) &&
|
||||
(cd b && attr_check ../a/b/g a/b/g)
|
||||
|
||||
'
|
||||
|
||||
test_expect_success 'core.attributesfile' '
|
||||
attr_check global unspecified &&
|
||||
git config core.attributesfile "$HOME/global-gitattributes" &&
|
||||
@ -72,26 +127,19 @@ test_expect_success 'core.attributesfile' '
|
||||
|
||||
test_expect_success 'attribute test: read paths from stdin' '
|
||||
|
||||
cat <<EOF > expect &&
|
||||
f: test: f
|
||||
a/f: test: f
|
||||
a/c/f: test: f
|
||||
a/g: test: a/g
|
||||
a/b/g: test: a/b/g
|
||||
b/g: test: unspecified
|
||||
a/b/h: test: a/b/h
|
||||
a/b/d/g: test: a/b/d/*
|
||||
onoff: test: unset
|
||||
offon: test: set
|
||||
no: test: unspecified
|
||||
a/b/d/no: test: a/b/d/*
|
||||
a/b/d/yes: test: unspecified
|
||||
EOF
|
||||
|
||||
grep -v notest < expect-all > expect &&
|
||||
sed -e "s/:.*//" < expect | git check-attr --stdin test > actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_expect_success 'attribute test: --all option' '
|
||||
|
||||
grep -v unspecified < expect-all | sort > expect &&
|
||||
sed -e "s/:.*//" < expect-all | uniq |
|
||||
git check-attr --stdin --all | sort > actual &&
|
||||
test_cmp expect actual
|
||||
'
|
||||
|
||||
test_expect_success 'root subdir attribute test' '
|
||||
|
||||
attr_check a/i a/i &&
|
||||
|
@ -20,12 +20,34 @@ int main(int argc, char **argv)
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (argc >= 2 && !strcmp(argv[1], "absolute_path")) {
|
||||
while (argc > 2) {
|
||||
puts(absolute_path(argv[2]));
|
||||
argc--;
|
||||
argv++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (argc == 4 && !strcmp(argv[1], "longest_ancestor_length")) {
|
||||
int len = longest_ancestor_length(argv[2], argv[3]);
|
||||
printf("%d\n", len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (argc >= 4 && !strcmp(argv[1], "prefix_path")) {
|
||||
char *prefix = argv[2];
|
||||
int prefix_len = strlen(prefix);
|
||||
int nongit_ok;
|
||||
setup_git_directory_gently(&nongit_ok);
|
||||
while (argc > 3) {
|
||||
puts(prefix_path(prefix, prefix_len, argv[3]));
|
||||
argc--;
|
||||
argv++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (argc == 4 && !strcmp(argv[1], "strip_path_suffix")) {
|
||||
char *prefix = strip_path_suffix(argv[2], argv[3]);
|
||||
printf("%s\n", prefix ? prefix : "(null)");
|
||||
|
@ -270,7 +270,7 @@ struct userdiff_driver *userdiff_find_by_path(const char *path)
|
||||
|
||||
if (!path)
|
||||
return NULL;
|
||||
if (git_checkattr(path, 1, &check))
|
||||
if (git_check_attr(path, 1, &check))
|
||||
return NULL;
|
||||
|
||||
if (ATTR_TRUE(check.value))
|
||||
|
2
ws.c
2
ws.c
@ -88,7 +88,7 @@ unsigned whitespace_rule(const char *pathname)
|
||||
struct git_attr_check attr_whitespace_rule;
|
||||
|
||||
setup_whitespace_attr_check(&attr_whitespace_rule);
|
||||
if (!git_checkattr(pathname, 1, &attr_whitespace_rule)) {
|
||||
if (!git_check_attr(pathname, 1, &attr_whitespace_rule)) {
|
||||
const char *value;
|
||||
|
||||
value = attr_whitespace_rule.value;
|
||||
|
Loading…
Reference in New Issue
Block a user