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