{"thread":{"id":"7033","subject":"[PATCH] Add git-config --remove-section, document --rename-section","startedAt":"2007-03-01T09:39:09Z","lastAt":"2007-03-03T06:33:35Z","messageCount":12,"participants":["Paolo Bonzini","Alex Riesen","Johannes Schindelin"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"35948","messageId":"es66vt$jej$1@sea.gmane.org","threadId":"7033","inReplyTo":null,"subject":"[PATCH] Add git-config --remove-section, document --rename-section","fromName":"Paolo Bonzini","fromEmail":"bonzini@gnu.org","sentAt":"2007-03-01T09:39:09Z","receivedAt":"2007-03-01T09:39:09Z","isPatch":true,"sender":{"key":"bonzini@gnu.org","avatar":"https://avatars.githubusercontent.com/u/42082?v=4"},"body":"As per the subject.  The existing --rename-section option is \nundocumented, while --remove-section is added by this patch based on the \ncode I had written for the \"git branch\" patch.\n\nPaolo\n\n\n* git-config: document --rename-section, provide --remove-section\n\nThis patch documents the previously undocumented option --rename-section\nand adds a new option to zap an entire section.\n\n\ndiff --git a/Documentation/git-config.txt b/Documentation/git-config.txt\nindex 6624484..68de588 100644\n--- a/Documentation/git-config.txt\n+++ b/Documentation/git-config.txt\n@@ -16,6 +16,8 @@ SYNOPSIS\n 'git-config' [--global] [type] --get-all name [value_regex]\n 'git-config' [--global] [type] --unset name [value_regex]\n 'git-config' [--global] [type] --unset-all name [value_regex]\n+'git-config' [--global] [type] --rename-section old_name new_name\n+'git-config' [--global] [type] --remove-section name\n 'git-config' [--global] -l | --list\n \n DESCRIPTION\n@@ -74,6 +76,12 @@ OPTIONS\n --global::\n \tUse global ~/.gitconfig file rather than the repository .git/config.\n \n+--remove-section::\n+\tRemove the given section from the configuration file.\n+\n+--rename-section::\n+\tRename the given section to a new name.\n+\n --unset::\n \tRemove the line matching the key from config file.\n \ndiff --git a/builtin-config.c b/builtin-config.c\nindex f1433a4..6b12fa1 100644\n--- a/builtin-config.c\n+++ b/builtin-config.c\n@@ -2,7 +2,7 @@\n #include \"cache.h\"\n \n static const char git_config_set_usage[] =\n-\"git-config [ --global ] [ --bool | --int ] [--get | --get-all | --get-regexp | --replace-all | --add | --unset | --unset-all] name [value [value_regex]] | --rename-section old_name new_name | --list\";\n+\"git-config [ --global ] [ --bool | --int ] [--get | --get-all | --get-regexp | --replace-all | --add | --unset | --unset-all] name [value [value_regex]] | --rename-section old_name new_name | --remove-section name | --list\";\n \n static char *key;\n static regex_t *key_regexp;\n@@ -168,6 +168,19 @@ int cmd_config(int argc, const char **argv, const char *prefix)\n \t\t\t}\n \t\t\treturn 0;\n \t\t}\n+\t\telse if (!strcmp(argv[1], \"--remove-section\")) {\n+\t\t\tint ret;\n+\t\t\tif (argc != 3)\n+\t\t\t\tusage(git_config_set_usage);\n+\t\t\tret = git_config_remove_section(argv[2]);\n+\t\t\tif (ret < 0)\n+\t\t\t\treturn ret;\n+\t\t\tif (ret == 0) {\n+\t\t\t\tfprintf(stderr, \"No such section!\\n\");\n+\t\t\t\treturn 1;\n+\t\t\t}\n+\t\t\treturn 0;\n+\t\t}\n \t\telse\n \t\t\tbreak;\n \t\targc--;\ndiff --git a/config.c b/config.c\nindex 0ff413b..49df7bd 100644\n--- a/config.c\n+++ b/config.c\n@@ -854,6 +859,33 @@ write_err_out:\n \n }\n \n+static int section_name_match (const char *buf, const char *name)\n+{\n+\tint i = 0, j = 0, dot = 0;\n+\tfor (; buf[i] && buf[i] != ']'; i++) {\n+\t\tif (!dot && isspace(buf[i])) {\n+\t\t\tdot = 1;\n+\t\t\tif (name[j++] != '.')\n+\t\t\t\tbreak;\n+\t\t\tfor (i++; isspace(buf[i]); i++)\n+\t\t\t\t; /* do nothing */\n+\t\t\tif (buf[i] != '\"')\n+\t\t\t\tbreak;\n+\t\t\tcontinue;\n+\t\t}\n+\t\tif (buf[i] == '\\\\' && dot)\n+\t\t\ti++;\n+\t\telse if (buf[i] == '\"' && dot) {\n+\t\t\tfor (i++; isspace(buf[i]); i++)\n+\t\t\t\t; /* do_nothing */\n+\t\t\tbreak;\n+\t\t}\n+\t\tif (buf[i] != name[j++])\n+\t\t\tbreak;\n+\t}\n+\treturn (buf[i] == ']' && name[j] == 0);\n+}\n+\n int git_config_rename_section(const char *old_name, const char *new_name)\n {\n \tint ret = 0;\n@@ -885,40 +917,15 @@ int git_config_rename_section(const char *old_name, const char *new_name)\n \t\tint length;\n \t\tfor (i = 0; buf[i] && isspace(buf[i]); i++)\n \t\t\t; /* do nothing */\n-\t\tif (buf[i] == '[') {\n+\t\tif (buf[i] == '[' && section_name_match (&buf[i+1], old_name)) {\n \t\t\t/* it's a section */\n-\t\t\tint j = 0, dot = 0;\n-\t\t\tfor (i++; buf[i] && buf[i] != ']'; i++) {\n-\t\t\t\tif (!dot && isspace(buf[i])) {\n-\t\t\t\t\tdot = 1;\n-\t\t\t\t\tif (old_name[j++] != '.')\n-\t\t\t\t\t\tbreak;\n-\t\t\t\t\tfor (i++; isspace(buf[i]); i++)\n-\t\t\t\t\t\t; /* do nothing */\n-\t\t\t\t\tif (buf[i] != '\"')\n-\t\t\t\t\t\tbreak;\n-\t\t\t\t\tcontinue;\n-\t\t\t\t}\n-\t\t\t\tif (buf[i] == '\\\\' && dot)\n-\t\t\t\t\ti++;\n-\t\t\t\telse if (buf[i] == '\"' && dot) {\n-\t\t\t\t\tfor (i++; isspace(buf[i]); i++)\n-\t\t\t\t\t\t; /* do_nothing */\n-\t\t\t\t\tbreak;\n-\t\t\t\t}\n-\t\t\t\tif (buf[i] != old_name[j++])\n-\t\t\t\t\tbreak;\n-\t\t\t}\n-\t\t\tif (buf[i] == ']' && old_name[j] == 0) {\n-\t\t\t\t/* old_name matches */\n-\t\t\t\tret++;\n-\t\t\t\tstore.baselen = strlen(new_name);\n-\t\t\t\tif (!store_write_section(out_fd, new_name)) {\n-\t\t\t\t\tret = write_error();\n-\t\t\t\t\tgoto out;\n-\t\t\t\t}\n-\t\t\t\tcontinue;\n+\t\t\tret++;\n+\t\t\tstore.baselen = strlen(new_name);\n+\t\t\tif (!store_write_section(out_fd, new_name)) {\n+\t\t\t\tret = write_error();\n+\t\t\t\tgoto out;\n \t\t\t}\n+\t\t\tcontinue;\n \t\t}\n \t\tlength = strlen(buf);\n \t\tif (write_in_full(out_fd, buf, length) != length) {\n@@ -934,3 +941,58 @@ int git_config_rename_section(const char *old_name, const char *new_name)\n \treturn ret;\n }\n \n+int git_config_remove_section(const char *name)\n+{\n+\tint ret = 0;\n+\tchar *config_filename;\n+\tstruct lock_file *lock = xcalloc(sizeof(struct lock_file), 1);\n+\tint out_fd;\n+\tint removing = 0;\n+\tchar buf[1024];\n+\n+\tconfig_filename = getenv(CONFIG_ENVIRONMENT);\n+\tif (!config_filename) {\n+\t\tconfig_filename = getenv(CONFIG_LOCAL_ENVIRONMENT);\n+\t\tif (!config_filename)\n+\t\t\tconfig_filename  = git_path(\"config\");\n+\t}\n+\tconfig_filename = xstrdup(config_filename);\n+\tout_fd = hold_lock_file_for_update(lock, config_filename, 0);\n+\tif (out_fd < 0) {\n+\t\tret = error(\"Could not lock config file!\");\n+\t\tgoto out;\n+\t}\n+\n+\tif (!(config_file = fopen(config_filename, \"rb\"))) {\n+\t\tret = error(\"Could not open config file!\");\n+\t\tgoto out;\n+\t}\n+\n+\twhile (fgets(buf, sizeof(buf), config_file)) {\n+\t\tint i;\n+\t\tint length;\n+\t\tfor (i = 0; buf[i] && isspace(buf[i]); i++)\n+\t\t\t; /* do nothing */\n+\t\tif (buf[i] == '[') {\n+\t\t\tif (section_name_match (&buf[i + 1], name)) {\n+\t\t\t\t/* name matches */\n+\t\t\t\tret++;\n+\t\t\t\tremoving = 1;\n+\t\t\t} else\n+\t\t\t\tremoving = 0;\n+\t\t}\n+\t\tif (removing)\n+\t\t\tcontinue;\n+\t\tlength = strlen(buf);\n+\t\tif (write_in_full(out_fd, buf, length) != length) {\n+\t\t\tret = write_error();\n+\t\t\tgoto out;\n+\t\t}\n+\t}\n+\tfclose(config_file);\n+\tif (close(out_fd) || commit_lock_file(lock) < 0)\n+\t\t\tret = error(\"Cannot commit config file!\");\n+ out:\n+\tfree(config_filename);\n+\treturn ret;\n+}\ndiff --git a/cache.h b/cache.h\nindex 8bbc142..585a9b4 100644\n--- a/cache.h\n+++ b/cache.h\n@@ -438,6 +439,7 @@ extern int git_config_bool(const char *, const char *);\n extern int git_config_set(const char *, const char *);\n extern int git_config_set_multivar(const char *, const char *, const char *, int);\n extern int git_config_rename_section(const char *, const char *);\n+extern int git_config_remove_section(const char *);\n extern int check_repository_format_version(const char *var, const char *value);\n \n #define MAX_GITNAME (1000)\n"},{"id":"36013","messageId":"81b0412b0703011351ldd903a8od2e4f76aded31519@mail.gmail.com","threadId":"7033","inReplyTo":"es66vt$jej$1@sea.gmane.org","subject":"Re: [PATCH] Add git-config --remove-section, document --rename-section","fromName":"Alex Riesen","fromEmail":"raa.lkml@gmail.com","sentAt":"2007-03-01T21:51:32Z","receivedAt":"2007-03-01T21:51:32Z","isPatch":true,"sender":{"key":"raa.lkml@gmail.com","avatar":"https://avatars.githubusercontent.com/u/324101?v=4"},"body":"On 3/1/07, Paolo Bonzini <bonzini@gnu.org> wrote:\n> As per the subject.  The existing --rename-section option is\n> undocumented, while --remove-section is added by this patch based on the\n> code I had written for the \"git branch\" patch.\n\nYou desperately need tests for this code.\n"},{"id":"36020","messageId":"Pine.LNX.4.63.0703012338370.22628@wbgn013.biozentrum.uni-wuerzburg.de","threadId":"7033","inReplyTo":"81b0412b0703011351ldd903a8od2e4f76aded31519@mail.gmail.com","subject":"[PATCH] add test for git-config --remove-section","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2007-03-01T22:41:08Z","receivedAt":"2007-03-01T22:41:08Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"\nThis adds a simple test if a section is properly removed, even if the \nsection header is repeated in the config.\n\nNot-yet-Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\nWaits-for-ack-by: Paolo Bonzini <bonzini@gnu.org>\n\n---\n\tOn Thu, 1 Mar 2007, Alex Riesen wrote:\n\n\t> On 3/1/07, Paolo Bonzini <bonzini@gnu.org> wrote:\n\t> > As per the subject.  The existing --rename-section option is\n\t> > undocumented, while --remove-section is added by this patch \n\t> > based on the code I had written for the \"git branch\" patch.\n\t> \n\t> You desperately need tests for this code.\n\n\tSomething like this? Totally untested (of course)...\n\n t/t1300-repo-config.sh |   16 ++++++++++++++++\n 1 files changed, 16 insertions(+), 0 deletions(-)\n\n\ndiff --git a/t/t1300-repo-config.sh b/t/t1300-repo-config.sh\nindex 3753e9f..6b15a3e 100755\n--- a/t/t1300-repo-config.sh\n+++ b/t/t1300-repo-config.sh\n@@ -391,6 +391,22 @@ EOF\n \n test_expect_success \"rename succeeded\" \"diff -u expect .git/config\"\n \n+test_expect_success \"remove section\" \"git config --remove-section branch.zwei\"\n+\n+cat > expect << EOF\n+# Hallo\n+\t#Bello\n+[branch \"zwei\"]\n+\tx = 1\n+[branch \"zwei\"]\n+\ty = 1\n+[branch \"drei\"]\n+weird\n+EOF\n+\n+test_expect_success \"section was removed properly\" \\\n+\t\"diff -u expect .git/config\"\n+\n test_expect_success numbers '\n \n \tgit-config kilo.gram 1k &&\n"},{"id":"36021","messageId":"Pine.LNX.4.63.0703012344270.22628@wbgn013.biozentrum.uni-wuerzburg.de","threadId":"7033","inReplyTo":"es66vt$jej$1@sea.gmane.org","subject":"Re: [PATCH] Add git-config --remove-section, document --rename-section","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2007-03-01T22:46:27Z","receivedAt":"2007-03-01T22:46:27Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Thu, 1 Mar 2007, Paolo Bonzini wrote:\n\n> As per the subject.  The existing --rename-section option is \n> undocumented, while --remove-section is added by this patch based on the \n> code I had written for the \"git branch\" patch.\n\nAm I right assuming that you copied rename_section(), and modified it to \nbe remove_section()?\n\nHow about modifying rename_section() so that if new_name == NULL, it \nremoves the section?\n\nBut I like the way you extracted section_name_match(). Makes the code much \nmore readable.\n\nCiao,\nDscho\n"},{"id":"36045","messageId":"45E7DCF1.9080602@gnu.org","threadId":"7033","inReplyTo":"Pine.LNX.4.63.0703012338370.22628@wbgn013.biozentrum.uni-wuerzburg.de","subject":"Re: [PATCH] add test for git-config --remove-section","fromName":"Paolo Bonzini","fromEmail":"paolo.bonzini@gmail.com","sentAt":"2007-03-02T08:14:41Z","receivedAt":"2007-03-02T08:14:41Z","isPatch":true,"sender":{"key":"paolo.bonzini@gmail.com","avatar":"https://gravatar.com/avatar/7817ef2e168b4ef0570c5bb5bdc1d4b44f34d3075fe32b871710dd942d0a89f5?d=mp&s=160"},"body":"Johannes Schindelin wrote:\n> This adds a simple test if a section is properly removed, even if the \n> section header is repeated in the config.\n> \n> Not-yet-Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>\n> Waits-for-ack-by: Paolo Bonzini <bonzini@gnu.org>\n\nThanks!\n\nPaolo\n"},{"id":"36047","messageId":"45E7DDB5.9060009@lu.unisi.ch","threadId":"7033","inReplyTo":"Pine.LNX.4.63.0703012344270.22628@wbgn013.biozentrum.uni-wuerzburg.de","subject":"Re: [PATCH] Add git-config --remove-section, document --rename-section","fromName":"Paolo Bonzini","fromEmail":"paolo.bonzini@gmail.com","sentAt":"2007-03-02T08:17:57Z","receivedAt":"2007-03-02T08:17:57Z","isPatch":true,"sender":{"key":"paolo.bonzini@gmail.com","avatar":"https://gravatar.com/avatar/7817ef2e168b4ef0570c5bb5bdc1d4b44f34d3075fe32b871710dd942d0a89f5?d=mp&s=160"},"body":"\n> Am I right assuming that you copied rename_section(), and modified it to \n> be remove_section()?\n\nYes, after extracting section_name_match.\n\n> How about modifying rename_section() so that if new_name == NULL, it \n> removes the section?\n\nIt's not so immediate, because rename_section has to print all the non-section lines anyway, while remove_section has to remove them too.  I agree though that there is some duplicate code in getting the filename to open.\n\nThanks for writing the test, having an example will make my future work easier.\n\nPaolo\n"},{"id":"36074","messageId":"Pine.LNX.4.63.0703021220420.22628@wbgn013.biozentrum.uni-wuerzburg.de","threadId":"7033","inReplyTo":"45E7DDB5.9060009@lu.unisi.ch","subject":"Re: [PATCH] Add git-config --remove-section, document --rename-section","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2007-03-02T11:23:08Z","receivedAt":"2007-03-02T11:23:08Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Fri, 2 Mar 2007, Paolo Bonzini wrote:\n\n> > How about modifying rename_section() so that if new_name == NULL, it \n> > removes the section?\n> \n> It's not so immediate, because rename_section has to print all the \n> non-section lines anyway, while remove_section has to remove them too.\n\nOf course you would have to move \"int removing\" and the related two lines \nto rename_section(), too.\n\nThe diff would be shorter, and if you then rename the function to \nrename_or_remove_section() it becomes all clearer.\n\nCiao,\nDscho\n\n> Thanks for writing the test, having an example will make my future work \n> easier.\n\nYou're welcome. Knowing how useful tests are is one of the good lessons of \nExtreme Programming...\n\nCiao,\nDscho\n"},{"id":"36081","messageId":"45E814D9.7020104@lu.unisi.ch","threadId":"7033","inReplyTo":"Pine.LNX.4.63.0703021220420.22628@wbgn013.biozentrum.uni-wuerzburg.de","subject":"Re: [PATCH] Add git-config --remove-section, document --rename-section","fromName":"Paolo Bonzini","fromEmail":"paolo.bonzini@lu.unisi.ch","sentAt":"2007-03-02T12:13:13Z","receivedAt":"2007-03-02T12:13:13Z","isPatch":true,"sender":{"key":"bonzini@gnu.org","avatar":"https://avatars.githubusercontent.com/u/42082?v=4"},"body":"\n> Of course you would have to move \"int removing\" and the related two lines \n> to rename_section(), too.\n> \n> The diff would be shorter, and if you then rename the function to \n> rename_or_remove_section() it becomes all clearer.\n\nIt's more different than it looks like.  For example, remove_section needs this,\n\n        if (buf[i] == '[') {\n                if (section_name_match (&buf[i + 1], name)) {\n\t\t} else\n\t\t\t...\n\t}\n\nwhile rename_section can use\n\n        if (buf[i] == '[' && section_name_match (&buf[i+1], old_name)) {\n\nand has more indenting in it.  The amount of indentation in the combined function is not makign things easier to read.\n\nPaolo\n"},{"id":"36099","messageId":"Pine.LNX.4.63.0703021640440.22628@wbgn013.biozentrum.uni-wuerzburg.de","threadId":"7033","inReplyTo":"45E814D9.7020104@lu.unisi.ch","subject":"Re: [PATCH] Add git-config --remove-section, document --rename-section","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2007-03-02T15:44:32Z","receivedAt":"2007-03-02T15:44:32Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Fri, 2 Mar 2007, Paolo Bonzini wrote:\n\n> > Of course you would have to move \"int removing\" and the related two \n> > lines to rename_section(), too.\n> > \n> > The diff would be shorter, and if you then rename the function to \n> > rename_or_remove_section() it becomes all clearer.\n> \n> It's more different than it looks like.  For example, remove_section needs this,\n> \n>         if (buf[i] == '[') {\n>                 if (section_name_match (&buf[i + 1], name)) {\n> \t\t} else\n> \t\t\t...\n> \t}\n> \n> while rename_section can use\n> \n>         if (buf[i] == '[' && section_name_match (&buf[i+1], old_name)) {\n\nBut it does not have to.\n\n\tif (buf[i] == '[') {\n\t\tif (section_name_match(&buf[i + 1], old_name) {\n\t\t\tif (new_name == NULL)\n\t\t\t\tremove = 1;\n\t\t\telse\n\t\t\t\t/* write new section */\n\t\t\tcontinue;\n\t\t}\n\t\tremove = 0;\n\t}\n\tif (!remove)\n\t\t/* write buf */\n\nCiao,\nDscho\n"},{"id":"36106","messageId":"45E850D8.4040306@lu.unisi.ch","threadId":"7033","inReplyTo":"Pine.LNX.4.63.0703021640440.22628@wbgn013.biozentrum.uni-wuerzburg.de","subject":"Re: [PATCH] Add git-config --remove-section, document --rename-section","fromName":"Paolo Bonzini","fromEmail":"paolo.bonzini@lu.unisi.ch","sentAt":"2007-03-02T16:29:12Z","receivedAt":"2007-03-02T16:29:12Z","isPatch":true,"sender":{"key":"bonzini@gnu.org","avatar":"https://avatars.githubusercontent.com/u/42082?v=4"},"body":"> \tif (buf[i] == '[') {\n> \t\tif (section_name_match(&buf[i + 1], old_name) {\n> \t\t\tif (new_name == NULL)\n> \t\t\t\tremove = 1;\n> \t\t\telse\n> \t\t\t\t/* write new section */\n> \t\t\tcontinue;\n> \t\t}\n> \t\tremove = 0;\n> \t}\n> \tif (!remove)\n> \t\t/* write buf */\n\nTry doing this and you'll see that the 8-character indentation makes it pretty hard. :-)\n\nPaolo\n"},{"id":"36126","messageId":"Pine.LNX.4.63.0703022152050.22628@wbgn013.biozentrum.uni-wuerzburg.de","threadId":"7033","inReplyTo":"45E850D8.4040306@lu.unisi.ch","subject":"[PATCH] git-config: document --rename-section, provide --remove-section","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2007-03-02T20:53:33Z","receivedAt":"2007-03-02T20:53:33Z","isPatch":true,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"\nFrom: Paolo Bonzini <bonzini@gnu.org>\n\nThis patch documents the previously undocumented option --rename-section\nand adds a new option to zap an entire section.\n\nHopefully-Signed-off-by: Paolo Bonzini <bonzini@gnu.org>\nSigned-off-by: Johannes Schindelin <Johannes.Schindelin@gmx.de>\n---\n\n\tI just made the changes to git_rename_section() myself, and added\n\tthe test case (which I made a little nastier, too), then made sure\n\tthat everything is fine.\n\n\tPaolo, do you agree with this patch? I left you as the author, \n\tbecause you did all the hard work.\n\n Documentation/git-config.txt |    8 +++++\n builtin-config.c             |   15 ++++++++++-\n config.c                     |   60 +++++++++++++++++++++++++----------------\n t/t1300-repo-config.sh       |   16 +++++++++++\n 4 files changed, 74 insertions(+), 25 deletions(-)\n\ndiff --git a/Documentation/git-config.txt b/Documentation/git-config.txt\nindex 6624484..68de588 100644\n--- a/Documentation/git-config.txt\n+++ b/Documentation/git-config.txt\n@@ -16,6 +16,8 @@ SYNOPSIS\n 'git-config' [--global] [type] --get-all name [value_regex]\n 'git-config' [--global] [type] --unset name [value_regex]\n 'git-config' [--global] [type] --unset-all name [value_regex]\n+'git-config' [--global] [type] --rename-section old_name new_name\n+'git-config' [--global] [type] --remove-section name\n 'git-config' [--global] -l | --list\n \n DESCRIPTION\n@@ -74,6 +76,12 @@ OPTIONS\n --global::\n \tUse global ~/.gitconfig file rather than the repository .git/config.\n \n+--remove-section::\n+\tRemove the given section from the configuration file.\n+\n+--rename-section::\n+\tRename the given section to a new name.\n+\n --unset::\n \tRemove the line matching the key from config file.\n \ndiff --git a/builtin-config.c b/builtin-config.c\nindex f1433a4..dfa403b 100644\n--- a/builtin-config.c\n+++ b/builtin-config.c\n@@ -2,7 +2,7 @@\n #include \"cache.h\"\n \n static const char git_config_set_usage[] =\n-\"git-config [ --global ] [ --bool | --int ] [--get | --get-all | --get-regexp | --replace-all | --add | --unset | --unset-all] name [value [value_regex]] | --rename-section old_name new_name | --list\";\n+\"git-config [ --global ] [ --bool | --int ] [--get | --get-all | --get-regexp | --replace-all | --add | --unset | --unset-all] name [value [value_regex]] | --rename-section old_name new_name | --remove-section name | --list\";\n \n static char *key;\n static regex_t *key_regexp;\n@@ -168,6 +168,19 @@ int cmd_config(int argc, const char **argv, const char *prefix)\n \t\t\t}\n \t\t\treturn 0;\n \t\t}\n+\t\telse if (!strcmp(argv[1], \"--remove-section\")) {\n+\t\t\tint ret;\n+\t\t\tif (argc != 3)\n+\t\t\t\tusage(git_config_set_usage);\n+\t\t\tret = git_config_rename_section(argv[2], NULL);\n+\t\t\tif (ret < 0)\n+\t\t\t\treturn ret;\n+\t\t\tif (ret == 0) {\n+\t\t\t\tfprintf(stderr, \"No such section!\\n\");\n+\t\t\t\treturn 1;\n+\t\t\t}\n+\t\t\treturn 0;\n+\t\t}\n \t\telse\n \t\t\tbreak;\n \t\targc--;\ndiff --git a/config.c b/config.c\nindex 0ff413b..5611d7a 100644\n--- a/config.c\n+++ b/config.c\n@@ -854,9 +854,37 @@ write_err_out:\n \n }\n \n+static int section_name_match (const char *buf, const char *name)\n+{\n+\tint i = 0, j = 0, dot = 0;\n+\tfor (; buf[i] && buf[i] != ']'; i++) {\n+\t\tif (!dot && isspace(buf[i])) {\n+\t\t\tdot = 1;\n+\t\t\tif (name[j++] != '.')\n+\t\t\t\tbreak;\n+\t\t\tfor (i++; isspace(buf[i]); i++)\n+\t\t\t\t; /* do nothing */\n+\t\t\tif (buf[i] != '\"')\n+\t\t\t\tbreak;\n+\t\t\tcontinue;\n+\t\t}\n+\t\tif (buf[i] == '\\\\' && dot)\n+\t\t\ti++;\n+\t\telse if (buf[i] == '\"' && dot) {\n+\t\t\tfor (i++; isspace(buf[i]); i++)\n+\t\t\t\t; /* do_nothing */\n+\t\t\tbreak;\n+\t\t}\n+\t\tif (buf[i] != name[j++])\n+\t\t\tbreak;\n+\t}\n+\treturn (buf[i] == ']' && name[j] == 0);\n+}\n+\n+/* if new_name == NULL, the section is removed instead */\n int git_config_rename_section(const char *old_name, const char *new_name)\n {\n-\tint ret = 0;\n+\tint ret = 0, remove = 0;\n \tchar *config_filename;\n \tstruct lock_file *lock = xcalloc(sizeof(struct lock_file), 1);\n \tint out_fd;\n@@ -887,31 +915,12 @@ int git_config_rename_section(const char *old_name, const char *new_name)\n \t\t\t; /* do nothing */\n \t\tif (buf[i] == '[') {\n \t\t\t/* it's a section */\n-\t\t\tint j = 0, dot = 0;\n-\t\t\tfor (i++; buf[i] && buf[i] != ']'; i++) {\n-\t\t\t\tif (!dot && isspace(buf[i])) {\n-\t\t\t\t\tdot = 1;\n-\t\t\t\t\tif (old_name[j++] != '.')\n-\t\t\t\t\t\tbreak;\n-\t\t\t\t\tfor (i++; isspace(buf[i]); i++)\n-\t\t\t\t\t\t; /* do nothing */\n-\t\t\t\t\tif (buf[i] != '\"')\n-\t\t\t\t\t\tbreak;\n+\t\t\tif (section_name_match (&buf[i+1], old_name)) {\n+\t\t\t\tret++;\n+\t\t\t\tif (new_name == NULL) {\n+\t\t\t\t\tremove = 1;\n \t\t\t\t\tcontinue;\n \t\t\t\t}\n-\t\t\t\tif (buf[i] == '\\\\' && dot)\n-\t\t\t\t\ti++;\n-\t\t\t\telse if (buf[i] == '\"' && dot) {\n-\t\t\t\t\tfor (i++; isspace(buf[i]); i++)\n-\t\t\t\t\t\t; /* do_nothing */\n-\t\t\t\t\tbreak;\n-\t\t\t\t}\n-\t\t\t\tif (buf[i] != old_name[j++])\n-\t\t\t\t\tbreak;\n-\t\t\t}\n-\t\t\tif (buf[i] == ']' && old_name[j] == 0) {\n-\t\t\t\t/* old_name matches */\n-\t\t\t\tret++;\n \t\t\t\tstore.baselen = strlen(new_name);\n \t\t\t\tif (!store_write_section(out_fd, new_name)) {\n \t\t\t\t\tret = write_error();\n@@ -919,7 +928,10 @@ int git_config_rename_section(const char *old_name, const char *new_name)\n \t\t\t\t}\n \t\t\t\tcontinue;\n \t\t\t}\n+\t\t\tremove = 0;\n \t\t}\n+\t\tif (remove)\n+\t\t\tcontinue;\n \t\tlength = strlen(buf);\n \t\tif (write_in_full(out_fd, buf, length) != length) {\n \t\t\tret = write_error();\ndiff --git a/t/t1300-repo-config.sh b/t/t1300-repo-config.sh\nindex 3753e9f..655d1e6 100755\n--- a/t/t1300-repo-config.sh\n+++ b/t/t1300-repo-config.sh\n@@ -391,6 +391,22 @@ EOF\n \n test_expect_success \"rename succeeded\" \"git diff expect .git/config\"\n \n+cat >> .git/config << EOF\n+  [branch \"zwei\"] a = 1 [branch \"vier\"]\n+EOF\n+\n+test_expect_success \"remove section\" \"git config --remove-section branch.zwei\"\n+\n+cat > expect << EOF\n+# Hallo\n+\t#Bello\n+[branch \"drei\"]\n+weird\n+EOF\n+\n+test_expect_success \"section was removed properly\" \\\n+\t\"diff -u expect .git/config\"\n+\n test_expect_success numbers '\n \n \tgit-config kilo.gram 1k &&\n-- \n1.5.0.2.2488.gdffb-dirty\n"},{"id":"36154","messageId":"45E916BF.8070308@lu.unisi.ch","threadId":"7033","inReplyTo":"Pine.LNX.4.63.0703022152050.22628@wbgn013.biozentrum.uni-wuerzburg.de","subject":"Re: [PATCH] git-config: document --rename-section, provide --remove-section","fromName":"Paolo Bonzini","fromEmail":"paolo.bonzini@lu.unisi.ch","sentAt":"2007-03-03T06:33:35Z","receivedAt":"2007-03-03T06:33:35Z","isPatch":true,"sender":{"key":"bonzini@gnu.org","avatar":"https://avatars.githubusercontent.com/u/42082?v=4"},"body":"> \tPaolo, do you agree with this patch?\n\nSure I do.\n\nSigned-off-by: Paolo Bonzini <bonzini@gnu.org>\n"}]}