@matheusbsbs / matheus-bagliano / commits / 6df42ab984
Fork 0

Add global and system-wide gitattributes

Allow gitattributes to be set globally and system wide. This way, settings for particular file types can be set in one place and apply for all user's repositories. The location of system-wide attributes file is $(prefix)/etc/gitattributes. The location of the global file can be configured by setting core.attributesfile. Some parts of the code were copied from the implementation of the same functionality in config.c. Signed-off-by: Petr Onderka <gsvick@gmail.com> Signed-off-by: Matthieu Moy <Matthieu.Moy@imag.fr> Signed-off-by: Junio C Hamano <gitster@pobox.com>

Petr Onderka committed Sep 1, 2010 at 00:42 UTC 6df42ab98480dcac473ca7d701cfca4a0051d0c1
6 files changed +95 -5
Documentation/config.txt
+6
@@ -450,6 +450,12 @@ core.excludesfile::
450 to the value of `$HOME` and "{tilde}user/" to the specified user's
451 home directory. See linkgit:gitignore[5].
452
453 +core.attributesfile::
454 + In addition to '.gitattributes' (per-directory) and
455 + '.git/info/attributes', git looks into this file for attributes
456 + (see linkgit:gitattributes[5]). Path expansions are made the same
457 + way as for `core.excludesfile`.
458 +
459 core.editor::
460 Commands such as `commit` and `tag` that lets you edit
461 messages by launching an editor uses the value of this
Documentation/gitattributes.txt
+10 -3
@@ -62,14 +62,21 @@ consults `$GIT_DIR/info/attributes` file (which has the highest
62 precedence), `.gitattributes` file in the same directory as the
63 path in question, and its parent directories up to the toplevel of the
64 work tree (the further the directory that contains `.gitattributes`
65 -is from the path in question, the lower its precedence).
65 +is from the path in question, the lower its precedence). Finally
66 +global and system-wide files are considered (they have the lowest
67 +precedence).
68
69 If you wish to affect only a single repository (i.e., to assign
68 -attributes to files that are particular to one user's workflow), then
70 +attributes to files that are particular to
71 +one user's workflow for that repository), then
72 attributes should be placed in the `$GIT_DIR/info/attributes` file.
73 Attributes which should be version-controlled and distributed to other
74 repositories (i.e., attributes of interest to all users) should go into
72 -`.gitattributes` files.
75 +`.gitattributes` files. Attributes that should affect all repositories
76 +for a single user should be placed in a file specified by the
77 +`core.attributesfile` configuration option (see linkgit:git-config[1]).
78 +Attributes for all users on a system should be placed in the
79 +`$(prefix)/etc/gitattributes` file.
80
81 Sometimes you would need to override an setting of an attribute
82 for a path to `unspecified` state. This can be done by listing
Makefile
+6
@@ -268,6 +268,7 @@ STRIP ?= strip
268 # infodir
269 # htmldir
270 # ETC_GITCONFIG (but not sysconfdir)
271 +# ETC_GITATTRIBUTES
272 # can be specified as a relative path some/where/else;
273 # this is interpreted as relative to $(prefix) and "git" at
274 # runtime figures out where they are based on the path to the executable.
@@ -286,9 +287,11 @@ htmldir = share/doc/git-doc
287 ifeq ($(prefix),/usr)
288 sysconfdir = /etc
289 ETC_GITCONFIG = $(sysconfdir)/gitconfig
290 +ETC_GITATTRIBUTES = $(sysconfdir)/gitattributes
291 else
292 sysconfdir = $(prefix)/etc
293 ETC_GITCONFIG = etc/gitconfig
294 +ETC_GITATTRIBUTES = etc/gitattributes
295 endif
296 lib = lib
297 # DESTDIR=
@@ -1502,6 +1505,7 @@ endif
1505
1506 SHA1_HEADER_SQ = $(subst ','\'',$(SHA1_HEADER))
1507 ETC_GITCONFIG_SQ = $(subst ','\'',$(ETC_GITCONFIG))
1508 +ETC_GITATTRIBUTES_SQ = $(subst ','\'',$(ETC_GITATTRIBUTES))
1509
1510 DESTDIR_SQ = $(subst ','\'',$(DESTDIR))
1511 bindir_SQ = $(subst ','\'',$(bindir))
@@ -1872,6 +1876,8 @@ builtin/init-db.s builtin/init-db.o: EXTRA_CPPFLAGS = \
1876
1877 config.s config.o: EXTRA_CPPFLAGS = -DETC_GITCONFIG='"$(ETC_GITCONFIG_SQ)"'
1878
1879 +attr.s attr.o: EXTRA_CPPFLAGS = -DETC_GITATTRIBUTES='"$(ETC_GITATTRIBUTES_SQ)"'
1880 +
1881 http.s http.o: EXTRA_CPPFLAGS = -DGIT_USER_AGENT='"git/$(GIT_VERSION)"'
1882
1883 ifdef NO_EXPAT
attr.c
+51 -1
@@ -1,5 +1,6 @@
1 #define NO_THE_INDEX_COMPATIBILITY_MACROS
2 #include "cache.h"
3 +#include "exec_cmd.h"
4 #include "attr.h"
5
6 const char git_attr__true[] = "(builtin)true";
@@ -10,6 +11,8 @@ static const char git_attr__unknown[] = "(builtin)unknown";
11 #define ATTR__UNSET NULL
12 #define ATTR__UNKNOWN git_attr__unknown
13
14 +static const char *attributes_file;
15 +
16 /*
17 * The basic design decision here is that we are not going to have
18 * insanely large number of attributes.
@@ -462,6 +465,32 @@ static void drop_attr_stack(void)
465 }
466 }
467
468 +const char *git_etc_gitattributes(void)
469 +{
470 + static const char *system_wide;
471 + if (!system_wide)
472 + system_wide = system_path(ETC_GITATTRIBUTES);
473 + return system_wide;
474 +}
475 +
476 +int git_attr_system(void)
477 +{
478 + return !git_env_bool("GIT_ATTR_NOSYSTEM", 0);
479 +}
480 +
481 +int git_attr_global(void)
482 +{
483 + return !git_env_bool("GIT_ATTR_NOGLOBAL", 0);
484 +}
485 +
486 +static int git_attr_config(const char *var, const char *value, void *dummy)
487 +{
488 + if (!strcmp(var, "core.attributesfile"))
489 + return git_config_pathname(&attributes_file, var, value);
490 +
491 + return 0;
492 +}
493 +
494 static void bootstrap_attr_stack(void)
495 {
496 if (!attr_stack) {
@@ -472,6 +501,25 @@ static void bootstrap_attr_stack(void)
501 elem->prev = attr_stack;
502 attr_stack = elem;
503
504 + if (git_attr_system()) {
505 + elem = read_attr_from_file(git_etc_gitattributes(), 1);
506 + if (elem) {
507 + elem->origin = NULL;
508 + elem->prev = attr_stack;
509 + attr_stack = elem;
510 + }
511 + }
512 +
513 + git_config(git_attr_config, NULL);
514 + if (git_attr_global() && attributes_file) {
515 + elem = read_attr_from_file(attributes_file, 1);
516 + if (elem) {
517 + elem->origin = NULL;
518 + elem->prev = attr_stack;
519 + attr_stack = elem;
520 + }
521 + }
522 +
523 if (!is_bare_repository() || direction == GIT_ATTR_INDEX) {
524 elem = read_attr(GITATTRIBUTES_FILE, 1);
525 elem->origin = strdup("");
@@ -499,7 +547,9 @@ static void prepare_attr_stack(const char *path, int dirlen)
547
548 /*
549 * At the bottom of the attribute stack is the built-in
502 - * set of attribute definitions. Then, contents from
550 + * set of attribute definitions, followed by the contents
551 + * of $(prefix)/etc/gitattributes and a file specified by
552 + * core.attributesfile. Then, contents from
553 * .gitattribute files from directories closer to the
554 * root to the ones in deeper directories are pushed
555 * to the stack. Finally, at the very top of the stack
configure.ac
+9 -1
@@ -282,7 +282,15 @@ GIT_PARSE_WITH(iconv))
282 GIT_PARSE_WITH_SET_MAKE_VAR(gitconfig, ETC_GITCONFIG,
283 Use VALUE instead of /etc/gitconfig as the
284 global git configuration file.
285 - If VALUE is not fully qualified it will be interpretted
285 + If VALUE is not fully qualified it will be interpreted
286 + as a path relative to the computed prefix at runtime.)
287 +
288 +#
289 +# Allow user to set ETC_GITATTRIBUTES variable
290 +GIT_PARSE_WITH_SET_MAKE_VAR(gitattributes, ETC_GITATTRIBUTES,
291 + Use VALUE instead of /etc/gitattributes as the
292 + global git attributes file.
293 + If VALUE is not fully qualified it will be interpreted
294 as a path relative to the computed prefix at runtime.)
295
296 #
t/t0003-attributes.sh
+13
@@ -36,6 +36,9 @@ test_expect_success 'setup' '
36 echo "d/* test=a/b/d/*"
37 echo "d/yes notest"
38 ) >a/b/.gitattributes
39 + (
40 + echo "global test=global"
41 + ) >$HOME/global-gitattributes
42
43 '
44
@@ -57,6 +60,16 @@ test_expect_success 'attribute test' '
60
61 '
62
63 +test_expect_success 'core.attributesfile' '
64 + attr_check global unspecified &&
65 + git config core.attributesfile "$HOME/global-gitattributes" &&
66 + attr_check global global &&
67 + git config core.attributesfile "~/global-gitattributes" &&
68 + attr_check global global &&
69 + echo "global test=precedence" >> .gitattributes &&
70 + attr_check global precedence
71 +'
72 +
73 test_expect_success 'attribute test: read paths from stdin' '
74
75 cat <<EOF > expect