diff --git a/include/git2/attr.h b/include/git2/attr.h index fad7183da..451eb6664 100644 --- a/include/git2/attr.h +++ b/include/git2/attr.h @@ -30,7 +30,7 @@ GIT_BEGIN_DECL * Then for file `xyz.c` looking up attribute "foo" gives a value for * which `GIT_ATTR_TRUE(value)` is true. */ -#define GIT_ATTR_TRUE(attr) ((attr) == git_l_attr__true) +#define GIT_ATTR_TRUE(attr) (git_attr_value(attr) == GIT_ATTR_TRUE_T) /** * GIT_ATTR_FALSE checks if an attribute is set off. In core git @@ -44,7 +44,7 @@ GIT_BEGIN_DECL * Then for file `zyx.h` looking up attribute "foo" gives a value for * which `GIT_ATTR_FALSE(value)` is true. */ -#define GIT_ATTR_FALSE(attr) ((attr) == git_l_attr__false) +#define GIT_ATTR_FALSE(attr) (git_attr_value(attr) == GIT_ATTR_FALSE_T) /** * GIT_ATTR_UNSPECIFIED checks if an attribute is unspecified. This @@ -62,7 +62,7 @@ GIT_BEGIN_DECL * file `onefile.rb` or looking up "bar" on any file will all give * `GIT_ATTR_UNSPECIFIED(value)` of true. */ -#define GIT_ATTR_UNSPECIFIED(attr) (!(attr) || (attr) == git_l_attr__unset) +#define GIT_ATTR_UNSPECIFIED(attr) (git_attr_value(attr) == GIT_ATTR_UNSPECIFIED_T) /** * GIT_ATTR_HAS_VALUE checks if an attribute is set to a value (as @@ -74,13 +74,29 @@ GIT_BEGIN_DECL * Given this, looking up "eol" for `onefile.txt` will give back the * string "lf" and `GIT_ATTR_SET_TO_VALUE(attr)` will return true. */ -#define GIT_ATTR_HAS_VALUE(attr) \ - ((attr) && (attr) != git_l_attr__unset && \ - (attr) != git_l_attr__true && (attr) != git_attr__false) +#define GIT_ATTR_HAS_VALUE(attr) (git_attr_value(attr) == GIT_ATTR_VALUE_T) -GIT_EXTERN(const char *) git_l_attr__true; -GIT_EXTERN(const char *) git_l_attr__false; -GIT_EXTERN(const char *) git_l_attr__unset; +typedef enum { + GIT_ATTR_UNSPECIFIED_T = 0, + GIT_ATTR_TRUE_T, + GIT_ATTR_FALSE_T, + GIT_ATTR_VALUE_T, +} git_attr_t; + +/* + * Return the value type for a given attribute. + * + * This can be either `TRUE`, `FALSE`, `UNSPECIFIED` (if the attribute + * was not set at all), or `VALUE`, if the attribute was set to + * an actual string. + * + * If the attribute has a `VALUE` string, it can be accessed normally + * as a NULL-terminated C string. + * + * @param attr The attribute + * @return the value type for the attribute + */ +git_attr_t git_attr_value(const char *attr); /** * Check attribute flags: Reading values from index and working directory. diff --git a/src/attr.c b/src/attr.c index 6fbd005d5..1c511993b 100644 --- a/src/attr.c +++ b/src/attr.c @@ -5,6 +5,25 @@ GIT__USE_STRMAP; +const char *git_attr__true = "[internal]__TRUE__"; +const char *git_attr__false = "[internal]__FALSE__"; +const char *git_attr__unset = "[internal]__UNSET__"; + +git_attr_t git_attr_value(const char *attr) +{ + if (attr == NULL || attr == git_attr__unset) + return GIT_ATTR_UNSPECIFIED_T; + + if (attr == git_attr__true) + return GIT_ATTR_TRUE_T; + + if (attr == git_attr__false) + return GIT_ATTR_FALSE_T; + + return GIT_ATTR_VALUE_T; +} + + static int collect_attr_files( git_repository *repo, uint32_t flags, diff --git a/src/attr_file.c b/src/attr_file.c index 837c42d8e..966da4069 100644 --- a/src/attr_file.c +++ b/src/attr_file.c @@ -5,10 +5,6 @@ #include "git2/tree.h" #include -const char *git_l_attr__true = "[internal]__TRUE__"; -const char *git_l_attr__false = "[internal]__FALSE__"; -const char *git_l_attr__unset = "[internal]__UNSET__"; - static int sort_by_hash_and_name(const void *a_raw, const void *b_raw); static void git_attr_rule__clear(git_attr_rule *rule); @@ -493,14 +489,14 @@ int git_attr_assignment__parse( } assign->name_hash = 5381; - assign->value = git_l_attr__true; + assign->value = git_attr__true; /* look for magic name prefixes */ if (*scan == '-') { - assign->value = git_l_attr__false; + assign->value = git_attr__false; scan++; } else if (*scan == '!') { - assign->value = git_l_attr__unset; /* explicit unspecified state */ + assign->value = git_attr__unset; /* explicit unspecified state */ scan++; } else if (*scan == '#') /* comment rest of line */ break; @@ -536,7 +532,7 @@ int git_attr_assignment__parse( } /* expand macros (if given a repo with a macro cache) */ - if (repo != NULL && assign->value == git_l_attr__true) { + if (repo != NULL && assign->value == git_attr__true) { git_attr_rule *macro = git_attr_cache__lookup_macro(repo, assign->name); diff --git a/src/attr_file.h b/src/attr_file.h index 7939f838a..9d6730d90 100644 --- a/src/attr_file.h +++ b/src/attr_file.h @@ -24,6 +24,10 @@ #define GIT_ATTR_FNMATCH_HASWILD (1U << 5) #define GIT_ATTR_FNMATCH_ALLOWSPACE (1U << 6) +extern const char *git_attr__true; +extern const char *git_attr__false; +extern const char *git_attr__unset; + typedef struct { char *pattern; size_t length;