{"thread":{"id":"25853","subject":"[PATCH 0/2] Create a shared config file","startedAt":"2010-11-25T17:21:03Z","lastAt":"2010-11-27T16:29:43Z","messageCount":6,"participants":["Nathan W. Panike","Jonathan Nieder","Nguyen Thai Ngoc Duy","Thiago Farina"],"isPatch":true,"patchVersion":1,"patchTotal":2},"messages":[{"id":"156725","messageId":"f687e6c4830e21db606db99b584864a61e5cf8c3.1290870042.git.nathan.panike@gmail.com","threadId":"25853","inReplyTo":"cover.1290870041.git.nathan.panike@gmail.com","subject":"[PATCH 1/2] Add support for a shared config file","fromName":"Nathan W. Panike","fromEmail":"nathan.panike@gmail.com","sentAt":"2010-11-25T17:21:03Z","receivedAt":"2010-11-25T17:21:03Z","isPatch":true,"sender":{"key":"nathan.panike@gmail.com","avatar":"https://avatars.githubusercontent.com/u/389447?v=4"},"body":"The idea is that a project develops indigenous aliases that\nshould be shared project-wide.  The only way to communicate this\nnow is by channels outside of git--email or IRC or such. We add\nsupport for the case where a project configuration can be in\n.gitconfig in the top level of the repository.\n\nSigned-off-by: Nathan W. Panike <nathan.panike@gmail.com>\n---\n builtin/config.c |    9 ++++++++-\n config.c         |   49 ++++++++++++++++++++++++++++++++++++++++++++++++-\n 2 files changed, 56 insertions(+), 2 deletions(-)\n\ndiff --git a/builtin/config.c b/builtin/config.c\nindex ca4a0db..26c679d 100644\n--- a/builtin/config.c\n+++ b/builtin/config.c\n@@ -154,7 +154,7 @@ static int get_value(const char *key_, const char *regex_)\n {\n \tint ret = -1;\n \tchar *tl;\n-\tchar *global = NULL, *repo_config = NULL;\n+\tchar *global = NULL, *repo_config = NULL, *shared = NULL;\n \tconst char *system_wide = NULL, *local;\n \n \tlocal = config_exclusive_filename;\n@@ -165,6 +165,8 @@ static int get_value(const char *key_, const char *regex_)\n \t\t\tglobal = xstrdup(mkpath(\"%s/.gitconfig\", home));\n \t\tif (git_config_system())\n \t\t\tsystem_wide = git_etc_gitconfig();\n+\t\tif(git_config_shared())\n+\t\t\tshared=xstrdup(\".gitconfig\");\n \t}\n \n \tkey = xstrdup(key_);\n@@ -198,11 +200,15 @@ static int get_value(const char *key_, const char *regex_)\n \t\tgit_config_from_file(show_config, system_wide, NULL);\n \tif (do_all && global)\n \t\tgit_config_from_file(show_config, global, NULL);\n+\tif (do_all && shared) \n+\t\tgit_config_from_shared_file(show_config, shared, NULL);\t\n \tif (do_all)\n \t\tgit_config_from_file(show_config, local, NULL);\n \tgit_config_from_parameters(show_config, NULL);\n \tif (!do_all && !seen)\n \t\tgit_config_from_file(show_config, local, NULL);\n+\tif (!do_all && !seen && shared) \n+\t\tgit_config_from_shared_file(show_config, shared, NULL);\t\n \tif (!do_all && !seen && global)\n \t\tgit_config_from_file(show_config, global, NULL);\n \tif (!do_all && !seen && system_wide)\n@@ -222,6 +228,7 @@ static int get_value(const char *key_, const char *regex_)\n free_strings:\n \tfree(repo_config);\n \tfree(global);\n+\tfree(shared);\n \treturn ret;\n }\n \ndiff --git a/config.c b/config.c\nindex c63d683..a9e6bec 100644\n--- a/config.c\n+++ b/config.c\n@@ -795,6 +795,38 @@ int git_config_from_file(config_fn_t fn, const char *filename, void *data)\n \treturn ret;\n }\n \n+struct config_interceptor {\n+\tconfig_fn_t fn;\n+\tvoid* data;\n+};\n+\n+/*\n+ * The purpose of this function is to keep a malicious contributor from\n+ * poisoning our configuration.  The idea of a shared configuration it to\n+ * pass around helpful stuff like aliases, but we do not want to allow someone\n+ * to say, change our email address or the url of the remote.\n+ */\n+\n+static int config_interceptor_fn(const char*name, const char* value, void* data)\n+{\n+\tint ret=0;\n+\tstruct config_interceptor *ci = (struct config_interceptor*)data;\n+\tif( !ci ) {\n+\t\treturn -1;\n+\t}\n+\tif(!prefixcmp(name,\"alias.\"))\n+\t\tret = (*ci->fn)(name,value,ci->data);\n+\treturn ret;\n+}\n+\n+int git_config_from_shared_file(config_fn_t fn,const char* filename, void* data)\n+{\n+\tstruct config_interceptor ci;\n+\tci.fn=fn;\n+\tci.data=data;\t\n+\treturn git_config_from_file(config_interceptor_fn,filename,&ci);\n+}\n+\n const char *git_etc_gitconfig(void)\n {\n \tstatic const char *system_wide;\n@@ -819,6 +851,11 @@ int git_config_global(void)\n \treturn !git_env_bool(\"GIT_CONFIG_NOGLOBAL\", 0);\n }\n \n+int git_config_shared(void)\n+{\n+\treturn !git_env_bool(\"GIT_CONFIG_NOSHARED\", 0);\n+}\n+\n int git_config_from_parameters(config_fn_t fn, void *data)\n {\n \tstatic int loaded_environment;\n@@ -840,7 +877,8 @@ int git_config(config_fn_t fn, void *data)\n \tint ret = 0, found = 0;\n \tchar *repo_config = NULL;\n \tconst char *home = NULL;\n-\n+\tconst char * shared = NULL;\n+\t\n \t/* Setting $GIT_CONFIG makes git read _only_ the given config file. */\n \tif (config_exclusive_filename)\n \t\treturn git_config_from_file(fn, config_exclusive_filename, data);\n@@ -860,6 +898,15 @@ int git_config(config_fn_t fn, void *data)\n \t\tfree(user_config);\n \t}\n \n+\tif (git_config_shared()) {\n+\t\tchar *shared_config=xstrdup(\".gitconfig\");\n+\t\tif (!access(shared_config, R_OK)) {\n+\t\t\tret += git_config_from_shared_file(fn, shared_config, data);\n+\t\t\tfound += 1;\n+\t\t}\n+\t\tfree(shared_config);\n+\t}\n+\t\n \trepo_config = git_pathdup(\"config\");\n \tif (!access(repo_config, R_OK)) {\n \t\tret += git_config_from_file(fn, repo_config, data);\n-- \n1.7.3.2.347.gd33a62\n"},{"id":"156726","messageId":"f15d6598e5e90de3bcdb8caf706735ac4809ad36.1290870042.git.nathan.panike@gmail.com","threadId":"25853","inReplyTo":"cover.1290870041.git.nathan.panike@gmail.com","subject":"[PATCH 2/2] Document toplevel gitconfig file","fromName":"Nathan W. Panike","fromEmail":"nathan.panike@gmail.com","sentAt":"2010-11-25T20:01:50Z","receivedAt":"2010-11-25T20:01:50Z","isPatch":true,"sender":{"key":"nathan.panike@gmail.com","avatar":"https://avatars.githubusercontent.com/u/389447?v=4"},"body":"Try to explain its security implications and how to turn it off.\n\nSigned-off-by: Nathan W. Panike <nathan.panike@gmail.com>\n---\n Documentation/config.txt |   11 +++++++++++\n 1 files changed, 11 insertions(+), 0 deletions(-)\n\ndiff --git a/Documentation/config.txt b/Documentation/config.txt\nindex 6a6c0b5..6ec9a0b 100644\n--- a/Documentation/config.txt\n+++ b/Documentation/config.txt\n@@ -8,6 +8,17 @@ is used to store the configuration for that repository, and\n fallback values for the `.git/config` file. The file `/etc/gitconfig`\n can be used to store a system-wide default configuration.\n \n+One can also create a `.gitconfig` file in the toplevel of the\n+repository. This config file will then be propogated to collaborators\n+when they pull from your repository.  Only `alias` config variables are\n+allowed to be set in this `.gitconfig` file.  One can turn off the\n+shared `.gitconfig` by setting the environment variable\n+'GIT_CONFIG_NOSHARED' to 1; it will then be propogated but will not be\n+used for configuration settings.  Note that this is a security issue\n+because you are basically allowing someone else to dictate your\n+configuration, but should be fine if you pay attention and do not use\n+aliases from someone else blindly.\n+\n The configuration variables are used by both the git plumbing\n and the porcelains. The variables are divided into sections, wherein\n the fully qualified variable name of the variable itself is the last\n-- \n1.7.3.2.347.gd33a62\n"},{"id":"156724","messageId":"cover.1290870041.git.nathan.panike@gmail.com","threadId":"25853","inReplyTo":null,"subject":"[PATCH 0/2] Create a shared config file","fromName":"Nathan W. Panike","fromEmail":"nathan.panike@gmail.com","sentAt":"2010-11-27T15:00:41Z","receivedAt":"2010-11-27T15:00:41Z","isPatch":true,"sender":{"key":"nathan.panike@gmail.com","avatar":"https://avatars.githubusercontent.com/u/389447?v=4"},"body":"Configuration should normally be on a per-repository or per-user basis.  There\nare cases where it would be helpful to have a project share configuration\nacross repositories and between developers.  Normally this happens only via\ne-mail or IRC or by word-of-mouth.  The solution implemented by these patches\nis to have a .gitconfig file in the toplevel of the repository.\n\nThis is not a finished implementation, as I have no tests written.  Instead,\nthis is ``one way to do it.''\n\nNathan W. Panike (2):\n  Add support for a shared config file\n  Document toplevel .gitconfig file\n\n Documentation/config.txt |   11 ++++++++++\n builtin/config.c         |    9 +++++++-\n config.c                 |   49 +++++++++++++++++++++++++++++++++++++++++++++-\n 3 files changed, 67 insertions(+), 2 deletions(-)\n\n-- \n1.7.3.2.347.gd33a62\n"},{"id":"156727","messageId":"20101127155202.GA25598@burratino","threadId":"25853","inReplyTo":"f15d6598e5e90de3bcdb8caf706735ac4809ad36.1290870042.git.nathan.panike@gmail.com","subject":"Re: [PATCH 2/2] Document toplevel gitconfig file","fromName":"Jonathan Nieder","fromEmail":"jrnieder@gmail.com","sentAt":"2010-11-27T15:52:02Z","receivedAt":"2010-11-27T15:52:02Z","isPatch":true,"sender":{"key":"jrnieder@gmail.com","avatar":"https://avatars.githubusercontent.com/u/281595?v=4"},"body":"Nathan W. Panike wrote:\n\n> --- a/Documentation/config.txt\n> +++ b/Documentation/config.txt\n> @@ -8,6 +8,17 @@ is used to store the configuration for that repository, and\n>  fallback values for the `.git/config` file. The file `/etc/gitconfig`\n>  can be used to store a system-wide default configuration.\n>  \n> +One can also create a `.gitconfig` file in the toplevel of the\n> +repository. This config file will then be propogated to collaborators\n> +when they pull from your repository.  Only `alias` config variables are\n> +allowed to be set in this `.gitconfig` file.  One can turn off the\n> +shared `.gitconfig` by setting the environment variable\n> +'GIT_CONFIG_NOSHARED' to 1; it will then be propogated but will not be\n> +used for configuration settings.\n\nPlease no.  Why not set up aliases in a setup-aliases.sh script and\nmention it in your README?\n\nIf I clone a repository to investigate it and then a typo results in\n\n\t$ git lgo\n\nemptying my $HOME directory, I would not call that a feature.\n"},{"id":"156728","messageId":"AANLkTi=6Q_MB-5kjZLCha30h0A4qdjhLhWUY0mLuCuoc@mail.gmail.com","threadId":"25853","inReplyTo":"cover.1290870041.git.nathan.panike@gmail.com","subject":"Re: [PATCH 0/2] Create a shared config file","fromName":"Nguyen Thai Ngoc Duy","fromEmail":"pclouds@gmail.com","sentAt":"2010-11-27T16:04:09Z","receivedAt":"2010-11-27T16:04:09Z","isPatch":true,"sender":{"key":"pclouds@gmail.com","avatar":"https://avatars.githubusercontent.com/u/720?v=4"},"body":"On Sat, Nov 27, 2010 at 10:00 PM, Nathan W. Panike\n<nathan.panike@gmail.com> wrote:\n> Configuration should normally be on a per-repository or per-user basis.  There\n> are cases where it would be helpful to have a project share configuration\n> across repositories and between developers.  Normally this happens only via\n> e-mail or IRC or by word-of-mouth.  The solution implemented by these patches\n> is to have a .gitconfig file in the toplevel of the repository.\n\nOr save the shared config in the repository and add an instruction in\n$GIT_DIR/config to include such config blob. We can worry less about\nmalicious config that way. If you are extremely nervous about it, you\ncan always point to a specific blob that you have checked.\n-- \nDuy\n"},{"id":"156729","messageId":"AANLkTi=0MUfdXppze4bPdMnE--koRTvMfRJ=L=cvieOX@mail.gmail.com","threadId":"25853","inReplyTo":"f687e6c4830e21db606db99b584864a61e5cf8c3.1290870042.git.nathan.panike@gmail.com","subject":"Re: [PATCH 1/2] Add support for a shared config file","fromName":"Thiago Farina","fromEmail":"tfransosi@gmail.com","sentAt":"2010-11-27T16:29:43Z","receivedAt":"2010-11-27T16:29:43Z","isPatch":true,"sender":{"key":"tfransosi@gmail.com","avatar":"https://avatars.githubusercontent.com/u/970071?v=4"},"body":"Some minor nits (style) below.\n\nOn Thu, Nov 25, 2010 at 3:21 PM, Nathan W. Panike\n<nathan.panike@gmail.com> wrote:\n> The idea is that a project develops indigenous aliases that\n> should be shared project-wide.  The only way to communicate this\n> now is by channels outside of git--email or IRC or such. We add\n> support for the case where a project configuration can be in\n> .gitconfig in the top level of the repository.\n>\n> Signed-off-by: Nathan W. Panike <nathan.panike@gmail.com>\n> ---\n>  builtin/config.c |    9 ++++++++-\n>  config.c         |   49 ++++++++++++++++++++++++++++++++++++++++++++++++-\n>  2 files changed, 56 insertions(+), 2 deletions(-)\n>\n> diff --git a/builtin/config.c b/builtin/config.c\n> index ca4a0db..26c679d 100644\n> --- a/builtin/config.c\n> +++ b/builtin/config.c\n> @@ -154,7 +154,7 @@ static int get_value(const char *key_, const char *regex_)\n>  {\n>        int ret = -1;\n>        char *tl;\n> -       char *global = NULL, *repo_config = NULL;\n> +       char *global = NULL, *repo_config = NULL, *shared = NULL;\n>        const char *system_wide = NULL, *local;\n>\n>        local = config_exclusive_filename;\n> @@ -165,6 +165,8 @@ static int get_value(const char *key_, const char *regex_)\n>                        global = xstrdup(mkpath(\"%s/.gitconfig\", home));\n>                if (git_config_system())\n>                        system_wide = git_etc_gitconfig();\n> +               if(git_config_shared())\n> +                       shared=xstrdup(\".gitconfig\");\nnit: add a space before and after the =\n\n>        }\n>\n>        key = xstrdup(key_);\n> @@ -198,11 +200,15 @@ static int get_value(const char *key_, const char *regex_)\n>                git_config_from_file(show_config, system_wide, NULL);\n>        if (do_all && global)\n>                git_config_from_file(show_config, global, NULL);\n> +       if (do_all && shared)\n> +               git_config_from_shared_file(show_config, shared, NULL);\n>        if (do_all)\n>                git_config_from_file(show_config, local, NULL);\n>        git_config_from_parameters(show_config, NULL);\n>        if (!do_all && !seen)\n>                git_config_from_file(show_config, local, NULL);\n> +       if (!do_all && !seen && shared)\n> +               git_config_from_shared_file(show_config, shared, NULL);\n>        if (!do_all && !seen && global)\n>                git_config_from_file(show_config, global, NULL);\n>        if (!do_all && !seen && system_wide)\n> @@ -222,6 +228,7 @@ static int get_value(const char *key_, const char *regex_)\n>  free_strings:\n>        free(repo_config);\n>        free(global);\n> +       free(shared);\n>        return ret;\n>  }\n>\n> diff --git a/config.c b/config.c\n> index c63d683..a9e6bec 100644\n> --- a/config.c\n> +++ b/config.c\n> @@ -795,6 +795,38 @@ int git_config_from_file(config_fn_t fn, const char *filename, void *data)\n>        return ret;\n>  }\n>\n> +struct config_interceptor {\n> +       config_fn_t fn;\n> +       void* data;\n> +};\n> +\nWould be good to add a description about what is this structure and what is for?\n\n> +/*\n> + * The purpose of this function is to keep a malicious contributor from\n> + * poisoning our configuration.  The idea of a shared configuration it to\n> + * pass around helpful stuff like aliases, but we do not want to allow someone\n> + * to say, change our email address or the url of the remote.\n> + */\n> +\n> +static int config_interceptor_fn(const char*name, const char* value, void* data)\n> +{\n> +       int ret=0;\nnit: add space before and after the =\n\n> +       struct config_interceptor *ci = (struct config_interceptor*)data;\n> +       if( !ci ) {\nwrong, wrong.\n\nI think the style used here is:\n\nif (!ci) {\n\nSo, add a space after the if, and no spaces in the () please.\n\n> +               return -1;\n> +       }\n> +       if(!prefixcmp(name,\"alias.\"))\nsame thing here about the space after the if\n\n> +               ret = (*ci->fn)(name,value,ci->data);\n> +       return ret;\n> +}\n> +\n> +int git_config_from_shared_file(config_fn_t fn,const char* filename, void* data)\n> +{\n> +       struct config_interceptor ci;\n> +       ci.fn=fn;\nnit: fix this too and the other occurrences below.\n"}]}