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