{"thread":{"id":"24703","subject":"[PATCH/RFC] Add global and system-wide gitattributes","startedAt":"2010-08-11T01:04:06Z","lastAt":"2010-09-02T15:49:48Z","messageCount":36,"participants":["Petr Onderka","Henrik Grubbström","Matthieu Moy","Junio C Hamano","Štěpán Němec","Ævar Arnfjörð Bjarmason"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"147708","messageId":"1281488646-7108-1-git-send-email-gsvick@gmail.com","threadId":"24703","inReplyTo":null,"subject":"[PATCH/RFC] Add global and system-wide gitattributes","fromName":"Petr Onderka","fromEmail":"gsvick@gmail.com","sentAt":"2010-08-11T01:04:06Z","receivedAt":"2010-08-11T01:04:06Z","isPatch":true,"sender":{"key":"gsvick@gmail.com","avatar":"https://avatars.githubusercontent.com/u/287848?v=4"},"body":"Allow gitattributes to be set globally and system wide in ~/.giattributes\nand $(prefix)/etc/gitattributes files, respectively. This way, settings\nfor particular file types can be set in one place and apply for all user's\nrepositories.\n\nContents of those two files are added to the attr_stack struct that\ncontains content of info/attributes, so that prepare_attr_stack()\nkeeps working as is and doesn't have to pop and then put back two more\nstructs (in addition to the \"info\" one).\n\nSome parts of the code were copied from the implementation of the same\nfunctionality in config.c.\n\nSigned-off-by: Petr Onderka <gsvick@gmail.com>\n---\nHi,\n\nI thought this feature would be useful for me, so I coded it up.\nWhat do you think? Is it ready to be included to the official repository as is?\n\n Documentation/gitattributes.txt |    5 ++-\n Makefile                        |    6 +++++\n attr.c                          |   43 ++++++++++++++++++++++++++++++++------\n configure.ac                    |    7 ++++++\n 4 files changed, 52 insertions(+), 9 deletions(-)\n\ndiff --git a/Documentation/gitattributes.txt b/Documentation/gitattributes.txt\nindex 564586b..351b014 100644\n--- a/Documentation/gitattributes.txt\n+++ b/Documentation/gitattributes.txt\n@@ -7,7 +7,7 @@ gitattributes - defining attributes per path\n \n SYNOPSIS\n --------\n-$GIT_DIR/info/attributes, .gitattributes\n+$GIT_DIR/info/attributes, /etc/gitattributes, ~/.gitattributes, .gitattributes\n \n \n DESCRIPTION\n@@ -58,7 +58,8 @@ attribute.  The rules how the pattern matches paths are the\n same as in `.gitignore` files; see linkgit:gitignore[5].\n \n When deciding what attributes are assigned to a path, git\n-consults `$GIT_DIR/info/attributes` file (which has the highest\n+consults `$GIT_DIR/info/attributes`, `~/.gitattributes`\n+and `$(prefix)/etc/gitconfig` files (in order of decreasing\n precedence), `.gitattributes` file in the same directory as the\n path in question, and its parent directories up to the toplevel of the\n work tree (the further the directory that contains `.gitattributes`\ndiff --git a/Makefile b/Makefile\nindex bc3c570..eadd2d7 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -268,6 +268,7 @@ STRIP ?= strip\n #   infodir\n #   htmldir\n #   ETC_GITCONFIG (but not sysconfdir)\n+#   ETC_GITATTRIBUTES\n # can be specified as a relative path some/where/else;\n # this is interpreted as relative to $(prefix) and \"git\" at\n # runtime figures out where they are based on the path to the executable.\n@@ -286,9 +287,11 @@ htmldir = share/doc/git-doc\n ifeq ($(prefix),/usr)\n sysconfdir = /etc\n ETC_GITCONFIG = $(sysconfdir)/gitconfig\n+ETC_GITATTRIBUTES = $(sysconfdir)/gitattributes\n else\n sysconfdir = $(prefix)/etc\n ETC_GITCONFIG = etc/gitconfig\n+ETC_GITATTRIBUTES = etc/gitattributes\n endif\n lib = lib\n # DESTDIR=\n@@ -1502,6 +1505,7 @@ endif\n \n SHA1_HEADER_SQ = $(subst ','\\'',$(SHA1_HEADER))\n ETC_GITCONFIG_SQ = $(subst ','\\'',$(ETC_GITCONFIG))\n+ETC_GITATTRIBUTES_SQ = $(subst ','\\'',$(ETC_GITATTRIBUTES))\n \n DESTDIR_SQ = $(subst ','\\'',$(DESTDIR))\n bindir_SQ = $(subst ','\\'',$(bindir))\n@@ -1872,6 +1876,8 @@ builtin/init-db.s builtin/init-db.o: EXTRA_CPPFLAGS = \\\n \n config.s config.o: EXTRA_CPPFLAGS = -DETC_GITCONFIG='\"$(ETC_GITCONFIG_SQ)\"'\n \n+attr.s attr.o: EXTRA_CPPFLAGS = -DETC_GITATTRIBUTES='\"$(ETC_GITATTRIBUTES_SQ)\"'\n+\n http.s http.o: EXTRA_CPPFLAGS = -DGIT_USER_AGENT='\"git/$(GIT_VERSION)\"'\n \n ifdef NO_EXPAT\ndiff --git a/attr.c b/attr.c\nindex 8ba606c..b1c3a30 100644\n--- a/attr.c\n+++ b/attr.c\n@@ -1,5 +1,6 @@\n #define NO_THE_INDEX_COMPATIBILITY_MACROS\n #include \"cache.h\"\n+#include \"exec_cmd.h\"\n #include \"attr.h\"\n \n const char git_attr__true[] = \"(builtin)true\";\n@@ -326,16 +327,16 @@ static struct attr_stack *read_attr_from_array(const char **list)\n static enum git_attr_direction direction;\n static struct index_state *use_index;\n \n-static struct attr_stack *read_attr_from_file(const char *path, int macro_ok)\n+static struct attr_stack *read_attr_from_file(const char *path, int macro_ok, struct attr_stack *res)\n {\n \tFILE *fp = fopen(path, \"r\");\n-\tstruct attr_stack *res;\n \tchar buf[2048];\n \tint lineno = 0;\n \n \tif (!fp)\n-\t\treturn NULL;\n-\tres = xcalloc(1, sizeof(*res));\n+\t\treturn res;\n+\tif (!res)\n+\t\tres = xcalloc(1, sizeof(*res));\n \twhile (fgets(buf, sizeof(buf), fp))\n \t\thandle_attr_line(res, buf, path, ++lineno, macro_ok);\n \tfclose(fp);\n@@ -407,10 +408,10 @@ static struct attr_stack *read_attr(const char *path, int macro_ok)\n \tif (direction == GIT_ATTR_CHECKOUT) {\n \t\tres = read_attr_from_index(path, macro_ok);\n \t\tif (!res)\n-\t\t\tres = read_attr_from_file(path, macro_ok);\n+\t\t\tres = read_attr_from_file(path, macro_ok, NULL);\n \t}\n \telse if (direction == GIT_ATTR_CHECKIN) {\n-\t\tres = read_attr_from_file(path, macro_ok);\n+\t\tres = read_attr_from_file(path, macro_ok, NULL);\n \t\tif (!res)\n \t\t\t/*\n \t\t\t * There is no checked out .gitattributes file there, but\n@@ -462,8 +463,28 @@ static void drop_attr_stack(void)\n \t}\n }\n \n+const char *git_etc_gitattributes(void)\n+{\n+\tstatic const char *system_wide;\n+\tif (!system_wide)\n+\t\tsystem_wide = system_path(ETC_GITATTRIBUTES);\n+\treturn system_wide;\n+}\n+\n+int git_attr_system(void)\n+{\n+\treturn !git_env_bool(\"GIT_ATTR_NOSYSTEM\", 0);\n+}\n+\n+int git_attr_global(void)\n+{\n+\treturn !git_env_bool(\"GIT_ATTR_NOGLOBAL\", 0);\n+}\n+\n static void bootstrap_attr_stack(void)\n {\n+\tconst char *home;\n+\n \tif (!attr_stack) {\n \t\tstruct attr_stack *elem;\n \n@@ -480,7 +501,15 @@ static void bootstrap_attr_stack(void)\n \t\t\tdebug_push(elem);\n \t\t}\n \n-\t\telem = read_attr_from_file(git_path(INFOATTRIBUTES_FILE), 1);\n+\t\telem = read_attr_from_file(git_path(INFOATTRIBUTES_FILE), 1, NULL);\n+\t\thome = get_home_directory();\n+\t\tif (git_attr_global() && home) {\n+\t\t\tchar *user_attr = xstrdup(mkpath(\"%s/%s\", home, GITATTRIBUTES_FILE));\n+\t\t\telem = read_attr_from_file(user_attr, 1, elem);\n+\t\t\tfree(user_attr);\n+\t\t}\n+\t\tif (git_attr_system())\n+\t\t\telem = read_attr_from_file(git_etc_gitattributes(), 1, elem);\n \t\tif (!elem)\n \t\t\telem = xcalloc(1, sizeof(*elem));\n \t\telem->origin = NULL;\ndiff --git a/configure.ac b/configure.ac\nindex 5601e8b..773b835 100644\n--- a/configure.ac\n+++ b/configure.ac\n@@ -285,6 +285,13 @@ GIT_PARSE_WITH_SET_MAKE_VAR(gitconfig, ETC_GITCONFIG,\n \t\t\tIf VALUE is not fully qualified it will be interpretted\n \t\t\tas a path relative to the computed prefix at runtime.)\n \n+# Allow user to set ETC_GITATTRIBUTS variable\n+GIT_PARSE_WITH_SET_MAKE_VAR(gitattributes, ETC_GITATTRIBUTES,\n+\t\t\tUse VALUE instead of /etc/gitattributes as the\n+\t\t\tglobal git attributes file.\n+\t\t\tIf VALUE is not fully qualified it will be interpretted\n+\t\t\tas a path relative to the computed prefix at runtime.)\n+\n #\n # Allow user to set the default pager\n GIT_PARSE_WITH_SET_MAKE_VAR(pager, DEFAULT_PAGER,\n-- \n1.7.1.msysgit.0.10.g9ffa0\n"},{"id":"147750","messageId":"Pine.GSO.4.63.1008111059281.1471@shipon.roxen.com","threadId":"24703","inReplyTo":"1281488646-7108-1-git-send-email-gsvick@gmail.com","subject":"Re: [PATCH/RFC] Add global and system-wide gitattributes","fromName":"Henrik Grubbström","fromEmail":"grubba@roxen.com","sentAt":"2010-08-11T09:20:39Z","receivedAt":"2010-08-11T09:20:39Z","isPatch":true,"sender":{"key":"grubba@roxen.com","avatar":null},"body":"Hi.\n\nOn Wed, 11 Aug 2010, Petr Onderka wrote:\n\n> Allow gitattributes to be set globally and system wide in ~/.giattributes\n                                                                ^^\nI assume you mean \"~/.gitattributes\" (ie missing a 't').\n\n> and $(prefix)/etc/gitattributes files, respectively. This way, settings\n> for particular file types can be set in one place and apply for all user's\n> repositories.\n[...]\n> Hi,\n>\n> I thought this feature would be useful for me, so I coded it up.\n> What do you think? Is it ready to be included to the official \n> repository as is?\n\nThe feature as such seems reasonable.\n\n> diff --git a/Documentation/gitattributes.txt b/Documentation/gitattributes.txt\n> index 564586b..351b014 100644\n> --- a/Documentation/gitattributes.txt\n> +++ b/Documentation/gitattributes.txt\n[...]\n> When deciding what attributes are assigned to a path, git\n> -consults `$GIT_DIR/info/attributes` file (which has the highest\n> +consults `$GIT_DIR/info/attributes`, `~/.gitattributes`\n> +and `$(prefix)/etc/gitconfig` files (in order of decreasing\n> precedence), `.gitattributes` file in the same directory as the\n> path in question, and its parent directories up to the toplevel of the\n> work tree (the further the directory that contains `.gitattributes`\n\nI'm not sure if the above priority order is the most desireable order, \nsince the user may want to set a default attribute, and have it to be \noverridden by the .gitattributes in the repositories.\n\n> diff --git a/configure.ac b/configure.ac\n> index 5601e8b..773b835 100644\n> --- a/configure.ac\n> +++ b/configure.ac\n> @@ -285,6 +285,13 @@ GIT_PARSE_WITH_SET_MAKE_VAR(gitconfig, ETC_GITCONFIG,\n> \t\t\tIf VALUE is not fully qualified it will be interpretted\n                                                                            ^^\nSpello (not your fault): \"interpreted\".\n\n> \t\t\tas a path relative to the computed prefix at runtime.)\n>\n> +# Allow user to set ETC_GITATTRIBUTS variable\n> +GIT_PARSE_WITH_SET_MAKE_VAR(gitattributes, ETC_GITATTRIBUTES,\n> +\t\t\tUse VALUE instead of /etc/gitattributes as the\n> +\t\t\tglobal git attributes file.\n> +\t\t\tIf VALUE is not fully qualified it will be interpretted\n                                                                            ^^\nSame.\n\n> +\t\t\tas a path relative to the computed prefix at runtime.)\n> +\n\n--\nHenrik Grubbström\t\t\t\t\tgrubba@grubba.org\nRoxen Internet Software AB\t\t\t\tgrubba@roxen.com"},{"id":"147754","messageId":"AANLkTi=q-tdtaWp8O3AHyvynL97LJuy7e9HUFwfkmX3O@mail.gmail.com","threadId":"24703","inReplyTo":"Pine.GSO.4.63.1008111059281.1471@shipon.roxen.com","subject":"Re: [PATCH/RFC] Add global and system-wide gitattributes","fromName":"Petr Onderka","fromEmail":"gsvick@gmail.com","sentAt":"2010-08-11T10:50:45Z","receivedAt":"2010-08-11T10:50:45Z","isPatch":true,"sender":{"key":"gsvick@gmail.com","avatar":"https://avatars.githubusercontent.com/u/287848?v=4"},"body":"Hi,\n\n>> Allow gitattributes to be set globally and system wide in ~/.giattributes\n>\n>                                                               ^^\n> I assume you mean \"~/.gitattributes\" (ie missing a 't').\n\nYeah.\n\n> I'm not sure if the above priority order is the most desireable order, since\n> the user may want to set a default attribute, and have it to be overridden\n> by the .gitattributes in the repositories.\n\nI wasn't sure either. I'm assuming info/gitattributes was made with\nhigher priority, so that that users could override .gitattributes\nwithout polluting their repository, so I made the new ones behave the\nsame way. But now that I think of it, you probably want to do that\nonly for a specific repository, and have defaults for all repositories\nthat could be overriden by local .gitattributes. I'm going to rewrite\nit this way.\n\nPetr Onderka\n"},{"id":"147760","messageId":"vpq39uluy97.fsf@bauges.imag.fr","threadId":"24703","inReplyTo":"1281488646-7108-1-git-send-email-gsvick@gmail.com","subject":"Re: [PATCH/RFC] Add global and system-wide gitattributes","fromName":"Matthieu Moy","fromEmail":"matthieu.moy@grenoble-inp.fr","sentAt":"2010-08-11T12:31:16Z","receivedAt":"2010-08-11T12:31:16Z","isPatch":true,"sender":{"key":"matthieu.moy@grenoble-inp.fr","avatar":"https://gravatar.com/avatar/72c8a2705971a25dfaff23cece15130d405685845d911aedd5667ace277f3fc5?d=mp&s=160"},"body":"Petr Onderka <gsvick@gmail.com> writes:\n\n> Allow gitattributes to be set globally and system wide in ~/.giattributes\n> and $(prefix)/etc/gitattributes files, respectively. This way, settings\n> for particular file types can be set in one place and apply for all user's\n> repositories.\n\nThe feature is definitely useful, and I'll use it as soon as it gets\ninto git.git ;-).\n\nOne point: we need to make sure the choice for the the user-wide\nfilename is the right one, since it's a pain to change it later.\n\nWe already have ~/.gitconfig, which often points to ~/.gitexcludes or\n~/.gitignored (but this filename is specified with a config variable,\nfor which we didn't manage to agree on a default value). We're about\nto add ~/.gitattributes. That makes 3 ~/.git* files, and I think it's\ntime to make it a directory (similar to $GIT_DIR/info/)\n\nI think it should be done like this:\n\n1) Default core.excludesfile to $CONF/exclude\n\n2) Make your user-wide gitattribute $CONF/attributes\n\n3) Optionally, read $CONF/config as well as ~/.gitconfig so that\n   people can have all their git configuration in the same directory.\n\nNow, we need to agree on $CONF. Some non-options are:\n\n* CONF=~/.gitconfig would clash with the file ~/.gitconfig\n\n* CONF=~/.git would prevent people from versionning their $HOME.\n\nI'd be in favor of following the freedesktop standard (roughly,\ndefaulting to ~/.config/git):\n\n  http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html\n\nbecause other applications start using it, and it allows one to easily\nkeep the configuration in a (typically git-versionned) ~/.config\ndirectory. And if we are to choose a config directory, it doesn't harm\nto chose one consistant with other applications and with a standard.\n\nI never got time to implement this. If you're willing to do something\nlike that, that would be great. If not, I'd suggest having a config\nvariable to point to the user-wide gitattributes file (without a\ndefault value), because it allows a future transition by giving a\ndefault value to the variable.\n\n-- \nMatthieu Moy\nhttp://www-verimag.imag.fr/~moy/\n"},{"id":"147834","messageId":"7vzkwsvllz.fsf@alter.siamese.dyndns.org","threadId":"24703","inReplyTo":"1281488646-7108-1-git-send-email-gsvick@gmail.com","subject":"Re: [PATCH/RFC] Add global and system-wide gitattributes","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-08-11T22:19:04Z","receivedAt":"2010-08-11T22:19:04Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Petr Onderka <gsvick@gmail.com> writes:\n\n> @@ -480,7 +501,15 @@ static void bootstrap_attr_stack(void)\n>  \t\t\tdebug_push(elem);\n>  \t\t}\n>  \n> -\t\telem = read_attr_from_file(git_path(INFOATTRIBUTES_FILE), 1);\n> +\t\telem = read_attr_from_file(git_path(INFOATTRIBUTES_FILE), 1, NULL);\n> +\t\thome = get_home_directory();\n> +\t\tif (git_attr_global() && home) {\n> +\t\t\tchar *user_attr = xstrdup(mkpath(\"%s/%s\", home, GITATTRIBUTES_FILE));\n> +\t\t\telem = read_attr_from_file(user_attr, 1, elem);\n> +\t\t\tfree(user_attr);\n> +\t\t}\n> +\t\tif (git_attr_system())\n> +\t\t\telem = read_attr_from_file(git_etc_gitattributes(), 1, elem);\n\nHave you read the comment at the top of prepare-attr-stack?  This patch\nfeels triply wrong:\n\n - The attribute stack is arranged to have higher precedence file near the\n   top ($GIT_DIR/info/attributes used to be the highest).  The above\n   addition means that ~/.gitattributes from user's home trumps what is in\n   a particular repository.  That is backwards.  You may work on more than\n   one projects and have more than one repositories.  What you share among\n   them personally will go to ~/.gitattributes, while a setting specific\n   to a particular repository goes to $GIT_DIR/info/attributes and the\n   latter needs to be able to override the former.\n\n - Same thing for git_attr_system() being at the end, which means you set\n   up your own $GIT_DIR/info/attributes (or ~/.gitattributes) carefully\n   but that can be broken by a selfish sysadmin who puts stuff that is\n   only useful to him in /etc/gitattributes, which is not what you want.\n\n - Whenever we enter a new directory (either recursing into, or coming\n   back up), prepare_attr_stack() is called to pop the attributes records\n   from now-exited directories and push the attributes records from\n   directories we are about to descend into.  The current code knows that\n   the topmost element on the stack is special ($GIT_DIR/info/attributes)\n   and first pops it, adjust the stack for elements that came from the\n   directory hierarcy, and then pushes that back.  I don't see any code in\n   the patch to do the equivalent for these two new attribute sources.\n"},{"id":"148191","messageId":"AANLkTi=2tRjGicxJxnJ3xccCGxcP3bLUy8u0O7q85D=R@mail.gmail.com","threadId":"24703","inReplyTo":"7vzkwsvllz.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH/RFC] Add global and system-wide gitattributes","fromName":"Petr Onderka","fromEmail":"gsvick@gmail.com","sentAt":"2010-08-16T16:51:54Z","receivedAt":"2010-08-16T16:51:54Z","isPatch":true,"sender":{"key":"gsvick@gmail.com","avatar":"https://avatars.githubusercontent.com/u/287848?v=4"},"body":"Hi,\n\nOn Thu, Aug 12, 2010 at 00:19, Junio C Hamano <gitster@pobox.com> wrote:\n> Have you read the comment at the top of prepare-attr-stack?  This patch\n> feels triply wrong:\n>\n>  - The attribute stack is arranged to have higher precedence file near the\n>   top ($GIT_DIR/info/attributes used to be the highest).  The above\n>   addition means that ~/.gitattributes from user's home trumps what is in\n>   a particular repository.  That is backwards.  You may work on more than\n>   one projects and have more than one repositories.  What you share among\n>   them personally will go to ~/.gitattributes, while a setting specific\n>   to a particular repository goes to $GIT_DIR/info/attributes and the\n>   latter needs to be able to override the former.\n>\n>  - Same thing for git_attr_system() being at the end, which means you set\n>   up your own $GIT_DIR/info/attributes (or ~/.gitattributes) carefully\n>   but that can be broken by a selfish sysadmin who puts stuff that is\n>   only useful to him in /etc/gitattributes, which is not what you want.\n>\n>  - Whenever we enter a new directory (either recursing into, or coming\n>   back up), prepare_attr_stack() is called to pop the attributes records\n>   from now-exited directories and push the attributes records from\n>   directories we are about to descend into.  The current code knows that\n>   the topmost element on the stack is special ($GIT_DIR/info/attributes)\n>   and first pops it, adjust the stack for elements that came from the\n>   directory hierarcy, and then pushes that back.  I don't see any code in\n>   the patch to do the equivalent for these two new attribute sources.\n\nYeah, I realize now that I got the precedence wrong, the corrected\npatch is in the following email.\n\nBut to your third point, I read the comment and the code worked,\nbecause I put all the attributes from the 3 files into one attr_stack\nstruct (the one at the top of the stack). That's why I changed\nread_attr_from_file too. Of course this is irrelevant now that those\nattributes will be at the bottom of the stack.\n\nPetr Onderka\n"},{"id":"148192","messageId":"1281977813-6528-1-git-send-email-gsvick@gmail.com","threadId":"24703","inReplyTo":"AANLkTi=2tRjGicxJxnJ3xccCGxcP3bLUy8u0O7q85D=R@mail.gmail.com","subject":"[PATCH v2] Add global and system-wide gitattributes","fromName":"Petr Onderka","fromEmail":"gsvick@gmail.com","sentAt":"2010-08-16T16:56:53Z","receivedAt":"2010-08-16T16:56:53Z","isPatch":true,"sender":{"key":"gsvick@gmail.com","avatar":"https://avatars.githubusercontent.com/u/287848?v=4"},"body":"Allow gitattributes to be set globally and system wide. This way, settings\nfor particular file types can be set in one place and apply for all user's\nrepositories.\n\nThe location of system-wide attributes file is $(prefix)/etc/gitattributes.\nThe location of the global file can be configured by setting\ncore.attributesfile.\n\nSome parts of the code were copied from the implementation of the same\nfunctionality in config.c.\n\nSigned-off-by: Petr Onderka <gsvick@gmail.com>\n---\nThis version has the correct precedence for global and system-wide attributes.\n\nI decided not to implement having user config files in a directory (at least\nfor now). The location of the global attributes file can be set using\ncore.attributesfile. This setting has no default, as Matthieu suggested.\n\n Documentation/config.txt        |    6 +++++\n Documentation/gitattributes.txt |   13 ++++++++--\n Makefile                        |    6 +++++\n attr.c                          |   44 ++++++++++++++++++++++++++++++++++++++-\n cache.h                         |    1 +\n config.c                        |    3 ++\n configure.ac                    |   10 ++++++++-\n environment.c                   |    1 +\n 8 files changed, 79 insertions(+), 5 deletions(-)\n\ndiff --git a/Documentation/config.txt b/Documentation/config.txt\nindex f81fb91..e5034f4 100644\n--- a/Documentation/config.txt\n+++ b/Documentation/config.txt\n@@ -450,6 +450,12 @@ core.excludesfile::\n \tto the value of `$HOME` and \"{tilde}user/\" to the specified user's\n \thome directory.  See linkgit:gitignore[5].\n \n+core.attributesfile::\n+\tIn addition to '.gitattributes' (per-directory) and\n+\t'.git/info/attributes', git looks into this file for attributes\n+\t(see linkgit:gitattributes[5]). Path expansions are made the same\n+\tway as for `core.excludesfile`.\n+\n core.editor::\n \tCommands such as `commit` and `tag` that lets you edit\n \tmessages by launching an editor uses the value of this\ndiff --git a/Documentation/gitattributes.txt b/Documentation/gitattributes.txt\nindex 564586b..c6bdeae 100644\n--- a/Documentation/gitattributes.txt\n+++ b/Documentation/gitattributes.txt\n@@ -62,14 +62,21 @@ consults `$GIT_DIR/info/attributes` file (which has the highest\n precedence), `.gitattributes` file in the same directory as the\n path in question, and its parent directories up to the toplevel of the\n work tree (the further the directory that contains `.gitattributes`\n-is from the path in question, the lower its precedence).\n+is from the path in question, the lower its precedence). Finally\n+global and system-wide files are considered (they have the lowest\n+precedence).\n \n If you wish to affect only a single repository (i.e., to assign\n-attributes to files that are particular to one user's workflow), then\n+attributes to files that are particular to\n+one user's workflow for that repository), then\n attributes should be placed in the `$GIT_DIR/info/attributes` file.\n Attributes which should be version-controlled and distributed to other\n repositories (i.e., attributes of interest to all users) should go into\n-`.gitattributes` files.\n+`.gitattributes` files. Attributes that should affect all repositories\n+for a single user should be placed in a file specified by the\n+`core.attributesfile` configuration option (see linkgit:git-config[1]).\n+Attributes for all users on a system should be placed in the\n+`$(prefix)/etc/gitattributes` file.\n \n Sometimes you would need to override an setting of an attribute\n for a path to `unspecified` state.  This can be done by listing\ndiff --git a/Makefile b/Makefile\nindex f33648d..3bfc483 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -268,6 +268,7 @@ STRIP ?= strip\n #   infodir\n #   htmldir\n #   ETC_GITCONFIG (but not sysconfdir)\n+#   ETC_GITATTRIBUTES\n # can be specified as a relative path some/where/else;\n # this is interpreted as relative to $(prefix) and \"git\" at\n # runtime figures out where they are based on the path to the executable.\n@@ -286,9 +287,11 @@ htmldir = share/doc/git-doc\n ifeq ($(prefix),/usr)\n sysconfdir = /etc\n ETC_GITCONFIG = $(sysconfdir)/gitconfig\n+ETC_GITATTRIBUTES = $(sysconfdir)/gitattributes\n else\n sysconfdir = $(prefix)/etc\n ETC_GITCONFIG = etc/gitconfig\n+ETC_GITATTRIBUTES = etc/gitattributes\n endif\n lib = lib\n # DESTDIR=\n@@ -1502,6 +1505,7 @@ endif\n \n SHA1_HEADER_SQ = $(subst ','\\'',$(SHA1_HEADER))\n ETC_GITCONFIG_SQ = $(subst ','\\'',$(ETC_GITCONFIG))\n+ETC_GITATTRIBUTES_SQ = $(subst ','\\'',$(ETC_GITATTRIBUTES))\n \n DESTDIR_SQ = $(subst ','\\'',$(DESTDIR))\n bindir_SQ = $(subst ','\\'',$(bindir))\n@@ -1872,6 +1876,8 @@ builtin/init-db.s builtin/init-db.o: EXTRA_CPPFLAGS = \\\n \n config.s config.o: EXTRA_CPPFLAGS = -DETC_GITCONFIG='\"$(ETC_GITCONFIG_SQ)\"'\n \n+attr.s attr.o: EXTRA_CPPFLAGS = -DETC_GITATTRIBUTES='\"$(ETC_GITATTRIBUTES_SQ)\"'\n+\n http.s http.o: EXTRA_CPPFLAGS = -DGIT_USER_AGENT='\"git/$(GIT_VERSION)\"'\n \n ifdef NO_EXPAT\ndiff --git a/attr.c b/attr.c\nindex 8ba606c..068e13b 100644\n--- a/attr.c\n+++ b/attr.c\n@@ -1,5 +1,6 @@\n #define NO_THE_INDEX_COMPATIBILITY_MACROS\n #include \"cache.h\"\n+#include \"exec_cmd.h\"\n #include \"attr.h\"\n \n const char git_attr__true[] = \"(builtin)true\";\n@@ -462,6 +463,24 @@ static void drop_attr_stack(void)\n \t}\n }\n \n+const char *git_etc_gitattributes(void)\n+{\n+\tstatic const char *system_wide;\n+\tif (!system_wide)\n+\t\tsystem_wide = system_path(ETC_GITATTRIBUTES);\n+\treturn system_wide;\n+}\n+\n+int git_attr_system(void)\n+{\n+\treturn !git_env_bool(\"GIT_ATTR_NOSYSTEM\", 0);\n+}\n+\n+int git_attr_global(void)\n+{\n+\treturn !git_env_bool(\"GIT_ATTR_NOGLOBAL\", 0);\n+}\n+\n static void bootstrap_attr_stack(void)\n {\n \tif (!attr_stack) {\n@@ -472,6 +491,27 @@ static void bootstrap_attr_stack(void)\n \t\telem->prev = attr_stack;\n \t\tattr_stack = elem;\n \n+\t\tif (git_attr_system()) {\n+\t\t\telem = read_attr_from_file(git_etc_gitattributes(), 1);\n+\t\t\tif (elem) {\n+\t\t\t\telem->origin = NULL;\n+\t\t\t\telem->prev = attr_stack;\n+\t\t\t\tattr_stack = elem;\n+\t\t\t}\n+\t\t}\n+\n+\t\tif (git_attr_global() && attributes_file) {\n+\t\t\tchar *user_attr = xstrdup(attributes_file);\n+\n+\t\t\telem = read_attr_from_file(user_attr, 1);\n+\t\t\tfree(user_attr);\n+\t\t\tif (elem) {\n+\t\t\t\telem->origin = NULL;\n+\t\t\t\telem->prev = attr_stack;\n+\t\t\t\tattr_stack = elem;\n+\t\t\t}\n+\t\t}\n+\n \t\tif (!is_bare_repository() || direction == GIT_ATTR_INDEX) {\n \t\t\telem = read_attr(GITATTRIBUTES_FILE, 1);\n \t\t\telem->origin = strdup(\"\");\n@@ -499,7 +539,9 @@ static void prepare_attr_stack(const char *path, int dirlen)\n \n \t/*\n \t * At the bottom of the attribute stack is the built-in\n-\t * set of attribute definitions.  Then, contents from\n+\t * set of attribute definitions, followed by the contents\n+\t * of $(prefix)/etc/gitattributes and a file specified by\n+\t * core.attributesfile.  Then, contents from\n \t * .gitattribute files from directories closer to the\n \t * root to the ones in deeper directories are pushed\n \t * to the stack.  Finally, at the very top of the stack\ndiff --git a/cache.h b/cache.h\nindex c9fa3df..cd95801 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -1030,6 +1030,7 @@ extern int pager_use_color;\n \n extern const char *editor_program;\n extern const char *excludes_file;\n+extern const char *attributes_file;\n \n /* base85 */\n int decode_85(char *dst, const char *line, int linelen);\ndiff --git a/config.c b/config.c\nindex cdcf583..f602cd4 100644\n--- a/config.c\n+++ b/config.c\n@@ -563,6 +563,9 @@ static int git_default_core_config(const char *var, const char *value)\n \tif (!strcmp(var, \"core.excludesfile\"))\n \t\treturn git_config_pathname(&excludes_file, var, value);\n \n+\tif (!strcmp(var, \"core.attributesfile\"))\n+\t\treturn git_config_pathname(&attributes_file, var, value);\n+\n \tif (!strcmp(var, \"core.whitespace\")) {\n \t\tif (!value)\n \t\t\treturn config_error_nonbool(var);\ndiff --git a/configure.ac b/configure.ac\nindex 5601e8b..c5b3a41 100644\n--- a/configure.ac\n+++ b/configure.ac\n@@ -282,7 +282,15 @@ GIT_PARSE_WITH(iconv))\n GIT_PARSE_WITH_SET_MAKE_VAR(gitconfig, ETC_GITCONFIG,\n \t\t\tUse VALUE instead of /etc/gitconfig as the\n \t\t\tglobal git configuration file.\n-\t\t\tIf VALUE is not fully qualified it will be interpretted\n+\t\t\tIf VALUE is not fully qualified it will be interpreted\n+\t\t\tas a path relative to the computed prefix at runtime.)\n+\n+#\n+# Allow user to set ETC_GITATTRIBUTES variable\n+GIT_PARSE_WITH_SET_MAKE_VAR(gitattributes, ETC_GITATTRIBUTES,\n+\t\t\tUse VALUE instead of /etc/gitattributes as the\n+\t\t\tglobal git attributes file.\n+\t\t\tIf VALUE is not fully qualified it will be interpreted\n \t\t\tas a path relative to the computed prefix at runtime.)\n \n #\ndiff --git a/environment.c b/environment.c\nindex 83d38d3..58f719a 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -38,6 +38,7 @@ const char *pager_program;\n int pager_use_color = 1;\n const char *editor_program;\n const char *excludes_file;\n+const char *attributes_file;\n enum auto_crlf auto_crlf = AUTO_CRLF_FALSE;\n int read_replace_refs = 1;\n enum eol eol = EOL_UNSET;\n-- \n1.7.2.1.2361.g5f8e3\n"},{"id":"148961","messageId":"87d3t7ow39.fsf@gmail.com","threadId":"24703","inReplyTo":"1281977813-6528-1-git-send-email-gsvick@gmail.com","subject":"Re: [PATCH v2] Add global and system-wide gitattributes","fromName":"Štěpán Němec","fromEmail":"stepnem@gmail.com","sentAt":"2010-08-25T09:55:22Z","receivedAt":"2010-08-25T09:55:22Z","isPatch":true,"sender":{"key":"stepnem@gmail.com","avatar":"https://avatars.githubusercontent.com/u/106838?v=4"},"body":"Petr Onderka <gsvick@gmail.com> writes:\n\n> Allow gitattributes to be set globally and system wide. This way, settings\n> for particular file types can be set in one place and apply for all user's\n> repositories.\n\n[...]\n\nI really can't wait till this gets into Git and I'm certainly not the\nonly one (thank you so much for working on it, Petr!). Any reason the\npatch still hasn't been applied?\n\n  Štěpán\n"},{"id":"149169","messageId":"vpqbp8mskv1.fsf@bauges.imag.fr","threadId":"24703","inReplyTo":"87d3t7ow39.fsf@gmail.com","subject":"Re: [PATCH v2] Add global and system-wide gitattributes","fromName":"Matthieu Moy","fromEmail":"matthieu.moy@grenoble-inp.fr","sentAt":"2010-08-28T17:33:22Z","receivedAt":"2010-08-28T17:33:22Z","isPatch":true,"sender":{"key":"matthieu.moy@grenoble-inp.fr","avatar":"https://gravatar.com/avatar/72c8a2705971a25dfaff23cece15130d405685845d911aedd5667ace277f3fc5?d=mp&s=160"},"body":"Štěpán Němec <stepnem@gmail.com> writes:\n\n> Petr Onderka <gsvick@gmail.com> writes:\n>\n>> Allow gitattributes to be set globally and system wide. This way, settings\n>> for particular file types can be set in one place and apply for all user's\n>> repositories.\n>\n> [...]\n>\n> I really can't wait till this gets into Git and I'm certainly not the\n> only one (thank you so much for working on it, Petr!).\n\nSame here ;-).\n\n> Any reason the patch still hasn't been applied?\n\nUsually, patches are applied if either\n\n1) Junio has personal interest in it, or\n\n2) Other people review the code and show interest for it.\n\nI guess none of the conditions were met here (and Junio was very busy\nthese days). I'm sure you can help about point 2) ;-)\n\n-- \nMatthieu Moy\nhttp://www-verimag.imag.fr/~moy/\n"},{"id":"149175","messageId":"vpqy6bqr3ep.fsf@bauges.imag.fr","threadId":"24703","inReplyTo":"1281977813-6528-1-git-send-email-gsvick@gmail.com","subject":"Re: [PATCH v2] Add global and system-wide gitattributes","fromName":"Matthieu Moy","fromEmail":"matthieu.moy@grenoble-inp.fr","sentAt":"2010-08-28T18:35:42Z","receivedAt":"2010-08-28T18:35:42Z","isPatch":true,"sender":{"key":"matthieu.moy@grenoble-inp.fr","avatar":"https://gravatar.com/avatar/72c8a2705971a25dfaff23cece15130d405685845d911aedd5667ace277f3fc5?d=mp&s=160"},"body":"Petr Onderka <gsvick@gmail.com> writes:\n\n> Allow gitattributes to be set globally and system wide. This way, settings\n> for particular file types can be set in one place and apply for all user's\n> repositories.\n>\n> The location of system-wide attributes file is $(prefix)/etc/gitattributes.\n> The location of the global file can be configured by setting\n> core.attributesfile.\n\nGood, I like this :-)\n\n> Some parts of the code were copied from the implementation of the same\n> functionality in config.c.\n\n(maybe you could say quickly which ones and why)\n\n> +\t\tif (git_attr_global() && attributes_file) {\n\nI tried this, and attributes_file was NULL here. I don't know how it\nworked for you, but there should be a call to git_config here.\n\n> +\t\t\tchar *user_attr = xstrdup(attributes_file);\n> +\n> +\t\t\telem = read_attr_from_file(user_attr, 1);\n> +\t\t\tfree(user_attr);\n\nAny reason for this xstrdup/free?\n\nPatch follows for these two points + a test, to be squashed into\nyours.\n\n-- \nMatthieu Moy\nhttp://www-verimag.imag.fr/~moy/\n"},{"id":"149176","messageId":"1283020870-24888-1-git-send-email-Matthieu.Moy@imag.fr","threadId":"24703","inReplyTo":"vpqy6bqr3ep.fsf@bauges.imag.fr","subject":"[PATCH] core.attributesfile: a fix, a simplification, and a test","fromName":"Matthieu Moy","fromEmail":"matthieu.moy@imag.fr","sentAt":"2010-08-28T18:41:10Z","receivedAt":"2010-08-28T18:41:10Z","isPatch":true,"sender":{"key":"git@matthieu-moy.fr","avatar":"https://avatars.githubusercontent.com/u/14709?v=4"},"body":"Patch meant to be squashed into the core.attributesfile.\n\n* attributes_file won't be set unless one calls git_config before => do\n  this.\n\n* There was a useless xstrdup/free in the code.\n\n* This really deserves a test, so I added one in t0003-attributes.sh.\n  (I've been too lazy to check the system-wide attributes file, though)\n\nSigned-off-by: Matthieu Moy <Matthieu.Moy@imag.fr>\n---\n attr.c                |    6 ++----\n t/t0003-attributes.sh |   14 ++++++++++++++\n 2 files changed, 16 insertions(+), 4 deletions(-)\n\ndiff --git a/attr.c b/attr.c\nindex 068e13b..342791a 100644\n--- a/attr.c\n+++ b/attr.c\n@@ -500,11 +500,9 @@ static void bootstrap_attr_stack(void)\n \t\t\t}\n \t\t}\n \n+\t\tgit_config(git_default_config, NULL);\n \t\tif (git_attr_global() && attributes_file) {\n-\t\t\tchar *user_attr = xstrdup(attributes_file);\n-\n-\t\t\telem = read_attr_from_file(user_attr, 1);\n-\t\t\tfree(user_attr);\n+\t\t\telem = read_attr_from_file(attributes_file, 1);\n \t\t\tif (elem) {\n \t\t\t\telem->origin = NULL;\n \t\t\t\telem->prev = attr_stack;\ndiff --git a/t/t0003-attributes.sh b/t/t0003-attributes.sh\nindex de38c7f..24286e5 100755\n--- a/t/t0003-attributes.sh\n+++ b/t/t0003-attributes.sh\n@@ -15,6 +15,7 @@ attr_check () {\n \n }\n \n+HOME=$(pwd)\n \n test_expect_success 'setup' '\n \n@@ -36,6 +37,9 @@ test_expect_success 'setup' '\n \t\techo \"d/* test=a/b/d/*\"\n \t\techo \"d/yes notest\"\n \t) >a/b/.gitattributes\n+\t(\n+\t\techo \"global test=global\"\n+\t) >$HOME/global-gitattributes\n \n '\n \n@@ -57,6 +61,16 @@ test_expect_success 'attribute test' '\n \n '\n \n+test_expect_success 'core.attributesfile' '\n+\tattr_check global unspecified &&\n+\tgit config core.attributesfile \"$HOME/global-gitattributes\" &&\n+\tattr_check global global &&\n+\tgit config core.attributesfile \"~/global-gitattributes\" &&\n+\tattr_check global global &&\n+\techo \"global test=precedence\" >> .gitattributes &&\n+\tattr_check global precedence\n+'\n+\n test_expect_success 'attribute test: read paths from stdin' '\n \n \tcat <<EOF > expect\n-- \n1.7.2.2.175.ga619d.dirty\n"},{"id":"149205","messageId":"87fwxxhfpp.fsf_-_@gmail.com","threadId":"24703","inReplyTo":"1283020870-24888-1-git-send-email-Matthieu.Moy@imag.fr","subject":"Re: [PATCH v3?] Add global and system-wide gitattributes","fromName":"Štěpán Němec","fromEmail":"stepnem@gmail.com","sentAt":"2010-08-29T10:32:18Z","receivedAt":"2010-08-29T10:32:18Z","isPatch":true,"sender":{"key":"stepnem@gmail.com","avatar":"https://avatars.githubusercontent.com/u/106838?v=4"},"body":"\nThanks, Matthieu!\n\nPetr's original patch doesn't apply cleanly due to a bogus context line\nafter a recent change in Makefile. For convenience, below is the updated\npatch including Matthieu's changes applicable to current master.\n\nAnd FWIW (I didn't try to build the documentation, though):\n\nTested-by: Štěpán Němec <stepnem@gmail.com>\n\n--- 8< ---\nFrom b63a6449dbf2c6d4a111ad840ae7d408afdd5e43 Mon Sep 17 00:00:00 2001\nFrom: Petr Onderka <gsvick@gmail.com>\nDate: Mon, 16 Aug 2010 16:56:53 +0000\nSubject: [PATCH] Add global and system-wide gitattributes\n\nAllow gitattributes to be set globally and system wide. This way, settings\nfor particular file types can be set in one place and apply for all user's\nrepositories.\n\nThe location of system-wide attributes file is $(prefix)/etc/gitattributes.\nThe location of the global file can be configured by setting\ncore.attributesfile.\n\nSome parts of the code were copied from the implementation of the same\nfunctionality in config.c.\n\nSigned-off-by: Petr Onderka <gsvick@gmail.com>\nSigned-off-by: Matthieu Moy <Matthieu.Moy@imag.fr>\n---\n Documentation/config.txt        |    6 +++++\n Documentation/gitattributes.txt |   13 +++++++++--\n Makefile                        |    6 +++++\n attr.c                          |   42 ++++++++++++++++++++++++++++++++++++++-\n cache.h                         |    1 +\n config.c                        |    3 ++\n configure.ac                    |   10 ++++++++-\n environment.c                   |    1 +\n t/t0003-attributes.sh           |   14 +++++++++++++\n 9 files changed, 91 insertions(+), 5 deletions(-)\n\ndiff --git a/Documentation/config.txt b/Documentation/config.txt\nindex 05ec3fe..0e15e72 100644\n--- a/Documentation/config.txt\n+++ b/Documentation/config.txt\n@@ -450,6 +450,12 @@ core.excludesfile::\n \tto the value of `$HOME` and \"{tilde}user/\" to the specified user's\n \thome directory.  See linkgit:gitignore[5].\n \n+core.attributesfile::\n+\tIn addition to '.gitattributes' (per-directory) and\n+\t'.git/info/attributes', git looks into this file for attributes\n+\t(see linkgit:gitattributes[5]). Path expansions are made the same\n+\tway as for `core.excludesfile`.\n+\n core.editor::\n \tCommands such as `commit` and `tag` that lets you edit\n \tmessages by launching an editor uses the value of this\ndiff --git a/Documentation/gitattributes.txt b/Documentation/gitattributes.txt\nindex 2e2370c..ebd4852 100644\n--- a/Documentation/gitattributes.txt\n+++ b/Documentation/gitattributes.txt\n@@ -62,14 +62,21 @@ consults `$GIT_DIR/info/attributes` file (which has the highest\n precedence), `.gitattributes` file in the same directory as the\n path in question, and its parent directories up to the toplevel of the\n work tree (the further the directory that contains `.gitattributes`\n-is from the path in question, the lower its precedence).\n+is from the path in question, the lower its precedence). Finally\n+global and system-wide files are considered (they have the lowest\n+precedence).\n \n If you wish to affect only a single repository (i.e., to assign\n-attributes to files that are particular to one user's workflow), then\n+attributes to files that are particular to\n+one user's workflow for that repository), then\n attributes should be placed in the `$GIT_DIR/info/attributes` file.\n Attributes which should be version-controlled and distributed to other\n repositories (i.e., attributes of interest to all users) should go into\n-`.gitattributes` files.\n+`.gitattributes` files. Attributes that should affect all repositories\n+for a single user should be placed in a file specified by the\n+`core.attributesfile` configuration option (see linkgit:git-config[1]).\n+Attributes for all users on a system should be placed in the\n+`$(prefix)/etc/gitattributes` file.\n \n Sometimes you would need to override an setting of an attribute\n for a path to `unspecified` state.  This can be done by listing\ndiff --git a/Makefile b/Makefile\nindex b4745a5..fdb7b4e 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -268,6 +268,7 @@ STRIP ?= strip\n #   infodir\n #   htmldir\n #   ETC_GITCONFIG (but not sysconfdir)\n+#   ETC_GITATTRIBUTES\n # can be specified as a relative path some/where/else;\n # this is interpreted as relative to $(prefix) and \"git\" at\n # runtime figures out where they are based on the path to the executable.\n@@ -286,9 +287,11 @@ htmldir = share/doc/git-doc\n ifeq ($(prefix),/usr)\n sysconfdir = /etc\n ETC_GITCONFIG = $(sysconfdir)/gitconfig\n+ETC_GITATTRIBUTES = $(sysconfdir)/gitattributes\n else\n sysconfdir = $(prefix)/etc\n ETC_GITCONFIG = etc/gitconfig\n+ETC_GITATTRIBUTES = etc/gitattributes\n endif\n lib = lib\n # DESTDIR=\n@@ -1502,6 +1505,7 @@ endif\n \n SHA1_HEADER_SQ = $(subst ','\\'',$(SHA1_HEADER))\n ETC_GITCONFIG_SQ = $(subst ','\\'',$(ETC_GITCONFIG))\n+ETC_GITATTRIBUTES_SQ = $(subst ','\\'',$(ETC_GITATTRIBUTES))\n \n DESTDIR_SQ = $(subst ','\\'',$(DESTDIR))\n bindir_SQ = $(subst ','\\'',$(bindir))\n@@ -1873,6 +1877,8 @@ builtin/init-db.s builtin/init-db.o: EXTRA_CPPFLAGS = \\\n \n config.s config.o: EXTRA_CPPFLAGS = -DETC_GITCONFIG='\"$(ETC_GITCONFIG_SQ)\"'\n \n+attr.s attr.o: EXTRA_CPPFLAGS = -DETC_GITATTRIBUTES='\"$(ETC_GITATTRIBUTES_SQ)\"'\n+\n http.s http.o: EXTRA_CPPFLAGS = -DGIT_HTTP_USER_AGENT='\"git/$(GIT_VERSION)\"'\n \n ifdef NO_EXPAT\ndiff --git a/attr.c b/attr.c\nindex 8ba606c..342791a 100644\n--- a/attr.c\n+++ b/attr.c\n@@ -1,5 +1,6 @@\n #define NO_THE_INDEX_COMPATIBILITY_MACROS\n #include \"cache.h\"\n+#include \"exec_cmd.h\"\n #include \"attr.h\"\n \n const char git_attr__true[] = \"(builtin)true\";\n@@ -462,6 +463,24 @@ static void drop_attr_stack(void)\n \t}\n }\n \n+const char *git_etc_gitattributes(void)\n+{\n+\tstatic const char *system_wide;\n+\tif (!system_wide)\n+\t\tsystem_wide = system_path(ETC_GITATTRIBUTES);\n+\treturn system_wide;\n+}\n+\n+int git_attr_system(void)\n+{\n+\treturn !git_env_bool(\"GIT_ATTR_NOSYSTEM\", 0);\n+}\n+\n+int git_attr_global(void)\n+{\n+\treturn !git_env_bool(\"GIT_ATTR_NOGLOBAL\", 0);\n+}\n+\n static void bootstrap_attr_stack(void)\n {\n \tif (!attr_stack) {\n@@ -472,6 +491,25 @@ static void bootstrap_attr_stack(void)\n \t\telem->prev = attr_stack;\n \t\tattr_stack = elem;\n \n+\t\tif (git_attr_system()) {\n+\t\t\telem = read_attr_from_file(git_etc_gitattributes(), 1);\n+\t\t\tif (elem) {\n+\t\t\t\telem->origin = NULL;\n+\t\t\t\telem->prev = attr_stack;\n+\t\t\t\tattr_stack = elem;\n+\t\t\t}\n+\t\t}\n+\n+\t\tgit_config(git_default_config, NULL);\n+\t\tif (git_attr_global() && attributes_file) {\n+\t\t\telem = read_attr_from_file(attributes_file, 1);\n+\t\t\tif (elem) {\n+\t\t\t\telem->origin = NULL;\n+\t\t\t\telem->prev = attr_stack;\n+\t\t\t\tattr_stack = elem;\n+\t\t\t}\n+\t\t}\n+\n \t\tif (!is_bare_repository() || direction == GIT_ATTR_INDEX) {\n \t\t\telem = read_attr(GITATTRIBUTES_FILE, 1);\n \t\t\telem->origin = strdup(\"\");\n@@ -499,7 +537,9 @@ static void prepare_attr_stack(const char *path, int dirlen)\n \n \t/*\n \t * At the bottom of the attribute stack is the built-in\n-\t * set of attribute definitions.  Then, contents from\n+\t * set of attribute definitions, followed by the contents\n+\t * of $(prefix)/etc/gitattributes and a file specified by\n+\t * core.attributesfile.  Then, contents from\n \t * .gitattribute files from directories closer to the\n \t * root to the ones in deeper directories are pushed\n \t * to the stack.  Finally, at the very top of the stack\ndiff --git a/cache.h b/cache.h\nindex eb77e1d..28d9497 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -1033,6 +1033,7 @@ extern int pager_use_color;\n \n extern const char *editor_program;\n extern const char *excludes_file;\n+extern const char *attributes_file;\n \n /* base85 */\n int decode_85(char *dst, const char *line, int linelen);\ndiff --git a/config.c b/config.c\nindex cdcf583..f602cd4 100644\n--- a/config.c\n+++ b/config.c\n@@ -563,6 +563,9 @@ static int git_default_core_config(const char *var, const char *value)\n \tif (!strcmp(var, \"core.excludesfile\"))\n \t\treturn git_config_pathname(&excludes_file, var, value);\n \n+\tif (!strcmp(var, \"core.attributesfile\"))\n+\t\treturn git_config_pathname(&attributes_file, var, value);\n+\n \tif (!strcmp(var, \"core.whitespace\")) {\n \t\tif (!value)\n \t\t\treturn config_error_nonbool(var);\ndiff --git a/configure.ac b/configure.ac\nindex 5601e8b..c5b3a41 100644\n--- a/configure.ac\n+++ b/configure.ac\n@@ -282,7 +282,15 @@ GIT_PARSE_WITH(iconv))\n GIT_PARSE_WITH_SET_MAKE_VAR(gitconfig, ETC_GITCONFIG,\n \t\t\tUse VALUE instead of /etc/gitconfig as the\n \t\t\tglobal git configuration file.\n-\t\t\tIf VALUE is not fully qualified it will be interpretted\n+\t\t\tIf VALUE is not fully qualified it will be interpreted\n+\t\t\tas a path relative to the computed prefix at runtime.)\n+\n+#\n+# Allow user to set ETC_GITATTRIBUTES variable\n+GIT_PARSE_WITH_SET_MAKE_VAR(gitattributes, ETC_GITATTRIBUTES,\n+\t\t\tUse VALUE instead of /etc/gitattributes as the\n+\t\t\tglobal git attributes file.\n+\t\t\tIf VALUE is not fully qualified it will be interpreted\n \t\t\tas a path relative to the computed prefix at runtime.)\n \n #\ndiff --git a/environment.c b/environment.c\nindex 83d38d3..58f719a 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -38,6 +38,7 @@ const char *pager_program;\n int pager_use_color = 1;\n const char *editor_program;\n const char *excludes_file;\n+const char *attributes_file;\n enum auto_crlf auto_crlf = AUTO_CRLF_FALSE;\n int read_replace_refs = 1;\n enum eol eol = EOL_UNSET;\ndiff --git a/t/t0003-attributes.sh b/t/t0003-attributes.sh\nindex 53bd7fc..7fe3b49 100755\n--- a/t/t0003-attributes.sh\n+++ b/t/t0003-attributes.sh\n@@ -15,6 +15,7 @@ attr_check () {\n \n }\n \n+HOME=$(pwd)\n \n test_expect_success 'setup' '\n \n@@ -36,6 +37,9 @@ test_expect_success 'setup' '\n \t\techo \"d/* test=a/b/d/*\"\n \t\techo \"d/yes notest\"\n \t) >a/b/.gitattributes\n+\t(\n+\t\techo \"global test=global\"\n+\t) >$HOME/global-gitattributes\n \n '\n \n@@ -57,6 +61,16 @@ test_expect_success 'attribute test' '\n \n '\n \n+test_expect_success 'core.attributesfile' '\n+\tattr_check global unspecified &&\n+\tgit config core.attributesfile \"$HOME/global-gitattributes\" &&\n+\tattr_check global global &&\n+\tgit config core.attributesfile \"~/global-gitattributes\" &&\n+\tattr_check global global &&\n+\techo \"global test=precedence\" >> .gitattributes &&\n+\tattr_check global precedence\n+'\n+\n test_expect_success 'attribute test: read paths from stdin' '\n \n \tcat <<EOF > expect\n-- \n1.7.1\n"},{"id":"149279","messageId":"7vy6bohde7.fsf@alter.siamese.dyndns.org","threadId":"24703","inReplyTo":"vpqbp8mskv1.fsf@bauges.imag.fr","subject":"Re: [PATCH v2] Add global and system-wide gitattributes","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-08-30T05:34:40Z","receivedAt":"2010-08-30T05:34:40Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Matthieu Moy <Matthieu.Moy@grenoble-inp.fr> writes:\n\n> Štěpán Němec <stepnem@gmail.com> writes:\n>\n>> Petr Onderka <gsvick@gmail.com> writes:\n>>\n>>> Allow gitattributes to be set globally and system wide. This way, settings\n>>> for particular file types can be set in one place and apply for all user's\n>>> repositories.\n>>\n>> [...]\n>>\n>> I really can't wait till this gets into Git and I'm certainly not the\n>> only one (thank you so much for working on it, Petr!).\n>\n> Same here ;-).\n>\n>> Any reason the patch still hasn't been applied?\n>\n> Usually, patches are applied if either\n>\n> 1) Junio has personal interest in it, or\n>\n> 2) Other people review the code and show interest for it.\n\n(1) is a bit more subtle than that.  Even when I do not foresee using a\nproposed feature myself, if I can imagine somebody else would benefit, and\nmore importantly if I can see a healthy rationale behind the change so\nthat I can convince myself to be an advocate of that change to the end\nusers, such a change will fall into category (1).  That is why I often ask\npeople to justify their changes better than they originally do.\n\nIsn't the patch in question on 'pu' to be tried by interested parties\nalready?\n"},{"id":"149290","messageId":"7vzkw4edc5.fsf@alter.siamese.dyndns.org","threadId":"24703","inReplyTo":"87fwxxhfpp.fsf_-_@gmail.com","subject":"Re: [PATCH v3?] Add global and system-wide gitattributes","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-08-30T08:04:10Z","receivedAt":"2010-08-30T08:04:10Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Štěpán Němec <stepnem@gmail.com> writes:\n\n> Thanks, Matthieu!\n>\n> Petr's original patch doesn't apply cleanly due to a bogus context line\n> after a recent change in Makefile. For convenience, below is the updated\n> patch including Matthieu's changes applicable to current master.\n>\n> And FWIW (I didn't try to build the documentation, though):\n>\n> Tested-by: Štěpán Němec <stepnem@gmail.com>\n\nThanks, but this seems to break t8005 for whatever reason.\n\n> diff --git a/t/t0003-attributes.sh b/t/t0003-attributes.sh\n> index 53bd7fc..7fe3b49 100755\n> --- a/t/t0003-attributes.sh\n> +++ b/t/t0003-attributes.sh\n> @@ -15,6 +15,7 @@ attr_check () {\n>  \n>  }\n>  \n> +HOME=$(pwd)\n\nI see a few tests here and there that uses the test-trash directory as\nHOME; perhaps we should have done that in test-lib.sh to make our life\neasier?\n"},{"id":"149291","messageId":"vpqvd6sik0n.fsf@bauges.imag.fr","threadId":"24703","inReplyTo":"7vzkw4edc5.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH v3?] Add global and system-wide gitattributes","fromName":"Matthieu Moy","fromEmail":"matthieu.moy@grenoble-inp.fr","sentAt":"2010-08-30T08:26:16Z","receivedAt":"2010-08-30T08:26:16Z","isPatch":true,"sender":{"key":"matthieu.moy@grenoble-inp.fr","avatar":"https://gravatar.com/avatar/72c8a2705971a25dfaff23cece15130d405685845d911aedd5667ace277f3fc5?d=mp&s=160"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> Štěpán Němec <stepnem@gmail.com> writes:\n>\n>> Thanks, Matthieu!\n>>\n>> Petr's original patch doesn't apply cleanly due to a bogus context line\n>> after a recent change in Makefile. For convenience, below is the updated\n>> patch including Matthieu's changes applicable to current master.\n>>\n>> And FWIW (I didn't try to build the documentation, though):\n>>\n>> Tested-by: Štěpán Němec <stepnem@gmail.com>\n>\n> Thanks, but this seems to break t8005 for whatever reason.\n\nThe guilty line is\n\n  git_config(git_default_config, NULL);\n\n(t8005 passes if I remove it).\n\nI don't understand why this breaks the test. It seems blame\n--encoding=UTF-8 relies on the fact that the i18n section of the\nconfiguration is not loaded.\n\nAn obvious fix on our side is to squash the patch below into the\nprevious ones, to make sure the attributes code loads only the core\nconfiguration. OTOH, it seems to me that the blame code is very\nfragile, but I'm not familiar with this code to say whether and how it\nshould be fixed.\n\nAny other thoughts?\n\ndiff --git a/attr.c b/attr.c\nindex 342791a..793a835 100644\n--- a/attr.c\n+++ b/attr.c\n@@ -500,7 +500,7 @@ static void bootstrap_attr_stack(void)\n                        }\n                }\n \n-               git_config(git_default_config, NULL);\n+               git_config(git_core_config, NULL);\n                if (git_attr_global() && attributes_file) {\n                        elem = read_attr_from_file(attributes_file, 1);\n                        if (elem) {\ndiff --git a/cache.h b/cache.h\nindex 28d9497..2d0bfa0 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -972,6 +972,7 @@ extern int update_server_info(int);\n \n typedef int (*config_fn_t)(const char *, const char *, void *);\n extern int git_default_config(const char *, const char *, void *);\n+extern int git_core_config(const char *, const char *, void *);\n extern int git_config_from_file(config_fn_t fn, const char *, void *);\n extern int git_config_parse_parameter(const char *text);\n extern int git_config_from_parameters(config_fn_t fn, void *data);\ndiff --git a/config.c b/config.c\nindex f602cd4..a2d1df9 100644\n--- a/config.c\n+++ b/config.c\n@@ -602,6 +602,14 @@ static int git_default_core_config(const char *var, const char *value)\n        return 0;\n }\n \n+/* \n+ * Wrapper around git_default_core_config, with type acceptable as\n+ * argument to git_config(...)\n+ */\n+int git_core_config(const char *var, const char *value, void *dummy) {\n+       return git_default_core_config(var, value);\n+}\n+\n static int git_default_user_config(const char *var, const char *value)\n {\n        if (!strcmp(var, \"user.name\")) {\n\n\n-- \nMatthieu Moy\nhttp://www-verimag.imag.fr/~moy/\n"},{"id":"149293","messageId":"8739twh3gc.fsf@gmail.com","threadId":"24703","inReplyTo":"7vy6bohde7.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH v2] Add global and system-wide gitattributes","fromName":"Štěpán Němec","fromEmail":"stepnem@gmail.com","sentAt":"2010-08-30T09:09:23Z","receivedAt":"2010-08-30T09:09:23Z","isPatch":true,"sender":{"key":"stepnem@gmail.com","avatar":"https://avatars.githubusercontent.com/u/106838?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> Matthieu Moy <Matthieu.Moy@grenoble-inp.fr> writes:\n>\n>> Štěpán Němec <stepnem@gmail.com> writes:\n>>\n>>> Petr Onderka <gsvick@gmail.com> writes:\n>>>\n>>>> Allow gitattributes to be set globally and system wide. This way, settings\n>>>> for particular file types can be set in one place and apply for all user's\n>>>> repositories.\n>>>\n>>> [...]\n>>>\n>>> I really can't wait till this gets into Git and I'm certainly not the\n>>> only one (thank you so much for working on it, Petr!).\n>>\n>> Same here ;-).\n>>\n>>> Any reason the patch still hasn't been applied?\n>>\n\n[...]\n\n>\n> Isn't the patch in question on 'pu' to be tried by interested parties\n> already?\n\nI see it now, sorry for the confusion. I didn't check when I saw no\nresponse to the mail.\n\nŠtěpán\n"},{"id":"149296","messageId":"1283161842-22689-1-git-send-email-Matthieu.Moy@imag.fr","threadId":"24703","inReplyTo":"7vzkw4edc5.fsf@alter.siamese.dyndns.org","subject":"[PATCH] tests: factor HOME=$(pwd) in test-lib.sh","fromName":"Matthieu Moy","fromEmail":"matthieu.moy@imag.fr","sentAt":"2010-08-30T09:50:42Z","receivedAt":"2010-08-30T09:50:42Z","isPatch":true,"sender":{"key":"git@matthieu-moy.fr","avatar":"https://avatars.githubusercontent.com/u/14709?v=4"},"body":"The same pattern is used in many tests, and makes it easy for new ones to\nrely on $HOME being a trashable, clean, directory.\n\nSigned-off-by: Matthieu Moy <Matthieu.Moy@imag.fr>\n---\nJunio C Hamano <gitster@pobox.com> writes:\n\n>> --- a/t/t0003-attributes.sh\n>> +++ b/t/t0003-attributes.sh\n>> +HOME=$(pwd)\n>\n> I see a few tests here and there that uses the test-trash directory as\n> HOME; perhaps we should have done that in test-lib.sh to make our life\n> easier?\n\nI just mimicked what the other tests were doing, but doing it in\ntest-lib.sh makes sense, yes. That also prevents accidental\nmodification of the actual $HOME when writing buggy tests.\n\nThe test-suite still passes if I apply this, so it's probably as easy\nas it seems to be :-). The patch comes on top of mine for\n.gitattributes, to remove my HOME=$(pwd).\n\n t/lib-cvs.sh                    |    3 ---\n t/t0001-init.sh                 |    6 ------\n t/t0003-attributes.sh           |    2 --\n t/t5601-clone.sh                |    2 --\n t/t9130-git-svn-authors-file.sh |    2 --\n t/test-lib.sh                   |    3 +++\n 6 files changed, 3 insertions(+), 15 deletions(-)\n\ndiff --git a/t/lib-cvs.sh b/t/lib-cvs.sh\nindex 648d161..ad90364 100644\n--- a/t/lib-cvs.sh\n+++ b/t/lib-cvs.sh\n@@ -3,9 +3,6 @@\n . ./test-lib.sh\n \n unset CVS_SERVER\n-# for clean cvsps cache\n-HOME=$(pwd)\n-export HOME\n \n if ! type cvs >/dev/null 2>&1\n then\ndiff --git a/t/t0001-init.sh b/t/t0001-init.sh\nindex 7c0a698..0543723 100755\n--- a/t/t0001-init.sh\n+++ b/t/t0001-init.sh\n@@ -171,8 +171,6 @@ test_expect_success 'init with init.templatedir set' '\n \tmkdir templatedir-source &&\n \techo Content >templatedir-source/file &&\n \t(\n-\t\tHOME=\"`pwd`\" &&\n-\t\texport HOME &&\n \t\ttest_config=\"${HOME}/.gitconfig\" &&\n \t\tgit config -f \"$test_config\"  init.templatedir \"${HOME}/templatedir-source\" &&\n \t\tmkdir templatedir-set &&\n@@ -188,8 +186,6 @@ test_expect_success 'init with init.templatedir set' '\n \n test_expect_success 'init --bare/--shared overrides system/global config' '\n \t(\n-\t\tHOME=\"`pwd`\" &&\n-\t\texport HOME &&\n \t\ttest_config=\"$HOME\"/.gitconfig &&\n \t\tunset GIT_CONFIG_NOGLOBAL &&\n \t\tgit config -f \"$test_config\" core.bare false &&\n@@ -205,8 +201,6 @@ test_expect_success 'init --bare/--shared overrides system/global config' '\n \n test_expect_success 'init honors global core.sharedRepository' '\n \t(\n-\t\tHOME=\"`pwd`\" &&\n-\t\texport HOME &&\n \t\ttest_config=\"$HOME\"/.gitconfig &&\n \t\tunset GIT_CONFIG_NOGLOBAL &&\n \t\tgit config -f \"$test_config\" core.sharedRepository 0666 &&\ndiff --git a/t/t0003-attributes.sh b/t/t0003-attributes.sh\nindex 24286e5..b884bb7 100755\n--- a/t/t0003-attributes.sh\n+++ b/t/t0003-attributes.sh\n@@ -15,8 +15,6 @@ attr_check () {\n \n }\n \n-HOME=$(pwd)\n-\n test_expect_success 'setup' '\n \n \tmkdir -p a/b/d a/c &&\ndiff --git a/t/t5601-clone.sh b/t/t5601-clone.sh\nindex 8abb71a..8617965 100755\n--- a/t/t5601-clone.sh\n+++ b/t/t5601-clone.sh\n@@ -163,8 +163,6 @@ test_expect_success 'clone a void' '\n \n test_expect_success 'clone respects global branch.autosetuprebase' '\n \t(\n-\t\tHOME=$(pwd) &&\n-\t\texport HOME &&\n \t\ttest_config=\"$HOME/.gitconfig\" &&\n \t\tunset GIT_CONFIG_NOGLOBAL &&\n \t\tgit config -f \"$test_config\" branch.autosetuprebase remote &&\ndiff --git a/t/t9130-git-svn-authors-file.sh b/t/t9130-git-svn-authors-file.sh\nindex 3c4f319..ec0a106 100755\n--- a/t/t9130-git-svn-authors-file.sh\n+++ b/t/t9130-git-svn-authors-file.sh\n@@ -95,8 +95,6 @@ test_expect_success 'fresh clone with svn.authors-file in config' '\n \t(\n \t\trm -r \"$GIT_DIR\" &&\n \t\ttest x = x\"$(git config svn.authorsfile)\" &&\n-\t\tHOME=\"`pwd`\" &&\n-\t\texport HOME &&\n \t\ttest_config=\"$HOME\"/.gitconfig &&\n \t\tunset GIT_CONFIG_NOGLOBAL &&\n \t\tunset GIT_DIR &&\ndiff --git a/t/test-lib.sh b/t/test-lib.sh\nindex 3a3d4c4..4eff908 100644\n--- a/t/test-lib.sh\n+++ b/t/test-lib.sh\n@@ -861,6 +861,9 @@ test_create_repo \"$test\"\n # in subprocesses like git equals our $PWD (for pathname comparisons).\n cd -P \"$test\" || exit 1\n \n+HOME=$(pwd)\n+export HOME\n+\n this_test=${0##*/}\n this_test=${this_test%%-*}\n for skp in $GIT_SKIP_TESTS\n-- \n1.7.2.2.175.ga619d.dirty\n"},{"id":"149297","messageId":"AANLkTi=81oEPHko45Mo2d1qn+qWy-TVLvrFcXaVKd8Lu@mail.gmail.com","threadId":"24703","inReplyTo":"1283161842-22689-1-git-send-email-Matthieu.Moy@imag.fr","subject":"Re: [PATCH] tests: factor HOME=$(pwd) in test-lib.sh","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2010-08-30T10:22:50Z","receivedAt":"2010-08-30T10:22:50Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"On Mon, Aug 30, 2010 at 09:50, Matthieu Moy <Matthieu.Moy@imag.fr> wrote:\n> The same pattern is used in many tests, and makes it easy for new ones to\n> rely on $HOME being a trashable, clean, directory.\n\nLooks good, but why not:\n\n> +HOME=$(pwd)\n> +export HOME\n\nThis instead:\n\nHOME=$TRASH_DIRECTORY\nexport HOME\n\nLooks like it might be more correct given this (always an absolute\npath), but I haven't tested:\n\ncase \"$test\" in\n/*) TRASH_DIRECTORY=\"$test\" ;;\n *) TRASH_DIRECTORY=\"$TEST_DIRECTORY/$test\" ;;\nesac\n"},{"id":"149298","messageId":"vpqtymcs74z.fsf@bauges.imag.fr","threadId":"24703","inReplyTo":"AANLkTi=81oEPHko45Mo2d1qn+qWy-TVLvrFcXaVKd8Lu@mail.gmail.com","subject":"Re: [PATCH] tests: factor HOME=$(pwd) in test-lib.sh","fromName":"Matthieu Moy","fromEmail":"matthieu.moy@grenoble-inp.fr","sentAt":"2010-08-30T10:54:20Z","receivedAt":"2010-08-30T10:54:20Z","isPatch":true,"sender":{"key":"matthieu.moy@grenoble-inp.fr","avatar":"https://gravatar.com/avatar/72c8a2705971a25dfaff23cece15130d405685845d911aedd5667ace277f3fc5?d=mp&s=160"},"body":"Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:\n\n> On Mon, Aug 30, 2010 at 09:50, Matthieu Moy <Matthieu.Moy@imag.fr> wrote:\n>> The same pattern is used in many tests, and makes it easy for new ones to\n>> rely on $HOME being a trashable, clean, directory.\n>\n> Looks good, but why not:\n>\n>> +HOME=$(pwd)\n>> +export HOME\n>\n> This instead:\n>\n> HOME=$TRASH_DIRECTORY\n> export HOME\n>\n> Looks like it might be more correct given this (always an absolute\n> path), but I haven't tested:\n\nThat should work too, but with your version, I have to think harder to\nmake sure $TRASH_DIRECTORY is absolute (that should be OK), and won't\nmake any issue with symlinks (I have no idea whether it is OK or not),\nwhile it's trivially correct with mine (pwd is absolute, and the -P\noption of the cd command right above prevents issue with symlinks).\n\n-- \nMatthieu Moy\nhttp://www-verimag.imag.fr/~moy/\n"},{"id":"149300","messageId":"AANLkTin=RG-48wPc2sUr+6-Tezgr4MhKfOqn3a3se52m@mail.gmail.com","threadId":"24703","inReplyTo":"vpqtymcs74z.fsf@bauges.imag.fr","subject":"Re: [PATCH] tests: factor HOME=$(pwd) in test-lib.sh","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2010-08-30T11:08:20Z","receivedAt":"2010-08-30T11:08:20Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"On Mon, Aug 30, 2010 at 10:54, Matthieu Moy\n<Matthieu.Moy@grenoble-inp.fr> wrote:\n> Ęvar Arnfjörš Bjarmason <avarab@gmail.com> writes:\n>\n>> On Mon, Aug 30, 2010 at 09:50, Matthieu Moy <Matthieu.Moy@imag.fr> wrote:\n>>> The same pattern is used in many tests, and makes it easy for new ones to\n>>> rely on $HOME being a trashable, clean, directory.\n>>\n>> Looks good, but why not:\n>>\n>>> +HOME=$(pwd)\n>>> +export HOME\n>>\n>> This instead:\n>>\n>> HOME=$TRASH_DIRECTORY\n>> export HOME\n>>\n>> Looks like it might be more correct given this (always an absolute\n>> path), but I haven't tested:\n>\n> That should work too, but with your version, I have to think harder to\n> make sure $TRASH_DIRECTORY is absolute (that should be OK), and won't\n> make any issue with symlinks (I have no idea whether it is OK or not),\n> while it's trivially correct with mine (pwd is absolute, and the -P\n> option of the cd command right above prevents issue with symlinks).\n\nI don't know what's best here (and I didn't look hard at this).\n\nbut I recently brought down the number of $(pwd) invocations in\ntest-lib.sh down to exactly 1, so everything that comes later is now\ndefined in terms of that pwd invocation.\n\nDefining everything that comes afterwards in terms of that pwd might\nbe clearer.\n\nBut it's a trivial issue.\n"},{"id":"149359","messageId":"7voccjesk7.fsf@alter.siamese.dyndns.org","threadId":"24703","inReplyTo":"vpqvd6sik0n.fsf@bauges.imag.fr","subject":"Re: [PATCH v3?] Add global and system-wide gitattributes","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-08-30T20:47:36Z","receivedAt":"2010-08-30T20:47:36Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Matthieu Moy <Matthieu.Moy@grenoble-inp.fr> writes:\n\n> I don't understand why this breaks the test. It seems blame\n> --encoding=UTF-8 relies on the fact that the i18n section of the\n> configuration is not loaded.\n\nThat's interesting; I haven't traced the codepath involved, but I do not\nthink \"configuration is not loaded\" is the issue. \"Reading either before\nthe main codepath is ready, or more likely overwriting/destroying what the\nmain codepath has read it by re-reading the configuration\" may be.\n\nPerhaps the part that reads encoding configuration is busted and is not\nexpected to be called way early or way late.  In short, this patch\nintroduces uncertainty that config reader is called at a random and\nunexpected (from the existing code's point of view) place in the codepath,\nand I wouldn't be very surprised if there are similar breakages introduced\nby it.\n\nWhat does the callchain look like when we bootstrap the attr stack for the\nfirst time with this patch applied?  Have we already located where the git\nrepository is?  Has the main codepath that wants to read encoding settings\nread them?  Has the main codepath already used the command line option\nthat overrides the settings it obtained from the configuration file?  Is\nthe extra reading of the config destroying that data?\n\nI am afraid that your patch to narrow the parts of the config that is read\nfrom this codepath is only sweeping the problem under the rug, making the\nissue harder to diagnose.  Wouldn't we see exactly the same issue if some\ncodepath (other than blame) wants to see a core.* configuration not to be\nread in this codepath for whatever reason?\n"},{"id":"149360","messageId":"7vbp8jerfq.fsf@alter.siamese.dyndns.org","threadId":"24703","inReplyTo":"7voccjesk7.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH v3?] Add global and system-wide gitattributes","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-08-30T21:11:53Z","receivedAt":"2010-08-30T21:11:53Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> Matthieu Moy <Matthieu.Moy@grenoble-inp.fr> writes:\n>\n>> I don't understand why this breaks the test. It seems blame\n>> --encoding=UTF-8 relies on the fact that the i18n section of the\n>> configuration is not loaded.\n>\n> That's interesting; I haven't traced the codepath involved, but I do not\n> think \"configuration is not loaded\" is the issue. \"Reading either before\n> the main codepath is ready, or more likely overwriting/destroying what the\n> main codepath has read it by re-reading the configuration\" may be.\n\nI think that hunch is correct.  A typical way we default to hardcoded\nvalue, overridable by configuration file, and then further use command\nline to override that, is for the main codepath to do the following in\nthis order:\n\n - call git_config(git_appropriate_config); this changes the variables\n   (with possibly hardcoded default) defined in environment.c;\n\n - parse command line options and override the variable;\n\n - use the variable at runtime.\n\nThis obviously relies on the main codepath having _total_ control of the\ncalls made to git_config().  If you call git_config(git_default_config)\nwhen an attribute is asked for for the first time (which would be way\nafter all of the above happened) behind the main codepath's back, you will\nof course break things.  In the \"blame\" case, aren't you stomping on\ngit_log_output_encoding?\n\nThe correct solution would be twofold, but the latter is rather painful:\n\n - The call from the bootstrap_attr_stack should use a callback that reads\n   only the attribute file location configuration and _nothing else_.\n\n   Also I do not think the parsing of this configuration variable needs to\n   be in git_default_config() to begin with, if you are reading it from\n   the bootstrap codepath on demand anyway, and not relying on the main\n   codepath of any particular program to be calling on git_config().\n\n - The way programs (this is not limited to blame and other rev-list\n   machinery users) implement the \"use configured values but let command\n   line override them\" need to be changed.\n   \n   One possibility is to copy the values determined by reading the config\n   and the command line to their own variables, so that later random call\n   to git_config() won't stomp on the actual values to be used.  This is\n   painful as environment.c variables are _meant_ to be easily usable as\n   global variables and copying them away (which means they now need to be\n   passed around throughout the callchain in the various APIs) defeats\n   the whole point of having them.\n"},{"id":"149383","messageId":"vpqhbibbthi.fsf@bauges.imag.fr","threadId":"24703","inReplyTo":"7vbp8jerfq.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH v3?] Add global and system-wide gitattributes","fromName":"Matthieu Moy","fromEmail":"matthieu.moy@grenoble-inp.fr","sentAt":"2010-08-30T22:55:53Z","receivedAt":"2010-08-30T22:55:53Z","isPatch":true,"sender":{"key":"matthieu.moy@grenoble-inp.fr","avatar":"https://gravatar.com/avatar/72c8a2705971a25dfaff23cece15130d405685845d911aedd5667ace277f3fc5?d=mp&s=160"},"body":"Junio C Hamano <gitster@pobox.com> writes:\n\n> Junio C Hamano <gitster@pobox.com> writes:\n>\n>> Matthieu Moy <Matthieu.Moy@grenoble-inp.fr> writes:\n>>\n>>> I don't understand why this breaks the test. It seems blame\n>>> --encoding=UTF-8 relies on the fact that the i18n section of the\n>>> configuration is not loaded.\n>>\n>> That's interesting; I haven't traced the codepath involved, but I do not\n>> think \"configuration is not loaded\" is the issue. \"Reading either before\n>> the main codepath is ready, or more likely overwriting/destroying what the\n>> main codepath has read it by re-reading the configuration\" may be.\n>\n> I think that hunch is correct.\n\nConfirmed.\n\n> A typical way we default to hardcoded value, overridable by\n> configuration file, and then further use command line to override\n> that, is for the main codepath to do the following in this order:\n>\n>  - call git_config(git_appropriate_config); this changes the variables\n>    (with possibly hardcoded default) defined in environment.c;\n>\n>  - parse command line options and override the variable;\n>\n>  - use the variable at runtime.\n\nYes, this is the problem, with git_log_output_encoding as you guessed.\n\n> The correct solution would be twofold, but the latter is rather painful:\n\nNot that much in the case of git_log_output_encoding, but other uses\nof the same pattern may exist.\n\n>  - The call from the bootstrap_attr_stack should use a callback that reads\n>    only the attribute file location configuration and _nothing else_.\n[...]\n>  - The way programs (this is not limited to blame and other rev-list\n>    machinery users) implement the \"use configured values but let command\n>    line override them\" need to be changed.\n\nI think it's reasonable to do both. Having both git_config() and\ncommand-line parsing write to the same variable is fragile and should\nbe avoided IMHO, but OTOH, arbitrary calls to\ngit_config(git_default_config) may break other things, so ...\n\n>    One possibility is to copy the values determined by reading the config\n>    and the command line to their own variables, so that later random call\n>    to git_config() won't stomp on the actual values to be used.  This is\n>    painful as environment.c variables are _meant_ to be easily usable as\n>    global variables and copying them away (which means they now need to be\n>    passed around throughout the callchain in the various APIs) defeats\n>    the whole point of having them.\n\nI just keep two global variables instead of two, and implement a\nstraightforward accessor. Command-line option parsing already used to\nwrite to a global variable, so it doesn't change much.\n\nNew patch serie follows,\n\n-- \nMatthieu Moy\nhttp://www-verimag.imag.fr/~moy/\n"},{"id":"149386","messageId":"1283210123-19752-1-git-send-email-Matthieu.Moy@imag.fr","threadId":"24703","inReplyTo":"vpqhbibbthi.fsf@bauges.imag.fr","subject":"[PATCH 1/3 v2] tests: factor HOME=$(pwd) in test-lib.sh","fromName":"Matthieu Moy","fromEmail":"matthieu.moy@imag.fr","sentAt":"2010-08-30T23:15:21Z","receivedAt":"2010-08-30T23:15:21Z","isPatch":true,"sender":{"key":"git@matthieu-moy.fr","avatar":"https://avatars.githubusercontent.com/u/14709?v=4"},"body":"The same pattern is used in many tests, and makes it easy for new ones to\nrely on $HOME being a trashable, clean, directory.\n\nSigned-off-by: Matthieu Moy <Matthieu.Moy@imag.fr>\n---\nJust re-ordered the patch to make this one the first.\n\nI took Ævar's suggestion of using $TRASH_DIRECTORY instead of $(pwd).\n\n t/lib-cvs.sh                    |    3 ---\n t/t0001-init.sh                 |    6 ------\n t/t0003-attributes.sh           |    1 -\n t/t5601-clone.sh                |    2 --\n t/t9130-git-svn-authors-file.sh |    2 --\n t/test-lib.sh                   |    3 +++\n 6 files changed, 3 insertions(+), 14 deletions(-)\n\ndiff --git a/t/lib-cvs.sh b/t/lib-cvs.sh\nindex 648d161..ad90364 100644\n--- a/t/lib-cvs.sh\n+++ b/t/lib-cvs.sh\n@@ -3,9 +3,6 @@\n . ./test-lib.sh\n \n unset CVS_SERVER\n-# for clean cvsps cache\n-HOME=$(pwd)\n-export HOME\n \n if ! type cvs >/dev/null 2>&1\n then\ndiff --git a/t/t0001-init.sh b/t/t0001-init.sh\nindex 7c0a698..0543723 100755\n--- a/t/t0001-init.sh\n+++ b/t/t0001-init.sh\n@@ -171,8 +171,6 @@ test_expect_success 'init with init.templatedir set' '\n \tmkdir templatedir-source &&\n \techo Content >templatedir-source/file &&\n \t(\n-\t\tHOME=\"`pwd`\" &&\n-\t\texport HOME &&\n \t\ttest_config=\"${HOME}/.gitconfig\" &&\n \t\tgit config -f \"$test_config\"  init.templatedir \"${HOME}/templatedir-source\" &&\n \t\tmkdir templatedir-set &&\n@@ -188,8 +186,6 @@ test_expect_success 'init with init.templatedir set' '\n \n test_expect_success 'init --bare/--shared overrides system/global config' '\n \t(\n-\t\tHOME=\"`pwd`\" &&\n-\t\texport HOME &&\n \t\ttest_config=\"$HOME\"/.gitconfig &&\n \t\tunset GIT_CONFIG_NOGLOBAL &&\n \t\tgit config -f \"$test_config\" core.bare false &&\n@@ -205,8 +201,6 @@ test_expect_success 'init --bare/--shared overrides system/global config' '\n \n test_expect_success 'init honors global core.sharedRepository' '\n \t(\n-\t\tHOME=\"`pwd`\" &&\n-\t\texport HOME &&\n \t\ttest_config=\"$HOME\"/.gitconfig &&\n \t\tunset GIT_CONFIG_NOGLOBAL &&\n \t\tgit config -f \"$test_config\" core.sharedRepository 0666 &&\ndiff --git a/t/t0003-attributes.sh b/t/t0003-attributes.sh\nindex de38c7f..114967a 100755\n--- a/t/t0003-attributes.sh\n+++ b/t/t0003-attributes.sh\n@@ -15,7 +15,6 @@ attr_check () {\n \n }\n \n-\n test_expect_success 'setup' '\n \n \tmkdir -p a/b/d a/c &&\ndiff --git a/t/t5601-clone.sh b/t/t5601-clone.sh\nindex 8abb71a..8617965 100755\n--- a/t/t5601-clone.sh\n+++ b/t/t5601-clone.sh\n@@ -163,8 +163,6 @@ test_expect_success 'clone a void' '\n \n test_expect_success 'clone respects global branch.autosetuprebase' '\n \t(\n-\t\tHOME=$(pwd) &&\n-\t\texport HOME &&\n \t\ttest_config=\"$HOME/.gitconfig\" &&\n \t\tunset GIT_CONFIG_NOGLOBAL &&\n \t\tgit config -f \"$test_config\" branch.autosetuprebase remote &&\ndiff --git a/t/t9130-git-svn-authors-file.sh b/t/t9130-git-svn-authors-file.sh\nindex 3c4f319..ec0a106 100755\n--- a/t/t9130-git-svn-authors-file.sh\n+++ b/t/t9130-git-svn-authors-file.sh\n@@ -95,8 +95,6 @@ test_expect_success 'fresh clone with svn.authors-file in config' '\n \t(\n \t\trm -r \"$GIT_DIR\" &&\n \t\ttest x = x\"$(git config svn.authorsfile)\" &&\n-\t\tHOME=\"`pwd`\" &&\n-\t\texport HOME &&\n \t\ttest_config=\"$HOME\"/.gitconfig &&\n \t\tunset GIT_CONFIG_NOGLOBAL &&\n \t\tunset GIT_DIR &&\ndiff --git a/t/test-lib.sh b/t/test-lib.sh\nindex 3a3d4c4..8e90f43 100644\n--- a/t/test-lib.sh\n+++ b/t/test-lib.sh\n@@ -861,6 +861,9 @@ test_create_repo \"$test\"\n # in subprocesses like git equals our $PWD (for pathname comparisons).\n cd -P \"$test\" || exit 1\n \n+HOME=\"$TRASH_DIRECTORY\"\n+export HOME\n+\n this_test=${0##*/}\n this_test=${this_test%%-*}\n for skp in $GIT_SKIP_TESTS\n-- \n1.7.2.2.175.ga619d.dirty\n"},{"id":"149384","messageId":"1283210123-19752-2-git-send-email-Matthieu.Moy@imag.fr","threadId":"24703","inReplyTo":"vpqhbibbthi.fsf@bauges.imag.fr","subject":"[PATCH 2/3] don't write to git_log_output_encoding outside git_config()","fromName":"Matthieu Moy","fromEmail":"matthieu.moy@imag.fr","sentAt":"2010-08-30T23:15:22Z","receivedAt":"2010-08-30T23:15:22Z","isPatch":true,"sender":{"key":"git@matthieu-moy.fr","avatar":"https://avatars.githubusercontent.com/u/14709?v=4"},"body":"The log encoding can be given by the user either with --encoding=foo or\nwith i18n.logoutputencoding. The code dealing with this used to write to\ngit_log_output_encoding in both places, making sure that --encoding=foo\nis dealt with after reading the configuration file.\n\nThis is a very fragile mechanism, since any further call to\ngit_config(git_default_config, ...) the value given on the command line.\n\nInstead, keep the config value and the cli value, and decide which one to\ntake at read time (in the straightforward accessor\nget_git_log_output_encoding()).\n\nSigned-off-by: Matthieu Moy <Matthieu.Moy@imag.fr>\n---\nSo, this isn't strictly necessary since the new version of the patch\nimplementing the gitattributes file doesn't read the full config\nanymore, but I think that makes the code more robust.\n\n builtin/log.c |    4 ++--\n cache.h       |   18 ++++++++++++++++++\n environment.c |    4 +++-\n pretty.c      |    4 ++--\n revision.c    |    4 ++--\n 5 files changed, 27 insertions(+), 7 deletions(-)\n\ndiff --git a/builtin/log.c b/builtin/log.c\nindex eaa1ee0..f30a6ba 100644\n--- a/builtin/log.c\n+++ b/builtin/log.c\n@@ -329,8 +329,8 @@ static void show_tagger(char *buf, int len, struct rev_info *rev)\n \tstruct strbuf out = STRBUF_INIT;\n \n \tpp_user_info(\"Tagger\", rev->commit_format, &out, buf, rev->date_mode,\n-\t\tgit_log_output_encoding ?\n-\t\tgit_log_output_encoding: git_commit_encoding);\n+\t\tget_git_log_output_encoding() ?\n+\t\tget_git_log_output_encoding(): git_commit_encoding);\n \tprintf(\"%s\", out.buf);\n \tstrbuf_release(&out);\n }\ndiff --git a/cache.h b/cache.h\nindex eb77e1d..7e10a39 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -1005,7 +1005,25 @@ extern int user_ident_explicitly_given;\n extern int user_ident_sufficiently_given(void);\n \n extern const char *git_commit_encoding;\n+\n+/* Value found in config file */\n extern const char *git_log_output_encoding;\n+\n+/* Value given in command line with --encoding */\n+extern const char *git_log_output_encoding_cli;\n+\n+/* \n+ * Prioritize the value given by the command-line over the value found\n+ * in the config file.\n+ */\n+static inline\n+const char *get_git_log_output_encoding()\n+{\n+\treturn git_log_output_encoding_cli ?\n+\t\tgit_log_output_encoding_cli :\n+\t\tgit_log_output_encoding;\n+}\n+\n extern const char *git_mailmap_file;\n \n /* IO helper functions */\ndiff --git a/environment.c b/environment.c\nindex 83d38d3..212f086 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -23,7 +23,9 @@ int log_all_ref_updates = -1; /* unspecified */\n int warn_ambiguous_refs = 1;\n int repository_format_version;\n const char *git_commit_encoding;\n-const char *git_log_output_encoding;\n+const char *git_log_output_encoding = NULL;\n+const char *git_log_output_encoding_cli = NULL;\n+\n int shared_repository = PERM_UMASK;\n const char *apply_default_whitespace;\n const char *apply_default_ignorewhitespace;\ndiff --git a/pretty.c b/pretty.c\nindex f85444b..4187a50 100644\n--- a/pretty.c\n+++ b/pretty.c\n@@ -1159,8 +1159,8 @@ char *reencode_commit_message(const struct commit *commit, const char **encoding\n {\n \tconst char *encoding;\n \n-\tencoding = (git_log_output_encoding\n-\t\t    ? git_log_output_encoding\n+\tencoding = (get_git_log_output_encoding()\n+\t\t    ? get_git_log_output_encoding()\n \t\t    : git_commit_encoding);\n \tif (!encoding)\n \t\tencoding = \"UTF-8\";\ndiff --git a/revision.c b/revision.c\nindex b1c1890..791c757 100644\n--- a/revision.c\n+++ b/revision.c\n@@ -1402,9 +1402,9 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg\n \t\trevs->grep_filter.all_match = 1;\n \t} else if ((argcount = parse_long_opt(\"encoding\", argv, &optarg))) {\n \t\tif (strcmp(optarg, \"none\"))\n-\t\t\tgit_log_output_encoding = xstrdup(optarg);\n+\t\t\tgit_log_output_encoding_cli = xstrdup(optarg);\n \t\telse\n-\t\t\tgit_log_output_encoding = \"\";\n+\t\t\tgit_log_output_encoding_cli = \"\";\n \t\treturn argcount;\n \t} else if (!strcmp(arg, \"--reverse\")) {\n \t\trevs->reverse ^= 1;\n-- \n1.7.2.2.175.ga619d.dirty\n"},{"id":"149385","messageId":"1283210123-19752-3-git-send-email-Matthieu.Moy@imag.fr","threadId":"24703","inReplyTo":"vpqhbibbthi.fsf@bauges.imag.fr","subject":"[PATCH 3/3 v4] Add global and system-wide gitattributes","fromName":"Matthieu Moy","fromEmail":"matthieu.moy@imag.fr","sentAt":"2010-08-30T23:15:23Z","receivedAt":"2010-08-30T23:15:23Z","isPatch":true,"sender":{"key":"git@matthieu-moy.fr","avatar":"https://avatars.githubusercontent.com/u/14709?v=4"},"body":"From: Petr Onderka <gsvick@gmail.com>\n\nAllow gitattributes to be set globally and system wide. This way, settings\nfor particular file types can be set in one place and apply for all user's\nrepositories.\n\nThe location of system-wide attributes file is $(prefix)/etc/gitattributes.\nThe location of the global file can be configured by setting\ncore.attributesfile.\n\nSome parts of the code were copied from the implementation of the same\nfunctionality in config.c.\n\nSigned-off-by: Petr Onderka <gsvick@gmail.com>\nSigned-off-by: Matthieu Moy <Matthieu.Moy@imag.fr>\n---\nThis version doesn't touch config.c, and calls git_config with a\ntrivial callback reading only the core.attributesfile variable.\n\nThis time, I did run the whole testsuite ;-).\n\n Documentation/config.txt        |    6 ++++\n Documentation/gitattributes.txt |   13 +++++++--\n Makefile                        |    6 ++++\n attr.c                          |   50 ++++++++++++++++++++++++++++++++++++++-\n cache.h                         |    1 +\n configure.ac                    |   10 +++++++-\n environment.c                   |    1 +\n t/t0003-attributes.sh           |   13 ++++++++++\n 8 files changed, 95 insertions(+), 5 deletions(-)\n\ndiff --git a/Documentation/config.txt b/Documentation/config.txt\nindex 05ec3fe..0e15e72 100644\n--- a/Documentation/config.txt\n+++ b/Documentation/config.txt\n@@ -450,6 +450,12 @@ core.excludesfile::\n \tto the value of `$HOME` and \"{tilde}user/\" to the specified user's\n \thome directory.  See linkgit:gitignore[5].\n \n+core.attributesfile::\n+\tIn addition to '.gitattributes' (per-directory) and\n+\t'.git/info/attributes', git looks into this file for attributes\n+\t(see linkgit:gitattributes[5]). Path expansions are made the same\n+\tway as for `core.excludesfile`.\n+\n core.editor::\n \tCommands such as `commit` and `tag` that lets you edit\n \tmessages by launching an editor uses the value of this\ndiff --git a/Documentation/gitattributes.txt b/Documentation/gitattributes.txt\nindex 2e2370c..ebd4852 100644\n--- a/Documentation/gitattributes.txt\n+++ b/Documentation/gitattributes.txt\n@@ -62,14 +62,21 @@ consults `$GIT_DIR/info/attributes` file (which has the highest\n precedence), `.gitattributes` file in the same directory as the\n path in question, and its parent directories up to the toplevel of the\n work tree (the further the directory that contains `.gitattributes`\n-is from the path in question, the lower its precedence).\n+is from the path in question, the lower its precedence). Finally\n+global and system-wide files are considered (they have the lowest\n+precedence).\n \n If you wish to affect only a single repository (i.e., to assign\n-attributes to files that are particular to one user's workflow), then\n+attributes to files that are particular to\n+one user's workflow for that repository), then\n attributes should be placed in the `$GIT_DIR/info/attributes` file.\n Attributes which should be version-controlled and distributed to other\n repositories (i.e., attributes of interest to all users) should go into\n-`.gitattributes` files.\n+`.gitattributes` files. Attributes that should affect all repositories\n+for a single user should be placed in a file specified by the\n+`core.attributesfile` configuration option (see linkgit:git-config[1]).\n+Attributes for all users on a system should be placed in the\n+`$(prefix)/etc/gitattributes` file.\n \n Sometimes you would need to override an setting of an attribute\n for a path to `unspecified` state.  This can be done by listing\ndiff --git a/Makefile b/Makefile\nindex b4745a5..fdb7b4e 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -268,6 +268,7 @@ STRIP ?= strip\n #   infodir\n #   htmldir\n #   ETC_GITCONFIG (but not sysconfdir)\n+#   ETC_GITATTRIBUTES\n # can be specified as a relative path some/where/else;\n # this is interpreted as relative to $(prefix) and \"git\" at\n # runtime figures out where they are based on the path to the executable.\n@@ -286,9 +287,11 @@ htmldir = share/doc/git-doc\n ifeq ($(prefix),/usr)\n sysconfdir = /etc\n ETC_GITCONFIG = $(sysconfdir)/gitconfig\n+ETC_GITATTRIBUTES = $(sysconfdir)/gitattributes\n else\n sysconfdir = $(prefix)/etc\n ETC_GITCONFIG = etc/gitconfig\n+ETC_GITATTRIBUTES = etc/gitattributes\n endif\n lib = lib\n # DESTDIR=\n@@ -1502,6 +1505,7 @@ endif\n \n SHA1_HEADER_SQ = $(subst ','\\'',$(SHA1_HEADER))\n ETC_GITCONFIG_SQ = $(subst ','\\'',$(ETC_GITCONFIG))\n+ETC_GITATTRIBUTES_SQ = $(subst ','\\'',$(ETC_GITATTRIBUTES))\n \n DESTDIR_SQ = $(subst ','\\'',$(DESTDIR))\n bindir_SQ = $(subst ','\\'',$(bindir))\n@@ -1873,6 +1877,8 @@ builtin/init-db.s builtin/init-db.o: EXTRA_CPPFLAGS = \\\n \n config.s config.o: EXTRA_CPPFLAGS = -DETC_GITCONFIG='\"$(ETC_GITCONFIG_SQ)\"'\n \n+attr.s attr.o: EXTRA_CPPFLAGS = -DETC_GITATTRIBUTES='\"$(ETC_GITATTRIBUTES_SQ)\"'\n+\n http.s http.o: EXTRA_CPPFLAGS = -DGIT_HTTP_USER_AGENT='\"git/$(GIT_VERSION)\"'\n \n ifdef NO_EXPAT\ndiff --git a/attr.c b/attr.c\nindex 8ba606c..eeb80d3 100644\n--- a/attr.c\n+++ b/attr.c\n@@ -1,5 +1,6 @@\n #define NO_THE_INDEX_COMPATIBILITY_MACROS\n #include \"cache.h\"\n+#include \"exec_cmd.h\"\n #include \"attr.h\"\n \n const char git_attr__true[] = \"(builtin)true\";\n@@ -462,6 +463,32 @@ static void drop_attr_stack(void)\n \t}\n }\n \n+const char *git_etc_gitattributes(void)\n+{\n+\tstatic const char *system_wide;\n+\tif (!system_wide)\n+\t\tsystem_wide = system_path(ETC_GITATTRIBUTES);\n+\treturn system_wide;\n+}\n+\n+int git_attr_system(void)\n+{\n+\treturn !git_env_bool(\"GIT_ATTR_NOSYSTEM\", 0);\n+}\n+\n+int git_attr_global(void)\n+{\n+\treturn !git_env_bool(\"GIT_ATTR_NOGLOBAL\", 0);\n+}\n+\n+static int git_attr_config(const char *var, const char *value, void *dummy)\n+{\n+\tif (!strcmp(var, \"core.attributesfile\"))\n+\t\treturn git_config_pathname(&attributes_file, var, value);\n+\t\n+\treturn 0;\n+}\n+\n static void bootstrap_attr_stack(void)\n {\n \tif (!attr_stack) {\n@@ -472,6 +499,25 @@ static void bootstrap_attr_stack(void)\n \t\telem->prev = attr_stack;\n \t\tattr_stack = elem;\n \n+\t\tif (git_attr_system()) {\n+\t\t\telem = read_attr_from_file(git_etc_gitattributes(), 1);\n+\t\t\tif (elem) {\n+\t\t\t\telem->origin = NULL;\n+\t\t\t\telem->prev = attr_stack;\n+\t\t\t\tattr_stack = elem;\n+\t\t\t}\n+\t\t}\n+\n+\t\tgit_config(git_attr_config, NULL);\n+\t\tif (git_attr_global() && attributes_file) {\n+\t\t\telem = read_attr_from_file(attributes_file, 1);\n+\t\t\tif (elem) {\n+\t\t\t\telem->origin = NULL;\n+\t\t\t\telem->prev = attr_stack;\n+\t\t\t\tattr_stack = elem;\n+\t\t\t}\n+\t\t}\n+\n \t\tif (!is_bare_repository() || direction == GIT_ATTR_INDEX) {\n \t\t\telem = read_attr(GITATTRIBUTES_FILE, 1);\n \t\t\telem->origin = strdup(\"\");\n@@ -499,7 +545,9 @@ static void prepare_attr_stack(const char *path, int dirlen)\n \n \t/*\n \t * At the bottom of the attribute stack is the built-in\n-\t * set of attribute definitions.  Then, contents from\n+\t * set of attribute definitions, followed by the contents\n+\t * of $(prefix)/etc/gitattributes and a file specified by\n+\t * core.attributesfile.  Then, contents from\n \t * .gitattribute files from directories closer to the\n \t * root to the ones in deeper directories are pushed\n \t * to the stack.  Finally, at the very top of the stack\ndiff --git a/cache.h b/cache.h\nindex 7e10a39..4b6e424 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -1051,6 +1051,7 @@ extern int pager_use_color;\n \n extern const char *editor_program;\n extern const char *excludes_file;\n+extern const char *attributes_file;\n \n /* base85 */\n int decode_85(char *dst, const char *line, int linelen);\ndiff --git a/configure.ac b/configure.ac\nindex 5601e8b..c5b3a41 100644\n--- a/configure.ac\n+++ b/configure.ac\n@@ -282,7 +282,15 @@ GIT_PARSE_WITH(iconv))\n GIT_PARSE_WITH_SET_MAKE_VAR(gitconfig, ETC_GITCONFIG,\n \t\t\tUse VALUE instead of /etc/gitconfig as the\n \t\t\tglobal git configuration file.\n-\t\t\tIf VALUE is not fully qualified it will be interpretted\n+\t\t\tIf VALUE is not fully qualified it will be interpreted\n+\t\t\tas a path relative to the computed prefix at runtime.)\n+\n+#\n+# Allow user to set ETC_GITATTRIBUTES variable\n+GIT_PARSE_WITH_SET_MAKE_VAR(gitattributes, ETC_GITATTRIBUTES,\n+\t\t\tUse VALUE instead of /etc/gitattributes as the\n+\t\t\tglobal git attributes file.\n+\t\t\tIf VALUE is not fully qualified it will be interpreted\n \t\t\tas a path relative to the computed prefix at runtime.)\n \n #\ndiff --git a/environment.c b/environment.c\nindex 212f086..32c6c96 100644\n--- a/environment.c\n+++ b/environment.c\n@@ -40,6 +40,7 @@ const char *pager_program;\n int pager_use_color = 1;\n const char *editor_program;\n const char *excludes_file;\n+const char *attributes_file;\n enum auto_crlf auto_crlf = AUTO_CRLF_FALSE;\n int read_replace_refs = 1;\n enum eol eol = EOL_UNSET;\ndiff --git a/t/t0003-attributes.sh b/t/t0003-attributes.sh\nindex 114967a..b884bb7 100755\n--- a/t/t0003-attributes.sh\n+++ b/t/t0003-attributes.sh\n@@ -35,6 +35,9 @@ test_expect_success 'setup' '\n \t\techo \"d/* test=a/b/d/*\"\n \t\techo \"d/yes notest\"\n \t) >a/b/.gitattributes\n+\t(\n+\t\techo \"global test=global\"\n+\t) >$HOME/global-gitattributes\n \n '\n \n@@ -56,6 +59,16 @@ test_expect_success 'attribute test' '\n \n '\n \n+test_expect_success 'core.attributesfile' '\n+\tattr_check global unspecified &&\n+\tgit config core.attributesfile \"$HOME/global-gitattributes\" &&\n+\tattr_check global global &&\n+\tgit config core.attributesfile \"~/global-gitattributes\" &&\n+\tattr_check global global &&\n+\techo \"global test=precedence\" >> .gitattributes &&\n+\tattr_check global precedence\n+'\n+\n test_expect_success 'attribute test: read paths from stdin' '\n \n \tcat <<EOF > expect\n-- \n1.7.2.2.175.ga619d.dirty\n"},{"id":"149399","messageId":"AANLkTik7d9Rhx5NudeKvVMFAYvVhGxoYzK2y+g3CP=Zj@mail.gmail.com","threadId":"24703","inReplyTo":"1283210123-19752-1-git-send-email-Matthieu.Moy@imag.fr","subject":"Re: [PATCH 1/3 v2] tests: factor HOME=$(pwd) in test-lib.sh","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2010-08-31T07:42:53Z","receivedAt":"2010-08-31T07:42:53Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"On Mon, Aug 30, 2010 at 23:15, Matthieu Moy <Matthieu.Moy@imag.fr> wrote:\n> The same pattern is used in many tests, and makes it easy for new ones to\n> rely on $HOME being a trashable, clean, directory.\n>\n> Signed-off-by: Matthieu Moy <Matthieu.Moy@imag.fr>\n> ---\n> Just re-ordered the patch to make this one the first.\n>\n> I took Ævar's suggestion of using $TRASH_DIRECTORY instead of $(pwd).\n\nThanks,\n\nAcked-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n"},{"id":"149504","messageId":"vpqbp8i2yns.fsf@bauges.imag.fr","threadId":"24703","inReplyTo":"1283210123-19752-3-git-send-email-Matthieu.Moy@imag.fr","subject":"Re: [PATCH 3/3 v4] Add global and system-wide gitattributes","fromName":"Matthieu Moy","fromEmail":"matthieu.moy@grenoble-inp.fr","sentAt":"2010-08-31T22:41:11Z","receivedAt":"2010-08-31T22:41:11Z","isPatch":true,"sender":{"key":"matthieu.moy@grenoble-inp.fr","avatar":"https://gravatar.com/avatar/72c8a2705971a25dfaff23cece15130d405685845d911aedd5667ace277f3fc5?d=mp&s=160"},"body":"Matthieu Moy <Matthieu.Moy@imag.fr> writes:\n\n> This version doesn't touch config.c, and calls git_config with a\n> trivial callback reading only the core.attributesfile variable.\n\nI see that pu has a variant of my fix:\n\n  17cd572 fixup! Add global and system-wide gitattributes\n\n(is the fixup! here on purpose, or is it a failed rebase -i?)\n\nJunio: your fixup fixes the git_config issue, but doesn't have the\ntest that my patch have. The difference is that your fixup moves the\nglobal variable attributes_file in attr.c, which sounds like a good\nidea. I'm resending my patch with this change for conveinience.\n\n-- \nMatthieu Moy\nhttp://www-verimag.imag.fr/~moy/\n"},{"id":"149505","messageId":"1283294563-3013-1-git-send-email-Matthieu.Moy@imag.fr","threadId":"24703","inReplyTo":"vpqbp8i2yns.fsf@bauges.imag.fr","subject":"[PATCH] Add global and system-wide gitattributes","fromName":"Matthieu Moy","fromEmail":"matthieu.moy@imag.fr","sentAt":"2010-08-31T22:42:43Z","receivedAt":"2010-08-31T22:42:43Z","isPatch":true,"sender":{"key":"git@matthieu-moy.fr","avatar":"https://avatars.githubusercontent.com/u/14709?v=4"},"body":"From: Petr Onderka <gsvick@gmail.com>\n\nAllow gitattributes to be set globally and system wide. This way, settings\nfor particular file types can be set in one place and apply for all user's\nrepositories.\n\nThe location of system-wide attributes file is $(prefix)/etc/gitattributes.\nThe location of the global file can be configured by setting\ncore.attributesfile.\n\nSome parts of the code were copied from the implementation of the same\nfunctionality in config.c.\n\nSigned-off-by: Petr Onderka <gsvick@gmail.com>\nSigned-off-by: Matthieu Moy <Matthieu.Moy@imag.fr>\n---\nHere it is!\n\n Documentation/config.txt        |    6 ++++\n Documentation/gitattributes.txt |   13 +++++++--\n Makefile                        |    6 ++++\n attr.c                          |   52 ++++++++++++++++++++++++++++++++++++++-\n configure.ac                    |   10 ++++++-\n t/t0003-attributes.sh           |   13 +++++++++\n 6 files changed, 95 insertions(+), 5 deletions(-)\n\ndiff --git a/Documentation/config.txt b/Documentation/config.txt\nindex 05ec3fe..0e15e72 100644\n--- a/Documentation/config.txt\n+++ b/Documentation/config.txt\n@@ -450,6 +450,12 @@ core.excludesfile::\n \tto the value of `$HOME` and \"{tilde}user/\" to the specified user's\n \thome directory.  See linkgit:gitignore[5].\n \n+core.attributesfile::\n+\tIn addition to '.gitattributes' (per-directory) and\n+\t'.git/info/attributes', git looks into this file for attributes\n+\t(see linkgit:gitattributes[5]). Path expansions are made the same\n+\tway as for `core.excludesfile`.\n+\n core.editor::\n \tCommands such as `commit` and `tag` that lets you edit\n \tmessages by launching an editor uses the value of this\ndiff --git a/Documentation/gitattributes.txt b/Documentation/gitattributes.txt\nindex 2e2370c..ebd4852 100644\n--- a/Documentation/gitattributes.txt\n+++ b/Documentation/gitattributes.txt\n@@ -62,14 +62,21 @@ consults `$GIT_DIR/info/attributes` file (which has the highest\n precedence), `.gitattributes` file in the same directory as the\n path in question, and its parent directories up to the toplevel of the\n work tree (the further the directory that contains `.gitattributes`\n-is from the path in question, the lower its precedence).\n+is from the path in question, the lower its precedence). Finally\n+global and system-wide files are considered (they have the lowest\n+precedence).\n \n If you wish to affect only a single repository (i.e., to assign\n-attributes to files that are particular to one user's workflow), then\n+attributes to files that are particular to\n+one user's workflow for that repository), then\n attributes should be placed in the `$GIT_DIR/info/attributes` file.\n Attributes which should be version-controlled and distributed to other\n repositories (i.e., attributes of interest to all users) should go into\n-`.gitattributes` files.\n+`.gitattributes` files. Attributes that should affect all repositories\n+for a single user should be placed in a file specified by the\n+`core.attributesfile` configuration option (see linkgit:git-config[1]).\n+Attributes for all users on a system should be placed in the\n+`$(prefix)/etc/gitattributes` file.\n \n Sometimes you would need to override an setting of an attribute\n for a path to `unspecified` state.  This can be done by listing\ndiff --git a/Makefile b/Makefile\nindex b4745a5..fdb7b4e 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -268,6 +268,7 @@ STRIP ?= strip\n #   infodir\n #   htmldir\n #   ETC_GITCONFIG (but not sysconfdir)\n+#   ETC_GITATTRIBUTES\n # can be specified as a relative path some/where/else;\n # this is interpreted as relative to $(prefix) and \"git\" at\n # runtime figures out where they are based on the path to the executable.\n@@ -286,9 +287,11 @@ htmldir = share/doc/git-doc\n ifeq ($(prefix),/usr)\n sysconfdir = /etc\n ETC_GITCONFIG = $(sysconfdir)/gitconfig\n+ETC_GITATTRIBUTES = $(sysconfdir)/gitattributes\n else\n sysconfdir = $(prefix)/etc\n ETC_GITCONFIG = etc/gitconfig\n+ETC_GITATTRIBUTES = etc/gitattributes\n endif\n lib = lib\n # DESTDIR=\n@@ -1502,6 +1505,7 @@ endif\n \n SHA1_HEADER_SQ = $(subst ','\\'',$(SHA1_HEADER))\n ETC_GITCONFIG_SQ = $(subst ','\\'',$(ETC_GITCONFIG))\n+ETC_GITATTRIBUTES_SQ = $(subst ','\\'',$(ETC_GITATTRIBUTES))\n \n DESTDIR_SQ = $(subst ','\\'',$(DESTDIR))\n bindir_SQ = $(subst ','\\'',$(bindir))\n@@ -1873,6 +1877,8 @@ builtin/init-db.s builtin/init-db.o: EXTRA_CPPFLAGS = \\\n \n config.s config.o: EXTRA_CPPFLAGS = -DETC_GITCONFIG='\"$(ETC_GITCONFIG_SQ)\"'\n \n+attr.s attr.o: EXTRA_CPPFLAGS = -DETC_GITATTRIBUTES='\"$(ETC_GITATTRIBUTES_SQ)\"'\n+\n http.s http.o: EXTRA_CPPFLAGS = -DGIT_HTTP_USER_AGENT='\"git/$(GIT_VERSION)\"'\n \n ifdef NO_EXPAT\ndiff --git a/attr.c b/attr.c\nindex 8ba606c..c94211a 100644\n--- a/attr.c\n+++ b/attr.c\n@@ -1,5 +1,6 @@\n #define NO_THE_INDEX_COMPATIBILITY_MACROS\n #include \"cache.h\"\n+#include \"exec_cmd.h\"\n #include \"attr.h\"\n \n const char git_attr__true[] = \"(builtin)true\";\n@@ -10,6 +11,8 @@ static const char git_attr__unknown[] = \"(builtin)unknown\";\n #define ATTR__UNSET NULL\n #define ATTR__UNKNOWN git_attr__unknown\n \n+static const char *attributes_file;\n+\n /*\n  * The basic design decision here is that we are not going to have\n  * insanely large number of attributes.\n@@ -462,6 +465,32 @@ static void drop_attr_stack(void)\n \t}\n }\n \n+const char *git_etc_gitattributes(void)\n+{\n+\tstatic const char *system_wide;\n+\tif (!system_wide)\n+\t\tsystem_wide = system_path(ETC_GITATTRIBUTES);\n+\treturn system_wide;\n+}\n+\n+int git_attr_system(void)\n+{\n+\treturn !git_env_bool(\"GIT_ATTR_NOSYSTEM\", 0);\n+}\n+\n+int git_attr_global(void)\n+{\n+\treturn !git_env_bool(\"GIT_ATTR_NOGLOBAL\", 0);\n+}\n+\n+static int git_attr_config(const char *var, const char *value, void *dummy)\n+{\n+\tif (!strcmp(var, \"core.attributesfile\"))\n+\t\treturn git_config_pathname(&attributes_file, var, value);\n+\t\n+\treturn 0;\n+}\n+\n static void bootstrap_attr_stack(void)\n {\n \tif (!attr_stack) {\n@@ -472,6 +501,25 @@ static void bootstrap_attr_stack(void)\n \t\telem->prev = attr_stack;\n \t\tattr_stack = elem;\n \n+\t\tif (git_attr_system()) {\n+\t\t\telem = read_attr_from_file(git_etc_gitattributes(), 1);\n+\t\t\tif (elem) {\n+\t\t\t\telem->origin = NULL;\n+\t\t\t\telem->prev = attr_stack;\n+\t\t\t\tattr_stack = elem;\n+\t\t\t}\n+\t\t}\n+\n+\t\tgit_config(git_attr_config, NULL);\n+\t\tif (git_attr_global() && attributes_file) {\n+\t\t\telem = read_attr_from_file(attributes_file, 1);\n+\t\t\tif (elem) {\n+\t\t\t\telem->origin = NULL;\n+\t\t\t\telem->prev = attr_stack;\n+\t\t\t\tattr_stack = elem;\n+\t\t\t}\n+\t\t}\n+\n \t\tif (!is_bare_repository() || direction == GIT_ATTR_INDEX) {\n \t\t\telem = read_attr(GITATTRIBUTES_FILE, 1);\n \t\t\telem->origin = strdup(\"\");\n@@ -499,7 +547,9 @@ static void prepare_attr_stack(const char *path, int dirlen)\n \n \t/*\n \t * At the bottom of the attribute stack is the built-in\n-\t * set of attribute definitions.  Then, contents from\n+\t * set of attribute definitions, followed by the contents\n+\t * of $(prefix)/etc/gitattributes and a file specified by\n+\t * core.attributesfile.  Then, contents from\n \t * .gitattribute files from directories closer to the\n \t * root to the ones in deeper directories are pushed\n \t * to the stack.  Finally, at the very top of the stack\ndiff --git a/configure.ac b/configure.ac\nindex 5601e8b..c5b3a41 100644\n--- a/configure.ac\n+++ b/configure.ac\n@@ -282,7 +282,15 @@ GIT_PARSE_WITH(iconv))\n GIT_PARSE_WITH_SET_MAKE_VAR(gitconfig, ETC_GITCONFIG,\n \t\t\tUse VALUE instead of /etc/gitconfig as the\n \t\t\tglobal git configuration file.\n-\t\t\tIf VALUE is not fully qualified it will be interpretted\n+\t\t\tIf VALUE is not fully qualified it will be interpreted\n+\t\t\tas a path relative to the computed prefix at runtime.)\n+\n+#\n+# Allow user to set ETC_GITATTRIBUTES variable\n+GIT_PARSE_WITH_SET_MAKE_VAR(gitattributes, ETC_GITATTRIBUTES,\n+\t\t\tUse VALUE instead of /etc/gitattributes as the\n+\t\t\tglobal git attributes file.\n+\t\t\tIf VALUE is not fully qualified it will be interpreted\n \t\t\tas a path relative to the computed prefix at runtime.)\n \n #\ndiff --git a/t/t0003-attributes.sh b/t/t0003-attributes.sh\nindex 114967a..b884bb7 100755\n--- a/t/t0003-attributes.sh\n+++ b/t/t0003-attributes.sh\n@@ -35,6 +35,9 @@ test_expect_success 'setup' '\n \t\techo \"d/* test=a/b/d/*\"\n \t\techo \"d/yes notest\"\n \t) >a/b/.gitattributes\n+\t(\n+\t\techo \"global test=global\"\n+\t) >$HOME/global-gitattributes\n \n '\n \n@@ -56,6 +59,16 @@ test_expect_success 'attribute test' '\n \n '\n \n+test_expect_success 'core.attributesfile' '\n+\tattr_check global unspecified &&\n+\tgit config core.attributesfile \"$HOME/global-gitattributes\" &&\n+\tattr_check global global &&\n+\tgit config core.attributesfile \"~/global-gitattributes\" &&\n+\tattr_check global global &&\n+\techo \"global test=precedence\" >> .gitattributes &&\n+\tattr_check global precedence\n+'\n+\n test_expect_success 'attribute test: read paths from stdin' '\n \n \tcat <<EOF > expect\n-- \n1.7.2.2.175.ga619d.dirty\n"},{"id":"149513","messageId":"7vfwxu8hg5.fsf@alter.siamese.dyndns.org","threadId":"24703","inReplyTo":"vpqbp8i2yns.fsf@bauges.imag.fr","subject":"Re: [PATCH 3/3 v4] Add global and system-wide gitattributes","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-08-31T23:56:26Z","receivedAt":"2010-08-31T23:56:26Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Matthieu Moy <Matthieu.Moy@grenoble-inp.fr> writes:\n\n> Matthieu Moy <Matthieu.Moy@imag.fr> writes:\n>\n>> This version doesn't touch config.c, and calls git_config with a\n>> trivial callback reading only the core.attributesfile variable.\n>\n> I see that pu has a variant of my fix:\n>\n>   17cd572 fixup! Add global and system-wide gitattributes\n>\n> (is the fixup! here on purpose, or is it a failed rebase -i?)\n\nIt wasn't a failed \"rebase -i\" but was a reminder to myself.  I didn't\nwant to squash that in before discussing on the list.\n\n> ... I'm resending my patch with this change for conveinience.\n\nWill take a look; it will have to wait until my git Wednesday this week to\nbe pushed out, though.\n\nThanks.\n"},{"id":"149536","messageId":"AANLkTim6Cb4vegGYG0ZtJxXvAwBxHYGOY7bQFbGSAcXV@mail.gmail.com","threadId":"24703","inReplyTo":"AANLkTik7d9Rhx5NudeKvVMFAYvVhGxoYzK2y+g3CP=Zj@mail.gmail.com","subject":"Re: [PATCH 1/3 v2] tests: factor HOME=$(pwd) in test-lib.sh","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2010-09-01T07:56:47Z","receivedAt":"2010-09-01T07:56:47Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"On Tue, Aug 31, 2010 at 07:42, Ævar Arnfjörð Bjarmason <avarab@gmail.com> wrote:\n> On Mon, Aug 30, 2010 at 23:15, Matthieu Moy <Matthieu.Moy@imag.fr> wrote:\n>> The same pattern is used in many tests, and makes it easy for new ones to\n>> rely on $HOME being a trashable, clean, directory.\n>>\n>> Signed-off-by: Matthieu Moy <Matthieu.Moy@imag.fr>\n>> ---\n>> Just re-ordered the patch to make this one the first.\n>>\n>> I took Ævar's suggestion of using $TRASH_DIRECTORY instead of $(pwd).\n>\n> Thanks,\n>\n> Acked-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n\nJunio: FYI you picked up v1 of this for next/pu, not this v2.\n"},{"id":"149567","messageId":"7vaao17ahi.fsf@alter.siamese.dyndns.org","threadId":"24703","inReplyTo":"AANLkTim6Cb4vegGYG0ZtJxXvAwBxHYGOY7bQFbGSAcXV@mail.gmail.com","subject":"Re: [PATCH 1/3 v2] tests: factor HOME=$(pwd) in test-lib.sh","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-09-01T15:24:25Z","receivedAt":"2010-09-01T15:24:25Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:\n\n> On Tue, Aug 31, 2010 at 07:42, Ævar Arnfjörð Bjarmason <avarab@gmail.com> wrote:\n>> On Mon, Aug 30, 2010 at 23:15, Matthieu Moy <Matthieu.Moy@imag.fr> wrote:\n>>> The same pattern is used in many tests, and makes it easy for new ones to\n>>> rely on $HOME being a trashable, clean, directory.\n>>>\n>>> Signed-off-by: Matthieu Moy <Matthieu.Moy@imag.fr>\n>>> ---\n>>> Just re-ordered the patch to make this one the first.\n>>>\n>>> I took Ævar's suggestion of using $TRASH_DIRECTORY instead of $(pwd).\n>>\n>> Thanks,\n>>\n>> Acked-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n>\n> Junio: FYI you picked up v1 of this for next/pu, not this v2.\n\nI know.\n\nThe originals all used $(pwd) as far as I saw, and it _is_ more faithful\nand correct refactoring not to use $TRASH_DIRECTORY in this patch, no?\nYou can choose to change it to use $TRASH but that should be done in a\nseparate patch.\n"},{"id":"149568","messageId":"AANLkTi=+_+62LqhnO6dee9fv=1_naGoNzsusNt9OpX_N@mail.gmail.com","threadId":"24703","inReplyTo":"7vaao17ahi.fsf@alter.siamese.dyndns.org","subject":"Re: [PATCH 1/3 v2] tests: factor HOME=$(pwd) in test-lib.sh","fromName":"Ævar Arnfjörð Bjarmason","fromEmail":"avarab@gmail.com","sentAt":"2010-09-01T15:40:50Z","receivedAt":"2010-09-01T15:40:50Z","isPatch":true,"sender":{"key":"avarab@gmail.com","avatar":"https://avatars.githubusercontent.com/u/45301?v=4"},"body":"On Wed, Sep 1, 2010 at 15:24, Junio C Hamano <gitster@pobox.com> wrote:\n> Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:\n>\n>> On Tue, Aug 31, 2010 at 07:42, Ævar Arnfjörð Bjarmason <avarab@gmail.com> wrote:\n>>> On Mon, Aug 30, 2010 at 23:15, Matthieu Moy <Matthieu.Moy@imag.fr> wrote:\n>>>> The same pattern is used in many tests, and makes it easy for new ones to\n>>>> rely on $HOME being a trashable, clean, directory.\n>>>>\n>>>> Signed-off-by: Matthieu Moy <Matthieu.Moy@imag.fr>\n>>>> ---\n>>>> Just re-ordered the patch to make this one the first.\n>>>>\n>>>> I took Ævar's suggestion of using $TRASH_DIRECTORY instead of $(pwd).\n>>>\n>>> Thanks,\n>>>\n>>> Acked-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>\n>>\n>> Junio: FYI you picked up v1 of this for next/pu, not this v2.\n>\n> I know.\n>\n> The originals all used $(pwd) as far as I saw, and it _is_ more faithful\n> and correct refactoring not to use $TRASH_DIRECTORY in this patch, no?\n> You can choose to change it to use $TRASH but that should be done in a\n> separate patch.\n\nI just wanted to note it in case you didn't see it. It's a trivial\nissue and I don't really care, I just wanted to note it in case the v2\nwent past you.\n"},{"id":"149575","messageId":"vpq7hj5xuz0.fsf@bauges.imag.fr","threadId":"24703","inReplyTo":"AANLkTi=+_+62LqhnO6dee9fv=1_naGoNzsusNt9OpX_N@mail.gmail.com","subject":"Re: [PATCH 1/3 v2] tests: factor HOME=$(pwd) in test-lib.sh","fromName":"Matthieu Moy","fromEmail":"matthieu.moy@grenoble-inp.fr","sentAt":"2010-09-01T16:57:23Z","receivedAt":"2010-09-01T16:57:23Z","isPatch":true,"sender":{"key":"matthieu.moy@grenoble-inp.fr","avatar":"https://gravatar.com/avatar/72c8a2705971a25dfaff23cece15130d405685845d911aedd5667ace277f3fc5?d=mp&s=160"},"body":"Ævar Arnfjörð Bjarmason <avarab@gmail.com> writes:\n\n>> The originals all used $(pwd) as far as I saw, and it _is_ more faithful\n>> and correct refactoring not to use $TRASH_DIRECTORY in this patch, no?\n>> You can choose to change it to use $TRASH but that should be done in a\n>> separate patch.\n>\n> I just wanted to note it in case you didn't see it. It's a trivial\n> issue and I don't really care, I just wanted to note it in case the v2\n> went past you.\n\nJust for the record: I don't care either ;-).\n\n-- \nMatthieu Moy\nhttp://www-verimag.imag.fr/~moy/\n"},{"id":"149630","messageId":"vpq7hj4h6ba.fsf@bauges.imag.fr","threadId":"24703","inReplyTo":"1283210123-19752-2-git-send-email-Matthieu.Moy@imag.fr","subject":"Re: [PATCH 2/3] don't write to git_log_output_encoding outside git_config()","fromName":"Matthieu Moy","fromEmail":"matthieu.moy@grenoble-inp.fr","sentAt":"2010-09-02T08:56:41Z","receivedAt":"2010-09-02T08:56:41Z","isPatch":true,"sender":{"key":"matthieu.moy@grenoble-inp.fr","avatar":"https://gravatar.com/avatar/72c8a2705971a25dfaff23cece15130d405685845d911aedd5667ace277f3fc5?d=mp&s=160"},"body":"Hi,\n\nI'm just raising attention on this patch. It didn't receive any\ncomment and didn't find its way to pu.\n\nI think it makes the code more robust, and would prevent accidental\nbugs like the one I introduced patching the gitattributes patch, but\nit's not critical.\n\nAnyway, if you (i.e. the mailing list, not Junio) don't like the\npatch, I'd prefer to have counter-argument than having the patch\nsilently ignored ;-).\n\nThanks,\n\nMatthieu Moy <Matthieu.Moy@imag.fr> writes:\n\n> The log encoding can be given by the user either with --encoding=foo or\n> with i18n.logoutputencoding. The code dealing with this used to write to\n> git_log_output_encoding in both places, making sure that --encoding=foo\n> is dealt with after reading the configuration file.\n>\n> This is a very fragile mechanism, since any further call to\n> git_config(git_default_config, ...) the value given on the command line.\n>\n> Instead, keep the config value and the cli value, and decide which one to\n> take at read time (in the straightforward accessor\n> get_git_log_output_encoding()).\n>\n> Signed-off-by: Matthieu Moy <Matthieu.Moy@imag.fr>\n> ---\n> So, this isn't strictly necessary since the new version of the patch\n> implementing the gitattributes file doesn't read the full config\n> anymore, but I think that makes the code more robust.\n>\n>  builtin/log.c |    4 ++--\n>  cache.h       |   18 ++++++++++++++++++\n>  environment.c |    4 +++-\n>  pretty.c      |    4 ++--\n>  revision.c    |    4 ++--\n>  5 files changed, 27 insertions(+), 7 deletions(-)\n>\n> diff --git a/builtin/log.c b/builtin/log.c\n> index eaa1ee0..f30a6ba 100644\n> --- a/builtin/log.c\n> +++ b/builtin/log.c\n> @@ -329,8 +329,8 @@ static void show_tagger(char *buf, int len, struct rev_info *rev)\n>  \tstruct strbuf out = STRBUF_INIT;\n>  \n>  \tpp_user_info(\"Tagger\", rev->commit_format, &out, buf, rev->date_mode,\n> -\t\tgit_log_output_encoding ?\n> -\t\tgit_log_output_encoding: git_commit_encoding);\n> +\t\tget_git_log_output_encoding() ?\n> +\t\tget_git_log_output_encoding(): git_commit_encoding);\n>  \tprintf(\"%s\", out.buf);\n>  \tstrbuf_release(&out);\n>  }\n> diff --git a/cache.h b/cache.h\n> index eb77e1d..7e10a39 100644\n> --- a/cache.h\n> +++ b/cache.h\n> @@ -1005,7 +1005,25 @@ extern int user_ident_explicitly_given;\n>  extern int user_ident_sufficiently_given(void);\n>  \n>  extern const char *git_commit_encoding;\n> +\n> +/* Value found in config file */\n>  extern const char *git_log_output_encoding;\n> +\n> +/* Value given in command line with --encoding */\n> +extern const char *git_log_output_encoding_cli;\n> +\n> +/* \n> + * Prioritize the value given by the command-line over the value found\n> + * in the config file.\n> + */\n> +static inline\n> +const char *get_git_log_output_encoding()\n> +{\n> +\treturn git_log_output_encoding_cli ?\n> +\t\tgit_log_output_encoding_cli :\n> +\t\tgit_log_output_encoding;\n> +}\n> +\n>  extern const char *git_mailmap_file;\n>  \n>  /* IO helper functions */\n> diff --git a/environment.c b/environment.c\n> index 83d38d3..212f086 100644\n> --- a/environment.c\n> +++ b/environment.c\n> @@ -23,7 +23,9 @@ int log_all_ref_updates = -1; /* unspecified */\n>  int warn_ambiguous_refs = 1;\n>  int repository_format_version;\n>  const char *git_commit_encoding;\n> -const char *git_log_output_encoding;\n> +const char *git_log_output_encoding = NULL;\n> +const char *git_log_output_encoding_cli = NULL;\n> +\n>  int shared_repository = PERM_UMASK;\n>  const char *apply_default_whitespace;\n>  const char *apply_default_ignorewhitespace;\n> diff --git a/pretty.c b/pretty.c\n> index f85444b..4187a50 100644\n> --- a/pretty.c\n> +++ b/pretty.c\n> @@ -1159,8 +1159,8 @@ char *reencode_commit_message(const struct commit *commit, const char **encoding\n>  {\n>  \tconst char *encoding;\n>  \n> -\tencoding = (git_log_output_encoding\n> -\t\t    ? git_log_output_encoding\n> +\tencoding = (get_git_log_output_encoding()\n> +\t\t    ? get_git_log_output_encoding()\n>  \t\t    : git_commit_encoding);\n>  \tif (!encoding)\n>  \t\tencoding = \"UTF-8\";\n> diff --git a/revision.c b/revision.c\n> index b1c1890..791c757 100644\n> --- a/revision.c\n> +++ b/revision.c\n> @@ -1402,9 +1402,9 @@ static int handle_revision_opt(struct rev_info *revs, int argc, const char **arg\n>  \t\trevs->grep_filter.all_match = 1;\n>  \t} else if ((argcount = parse_long_opt(\"encoding\", argv, &optarg))) {\n>  \t\tif (strcmp(optarg, \"none\"))\n> -\t\t\tgit_log_output_encoding = xstrdup(optarg);\n> +\t\t\tgit_log_output_encoding_cli = xstrdup(optarg);\n>  \t\telse\n> -\t\t\tgit_log_output_encoding = \"\";\n> +\t\t\tgit_log_output_encoding_cli = \"\";\n>  \t\treturn argcount;\n>  \t} else if (!strcmp(arg, \"--reverse\")) {\n>  \t\trevs->reverse ^= 1;\n\n-- \nMatthieu Moy\nhttp://www-verimag.imag.fr/~moy/\n"},{"id":"149650","messageId":"7veidc2lib.fsf@alter.siamese.dyndns.org","threadId":"24703","inReplyTo":"vpq7hj4h6ba.fsf@bauges.imag.fr","subject":"Re: [PATCH 2/3] don't write to git_log_output_encoding outside git_config()","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2010-09-02T15:49:48Z","receivedAt":"2010-09-02T15:49:48Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Matthieu Moy <Matthieu.Moy@grenoble-inp.fr> writes:\n\n> I'm just raising attention on this patch. It didn't receive any\n> comment and didn't find its way to pu.\n>\n> I think it makes the code more robust, and would prevent accidental\n> bugs like the one I introduced patching the gitattributes patch, but\n> it's not critical.\n\nIf we didn't have the fix to po/etc-gitattributes topic, the patch is\nabsolutely necessary as it stops bleeding.\n\nTwo points and a bit of discussion.\n\n(1) The patch claims that the existing \"have a variable in environment.c,\n    with possibly hardcoded default, update that variable by reading\n    config file at the startup, further override the same variable by\n    reading the command line, and use the final result from the variable\"\n    pattern is fragile, _if_ configuration files can be re-read at random\n    places outside the control of the main program.\n\n    The above claim _is_ correct, but is it the existing pattern that is\n    broken, or the uncontrolled reading of configuration file, that is the\n    real culprit (iow, you said \"X if Y\" but if Y is false then what X\n    claims does not matter)?\n\n    I don't think we have a satisfactory answer to that question yet.\n\n(2) If the answer to the question (1) is that the existing pattern is bad,\n    I agree that a mechanism to protect the value that the main program\n    decided to use (after taking environment.c default, config and its\n    command line processing) _is_ necessary, and the patch shows one\n    possible way to do so by replacing a single environment.c variable\n    with a pair of variables and an accessor macro.\n\n    (a) Is that the best solution to the problem, though?\n\n    (b) Does the solution show us a pattern that is easy to follow to\n        avoid the same problem with other environment.c variables?\n\nOne minor potential flaw I see is that while this solution can be applied\nto a variable of a type with an obvious \"unset\" value (e.g. pointer with\nNULL), we cannot use it for a variable of type \"int\" if it can truly take\nany value, because get_git_frotz() macro needs to be able to check if\ngit_fortz_cli has that \"unset\" value in order to decide which one of the\nvariables to use.  My gut feeling is that it wouldn't matter in real-life\n(most int-type knobs actually take uint values), but I didn't check.\n\nI care about (2-b) more than anything else.  For example, we see\n\"git_commit_encoding\" variable in cache.h in the context of your patch.\nThis particular patch does not have to (and I do not want it to) fix\npotential problems with that or any other variable, but it would be nice\nif the patch shows us an obvious and uniform way to apply the same fix\nwhen/if it becomes necessary.  IOW, we would want to make sure that this\nis a generic enough solution, not an ad-hoc workaround.\n\nIs there something we can do to make it easier to apply to other cases?\nPerhaps something along the lines of...\n\n    #define git_declare_var_pair(type, name, unset) \\\n    extern type name; \\\n    extern type name ## _cli; \\\n    static inline type get_ ## name (void) { \\\n    \treturn (name ## _cli != (unset)) \\\n        \t? name ## _cli \\\n                : name; \\\n    }\n\n    git_declare_var_pair(const char *, git_log_output_encoding, NULL)\n\nOr is it a way-premature generalization?\n\nBy the way, do we have a case where the main codepath reads an environment\nvariable and updates a variable in environment.c to be used with that\nvalue?  Then the existing \"fragile\" pattern for that case may look like:\n\n    - there is a variable with default value in environment.c;\n    - it is overwritten by reading configuration file;\n    - it is further overwritten by reading environ[];\n    - it is further overwritten by reading argv[];\n    - and then it is used.\n\nDoes the solution presented by this patch show us a pattern that is\napplicable to such a case as well?\n\n>> diff --git a/cache.h b/cache.h\n>> index eb77e1d..7e10a39 100644\n>> --- a/cache.h\n>> +++ b/cache.h\n>> @@ -1005,7 +1005,25 @@ extern int user_ident_explicitly_given;\n>>  extern int user_ident_sufficiently_given(void);\n>>  \n>>  extern const char *git_commit_encoding;\n>> +\n>> +/* Value found in config file */\n>>  extern const char *git_log_output_encoding;\n>> +\n>> +/* Value given in command line with --encoding */\n>> +extern const char *git_log_output_encoding_cli;\n>> +\n>> +/* \n>> + * Prioritize the value given by the command-line over the value found\n>> + * in the config file.\n>> + */\n>> +static inline\n>> +const char *get_git_log_output_encoding()\n>> +{\n>> +\treturn git_log_output_encoding_cli ?\n>> +\t\tgit_log_output_encoding_cli :\n>> +\t\tgit_log_output_encoding;\n>> +}\n>> +\n>>  extern const char *git_mailmap_file;\n"}]}