Merge branch 'po/etc-gitattributes'

* po/etc-gitattributes:
  Add global and system-wide gitattributes

Conflicts:
	Documentation/config.txt
	Makefile
This commit is contained in:
Junio C Hamano 2010-09-29 13:47:51 -07:00
commit 2851e8eba5
6 changed files with 95 additions and 5 deletions

View File

@ -459,6 +459,12 @@ core.askpass::
prompt. The external program shall be given a suitable prompt as prompt. The external program shall be given a suitable prompt as
command line argument and write the password on its STDOUT. command line argument and write the password on its STDOUT.
core.attributesfile::
In addition to '.gitattributes' (per-directory) and
'.git/info/attributes', git looks into this file for attributes
(see linkgit:gitattributes[5]). Path expansions are made the same
way as for `core.excludesfile`.
core.editor:: core.editor::
Commands such as `commit` and `tag` that lets you edit Commands such as `commit` and `tag` that lets you edit
messages by launching an editor uses the value of this messages by launching an editor uses the value of this

View File

@ -62,14 +62,21 @@ consults `$GIT_DIR/info/attributes` file (which has the highest
precedence), `.gitattributes` file in the same directory as the precedence), `.gitattributes` file in the same directory as the
path in question, and its parent directories up to the toplevel of the path in question, and its parent directories up to the toplevel of the
work tree (the further the directory that contains `.gitattributes` work tree (the further the directory that contains `.gitattributes`
is from the path in question, the lower its precedence). is from the path in question, the lower its precedence). Finally
global and system-wide files are considered (they have the lowest
precedence).
If you wish to affect only a single repository (i.e., to assign If you wish to affect only a single repository (i.e., to assign
attributes to files that are particular to one user's workflow), then attributes to files that are particular to
one user's workflow for that repository), then
attributes should be placed in the `$GIT_DIR/info/attributes` file. attributes should be placed in the `$GIT_DIR/info/attributes` file.
Attributes which should be version-controlled and distributed to other Attributes which should be version-controlled and distributed to other
repositories (i.e., attributes of interest to all users) should go into repositories (i.e., attributes of interest to all users) should go into
`.gitattributes` files. `.gitattributes` files. Attributes that should affect all repositories
for a single user should be placed in a file specified by the
`core.attributesfile` configuration option (see linkgit:git-config[1]).
Attributes for all users on a system should be placed in the
`$(prefix)/etc/gitattributes` file.
Sometimes you would need to override an setting of an attribute Sometimes you would need to override an setting of an attribute
for a path to `unspecified` state. This can be done by listing for a path to `unspecified` state. This can be done by listing

View File

@ -270,6 +270,7 @@ STRIP ?= strip
# infodir # infodir
# htmldir # htmldir
# ETC_GITCONFIG (but not sysconfdir) # ETC_GITCONFIG (but not sysconfdir)
# ETC_GITATTRIBUTES
# can be specified as a relative path some/where/else; # can be specified as a relative path some/where/else;
# this is interpreted as relative to $(prefix) and "git" at # this is interpreted as relative to $(prefix) and "git" at
# runtime figures out where they are based on the path to the executable. # runtime figures out where they are based on the path to the executable.
@ -288,9 +289,11 @@ htmldir = share/doc/git-doc
ifeq ($(prefix),/usr) ifeq ($(prefix),/usr)
sysconfdir = /etc sysconfdir = /etc
ETC_GITCONFIG = $(sysconfdir)/gitconfig ETC_GITCONFIG = $(sysconfdir)/gitconfig
ETC_GITATTRIBUTES = $(sysconfdir)/gitattributes
else else
sysconfdir = $(prefix)/etc sysconfdir = $(prefix)/etc
ETC_GITCONFIG = etc/gitconfig ETC_GITCONFIG = etc/gitconfig
ETC_GITATTRIBUTES = etc/gitattributes
endif endif
lib = lib lib = lib
# DESTDIR= # DESTDIR=
@ -1523,6 +1526,7 @@ endif
SHA1_HEADER_SQ = $(subst ','\'',$(SHA1_HEADER)) SHA1_HEADER_SQ = $(subst ','\'',$(SHA1_HEADER))
ETC_GITCONFIG_SQ = $(subst ','\'',$(ETC_GITCONFIG)) ETC_GITCONFIG_SQ = $(subst ','\'',$(ETC_GITCONFIG))
ETC_GITATTRIBUTES_SQ = $(subst ','\'',$(ETC_GITATTRIBUTES))
DESTDIR_SQ = $(subst ','\'',$(DESTDIR)) DESTDIR_SQ = $(subst ','\'',$(DESTDIR))
bindir_SQ = $(subst ','\'',$(bindir)) bindir_SQ = $(subst ','\'',$(bindir))
@ -1901,6 +1905,8 @@ builtin/init-db.s builtin/init-db.o: EXTRA_CPPFLAGS = \
config.s config.o: EXTRA_CPPFLAGS = -DETC_GITCONFIG='"$(ETC_GITCONFIG_SQ)"' config.s config.o: EXTRA_CPPFLAGS = -DETC_GITCONFIG='"$(ETC_GITCONFIG_SQ)"'
attr.s attr.o: EXTRA_CPPFLAGS = -DETC_GITATTRIBUTES='"$(ETC_GITATTRIBUTES_SQ)"'
http.s http.o: EXTRA_CPPFLAGS = -DGIT_HTTP_USER_AGENT='"git/$(GIT_VERSION)"' http.s http.o: EXTRA_CPPFLAGS = -DGIT_HTTP_USER_AGENT='"git/$(GIT_VERSION)"'
ifdef NO_EXPAT ifdef NO_EXPAT

52
attr.c
View File

@ -1,5 +1,6 @@
#define NO_THE_INDEX_COMPATIBILITY_MACROS #define NO_THE_INDEX_COMPATIBILITY_MACROS
#include "cache.h" #include "cache.h"
#include "exec_cmd.h"
#include "attr.h" #include "attr.h"
const char git_attr__true[] = "(builtin)true"; const char git_attr__true[] = "(builtin)true";
@ -10,6 +11,8 @@ static const char git_attr__unknown[] = "(builtin)unknown";
#define ATTR__UNSET NULL #define ATTR__UNSET NULL
#define ATTR__UNKNOWN git_attr__unknown #define ATTR__UNKNOWN git_attr__unknown
static const char *attributes_file;
/* /*
* The basic design decision here is that we are not going to have * The basic design decision here is that we are not going to have
* insanely large number of attributes. * insanely large number of attributes.
@ -462,6 +465,32 @@ static void drop_attr_stack(void)
} }
} }
const char *git_etc_gitattributes(void)
{
static const char *system_wide;
if (!system_wide)
system_wide = system_path(ETC_GITATTRIBUTES);
return system_wide;
}
int git_attr_system(void)
{
return !git_env_bool("GIT_ATTR_NOSYSTEM", 0);
}
int git_attr_global(void)
{
return !git_env_bool("GIT_ATTR_NOGLOBAL", 0);
}
static int git_attr_config(const char *var, const char *value, void *dummy)
{
if (!strcmp(var, "core.attributesfile"))
return git_config_pathname(&attributes_file, var, value);
return 0;
}
static void bootstrap_attr_stack(void) static void bootstrap_attr_stack(void)
{ {
if (!attr_stack) { if (!attr_stack) {
@ -472,6 +501,25 @@ static void bootstrap_attr_stack(void)
elem->prev = attr_stack; elem->prev = attr_stack;
attr_stack = elem; attr_stack = elem;
if (git_attr_system()) {
elem = read_attr_from_file(git_etc_gitattributes(), 1);
if (elem) {
elem->origin = NULL;
elem->prev = attr_stack;
attr_stack = elem;
}
}
git_config(git_attr_config, NULL);
if (git_attr_global() && attributes_file) {
elem = read_attr_from_file(attributes_file, 1);
if (elem) {
elem->origin = NULL;
elem->prev = attr_stack;
attr_stack = elem;
}
}
if (!is_bare_repository() || direction == GIT_ATTR_INDEX) { if (!is_bare_repository() || direction == GIT_ATTR_INDEX) {
elem = read_attr(GITATTRIBUTES_FILE, 1); elem = read_attr(GITATTRIBUTES_FILE, 1);
elem->origin = strdup(""); elem->origin = strdup("");
@ -499,7 +547,9 @@ static void prepare_attr_stack(const char *path, int dirlen)
/* /*
* At the bottom of the attribute stack is the built-in * At the bottom of the attribute stack is the built-in
* set of attribute definitions. Then, contents from * set of attribute definitions, followed by the contents
* of $(prefix)/etc/gitattributes and a file specified by
* core.attributesfile. Then, contents from
* .gitattribute files from directories closer to the * .gitattribute files from directories closer to the
* root to the ones in deeper directories are pushed * root to the ones in deeper directories are pushed
* to the stack. Finally, at the very top of the stack * to the stack. Finally, at the very top of the stack

View File

@ -282,7 +282,15 @@ GIT_PARSE_WITH(iconv))
GIT_PARSE_WITH_SET_MAKE_VAR(gitconfig, ETC_GITCONFIG, GIT_PARSE_WITH_SET_MAKE_VAR(gitconfig, ETC_GITCONFIG,
Use VALUE instead of /etc/gitconfig as the Use VALUE instead of /etc/gitconfig as the
global git configuration file. global git configuration file.
If VALUE is not fully qualified it will be interpretted If VALUE is not fully qualified it will be interpreted
as a path relative to the computed prefix at runtime.)
#
# Allow user to set ETC_GITATTRIBUTES variable
GIT_PARSE_WITH_SET_MAKE_VAR(gitattributes, ETC_GITATTRIBUTES,
Use VALUE instead of /etc/gitattributes as the
global git attributes file.
If VALUE is not fully qualified it will be interpreted
as a path relative to the computed prefix at runtime.) as a path relative to the computed prefix at runtime.)
# #

View File

@ -36,6 +36,9 @@ test_expect_success 'setup' '
echo "d/* test=a/b/d/*" echo "d/* test=a/b/d/*"
echo "d/yes notest" echo "d/yes notest"
) >a/b/.gitattributes ) >a/b/.gitattributes
(
echo "global test=global"
) >$HOME/global-gitattributes
' '
@ -57,6 +60,16 @@ test_expect_success 'attribute test' '
' '
test_expect_success 'core.attributesfile' '
attr_check global unspecified &&
git config core.attributesfile "$HOME/global-gitattributes" &&
attr_check global global &&
git config core.attributesfile "~/global-gitattributes" &&
attr_check global global &&
echo "global test=precedence" >> .gitattributes &&
attr_check global precedence
'
test_expect_success 'attribute test: read paths from stdin' ' test_expect_success 'attribute test: read paths from stdin' '
cat <<EOF > expect cat <<EOF > expect