1 /*
2  * Copyright (C) the libgit2 contributors. All rights reserved.
3  *
4  * This file is part of libgit2, distributed under the GNU GPL v2 with
5  * a Linking Exception. For full terms see the included COPYING file.
6  */
7 #ifndef INCLUDE_git_attr_h__
8 #define INCLUDE_git_attr_h__
9 
10 #include "common.h"
11 #include "types.h"
12 
13 /**
14  * @file git2/attr.h
15  * @brief Git attribute management routines
16  * @defgroup git_attr Git attribute management routines
17  * @ingroup Git
18  * @{
19  */
20 GIT_BEGIN_DECL
21 
22 /**
23  * GIT_ATTR_TRUE checks if an attribute is set on.  In core git
24  * parlance, this the value for "Set" attributes.
25  *
26  * For example, if the attribute file contains:
27  *
28  *    *.c foo
29  *
30  * Then for file `xyz.c` looking up attribute "foo" gives a value for
31  * which `GIT_ATTR_TRUE(value)` is true.
32  */
33 #define GIT_ATTR_IS_TRUE(attr)	(git_attr_value(attr) == GIT_ATTR_VALUE_TRUE)
34 
35 /**
36  * GIT_ATTR_FALSE checks if an attribute is set off.  In core git
37  * parlance, this is the value for attributes that are "Unset" (not to
38  * be confused with values that a "Unspecified").
39  *
40  * For example, if the attribute file contains:
41  *
42  *    *.h -foo
43  *
44  * Then for file `zyx.h` looking up attribute "foo" gives a value for
45  * which `GIT_ATTR_FALSE(value)` is true.
46  */
47 #define GIT_ATTR_IS_FALSE(attr) (git_attr_value(attr) == GIT_ATTR_VALUE_FALSE)
48 
49 /**
50  * GIT_ATTR_UNSPECIFIED checks if an attribute is unspecified.  This
51  * may be due to the attribute not being mentioned at all or because
52  * the attribute was explicitly set unspecified via the `!` operator.
53  *
54  * For example, if the attribute file contains:
55  *
56  *    *.c foo
57  *    *.h -foo
58  *    onefile.c !foo
59  *
60  * Then for `onefile.c` looking up attribute "foo" yields a value with
61  * `GIT_ATTR_UNSPECIFIED(value)` of true.  Also, looking up "foo" on
62  * file `onefile.rb` or looking up "bar" on any file will all give
63  * `GIT_ATTR_UNSPECIFIED(value)` of true.
64  */
65 #define GIT_ATTR_IS_UNSPECIFIED(attr) (git_attr_value(attr) == GIT_ATTR_VALUE_UNSPECIFIED)
66 
67 /**
68  * GIT_ATTR_HAS_VALUE checks if an attribute is set to a value (as
69  * opposed to TRUE, FALSE or UNSPECIFIED).  This would be the case if
70  * for a file with something like:
71  *
72  *    *.txt eol=lf
73  *
74  * Given this, looking up "eol" for `onefile.txt` will give back the
75  * string "lf" and `GIT_ATTR_SET_TO_VALUE(attr)` will return true.
76  */
77 #define GIT_ATTR_HAS_VALUE(attr) (git_attr_value(attr) == GIT_ATTR_VALUE_STRING)
78 
79 /**
80  * Possible states for an attribute
81  */
82 typedef enum {
83 	GIT_ATTR_VALUE_UNSPECIFIED = 0, /**< The attribute has been left unspecified */
84 	GIT_ATTR_VALUE_TRUE,   /**< The attribute has been set */
85 	GIT_ATTR_VALUE_FALSE,  /**< The attribute has been unset */
86 	GIT_ATTR_VALUE_STRING, /**< This attribute has a value */
87 } git_attr_value_t;
88 
89 /**
90  * Return the value type for a given attribute.
91  *
92  * This can be either `TRUE`, `FALSE`, `UNSPECIFIED` (if the attribute
93  * was not set at all), or `VALUE`, if the attribute was set to an
94  * actual string.
95  *
96  * If the attribute has a `VALUE` string, it can be accessed normally
97  * as a NULL-terminated C string.
98  *
99  * @param attr The attribute
100  * @return the value type for the attribute
101  */
102 GIT_EXTERN(git_attr_value_t) git_attr_value(const char *attr);
103 
104 /**
105  * Check attribute flags: Reading values from index and working directory.
106  *
107  * When checking attributes, it is possible to check attribute files
108  * in both the working directory (if there is one) and the index (if
109  * there is one).  You can explicitly choose where to check and in
110  * which order using the following flags.
111  *
112  * Core git usually checks the working directory then the index,
113  * except during a checkout when it checks the index first.  It will
114  * use index only for creating archives or for a bare repo (if an
115  * index has been specified for the bare repo).
116  */
117 #define GIT_ATTR_CHECK_FILE_THEN_INDEX	0
118 #define GIT_ATTR_CHECK_INDEX_THEN_FILE	1
119 #define GIT_ATTR_CHECK_INDEX_ONLY		2
120 
121 /**
122  * Check attribute flags: controlling extended attribute behavior.
123  *
124  * Normally, attribute checks include looking in the /etc (or system
125  * equivalent) directory for a `gitattributes` file.  Passing this
126  * flag will cause attribute checks to ignore that file.
127  * equivalent) directory for a `gitattributes` file.  Passing the
128  * `GIT_ATTR_CHECK_NO_SYSTEM` flag will cause attribute checks to
129  * ignore that file.
130  *
131  * Passing the `GIT_ATTR_CHECK_INCLUDE_HEAD` flag will use attributes
132  * from a `.gitattributes` file in the repository at the HEAD revision.
133  *
134  * Passing the `GIT_ATTR_CHECK_INCLUDE_COMMIT` flag will use attributes
135  * from a `.gitattributes` file in a specific commit.
136  */
137 #define GIT_ATTR_CHECK_NO_SYSTEM        (1 << 2)
138 #define GIT_ATTR_CHECK_INCLUDE_HEAD     (1 << 3)
139 #define GIT_ATTR_CHECK_INCLUDE_COMMIT   (1 << 4)
140 
141 /**
142 * An options structure for querying attributes.
143 */
144 typedef struct {
145 	unsigned int version;
146 
147 	/** A combination of GIT_ATTR_CHECK flags */
148 	unsigned int flags;
149 
150 #ifdef GIT_DEPRECATE_HARD
151 	void *reserved;
152 #else
153 	git_oid *commit_id;
154 #endif
155 
156 	/**
157 	 * The commit to load attributes from, when
158 	 * `GIT_ATTR_CHECK_INCLUDE_COMMIT` is specified.
159 	 */
160 	git_oid attr_commit_id;
161 } git_attr_options;
162 
163 #define GIT_ATTR_OPTIONS_VERSION 1
164 #define GIT_ATTR_OPTIONS_INIT {GIT_ATTR_OPTIONS_VERSION}
165 
166 /**
167  * Look up the value of one git attribute for path.
168  *
169  * @param value_out Output of the value of the attribute.  Use the GIT_ATTR_...
170  *             macros to test for TRUE, FALSE, UNSPECIFIED, etc. or just
171  *             use the string value for attributes set to a value.  You
172  *             should NOT modify or free this value.
173  * @param repo The repository containing the path.
174  * @param flags A combination of GIT_ATTR_CHECK... flags.
175  * @param path The path to check for attributes.  Relative paths are
176  *             interpreted relative to the repo root.  The file does
177  *             not have to exist, but if it does not, then it will be
178  *             treated as a plain file (not a directory).
179  * @param name The name of the attribute to look up.
180  */
181 GIT_EXTERN(int) git_attr_get(
182 	const char **value_out,
183 	git_repository *repo,
184 	uint32_t flags,
185 	const char *path,
186 	const char *name);
187 
188 /**
189  * Look up the value of one git attribute for path with extended options.
190  *
191  * @param value_out Output of the value of the attribute.  Use the GIT_ATTR_...
192  *             macros to test for TRUE, FALSE, UNSPECIFIED, etc. or just
193  *             use the string value for attributes set to a value.  You
194  *             should NOT modify or free this value.
195  * @param repo The repository containing the path.
196  * @param opts The `git_attr_options` to use when querying these attributes.
197  * @param path The path to check for attributes.  Relative paths are
198  *             interpreted relative to the repo root.  The file does
199  *             not have to exist, but if it does not, then it will be
200  *             treated as a plain file (not a directory).
201  * @param name The name of the attribute to look up.
202  */
203 GIT_EXTERN(int) git_attr_get_ext(
204 	const char **value_out,
205 	git_repository *repo,
206 	git_attr_options *opts,
207 	const char *path,
208 	const char *name);
209 
210 /**
211  * Look up a list of git attributes for path.
212  *
213  * Use this if you have a known list of attributes that you want to
214  * look up in a single call.  This is somewhat more efficient than
215  * calling `git_attr_get()` multiple times.
216  *
217  * For example, you might write:
218  *
219  *     const char *attrs[] = { "crlf", "diff", "foo" };
220  *     const char **values[3];
221  *     git_attr_get_many(values, repo, 0, "my/fun/file.c", 3, attrs);
222  *
223  * Then you could loop through the 3 values to get the settings for
224  * the three attributes you asked about.
225  *
226  * @param values_out An array of num_attr entries that will have string
227  *             pointers written into it for the values of the attributes.
228  *             You should not modify or free the values that are written
229  *             into this array (although of course, you should free the
230  *             array itself if you allocated it).
231  * @param repo The repository containing the path.
232  * @param flags A combination of GIT_ATTR_CHECK... flags.
233  * @param path The path inside the repo to check attributes.  This
234  *             does not have to exist, but if it does not, then
235  *             it will be treated as a plain file (i.e. not a directory).
236  * @param num_attr The number of attributes being looked up
237  * @param names An array of num_attr strings containing attribute names.
238  */
239 GIT_EXTERN(int) git_attr_get_many(
240 	const char **values_out,
241 	git_repository *repo,
242 	uint32_t flags,
243 	const char *path,
244 	size_t num_attr,
245 	const char **names);
246 
247 /**
248  * Look up a list of git attributes for path with extended options.
249  *
250  * @param values_out An array of num_attr entries that will have string
251  *             pointers written into it for the values of the attributes.
252  *             You should not modify or free the values that are written
253  *             into this array (although of course, you should free the
254  *             array itself if you allocated it).
255  * @param repo The repository containing the path.
256  * @param opts The `git_attr_options` to use when querying these attributes.
257  * @param path The path inside the repo to check attributes.  This
258  *             does not have to exist, but if it does not, then
259  *             it will be treated as a plain file (i.e. not a directory).
260  * @param num_attr The number of attributes being looked up
261  * @param names An array of num_attr strings containing attribute names.
262  */
263 GIT_EXTERN(int) git_attr_get_many_ext(
264 	const char **values_out,
265 	git_repository *repo,
266 	git_attr_options *opts,
267 	const char *path,
268 	size_t num_attr,
269 	const char **names);
270 
271 /**
272  * The callback used with git_attr_foreach.
273  *
274  * This callback will be invoked only once per attribute name, even if there
275  * are multiple rules for a given file. The highest priority rule will be
276  * used.
277  *
278  * @see git_attr_foreach.
279  *
280  * @param name The attribute name.
281  * @param value The attribute value. May be NULL if the attribute is explicitly
282  *              set to UNSPECIFIED using the '!' sign.
283  * @param payload A user-specified pointer.
284  * @return 0 to continue looping, non-zero to stop. This value will be returned
285  *         from git_attr_foreach.
286  */
287 typedef int GIT_CALLBACK(git_attr_foreach_cb)(const char *name, const char *value, void *payload);
288 
289 /**
290  * Loop over all the git attributes for a path.
291  *
292  * @param repo The repository containing the path.
293  * @param flags A combination of GIT_ATTR_CHECK... flags.
294  * @param path Path inside the repo to check attributes.  This does not have
295  *             to exist, but if it does not, then it will be treated as a
296  *             plain file (i.e. not a directory).
297  * @param callback Function to invoke on each attribute name and value.
298  *                 See git_attr_foreach_cb.
299  * @param payload Passed on as extra parameter to callback function.
300  * @return 0 on success, non-zero callback return value, or error code
301  */
302 GIT_EXTERN(int) git_attr_foreach(
303 	git_repository *repo,
304 	uint32_t flags,
305 	const char *path,
306 	git_attr_foreach_cb callback,
307 	void *payload);
308 
309 /**
310  * Loop over all the git attributes for a path with extended options.
311  *
312  * @param repo The repository containing the path.
313  * @param opts The `git_attr_options` to use when querying these attributes.
314  * @param path Path inside the repo to check attributes.  This does not have
315  *             to exist, but if it does not, then it will be treated as a
316  *             plain file (i.e. not a directory).
317  * @param callback Function to invoke on each attribute name and value.
318  *                 See git_attr_foreach_cb.
319  * @param payload Passed on as extra parameter to callback function.
320  * @return 0 on success, non-zero callback return value, or error code
321  */
322 GIT_EXTERN(int) git_attr_foreach_ext(
323 	git_repository *repo,
324 	git_attr_options *opts,
325 	const char *path,
326 	git_attr_foreach_cb callback,
327 	void *payload);
328 
329 /**
330  * Flush the gitattributes cache.
331  *
332  * Call this if you have reason to believe that the attributes files on
333  * disk no longer match the cached contents of memory.  This will cause
334  * the attributes files to be reloaded the next time that an attribute
335  * access function is called.
336  *
337  * @param repo The repository containing the gitattributes cache
338  * @return 0 on success, or an error code
339  */
340 GIT_EXTERN(int) git_attr_cache_flush(
341 	git_repository *repo);
342 
343 /**
344  * Add a macro definition.
345  *
346  * Macros will automatically be loaded from the top level `.gitattributes`
347  * file of the repository (plus the build-in "binary" macro).  This
348  * function allows you to add others.  For example, to add the default
349  * macro, you would call:
350  *
351  *     git_attr_add_macro(repo, "binary", "-diff -crlf");
352  */
353 GIT_EXTERN(int) git_attr_add_macro(
354 	git_repository *repo,
355 	const char *name,
356 	const char *values);
357 
358 /** @} */
359 GIT_END_DECL
360 #endif
361 
362