{"thread":{"id":"25517","subject":"[RFC PATCH v2 0/3] Documentation: refactor config variable descriptions","startedAt":"2010-10-22T05:02:28Z","lastAt":"2010-11-02T13:42:48Z","messageCount":19,"participants":["Thomas Rast","Jakub Narebski","Jeff King","Jens Lehmann"],"isPatch":true,"patchVersion":2,"patchTotal":3},"messages":[{"id":"154098","messageId":"cover.1287690696.git.trast@student.ethz.ch","threadId":"25517","inReplyTo":null,"subject":"[RFC PATCH v2 0/3] Documentation: refactor config variable descriptions","fromName":"Thomas Rast","fromEmail":"trast@student.ethz.ch","sentAt":"2010-10-22T05:02:28Z","receivedAt":"2010-10-22T05:02:28Z","isPatch":true,"sender":{"key":"tr@thomasrast.ch","avatar":"https://avatars.githubusercontent.com/u/153510?v=4"},"body":"This resurrects (finally) the earlier attempt at\n\n  http://mid.gmane.org/cover.1280169048.git.trast@student.ethz.ch\n\nIt tries the inverse approach: teaching the script how to find config\nvariable blocks in each manpage, and then linking them from the main\nlist.  (Obviously just inserting them into the main list could also\nwork.)\n\nIn other words, it attempts to push out the \"original\" documentation\nof each variable from the main list to the individual manpage, which\nis exactly opposite from v1.\n\nThis has the advantage that it does not make the source .txt for each\nmanpage \"unreadable by themselves\", as the earlier approach did (and\nJonathan noticed).\n\nIt also has the advantage that it will shrink config-vars.txt over\ntime.\n\nInstead of going through all manpages again, I just tacked on a sample\npatch as 3/3 that shows what the use/effect could be.  Once we settle\non the direction (v1 or v2) of the refactoring, I'll make more patches\nor resurrect the old ones.\n\nI'm afraid 1/3 (semantically unchanged from the equivalent patch in\nv1) will again not make it through, so I again pushed this out:\n\n  git://repo.or.cz/git/trast.git t/doc-config-extraction-v2\n\n(incidentally v1 is still there as t/doc-config-extraction).  I based\nit on master; 1/3 is prone to conflicts but can easily be recreated\nfrom scratch.\n\n\nThomas Rast (3):\n  Documentation: Move variables from config.txt to separate file\n  Documentation: complete config list from other manpages\n  Documentation: move format.* documentation to format-patch\n\n Documentation/Makefile              |    9 +-\n Documentation/config-vars-src.txt   | 1691 +++++++++++++++++++++++++++++++++\n Documentation/config.txt            | 1748 +----------------------------------\n Documentation/git-format-patch.txt  |   65 ++-\n Documentation/make-config-list.perl |  131 +++\n 5 files changed, 1892 insertions(+), 1752 deletions(-)\n create mode 100644 Documentation/config-vars-src.txt\n create mode 100755 Documentation/make-config-list.perl\n\n-- \n1.7.3.1.281.g5da0b\n"},{"id":"154099","messageId":"48770d33c558c07b5457c3011512b15486602b31.1287690696.git.trast@student.ethz.ch","threadId":"25517","inReplyTo":"cover.1287690696.git.trast@student.ethz.ch","subject":"[RFC PATCH v2 3/3] Documentation: move format.* documentation to format-patch","fromName":"Thomas Rast","fromEmail":"trast@student.ethz.ch","sentAt":"2010-10-22T05:02:31Z","receivedAt":"2010-10-22T05:02:31Z","isPatch":true,"sender":{"key":"tr@thomasrast.ch","avatar":"https://avatars.githubusercontent.com/u/153510?v=4"},"body":"Signed-off-by: Thomas Rast <trast@student.ethz.ch>\n---\n Documentation/config-vars-src.txt  |   56 -------------------------------\n Documentation/git-format-patch.txt |   65 +++++++++++++++++++++++++++++++++--\n 2 files changed, 61 insertions(+), 60 deletions(-)\n\ndiff --git a/Documentation/config-vars-src.txt b/Documentation/config-vars-src.txt\nindex 949259c..e12ff6e 100644\n--- a/Documentation/config-vars-src.txt\n+++ b/Documentation/config-vars-src.txt\n@@ -775,67 +775,11 @@ fetch.unpackLimit::\n \tespecially on slow filesystems.  If not set, the value of\n \t`transfer.unpackLimit` is used instead.\n \n-format.attach::\n-\tEnable multipart/mixed attachments as the default for\n-\t'format-patch'.  The value can also be a double quoted string\n-\twhich will enable attachments as the default and set the\n-\tvalue as the boundary.  See the --attach option in\n-\tlinkgit:git-format-patch[1].\n-\n-format.numbered::\n-\tA boolean which can enable or disable sequence numbers in patch\n-\tsubjects.  It defaults to \"auto\" which enables it only if there\n-\tis more than one patch.  It can be enabled or disabled for all\n-\tmessages by setting it to \"true\" or \"false\".  See --numbered\n-\toption in linkgit:git-format-patch[1].\n-\n-format.headers::\n-\tAdditional email headers to include in a patch to be submitted\n-\tby mail.  See linkgit:git-format-patch[1].\n-\n-format.to::\n-format.cc::\n-\tAdditional recipients to include in a patch to be submitted\n-\tby mail.  See the --to and --cc options in\n-\tlinkgit:git-format-patch[1].\n-\n-format.subjectprefix::\n-\tThe default for format-patch is to output files with the '[PATCH]'\n-\tsubject prefix. Use this variable to change that prefix.\n-\n-format.signature::\n-\tThe default for format-patch is to output a signature containing\n-\tthe git version number. Use this variable to change that default.\n-\tSet this variable to the empty string (\"\") to suppress\n-\tsignature generation.\n-\n-format.suffix::\n-\tThe default for format-patch is to output files with the suffix\n-\t`.patch`. Use this variable to change that suffix (make sure to\n-\tinclude the dot if you want it).\n-\n format.pretty::\n \tThe default pretty format for log/show/whatchanged command,\n \tSee linkgit:git-log[1], linkgit:git-show[1],\n \tlinkgit:git-whatchanged[1].\n \n-format.thread::\n-\tThe default threading style for 'git format-patch'.  Can be\n-\ta boolean value, or `shallow` or `deep`.  `shallow` threading\n-\tmakes every mail a reply to the head of the series,\n-\twhere the head is chosen from the cover letter, the\n-\t`\\--in-reply-to`, and the first patch mail, in this order.\n-\t`deep` threading makes every mail a reply to the previous one.\n-\tA true boolean value is the same as `shallow`, and a false\n-\tvalue disables threading.\n-\n-format.signoff::\n-    A boolean value which lets you enable the `-s/--signoff` option of\n-    format-patch by default. *Note:* Adding the Signed-off-by: line to a\n-    patch should be a conscious act and means that you certify you have\n-    the rights to submit this work under the same open source license.\n-    Please see the 'SubmittingPatches' document for further discussion.\n-\n gc.aggressiveWindow::\n \tThe window size parameter used in the delta compression\n \talgorithm used by 'git gc --aggressive'.  This defaults\ndiff --git a/Documentation/git-format-patch.txt b/Documentation/git-format-patch.txt\nindex 9dcafc6..6154e98 100644\n--- a/Documentation/git-format-patch.txt\n+++ b/Documentation/git-format-patch.txt\n@@ -211,10 +211,9 @@ you can use `--suffix=-patch` to get `0001-description-of-my-change-patch`.\n \n CONFIGURATION\n -------------\n-You can specify extra mail header lines to be added to each message,\n-defaults for the subject prefix and file suffix, number patches when\n-outputting more than one patch, add \"To\" or \"Cc:\" headers, configure\n-attachments, and sign off patches with configuration variables.\n+\n+'git format-patch' has a lot of configuration variables.  A short\n+example:\n \n ------------\n [format]\n@@ -226,8 +225,66 @@ attachments, and sign off patches with configuration variables.\n \tcc = <email>\n \tattach [ = mime-boundary-string ]\n \tsignoff = true\n+\tsignature = \"Hello, world!\\n\"\n+\tthread = shallow\n ------------\n \n+The individual variables are as follows:\n+\n+format.attach::\n+\tEnable multipart/mixed attachments as the default for\n+\t'format-patch'.  The value can also be a double quoted string\n+\twhich will enable attachments as the default and set the\n+\tvalue as the boundary.  See the --attach option.\n+\n+format.numbered::\n+\tA boolean which can enable or disable sequence numbers in patch\n+\tsubjects.  It defaults to \"auto\" which enables it only if there\n+\tis more than one patch.  It can be enabled or disabled for all\n+\tmessages by setting it to \"true\" or \"false\".  See the --numbered\n+\toption.\n+\n+format.headers::\n+\tAdditional email headers to include in a patch to be submitted\n+\tby mail.\n+\n+format.to::\n+format.cc::\n+\tAdditional recipients to include in a patch to be submitted\n+\tby mail.  See the --to and --cc options above.\n+\n+format.subjectprefix::\n+\tThe default for format-patch is to output files with the '[PATCH]'\n+\tsubject prefix. Use this variable to change that prefix.\n+\n+format.signature::\n+\tThe default for format-patch is to output a signature containing\n+\tthe git version number. Use this variable to change that default.\n+\tSet this variable to the empty string (\"\") to suppress\n+\tsignature generation.\n+\n+format.suffix::\n+\tThe default for format-patch is to output files with the suffix\n+\t`.patch`. Use this variable to change that suffix (make sure to\n+\tinclude the dot if you want it).\n+\n+format.thread::\n+\tThe default threading style for 'git format-patch'.  Can be\n+\ta boolean value, or `shallow` or `deep`.  `shallow` threading\n+\tmakes every mail a reply to the head of the series,\n+\twhere the head is chosen from the cover letter, the\n+\t`\\--in-reply-to`, and the first patch mail, in this order.\n+\t`deep` threading makes every mail a reply to the previous one.\n+\tA true boolean value is the same as `shallow`, and a false\n+\tvalue disables threading.\n+\n+format.signoff::\n+    A boolean value which lets you enable the `-s/--signoff` option of\n+    format-patch by default. *Note:* Adding the Signed-off-by: line to a\n+    patch should be a conscious act and means that you certify you have\n+    the rights to submit this work under the same open source license.\n+    Please see the 'SubmittingPatches' document for further discussion.\n+\n \n EXAMPLES\n --------\n-- \n1.7.3.1.281.g5da0b\n"},{"id":"154105","messageId":"201010220819.25901.jnareb@gmail.com","threadId":"25517","inReplyTo":"8145782bddf60325909f328337cb76d25c4402cf.1287690696.git.trast@student.ethz.ch","subject":"Re: [RFC PATCH v2 2/3] Documentation: complete config list from other manpages","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2010-10-22T06:19:24Z","receivedAt":"2010-10-22T06:19:24Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Dnia piątek 22. października 2010 07:02, Thomas Rast napisał:\n> Add an autogeneration script that inserts links to other manpages\n> describing config variables, as follows:\n> \n> * parse config-vars-src.txt (as it now needs to be renamed) to find\n>   out its current contents\n> \n> * parse each manpage source (following includes) for config variable\n>   headers (the blocks are ignored)\n> \n> * assemble a new config-vars.txt that completes the original list with\n>   \"See linkgit:git-foo[1]\" entries for all variables that were not in\n>   it.\n> \n> Signed-off-by: Thomas Rast <trast@student.ethz.ch>\n> ---\n>  Documentation/Makefile              |    9 +-\n>  Documentation/config-vars-src.txt   | 1747 +++++++++++++++++++++++++++++++++++\n>  Documentation/config-vars.txt       | 1747 -----------------------------------\n>  Documentation/make-config-list.perl |  131 +++\n>  4 files changed, 1886 insertions(+), 1748 deletions(-)\n>  create mode 100644 Documentation/config-vars-src.txt\n>  delete mode 100644 Documentation/config-vars.txt\n>  create mode 100755 Documentation/make-config-list.perl\n\nCould you please resend this patch using rename detection \n(git format-patch -M)?  It would make it clear what the difference\nbetween config-vars and config-vars-src is, if any.\n\n-- \nJakub Narebski\nPoland\n"},{"id":"154119","messageId":"201010221018.12558.jnareb@gmail.com","threadId":"25517","inReplyTo":"c3f621cd062b2c4f80aa2e8dadcfddbc042aefaa.1287690696.git.trast@student.ethz.ch","subject":"Re: [RFC PATCH v2 1/3] Documentation: Move variables from config.txt to separate file","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2010-10-22T08:18:11Z","receivedAt":"2010-10-22T08:18:11Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"On Fri, 22 Oct 2010, Thomas Rast wrote:\n\n> Signed-off-by: Thomas Rast <trast@student.ethz.ch>\n> ---\n>  Documentation/config-vars.txt | 1747 ++++++++++++++++++++++++++++++++++++++++\n>  Documentation/config.txt      | 1748 +----------------------------------------\n>  2 files changed, 1748 insertions(+), 1747 deletions(-)\n>  create mode 100644 Documentation/config-vars.txt\n\nI like it, even if the rest of this series would not get accepted.\n\n-- \nJakub Narebski\nPoland\n"},{"id":"154147","messageId":"201010221631.55580.jnareb@gmail.com","threadId":"25517","inReplyTo":"8145782bddf60325909f328337cb76d25c4402cf.1287690696.git.trast@student.ethz.ch","subject":"Re: [RFC PATCH v2 2/3] Documentation: complete config list from other manpages","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2010-10-22T14:31:52Z","receivedAt":"2010-10-22T14:31:52Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"On Fri, 22 Oct 2010 07:02, Thomas Rast wrote:\n\n> Add an autogeneration script that inserts links to other manpages\n> describing config variables, as follows:\n>\n> * parse config-vars-src.txt (as it now needs to be renamed) to find\n>   out its current contents\n> \n> * parse each manpage source (following includes) for config variable\n>   headers (the blocks are ignored)\n> \n> * assemble a new config-vars.txt that completes the original list with\n>   \"See linkgit:git-foo[1]\" entries for all variables that were not in\n>   it.\n\nSo is this script about automatically managing links from git-config\nmanpage to manpages of individual commands?  Does it mean that for \nsomething like the following in Documentation/config-vars-src.txt\n\n  foo.bar::\n  \tLorem ipsum dolor sit amet, consectetur adipisicing elit,\n  \tsed do eiusmod tempor incididunt ut labore et dolore magna\n  \taliqua.\n\nand if `foo.bar` is referenced in Documentation/git-foo.txt in some way\n(from reading source of mentioned autogeneration script it considers\nonly 'foo.bar::', like in Documentation/git-send-email.txt), then it\nadds\n\n  See linkgit:git-foo[1]\n\nat the end of description of variable in Documentation/config-vars-src.txt\n(taking into account continuation blocks)?  What about config variables\nmentioned in different ways, e.g. '`foo.bar`', like in git-update-index\ndocumentation?  Does it checks that 'See linkgit:git-foo[1]' already\nexists, e.g. in extended form 'See linkgit:git-foo[1].  True by default.'?\n \nOr is it about automatically creating and updating blocks like this:\n\n  sendemail.aliasesfile::\n  sendemail.aliasfiletype::\n  sendemail.bcc::\n  sendemail.cc::\n  [...]\n  sendemail.thread::\n  sendemail.validate::\n  \tSee linkgit:git-send-email[1] for description.\n\n\nSee also comments below, where I realized what this scipt does...\nThis really should be in commit message.\n\n> Signed-off-by: Thomas Rast <trast@student.ethz.ch>\n> ---\n>  Documentation/Makefile              |    9 +-\n>  Documentation/config-vars-src.txt   | 1747 +++++++++++++++++++++++++++++++++++\n>  Documentation/config-vars.txt       | 1747 -----------------------------------\n>  Documentation/make-config-list.perl |  131 +++\n>  4 files changed, 1886 insertions(+), 1748 deletions(-)\n>  create mode 100644 Documentation/config-vars-src.txt\n>  delete mode 100644 Documentation/config-vars.txt\n>  create mode 100755 Documentation/make-config-list.perl\n\n[...]\n\n> diff --git a/Documentation/make-config-list.perl b/Documentation/make-config-list.perl\n> new file mode 100755\n> index 0000000..f086867\n> --- /dev/null\n> +++ b/Documentation/make-config-list.perl\n> @@ -0,0 +1,131 @@\n> +#!/usr/bin/perl\n\nWhile other helper scripts do not include comments describing them, it\nwould be nice to have here description what script does and for what it\nis used.\n\nComments in code would also be nice.\n\n\nThe code lacks consistency:\n\n> +\topen my $fh, \"<\", $file or die \"cannot open $file: $!\";\nvs\n> +\tmy $fp;\n> +\topen $fp, '<', $name or die \"open $name failed: $!\";\n\n> +\tclose $fh or die \"eh? close failed: $!\";\nvs\n> +\tclose $fp or die \"close $name failed: $!\";\n\n\n> +\n> +use strict;\n> +use warnings;\n> +use Getopt::Long;\n> +\n> +my %ignore;\n> +\n> +my $rc = GetOptions(\n> +\t\"mainlist=s\" => \\my $mainlistfile,\n> +\t\"ignore=s\" => sub { $ignore{$_[1]} = 1 },\n> +\t\"no-sort\" => \\my $no_sort,\n> +\t);\n> +\n> +if (!$rc or (!-r $mainlistfile)) {\n> +\tprint \"$0 --mainlist=<mainlist> [--ignore=<ignore>...] <asciidoc_manpage>...\\n\";\n> +\texit 1;\n> +}\n\nThe names <mainlist> (which is file with list of configuration variables\nto modify), <ignore> (which is about ignoring some asciidoc_manpage files,\nbut only when recursing / following linkgit links) doesn't tell us much\nby themselves.  It really needs either better names, or comment describing\nwhat they mean, or both.\n\n> +\n\nIt would be good to have comment what this subroutine does.  It reads\nand parses file with list of config variables and their description,\nand returns reference to list of variables, in the order they were in\nfile, and reference to hash with contents:\n  variable => [ lines of description of variable ]\n\n> +sub read_varlist {\n> +\tmy ($file) = @_;\n> +\n> +\topen my $fh, \"<\", $file or die \"cannot open $file: $!\";\n> +\tmy (%mainlist, @mainvars);\n> +\n> +\tmy ($v, $last_v);\n> +\tmy $in_block = 0;\n> +\twhile (<$fh>) {\n> +\t\tif (/^(\\S+)::/) {\n> +\t\t\t$v = lc $1;\n> +\t\t\t$in_block = 0;\n> +\t\t\tpush @{$mainlist{$v}}, $_;\n> +\t\t\tpush @mainvars, $v;\n\nO.K., that is easy to understand (if one remembers about autovivification\nin Perl).  But shouldn't we check if we are not in literal block, just\nin case?\n\n> +\t\t} elsif (/^$/ && !$in_block) {\n> +\t\t\tif (defined $last_v && !$#{$mainlist{$last_v}}) {\n> +\t\t\t\t$mainlist{$last_v} = $mainlist{$v};\n> +\t\t\t}\n> +\t\t\t$last_v = $v;\n\nWhat is this branch / this code about?\n\n> +\t\t} elsif (defined $v) {\n> +\t\t\tpush @{$mainlist{$v}}, $_;\n> +\t\t\t$in_block = !$in_block if /^--$/;\n\nO.K., easy to understand.\n\n> +\t\t}\n> +\t}\n> +\n> +\tclose $fh or die \"eh? close failed: $!\";\n> +\n> +\treturn \\%mainlist, \\@mainvars;\n> +}\n> +\n\nIt would be nice to have description what those variables should contain\n(what structure would they have).\n\n> +my %vars;\n> +my %sections;\n> +\n\nIt would be good to have comment what this subroutine does; better name\nthan 'read_file' would also be good.\n\nThis subroutine does *two* things: finds _manual_ section that manpage\nbelongs to, to create correct link (e.g. 1 for git-send-email(1), 5 for\ngitattributes(5), 7 for gitcli(7)), and finds all manpages that refer\nto config variable using '^foo.bar::': $vars{'foo.bar'} = [ 'git-foo', ... ]\n\nIt would also automatically follow includes, excluding ignored files\nfrom following 'include::<filename>[]' links.\n\n> +sub read_file {\n> +\tmy ($name, $main_name) = @_;\n\n$name is name of current file, $main_name is name of file that included\nit, isn't it?\n\n> +\tif (!defined $main_name) {\n> +\t\t$main_name = $name;\n> +\t}\n> +\tmy $manpage_name = $main_name;\n> +\t$manpage_name =~ s/\\.txt//;\n> +\tmy $fp;\n> +\topen $fp, '<', $name or die \"open $name failed: $!\";\n> +\twhile (<$fp>) {\n> +\t\tif ($. < 5 && /^$manpage_name\\((\\d+)\\)/) {\n> +\t\t\t$sections{$manpage_name} = $1;\n> +\t\t}\n\nShouldn't it be always first line of manpage?\n\n> +\t\tif (/^([a-z0-9]+\\.[a-z<>0-9.]+)::/) {\n> +\t\t\tpush @{$vars{$1}}, $manpage_name;\n> +\t\t}\n> +\t\tif (/^include::\\s*(\\S+)\\s*\\[\\]/\n> +\t\t    && !exists $ignore{$1}) {\n> +\t\t\tread_file($1, $main_name);\n> +\t\t}\n> +\t}\n> +\tclose $fp or die \"close $name failed: $!\";\n> +}\n> +\n> +foreach my $name (@ARGV) {\n> +\tread_file($name);\n> +}\n> +\n> +my ($mainlist, $mainvars) = read_varlist($mainlistfile);\n> +\n> +my @all_keys = @$mainvars;\n> +foreach my $k (keys %vars) {\n> +\tif (!exists $mainlist->{$k}) {\n> +\t\tpush @all_keys, $k;\n> +\t}\n\nNice, so it would detect config variables which are missing from\nconfig-vars-src.txt\n\n> +}\n> +\n> +@all_keys = sort @all_keys unless $no_sort;\n> +\n> +my %out;\n> +foreach my $k (@all_keys) {\n> +\tif (exists $mainlist->{$k}) {\n> +\t\tpush @{$out{$k}}, @{$mainlist->{$k}}, \"\\n\";\n\nAh, so it doesn't add 'See linkgit:git-foo[1]' if 'foo.bar' is present\nin config-vars-src.txt, but only generate notice about config variable\nin git-config manpage, refering to the page where it is defined and\ndescribed.\n\nThis should be make more clear in commit message.\n\n\n> +\t} elsif (exists $vars{$k}) {\n> +\t\tpush @{$out{$k}}, $k . \"::\\n\";\n> +\t\tpush @{$out{$k}}, \"\\tSee \";\n\nWouldn't this result in something like\n\n  sendemail.aliasesfile::\n  \tSee linkgit:git-send-email[1]\n\n  sendemail.aliasfiletype::\n  \tSee linkgit:git-send-email[1]\n\ninstead of\n\n  sendemail.aliasesfile::\n  sendemail.aliasfiletype::\n  \tSee linkgit:git-send-email[1]\n\nin the case where config-vars-src.txt is missing some variable?\nAh, I see that it is collapsed later.\n\n> +\t\tmy $sep = \" \";\n\nNot $sep = \"\", or \"\\tSee\"?  Otherwise you would get \"\\tSee  linkgit:git-foo[1]\"\nwith double space.\n\n> +\t\tforeach my $p (sort @{$vars{$k}}) {\n> +\t\t\tnext if ($p =~ /$mainlistfile/);\n\n> +\t\t\tif (!exists $sections{$p}) {\n> +\t\t\t\twarn \"section for $p unknown\";\n> +\t\t\t\t$sections{$p} = 1;\n> +\t\t\t}\n> +\t\t\tpush @{$out{$k}}, $sep . \"linkgit:\" . $p . \"[\" . $sections{$p} . \"]\";\n\nA bit of possible (but perhaps not necessary) refactoring:\n\n  +\t\t\tpush @{$out{$k}}, $sep . gen_linkgit($p);\n\n(or something like that).\n\n\nBesides wouldn't it be better to do collapsing based on data, not on \nformatted string?\n\n> +\t\t\t$sep = \", \";\n> +\t\t}\n> +\t\tpush @{$out{$k}}, \".\\n\\n\";\n> +\t} else {\n> +\t\tdie \"can't happen: $k not in any source\";\n> +\t}\n> +}\n> +\n\n\nA comment what this loop does would be nice.\n\nNote that we don't really have to do this collapsing for existing \ncontents; only for contents that was generated by this script.\n\n> +for (my $i = 0; $i < $#all_keys; $i++) {\n\n> +\tnext if $#{$out{$all_keys[$i]}} != $#{$out{$all_keys[$i+1]}};\n> +\tmy $same = 1;\n> +\tfor (my $j = 1; $j <= $#{$out{$all_keys[$i]}}; $j++) {\n> +\t\tif ($out{$all_keys[$i]}[$j] ne $out{$all_keys[$i+1]}[$j]) {\n> +\t\t\t$same = 0;\n> +\t\t\tlast;\n> +\t\t}\n> +\t}\n\nA bit of possible (but perhaps not necessary) refactoring:\n\n  +\tnext unless eq_deeply($out{$all_keys[$i]}, $out{$all_keys[$i+1]});\n\n(or eq_deeply_arr).\n\n> +\tif ($same) {\n> +\t\t$out{$all_keys[$i]} = [$out{$all_keys[$i]}[0]];\n> +\t}\n> +}\n\nI really think that we can do this in an easier, more elegant, and not\nthat convoluted way.\n\nFirst, we don't really need to store 'foo.bar::' as first element in\n$out{'foo.bar'}.  Second, then compacting is just grouping hash by value.\n\n> +\n> +foreach my $k (@all_keys) {\n> +\tprint @{$out{$k}};\n> +}\n> -- \n> 1.7.3.1.281.g5da0b\n> \n> \n\n-- \nJakub Narebski\nPoland\n"},{"id":"154155","messageId":"201010221717.55818.jnareb@gmail.com","threadId":"25517","inReplyTo":"cover.1287690696.git.trast@student.ethz.ch","subject":"Re: [RFC PATCH v2 0/3] Documentation: refactor config variable descriptions","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2010-10-22T15:17:54Z","receivedAt":"2010-10-22T15:17:54Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"On Fri, 22 Oct 2010, Thomas Rast wrote:\n\n> Thomas Rast (3):\n>   Documentation: Move variables from config.txt to separate file\n>   Documentation: complete config list from other manpages\n>   Documentation: move format.* documentation to format-patch\n\nNote that patches 1/3 and 2/3 didn't made it to git mailing list\nbeause they were too large for vger anti-SPAM filter.  The 2/3\ncan use rename detection (-M) to be much smaller.\n\n-- \nJakub Narebski\nPoland\n"},{"id":"154162","messageId":"20101022155307.GB5554@sigill.intra.peff.net","threadId":"25517","inReplyTo":"cover.1287690696.git.trast@student.ethz.ch","subject":"Re: [RFC PATCH v2 0/3] Documentation: refactor config variable descriptions","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2010-10-22T15:53:07Z","receivedAt":"2010-10-22T15:53:07Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Fri, Oct 22, 2010 at 07:02:28AM +0200, Thomas Rast wrote:\n\n> This resurrects (finally) the earlier attempt at\n> \n>   http://mid.gmane.org/cover.1280169048.git.trast@student.ethz.ch\n> \n> It tries the inverse approach: teaching the script how to find config\n> variable blocks in each manpage, and then linking them from the main\n> list.  (Obviously just inserting them into the main list could also\n> work.)\n> \n> In other words, it attempts to push out the \"original\" documentation\n> of each variable from the main list to the individual manpage, which\n> is exactly opposite from v1.\n\nThanks for working on this.\n\nI think this approach is much saner for writers and readers of the\nsource files, and I think the output is much better (in particular, the\ngiant list having \"see X\" pointers instead of the actual description\nblocks).\n\nYour 2/3 doesn't seem to have made it through to the list, but I pulled\nfrom your repository and looked at it. I have two comments on the\napproach:\n\n  1. It looks like you're more or less just parsing \"::\" list keys from\n     all of the manpages. This seems somewhat fragile, as there could be\n     other non-config lists. Can we at least restrict it to\n     CONFIGURATION sections? It would be nice if we could put in some\n     kind of semantic markup, but I'm not sure how painful that would be\n     with asciidoc (we could always resort to comments in the source,\n     but that would probably get unreadable quickly).\n\n  2. You recursively follow includes via include::. This means that the\n     make rule is not accurate. E.g., try:\n\n       rm cmds-mainporcelain.txt config-vars.txt\n       make config-vars.txt\n\n     which should fail, as we actually depend on cmds-mainporcelain.txt.\n     Doing it accurately and automatically would mean making .depend\n     files for make.\n\n     But I wonder if the recursive lookup is really required. Some of\n     the includes with config files can just go away (e.g.,\n     merge-config.txt is included only by config-vars-src.txt and\n     git-merge.txt; it can just be merged straight into git-merge.txt\n     once this system exists). Others, like pretty-formats.txt, should,\n     IMHO, get their own user-visible page. Right now with your script\n     you get[1]:\n\n       format.pretty::\n               The default pretty format for log/show/whatchanged command,\n               See linkgit:git-log[1], linkgit:git-show[1],\n               linkgit:git-whatchanged[1].\n\n     but I would rather see[2]:\n\n       format.pretty::\n               See linkgit:gitpretty[7].\n\n     [1]: I assume the single line of block description is an error in\n          your script.\n\n     [2]: Actually, as I mentioned a long time ago, I think it would be\n          nicer to have a table like:\n\n             format.attach         linkgit:git-format-patch[1]\n             format.cc             linkgit:git-format-patch[1]\n             format.headers        linkgit:git-format-patch[1]\n             format.pretty         linkgit:gitpretty[7]\n\n> I'm afraid 1/3 (semantically unchanged from the equivalent patch in\n> v1) will again not make it through, so I again pushed this out:\n> \n>   git://repo.or.cz/git/trast.git t/doc-config-extraction-v2\n\nYeah, I saw neither 1/3 nor 2/3 on the list.\n\n-Peff\n"},{"id":"154286","messageId":"8145782bddf60325909f328337cb76d25c4402cf.1287872553.git.trast@student.ethz.ch","threadId":"25517","inReplyTo":"8145782bddf60325909f328337cb76d25c4402cf.1287690696.git.trast@student.ethz.ch","subject":"[PATCH] Documentation: complete config list from other manpages","fromName":"Thomas Rast","fromEmail":"trast@student.ethz.ch","sentAt":"2010-10-23T22:24:09Z","receivedAt":"2010-10-23T22:24:09Z","isPatch":true,"sender":{"key":"tr@thomasrast.ch","avatar":"https://avatars.githubusercontent.com/u/153510?v=4"},"body":"Add an autogeneration script that inserts links to other manpages\ndescribing config variables, as follows:\n\n* parse config-vars-src.txt (as it now needs to be renamed) to find\n  out its current contents\n\n* parse each manpage source (following includes) for config variable\n  headers (the blocks are ignored)\n\n* assemble a new config-vars.txt that completes the original list with\n  \"See linkgit:git-foo[1]\" entries for all variables that were not in\n  it.\n\nSigned-off-by: Thomas Rast <trast@student.ethz.ch>\n---\n\nJakub Narebski wrote:\n> Could you please resend this patch using rename detection \n> (git format-patch -M)?  It would make it clear what the difference\n> between config-vars and config-vars-src is, if any.\n\nRight, sorry about that.  There wasn't supposed to be any; I'm\nresending what I pushed out for everyone's convenience, but the stray\nchange will be gone in the final version.\n\n\n Documentation/Makefile                             |    9 ++-\n .../{config-vars.txt => config-vars-src.txt}       |    2 +-\n Documentation/make-config-list.perl                |  131 ++++++++++++++++++++\n 3 files changed, 140 insertions(+), 2 deletions(-)\n rename Documentation/{config-vars.txt => config-vars-src.txt} (99%)\n create mode 100755 Documentation/make-config-list.perl\n\ndiff --git a/Documentation/Makefile b/Documentation/Makefile\nindex e117bc4..747b849 100644\n--- a/Documentation/Makefile\n+++ b/Documentation/Makefile\n@@ -125,7 +125,7 @@ endif\n \n SHELL_PATH ?= $(SHELL)\n # Shell quote;\n-SHELL_PATH_SQ = $(subst ','\\'',$(SHELL_PATH))\n+SHELL_PATH_SQ = $(subst ','\\'',$(SHELL_PATH)) #'\n \n #\n # Please note that there is a minor bug in asciidoc.\n@@ -320,6 +320,13 @@ howto-index.txt: howto-index.sh $(wildcard howto/*.txt)\n \t'$(SHELL_PATH_SQ)' ./howto-index.sh $(wildcard howto/*.txt) >$@+ && \\\n \tmv $@+ $@\n \n+config-vars.txt: config-vars-src.txt $(MAN1_TXT) $(MAN5_TXT) $(MAN7_TXT)\n+\t./make-config-list.perl --mainlist=config-vars-src.txt \\\n+\t\t--ignore=config-vars.txt \\\n+\t\t$(MAN1_TXT) $(MAN5_TXT) $(MAN7_TXT) \\\n+\t\t> config-vars.txt+ && \\\n+\tmv config-vars.txt+ config-vars.txt\n+\n $(patsubst %,%.html,$(ARTICLES)) : %.html : %.txt\n \t$(QUIET_ASCIIDOC)$(ASCIIDOC) $(ASCIIDOC_EXTRA) -b xhtml11 $*.txt\n \ndiff --git a/Documentation/config-vars.txt b/Documentation/config-vars-src.txt\nsimilarity index 99%\nrename from Documentation/config-vars.txt\nrename to Documentation/config-vars-src.txt\nindex a8d37a7..949259c 100644\n--- a/Documentation/config-vars.txt\n+++ b/Documentation/config-vars-src.txt\n@@ -936,7 +936,7 @@ gitcvs.dbname::\n \n gitcvs.dbdriver::\n \tUsed Perl DBI driver. You can specify any available driver\n-        for this here, but it might not work. git-cvsserver is tested\n+\tfor this here, but it might not work. git-cvsserver is tested\n \twith 'DBD::SQLite', reported to work with 'DBD::Pg', and\n \treported *not* to work with 'DBD::mysql'. Experimental feature.\n \tMay not contain double colons (`:`). Default: 'SQLite'.\ndiff --git a/Documentation/make-config-list.perl b/Documentation/make-config-list.perl\nnew file mode 100755\nindex 0000000..f086867\n--- /dev/null\n+++ b/Documentation/make-config-list.perl\n@@ -0,0 +1,131 @@\n+#!/usr/bin/perl\n+\n+use strict;\n+use warnings;\n+use Getopt::Long;\n+\n+my %ignore;\n+\n+my $rc = GetOptions(\n+\t\"mainlist=s\" => \\my $mainlistfile,\n+\t\"ignore=s\" => sub { $ignore{$_[1]} = 1 },\n+\t\"no-sort\" => \\my $no_sort,\n+\t);\n+\n+if (!$rc or (!-r $mainlistfile)) {\n+\tprint \"$0 --mainlist=<mainlist> [--ignore=<ignore>...] <asciidoc_manpage>...\\n\";\n+\texit 1;\n+}\n+\n+sub read_varlist {\n+\tmy ($file) = @_;\n+\n+\topen my $fh, \"<\", $file or die \"cannot open $file: $!\";\n+\tmy (%mainlist, @mainvars);\n+\n+\tmy ($v, $last_v);\n+\tmy $in_block = 0;\n+\twhile (<$fh>) {\n+\t\tif (/^(\\S+)::/) {\n+\t\t\t$v = lc $1;\n+\t\t\t$in_block = 0;\n+\t\t\tpush @{$mainlist{$v}}, $_;\n+\t\t\tpush @mainvars, $v;\n+\t\t} elsif (/^$/ && !$in_block) {\n+\t\t\tif (defined $last_v && !$#{$mainlist{$last_v}}) {\n+\t\t\t\t$mainlist{$last_v} = $mainlist{$v};\n+\t\t\t}\n+\t\t\t$last_v = $v;\n+\t\t} elsif (defined $v) {\n+\t\t\tpush @{$mainlist{$v}}, $_;\n+\t\t\t$in_block = !$in_block if /^--$/;\n+\t\t}\n+\t}\n+\n+\tclose $fh or die \"eh? close failed: $!\";\n+\n+\treturn \\%mainlist, \\@mainvars;\n+}\n+\n+my %vars;\n+my %sections;\n+\n+sub read_file {\n+\tmy ($name, $main_name) = @_;\n+\tif (!defined $main_name) {\n+\t\t$main_name = $name;\n+\t}\n+\tmy $manpage_name = $main_name;\n+\t$manpage_name =~ s/\\.txt//;\n+\tmy $fp;\n+\topen $fp, '<', $name or die \"open $name failed: $!\";\n+\twhile (<$fp>) {\n+\t\tif ($. < 5 && /^$manpage_name\\((\\d+)\\)/) {\n+\t\t\t$sections{$manpage_name} = $1;\n+\t\t}\n+\t\tif (/^([a-z0-9]+\\.[a-z<>0-9.]+)::/) {\n+\t\t\tpush @{$vars{$1}}, $manpage_name;\n+\t\t}\n+\t\tif (/^include::\\s*(\\S+)\\s*\\[\\]/\n+\t\t    && !exists $ignore{$1}) {\n+\t\t\tread_file($1, $main_name);\n+\t\t}\n+\t}\n+\tclose $fp or die \"close $name failed: $!\";\n+}\n+\n+foreach my $name (@ARGV) {\n+\tread_file($name);\n+}\n+\n+my ($mainlist, $mainvars) = read_varlist($mainlistfile);\n+\n+my @all_keys = @$mainvars;\n+foreach my $k (keys %vars) {\n+\tif (!exists $mainlist->{$k}) {\n+\t\tpush @all_keys, $k;\n+\t}\n+}\n+\n+@all_keys = sort @all_keys unless $no_sort;\n+\n+my %out;\n+foreach my $k (@all_keys) {\n+\tif (exists $mainlist->{$k}) {\n+\t\tpush @{$out{$k}}, @{$mainlist->{$k}}, \"\\n\";\n+\t} elsif (exists $vars{$k}) {\n+\t\tpush @{$out{$k}}, $k . \"::\\n\";\n+\t\tpush @{$out{$k}}, \"\\tSee \";\n+\t\tmy $sep = \" \";\n+\t\tforeach my $p (sort @{$vars{$k}}) {\n+\t\t\tnext if ($p =~ /$mainlistfile/);\n+\t\t\tif (!exists $sections{$p}) {\n+\t\t\t\twarn \"section for $p unknown\";\n+\t\t\t\t$sections{$p} = 1;\n+\t\t\t}\n+\t\t\tpush @{$out{$k}}, $sep . \"linkgit:\" . $p . \"[\" . $sections{$p} . \"]\";\n+\t\t\t$sep = \", \";\n+\t\t}\n+\t\tpush @{$out{$k}}, \".\\n\\n\";\n+\t} else {\n+\t\tdie \"can't happen: $k not in any source\";\n+\t}\n+}\n+\n+for (my $i = 0; $i < $#all_keys; $i++) {\n+\tnext if $#{$out{$all_keys[$i]}} != $#{$out{$all_keys[$i+1]}};\n+\tmy $same = 1;\n+\tfor (my $j = 1; $j <= $#{$out{$all_keys[$i]}}; $j++) {\n+\t\tif ($out{$all_keys[$i]}[$j] ne $out{$all_keys[$i+1]}[$j]) {\n+\t\t\t$same = 0;\n+\t\t\tlast;\n+\t\t}\n+\t}\n+\tif ($same) {\n+\t\t$out{$all_keys[$i]} = [$out{$all_keys[$i]}[0]];\n+\t}\n+}\n+\n+foreach my $k (@all_keys) {\n+\tprint @{$out{$k}};\n+}\n-- \n1.7.3.2.239.gbefc4\n"},{"id":"154287","messageId":"201010240030.55865.jnareb@gmail.com","threadId":"25517","inReplyTo":"8145782bddf60325909f328337cb76d25c4402cf.1287872553.git.trast@student.ethz.ch","subject":"Re: [PATCH] Documentation: complete config list from other manpages","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2010-10-23T22:30:54Z","receivedAt":"2010-10-23T22:30:54Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Thomas Rast wrote:\n\n> ---\n> \n> Jakub Narebski wrote:\n> > Could you please resend this patch using rename detection \n> > (git format-patch -M)?  It would make it clear what the difference\n> > between config-vars and config-vars-src is, if any.\n> \n> Right, sorry about that.  There wasn't supposed to be any; I'm\n> resending what I pushed out for everyone's convenience, but the stray\n> change will be gone in the final version.\n\nAnd because it is now below vger's anti-SPAM limit on size of message,\nit is now visible at git@vger.kernel.org\n\n-- \nJakub Narebski\nPoland\n"},{"id":"154291","messageId":"201010240324.42721.trast@student.ethz.ch","threadId":"25517","inReplyTo":"20101022155307.GB5554@sigill.intra.peff.net","subject":"Re: [RFC PATCH v2 0/3] Documentation: refactor config variable descriptions","fromName":"Thomas Rast","fromEmail":"trast@student.ethz.ch","sentAt":"2010-10-24T01:24:42Z","receivedAt":"2010-10-24T01:24:42Z","isPatch":true,"sender":{"key":"tr@thomasrast.ch","avatar":"https://avatars.githubusercontent.com/u/153510?v=4"},"body":"Jeff King wrote:\n>   1. It looks like you're more or less just parsing \"::\" list keys from\n>      all of the manpages. This seems somewhat fragile, as there could be\n>      other non-config lists. Can we at least restrict it to\n>      CONFIGURATION sections? It would be nice if we could put in some\n>      kind of semantic markup, but I'm not sure how painful that would be\n>      with asciidoc (we could always resort to comments in the source,\n>      but that would probably get unreadable quickly).\n\nI figured for consistency and ease of lookup *all* configuration docs\nshould name the variables in the same format.  It can still be helpful\nto mention them elsewhere, e.g. in the option documentations, but the\nmain docs should be a CONFIGURATION section formatted like this.\n\nOr do you think that would be a bad thing?\n\nAs for false positives, we could do the CONFIGURATION but in any case\nI was hoping to avoid a special markup by using an asciidoc markup to\nmark false positives if they arise (there currently aren't any).\nE.g., it should be possible to make a {noconfig} attribute that\nexpands to nothing or so.  [Then again the same trick could be used\nfor all configs...]\n\n>      [2]: Actually, as I mentioned a long time ago, I think it would be\n>           nicer to have a table like:\n> \n>              format.attach         linkgit:git-format-patch[1]\n>              format.cc             linkgit:git-format-patch[1]\n>              format.headers        linkgit:git-format-patch[1]\n>              format.pretty         linkgit:gitpretty[7]\n\nTrue, you said that.  I'll hack it into this format, since it's easy\nto do once the parsers are stable and can then just say something like\n\"herein\" for all the ones actually in git-config(1).\n\n-- \nThomas Rast\ntrast@{inf,student}.ethz.ch\n"},{"id":"154333","messageId":"201010241636.51106.jnareb@gmail.com","threadId":"25517","inReplyTo":"8145782bddf60325909f328337cb76d25c4402cf.1287872553.git.trast@student.ethz.ch","subject":"Re: [PATCH] Documentation: complete config list from other manpages","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2010-10-24T14:36:50Z","receivedAt":"2010-10-24T14:36:50Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"This is second review, with the same comments ad the one before,\nand containing proposal for simpler autogeneration script.\n\nOn Sat, 24 Oct 2010, Thomas Rast wrote:\n\n> Add an autogeneration script that inserts links to other manpages\n> describing config variables,\n\nActualy it is \"Add ... and run it to generate config-vars.txt\",\nor \"Create ... and use it to ...\", isn't it.\n\n> as follows: \n> \n> * parse config-vars-src.txt (as it now needs to be renamed) to find\n>   out its current contents\n> \n> * parse each manpage source (following includes) for config variable\n>   headers (the blocks are ignored)\n> \n> * assemble a new config-vars.txt that completes the original list with\n>   \"See linkgit:git-foo[1]\" entries for all variables that were not in\n>   it.\n\nI find this itemized list slightly hard to read (as you can see by the\nconfusion shown in previous review of this patch).  I think it would be\nbetter to describe _goal_ of this script first, and only then how it \ndoes that.\n\nFor example:\n\n  The Documentation/make-config-list.perl script finds all config\n  variables that are defined in individual manpages that are missing\n  from the list of all config variable (in git-config(1) manpage).\n  It then generates stub[1] documentation for those missing config\n  variables at appropriate place in Documentation/config-vars.txt,\n  using the following form:\n\n    foo.bar::\n    foo.baz::\n    \tSee linkgit:git-foo[1].\n\n  It does that by parsing config-vars-src.txt (now source for \n  config-vars.txt) getting list of all config variables to find later\n  which ones are missing, parsing each manpage source provided on \n  command line (following includes) for config variable headers to\n  find which config variables are described directly on individual\n  manpages, then it assembles config-vars.txt with missing variables\n  added[2].\n\n  NOTE that as a side-effect list of config variables would be sorted\n  in alphabetical order[3]\n\n[1] Not a best word, but I couldn't think of a better one.\n[2] This paragraph could be done as itemized list, as before.\n[3] In my proposal it is not necessary; note that some of config \n    variables are grouped _by function_ to be close together, and\n    your script would destroy that.\n\n> \n> Signed-off-by: Thomas Rast <trast@student.ethz.ch>\n> ---\n> \n> Jakub Narebski wrote:\n> > Could you please resend this patch using rename detection \n> > (git format-patch -M)?  It would make it clear what the difference\n> > between config-vars and config-vars-src is, if any.\n> \n> Right, sorry about that.  There wasn't supposed to be any; I'm\n> resending what I pushed out for everyone's convenience, but the stray\n> change will be gone in the final version.\n\nStray changes (there are 2 of them).\n\n>  Documentation/Makefile                             |    9 ++-\n>  .../{config-vars.txt => config-vars-src.txt}       |    2 +-\n>  Documentation/make-config-list.perl                |  131 ++++++++++++++++++++\n>  3 files changed, 140 insertions(+), 2 deletions(-)\n>  rename Documentation/{config-vars.txt => config-vars-src.txt} (99%)\n>  create mode 100755 Documentation/make-config-list.perl\n> \n> diff --git a/Documentation/Makefile b/Documentation/Makefile\n> index e117bc4..747b849 100644\n> --- a/Documentation/Makefile\n> +++ b/Documentation/Makefile\n> @@ -125,7 +125,7 @@ endif\n>  \n>  SHELL_PATH ?= $(SHELL)\n>  # Shell quote;\n> -SHELL_PATH_SQ = $(subst ','\\'',$(SHELL_PATH))\n> +SHELL_PATH_SQ = $(subst ','\\'',$(SHELL_PATH)) #'\n>  \n>  #\n>  # Please note that there is a minor bug in asciidoc.\n\nStray change, doesn't belong in this commit (and probably should be\nskipped altogether).\n\nBTW. there was a proposal to do something like that by saving quote\nin a variable, and using it in shell quoting...\n\n> @@ -320,6 +320,13 @@ howto-index.txt: howto-index.sh $(wildcard howto/*.txt)\n>  \t'$(SHELL_PATH_SQ)' ./howto-index.sh $(wildcard howto/*.txt) >$@+ && \\\n>  \tmv $@+ $@\n>  \n> +config-vars.txt: config-vars-src.txt $(MAN1_TXT) $(MAN5_TXT) $(MAN7_TXT)\n> +\t./make-config-list.perl --mainlist=config-vars-src.txt \\\n> +\t\t--ignore=config-vars.txt \\\n> +\t\t$(MAN1_TXT) $(MAN5_TXT) $(MAN7_TXT) \\\n> +\t\t> config-vars.txt+ && \\\n\n\nVery, very minor nitpick: wouldn't it read better as the following?\n\n  +\t./make-config-list.perl \\\n  +\t\t--mainlist=config-vars-src.txt \\\n  +\t\t--ignore=config-vars.txt \\\n  +\t\t$(MAN1_TXT) $(MAN5_TXT) $(MAN7_TXT) \\\n  +\t\t> config-vars.txt+ && \\\n\n> +\t\t> config-vars.txt+ && \\\n> +\tmv config-vars.txt+ config-vars.txt\n> +\n>  $(patsubst %,%.html,$(ARTICLES)) : %.html : %.txt\n>  \t$(QUIET_ASCIIDOC)$(ASCIIDOC) $(ASCIIDOC_EXTRA) -b xhtml11 $*.txt\n>  \n> diff --git a/Documentation/config-vars.txt b/Documentation/config-vars-src.txt\n> similarity index 99%\n> rename from Documentation/config-vars.txt\n> rename to Documentation/config-vars-src.txt\n> index a8d37a7..949259c 100644\n> --- a/Documentation/config-vars.txt\n> +++ b/Documentation/config-vars-src.txt\n> @@ -936,7 +936,7 @@ gitcvs.dbname::\n>  \n>  gitcvs.dbdriver::\n>  \tUsed Perl DBI driver. You can specify any available driver\n> -        for this here, but it might not work. git-cvsserver is tested\n> +\tfor this here, but it might not work. git-cvsserver is tested\n>  \twith 'DBD::SQLite', reported to work with 'DBD::Pg', and\n>  \treported *not* to work with 'DBD::mysql'. Experimental feature.\n>  \tMay not contain double colons (`:`). Default: 'SQLite'.\n\nStray change (spaces to tab), which should be done as separate \n\"whitespace cleanup\" patch.\n\n> diff --git a/Documentation/make-config-list.perl b/Documentation/make-config-list.perl\n> new file mode 100755\n> index 0000000..f086867\n> --- /dev/null\n> +++ b/Documentation/make-config-list.perl\n> @@ -0,0 +1,131 @@\n> +#!/usr/bin/perl\n> +\n> +use strict;\n> +use warnings;\n> +use Getopt::Long;\n> +\n> +my %ignore;\n> +\n> +my $rc = GetOptions(\n> +\t\"mainlist=s\" => \\my $mainlistfile,\n> +\t\"ignore=s\" => sub { $ignore{$_[1]} = 1 },\n> +\t\"no-sort\" => \\my $no_sort,\n> +\t);\n\nErrr, wouldn't it be better to do it this way:\n\n  +my $sort = 1;\n  +my $rc = GetOptions(\n  +\t\"mainlist=s\" => \\my $mainlistfile,\n  +\t\"ignore=s\" => \\my @ignore,\n  +\t\"sort!\" => \\$sort,\n  +);\n  +my %ignore = map { $_ => 1 } @ignore;\n\nThough it is not necessary; I guess it is a matter of taste.\n\nBTW. does your sript work correctly with `--no-sort`?\n\n> +\n> +if (!$rc or (!-r $mainlistfile)) {\n> +\tprint \"$0 --mainlist=<mainlist> [--ignore=<ignore>...] <asciidoc_manpage>...\\n\";\n> +\texit 1;\n> +}\n\nI'd rather you did a better error handling:\n\n  +if (!$rc || !defined $mainlistfile) {\n  +\tprint \"$0 --mainlist=<mainlist> [--ignore=<ignore>...] <asciidoc_manpage>...\\n\";\n  +\texit 1;\n  +}\n\nand leave handling '!-r $mainlistfile' to read_varlist() subroutine.\n\n> +\n\nThis subroutine needs description, I think; at least oneline comment\ndescribing it.\n\n> +sub read_varlist {\n> +\tmy ($file) = @_;\n> +\n> +\topen my $fh, \"<\", $file or die \"cannot open $file: $!\";\n\nYou are a bit inconsistent here.  read_varlist() has\n\n   \topen my $fh, \"<\", $file or die \"cannot open $file: $!\";\n\nwhile read_file() has\n\n   \tmy $fp;\n   \topen $fp, '<', $name or die \"open $name failed: $!\";\n\nNote that you can use the same name of filehandle (e.g. $fh), as it is\nlocal to the subroutine.\n\n> +\tmy (%mainlist, @mainvars);\n> +\n> +\tmy ($v, $last_v);\n> +\tmy $in_block = 0;\n\nI would done this differently, and IMHO in a simpler way.  Instead of\ngenerating %mainvars structure, that holds for each variable the contents\nof its description (in the form of list of lines), adding missing \nvariables to it, and then (re)generating config-vars.txt from it:\n\n  --mainlist=config-vars-src.txt\n          |\n          v\n  @mainlist, %mainvars\n          |\n          |  <-- %vars <-- <asciidoc_manpage>...\n          |\n          v\n  @all_keys, %out\n          |\n          v\n  > config-vars.txt+\n\nwouldn't it be better to simply store where description of each variable\nbegins in a file (line number, or file position), and then use it to \ninject generated description for missing variables in correct place?\n\n> +\twhile (<$fh>) {\n> +\t\tif (/^(\\S+)::/) {\n> +\t\t\t$v = lc $1;\n\nNote: because you are (re)generating config-vars.txt from those data\nstructures this has an unfortunate side-effect of lowercasing all config\nvariable names in final config-bars.txt, e.g. it would replace\n`core.ignoreCygwinFSTricks` with `core.ignorecygwinfstricks`.\n\n> +\t\t\t$in_block = 0;\n> +\t\t\tpush @{$mainlist{$v}}, $_;\n> +\t\t\tpush @mainvars, $v;\n\nSo in the proposed implementation it would simply be:\n\n  +\t\t\t$mainlist{lc($v)} = $.;\n  +\t\t\tpush @mainvars, $v;\n\nI think lc($v) is needed only in %mainlist keys.\n\n> +\t\t} elsif (/^$/ && !$in_block) {\n> +\t\t\tif (defined $last_v && !$#{$mainlist{$last_v}}) {\n> +\t\t\t\t$mainlist{$last_v} = $mainlist{$v};\n> +\t\t\t}\n> +\t\t\t$last_v = $v;\n\nBesides, if I understand it correctly, that any empty line which does\nnot precede config variable definition, and is not inside literal block,\nis a *bug* in AsciiDoc markup.  It should be \"^+$\" (continuation),\nnot \"^$\".\n\nThis branch of conditional would be simply not required in proposed\nalternate solution.\n\n\nBy the way, why you do not follow includes in this file (for example\n'include::merge-config.txt[]'?\n\n> +\t\t} elsif (defined $v) {\n> +\t\t\tpush @{$mainlist{$v}}, $_;\n> +\t\t\t$in_block = !$in_block if /^--$/;\n> +\t\t}\n\nThis branch of conditional would be simply not required in proposed\nalternate solution.\n\nWell... assuming that we do not have lines matching /^(\\S+)::/ in literal\nblocks (which we don't, and which you also assume).\n\n> +\t}\n> +\n> +\tclose $fh or die \"eh? close failed: $!\";\n\nYou are a bit inconsistent here.  read_varlist() has\n\n   \tclose $fh or die \"eh? close failed: $!\";\n\nwhile read_file() has\n\n   \tclose $fp or die \"close $name failed: $!\";\n\n> +\n> +\treturn \\%mainlist, \\@mainvars;\n> +}\n> +\n> +my %vars;\n> +my %sections;\n\nI think those variables needs better names, for example\n%vars_manpages (as it is mapping from config variable name found in\nmanpage to list of manpages it was found in) and %manpage_section\n(as it is mapping from manpage name to man section, for purpose of\nlinking).\n\nThough perhaps %vars could be left as is...\n\n> +\n\nThis subroutine needs description, I think; at least oneline comment\ndescribing it.  And probably better name, like read_manpage().\n\n> +sub read_file {\n> +\tmy ($name, $main_name) = @_;\n> +\tif (!defined $main_name) {\n> +\t\t$main_name = $name;\n> +\t}\n> +\tmy $manpage_name = $main_name;\n> +\t$manpage_name =~ s/\\.txt//;\n\nWouldn't it be simpler to pass $filename, $manpage as arguments to\nread_file(), rather than $filename/$name, $main_name?\n\nIt would read as:\n\n  +# Parse manpages for config variables and sections, following includes\n  +sub read_manpage {\n  +\tmy ($filename, $manpage) = @_;\n  +\tif (!defined $manpage) {\n  +\t\t$manpage = $filename;\n  +\t\t$manpage =~ s/\\.txt//;\n  +\t}\n\nAnd of course s/$name/$filename/ and s/$manpage_name/$manpage/.  Well, \nthe change of variable names is not really necessary.\n\n> +\tmy $fp;\n> +\topen $fp, '<', $name or die \"open $name failed: $!\";\n> +\twhile (<$fp>) {\n> +\t\tif ($. < 5 && /^$manpage_name\\((\\d+)\\)/) {\n> +\t\t\t$sections{$manpage_name} = $1;\n> +\t\t}\n> +\t\tif (/^([a-z0-9]+\\.[a-z<>0-9.]+)::/) {\n> +\t\t\tpush @{$vars{$1}}, $manpage_name;\n> +\t\t}\n> +\t\tif (/^include::\\s*(\\S+)\\s*\\[\\]/\n> +\t\t    && !exists $ignore{$1}) {\n> +\t\t\tread_file($1, $main_name);\n> +\t\t}\n> +\t}\n> +\tclose $fp or die \"close $name failed: $!\";\n> +}\n> +\n> +foreach my $name (@ARGV) {\n> +\tread_file($name);\n> +}\n\nO.K. nicely done.  This would be unchanged in proposed alternate \nsolution.\n\n> +\n> +my ($mainlist, $mainvars) = read_varlist($mainlistfile);\n> +\n> +my @all_keys = @$mainvars;\n> +foreach my $k (keys %vars) {\n> +\tif (!exists $mainlist->{$k}) {\n> +\t\tpush @all_keys, $k;\n> +\t}\n> +}\n\nI propose the following:\n\n  +my @missing_vars = ();\n  +foreach my $k (keys %vars) {\n  +\tif (!exists $mainlist->{$k}) {\n  +\t\tpush @missing_vars, $k;\n  +\t}\n  +}\n\nor even\n\n  +foreach my $k (keys %vars) {\n  +\tif (exists $mainlist->{$k}) {\n  +\t\tdelete $vars{$k};\n  +\t}\n  +}\n\nso that %vars would now contain only missing variables.\n\n> +\n> +@all_keys = sort @all_keys unless $no_sort;\n\nSo if you pass `--no-sort` to this script, all missing variables would\nbe put at the end, and if you pass it, the order of variables would be\nchanged, isn't it?\n\n> +\n> +my %out;\n> +foreach my $k (@all_keys) {\n> +\tif (exists $mainlist->{$k}) {\n> +\t\tpush @{$out{$k}}, @{$mainlist->{$k}}, \"\\n\";\n> +\t} elsif (exists $vars{$k}) {\n> +\t\tpush @{$out{$k}}, $k . \"::\\n\";\n> +\t\tpush @{$out{$k}}, \"\\tSee \";\n> +\t\tmy $sep = \" \";\n> +\t\tforeach my $p (sort @{$vars{$k}}) {\n> +\t\t\tnext if ($p =~ /$mainlistfile/);\n> +\t\t\tif (!exists $sections{$p}) {\n> +\t\t\t\twarn \"section for $p unknown\";\n> +\t\t\t\t$sections{$p} = 1;\n> +\t\t\t}\n> +\t\t\tpush @{$out{$k}}, $sep . \"linkgit:\" . $p . \"[\" . $sections{$p} . \"]\";\n> +\t\t\t$sep = \", \";\n> +\t\t}\n> +\t\tpush @{$out{$k}}, \".\\n\\n\";\n> +\t} else {\n> +\t\tdie \"can't happen: $k not in any source\";\n> +\t}\n> +}\n> +\n> +for (my $i = 0; $i < $#all_keys; $i++) {\n> +\tnext if $#{$out{$all_keys[$i]}} != $#{$out{$all_keys[$i+1]}};\n> +\tmy $same = 1;\n> +\tfor (my $j = 1; $j <= $#{$out{$all_keys[$i]}}; $j++) {\n> +\t\tif ($out{$all_keys[$i]}[$j] ne $out{$all_keys[$i+1]}[$j]) {\n> +\t\t\t$same = 0;\n> +\t\t\tlast;\n> +\t\t}\n> +\t}\n> +\tif ($same) {\n> +\t\t$out{$all_keys[$i]} = [$out{$all_keys[$i]}[0]];\n> +\t}\n> +}\n> +\n> +foreach my $k (@all_keys) {\n> +\tprint @{$out{$k}};\n> +}\n\nInstead of that, I would propose the following UNTESTED code:\n\n-- 8< --\n%vars = find_insertion_points($mainlist, \\%vars);\n# %vars has now the following format:\n# 'name' => {\n# \t'lineno' => line of $mainfile where description should be inserted\n# \t'manpages' => [ <manpage_name>... ]\n# }\n\n# group by insertion point\nmy %insertion_point; ## or just %insert\nforeach my $v (keys %vars) {\n\tpush @{$insertion_point{$v->{'lineno'}}}, $v;\n}\n\nopen my $fh, '<', $mainfile\n\tor die \"cannot open '$mainfile': $!\";\nwhile (my $line = <$fh>) {\n\tif (exists $insertion_point{$.}) {\n\t\tprint document_vars($insertion_point{$.}, \\%vars);\n\t\tprint \"\\n\";\n\t}\n\tprint $line;\n}\n# special case: insertion after last line in $mainfile\nprint document_vars($insertion_point{-1}, \\%vars)\n\tif exists $insertion_point{-1};\nclose $fh\n\tor die \"cannot close '$mainfile': $!\";\n\nexit 0;\n\n## those subroutines should probably be defined earlier\n\nsub find_insertion_points {\n\tmy ($mainlist, $missing_vars) = @_;\n\n\tmy %res; ## not required if we modify %$missing_vars in-place\n\n\tmy %all_vars = (%$mainlist, %$missing_vars);\n\tmy $lineno = -1; # means after last line\n\n\t# reverse order because we want to find a place before which to insert\n\t# generated documentation; it is easy to find where description\n\t# of variable begins, but in general harder to find where it ends.\n\tforeach my $key (reverse sort { lc($a) cmp lc($b) } keys %all_vars) {\n\t\tmy $val = $all_vars{$key};\n\t\tif (ref $val) {\n\t\t\t# this came from %$missing_vars\n\t\t\t$res{$v} = { 'lineno' => $lineno, 'manpages' => $val };\n\t\t\t## or $missing_vars->{$v} instead of $res{$v} if in-place\n\t\t} else {\n\t\t\t# this came from %$mainlist\n\t\t\t$lineno = $value;\n\t\t}\n\t}\n\treturn %res; ## not required if in-place\n}\n\n## this is single place where we need to change code if output changes,\n## e.g. to\n##\n##   format.attach         linkgit:git-format-patch[1]\n##   format.cc             linkgit:git-format-patch[1]\n##   format.headers        linkgit:git-format-patch[1]\n##   format.pretty         linkgit:gitpretty[7]\nsub document_vars {\n\tmy ($keylist, $vars) = @_;\n\n\t# generate output for each key now, to compact output, because it is\n\t# easier to compare strings than arrays\n\tforeach my $k (@$keylist) {\n\t\t$vars->{$k}{'output'} = \"\\tSee: \".gen_links($vars->{$k}{'manpages'}).\".\\n\";\n\t}\n\n\tmy $output = '';\n\t## the below could be done in different way, e.g. using new array for\n\t## sorted keys, and using 'my $k = pop @keys' etc.\n\t$keylist = [ sort @$keylist ];\n\tfor (my $i = 0; $i < @$keylist; $i++) {\n\t\tmy $k = $keylist->[$i];\n\t\t$output .= \"$k::\\n\";\n\t\tunless ($i <= $#@$keylist &&\n\t\t        $keylist->[$i]{'output'} eq $keylist->[$i+1]{'output'}) {\n\t\t\t$output .= $k->{'output'};\n\t\t}\n\t}\n\n\treturn $output;\n}\n\n## we can make it smarter in the future, for example:\n## 'linkgit:git-foo[1], linkgit:git-bar[1] and linkgit:git-baz[1] for details';\nsub gen_links {\n\tmy $manpages = shift;\n\treturn join(\", \", map { linkgit($_) } @$manpages);\n}\n\nsub linkgit {\n\tmy $manpage = shift;\n\n\tif (!exists $manpage_section{$manpage}) {\n\t\twarn \"section for $manpage unknown\\n\";\n\t\t$manpage_section{$manpage} = 1;\n\t}\n\treturn \"linkgit:${manpage}[$manpage_section{$manpage}]\";\n}\n\n__END__\n-- >8 --\n\n-- \nJakub Narebski\nPoland\n"},{"id":"154346","messageId":"201010242244.24326.jnareb@gmail.com","threadId":"25517","inReplyTo":"201010241636.51106.jnareb@gmail.com","subject":"[RFC PATCH v3 2/3] Documentation: complete config list from other manpages","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2010-10-24T20:44:22Z","receivedAt":"2010-10-24T20:44:22Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"From: Thomas Rast <trast@student.ethz.ch>\n\nAdd an autogeneration script Documentation/make-config-list.perl\nthat complete list of config variables with missing variables\nfrom other manpages.\n\nThis script generates minimal documentation for those missing config\nvariables at appropriate place in Documentation/config-vars.txt,\nusing the following form:\n\n    foo.bar::\n    foo.baz::\n        See linkgit:git-foo[1].\n\n\nIt does that as follows:\n\n* parse config-vars-src.txt (was config-vars.txt, which is now generated)\n  to find out config variables it contains\n\n* parse each manpage source (following includes) for config variable\n  headers\n\n* assemble a new config-vars.txt that completes the original list with\n  \"See linkgit:git-foo[1]\" entries for all variables that were not in\n  it config-vars-src.txt\n\nSigned-off-by: Thomas Rast <trast@student.ethz.ch>\nSigned-off-by: Jakub Narebski <jnareb@gmail.com>\n---\nThis is my take on commit message and on autogeneration script.  I have\nattached diff between config-vars-src.txt and generated config-vars.txt.\n\nThe differences from v2 by Thomas Rast:\n* Removed stray changes to Documentation/Makefile and \n  Documentation/config-vars-src.txt\n\n* The config-vars.txt target now depends on $(cmds_txt), which are \n  included by git.txt (without it, and without 'make doc' ran, the\n  generation of \"make -C Documentation config-vars.txt\" failed because\n  it couldn't find IIRC cmds-mainporcelain.txt).  See below.\n\n* The config-vars.txt target now uses $(QUIET_GEN) and $(PERL_PATH),\n  and makes use of make's automatic variables ($@, $<), like other\n  targets that run *.perl scripts.  It uses $(MAN_TXT) in place of\n  its definition, i.e. '$(MAN1_TXT) $(MAN5_TXT) $(MAN7_TXT)'\n\n* The make-config-vars.perl invocation in config-vars.txt target\n  now has extra '--ignore=merge-config.txt' because config-vars.src.txt\n  contains 'include::merge-config.txt[]'.  See below.\n\n* The make-config-vars.perl got rewritten according to proposals in\n  parent email.  In general this means that instead of decomposing\n  config-vars-src.txt, adding documentation of missing variables,\n  and then recomposing it into config-vars.txt (with side-effects\n  such as lowercasing variable names, and sorting variables), it\n  simply finds places where to insert missing documentation, and\n  generates and inserts it there.\n\n  This means that read_varlist() got simplified, and main code got\n  rewritten.\n\nThe patch with differences between Thomas patch and mine is attached\nas text/plain to this email.\n\n\nIssues to be solved (aka why this is an RFC):\n* Dependencies for config-vars.txt target; probably just needs \n  modification to build-docdep.perl script.\n\n* read_varlist does not follow includes, and that is why we had to\n  manually ignore merge-config.txt\n\n* Either sorting or inserting generated documentation could be\n  improved; as can be seen in attached config-vars.txt the variables\n  from manpage for git-http-backend got split.\n\n\n Documentation/Makefile                             |    5 +\n .../{config-vars.txt => config-vars-src.txt}       |    0\n Documentation/make-config-list.perl                |  174 ++++++++++++++++++++\n 3 files changed, 179 insertions(+), 0 deletions(-)\n rename Documentation/{config-vars.txt => config-vars-src.txt} (100%)\n create mode 100755 Documentation/make-config-list.perl\n\ndiff --git a/Documentation/Makefile b/Documentation/Makefile\nindex e117bc4..be35bf3 100644\n--- a/Documentation/Makefile\n+++ b/Documentation/Makefile\n@@ -320,6 +320,11 @@ howto-index.txt: howto-index.sh $(wildcard howto/*.txt)\n \t'$(SHELL_PATH_SQ)' ./howto-index.sh $(wildcard howto/*.txt) >$@+ && \\\n \tmv $@+ $@\n \n+config-vars.txt: config-vars-src.txt $(MAN_TXT) $(cmds_txt)\n+\t$(QUIET_GEN)$(PERL_PATH) ./make-config-list.perl \\\n+\t\t--mainlist=$< --ignore=$@ --ignore=merge-config.txt $(MAN_TXT) >$@+ && \\\n+\tmv $@+ $@\n+\n $(patsubst %,%.html,$(ARTICLES)) : %.html : %.txt\n \t$(QUIET_ASCIIDOC)$(ASCIIDOC) $(ASCIIDOC_EXTRA) -b xhtml11 $*.txt\n \ndiff --git a/Documentation/config-vars.txt b/Documentation/config-vars-src.txt\nsimilarity index 100%\nrename from Documentation/config-vars.txt\nrename to Documentation/config-vars-src.txt\ndiff --git a/Documentation/make-config-list.perl b/Documentation/make-config-list.perl\nnew file mode 100755\nindex 0000000..fe7ac70\n--- /dev/null\n+++ b/Documentation/make-config-list.perl\n@@ -0,0 +1,174 @@\n+#!/usr/bin/perl\n+\n+use strict;\n+use warnings;\n+use Getopt::Long;\n+use Cwd;\n+use Data::Dumper;\n+\n+\n+my %ignore;\n+my $rc = GetOptions(\n+\t\"mainlist=s\" => \\my $mainlistfile,\n+\t\"ignore=s\" => sub { $ignore{$_[1]} = 1 },\n+);\n+\n+if (!$rc || !defined $mainlistfile) {\n+\tprint \"$0 --mainlist=<mainlist> [--ignore=<ignore>...] <asciidoc_manpage>...\\n\";\n+\texit 1;\n+}\n+\n+\n+sub read_varlist {\n+\tmy ($filename) = @_;\n+\n+\topen my $fh, '<', $filename\n+\t\tor die \"Couldn't open '$filename' for reading: $!\";\n+\n+\tmy (%mainlist, @mainvars);\n+\twhile (<$fh>) {\n+\t\tif (/^(\\S+)::/) {\n+\t\t\tmy $v = $1;\n+\t\t\tpush @mainvars, $v;\n+\t\t\t$mainlist{lc($v)} = $.;\n+\t\t}\n+\t}\n+\n+\tclose $fh\n+\t\tor die \"Couldn't close '$filename': $!\";\n+\n+\treturn \\%mainlist, \\@mainvars;\n+}\n+\n+my %var_manpages;\n+my %manpage_section;\n+\n+sub read_man_txt {\n+\tmy ($filename, $manpage) = @_;\n+\tif (!defined $manpage) {\n+\t\t$manpage = $filename;\n+\t\t$manpage =~ s/\\.txt//;\n+\t}\n+\n+\topen my $fh, '<', $filename\n+\t\tor die \"Couldn't open '$filename' for reading: $!\";\n+\twhile (<$fh>) {\n+\t\tif ($. < 5 && /^$manpage\\((\\d+)\\)/) {\n+\t\t\t$manpage_section{$manpage} = $1;\n+\t\t}\n+\t\tif (/^([a-z0-9]+\\.[a-zA-Z<>0-9.]+)::/) {\n+\t\t\tpush @{$var_manpages{$1}}, $manpage;\n+\t\t}\n+\t\tif (/^include::\\s*(\\S+)\\s*\\[\\]/ &&\n+\t\t    !exists $ignore{$1}) {\n+\t\t\tread_man_txt($1, $manpage);\n+\t\t}\n+\t}\n+\tclose $fh\n+\t\tor die \"Couldn't close '$filename': $!\";\n+}\n+\n+sub find_insertion_points {\n+\tmy ($mainlist, $missing_vars) = @_;\n+\tmy %insert;\n+\n+\tmy %all_vars = (%$mainlist, %$missing_vars);\n+\tmy $lineno = -1; # means after last line\n+\n+\t# reverse order because we want to find a place before which to insert\n+\t# generated documentation; it is easy to find where description\n+\t# of variable begins, but in general harder to find where it ends.\n+\tmy @sorted_vars = reverse sort { lc($a) cmp lc($b) } keys %all_vars;\n+\t#print STDERR join(\"\\n\", @sorted_vars).\"\\n\";\n+\tforeach my $key (@sorted_vars) {\n+\t\tmy $val = $all_vars{$key};\n+\t\tif (ref $val) {\n+\t\t\t# this came from %$missing_vars\n+\t\t\tpush @{$insert{$lineno}}, $key;\n+\t\t\tprint STDERR \"$key missing ($lineno)\\n\";\n+\t\t} else {\n+\t\t\t# this came from %$mainlist\n+\t\t\tif ($lineno < 0) {\n+\t\t\t\t# $lineno < 0 means after end of file (special case)\n+\t\t\t\t$lineno = $val;\n+\t\t\t} else {\n+\t\t\t\t# this is in case of unsorted entries in $mainlistfile\n+\t\t\t\t$lineno = $val < $lineno ? $val : $lineno; # min($val, $lineno)\n+\t\t\t}\n+\t\t\tprint STDERR \"$key $val $lineno\\n\";\n+\t\t}\n+\t}\n+\treturn %insert;\n+}\n+\n+sub vars_documentation {\n+\tmy ($keylist, $vars) = @_;\n+\tmy @keys = sort @$keylist;\n+\tmy %out;\n+\n+\t# generate output for each key now, because it is easier to compare\n+\t# strings than arrays; comparing which is needed for compacting output\n+\tforeach my $k (@keys) {\n+\t\t$out{$k} = \"\\tSee: \".gen_links($vars->{$k}).\".\\n\";\n+\t}\n+\n+\tmy $output = '';\n+\twhile (my $k = pop @keys) {\n+\t\t$output .= $k.\"::\\n\";\n+\t\tunless (@keys && $out{$k} eq $out{$keys[0]}) {\n+\t\t\t$output .= $out{$k};\n+\t\t}\n+\t}\n+\treturn $output;\n+}\n+\n+sub gen_links {\n+\tmy $manpages = shift;\n+\treturn join(\", \", map { linkgit($_) } @$manpages);\n+}\n+\n+sub linkgit {\n+\tmy $manpage = shift;\n+\n+\tif (!exists $manpage_section{$manpage}) {\n+\t\twarn \"section for $manpage unknown\\n\";\n+\t\t$manpage_section{$manpage} = 1;\n+\t}\n+\treturn \"linkgit:${manpage}[$manpage_section{$manpage}]\";\n+}\n+\n+\n+foreach my $name (@ARGV) {\n+\tread_man_txt($name);\n+}\n+\n+my ($mainlist, $mainvars) = read_varlist($mainlistfile);\n+\n+my @missing_vars =\n+\tgrep { !exists $mainlist->{lc($_)} } keys %var_manpages;\n+my %missing_vars =\n+\tmap { $_ => $var_manpages{$_} } @missing_vars;\n+\n+my %insert = find_insertion_points($mainlist, \\%missing_vars);\n+$Data::Dumper::Indent = 0;\n+$Data::Dumper::Sortkeys = 1;\n+$Data::Dumper::Terse = 1;\n+#print STDERR Dumper(\\%insert);\n+\n+open my $fh, '<', $mainlistfile\n+\tor die \"Couldn't open '$mainlistfile' for reading: $!\";\n+while (<$fh>) {\n+\tif (exists $insert{$.}) {\n+\t\tprint vars_documentation($insert{$.}, \\%missing_vars);\n+\t\tprint \"\\n\";\n+\t}\n+\tprint;\n+}\n+# special case: insertion after last line in $mainlistfile\n+print vars_documentation($insert{-1}, \\%missing_vars)\n+\tif exists $insert{-1};\n+close $fh\n+\tor die \"Couldn't close '$mainlistfile': $!\";\n+\n+exit 0;\n+__END__\n-- \n1.7.3\n\n\n\ndiff --git 1/Documentation/config-vars-src.txt 2/Documentation/config-vars.txt\nindex a8d37a7..e8c7eb3 100644\n--- 1/Documentation/config-vars-src.txt\n+++ 2/Documentation/config-vars.txt\n@@ -680,6 +680,9 @@ commit.template::\n \t\"{tilde}/\" is expanded to the value of `$HOME` and \"{tilde}user/\" to the\n \tspecified user's home directory.\n \n+cvsexportcommit.cvsdir::\n+\tSee: linkgit:git-cvsexportcommit[1].\n+\n diff.autorefreshindex::\n \tWhen using 'git diff' to compare with work tree\n \tfiles, do not consider stat-only change as changed.\n@@ -699,6 +702,9 @@ diff.external::\n \tyou want to use an external diff program only on a subset of\n \tyour files, you\tmight want to use linkgit:gitattributes[5] instead.\n \n+diff.guitool::\n+\tSee: linkgit:git-difftool[1].\n+\n diff.mnemonicprefix::\n \tIf set, 'git diff' uses a prefix pair that is different from the\n \tstandard \"a/\" and \"b/\" depending on what is being compared.  When\n@@ -897,6 +903,10 @@ gitcvs.commitmsgannotation::\n \tAppend this string to each commit message. Set to empty string\n \tto disable this feature. Defaults to \"via git-CVS emulator\".\n \n+gitcvs.dbuser::\n+gitcvs.dbpass::\n+\tSee: linkgit:git-cvsserver[1].\n+\n gitcvs.enabled::\n \tWhether the CVS server interface is enabled for this repository.\n \tSee linkgit:git-cvsserver[1].\n@@ -1084,11 +1094,17 @@ help.autocorrect::\n \tvalue is 0 - the command will be just shown but not executed.\n \tThis is the default.\n \n+http.getanyfile::\n+\tSee: linkgit:git-http-backend[1].\n+\n http.proxy::\n \tOverride the HTTP proxy, normally configured using the 'http_proxy'\n \tenvironment variable (see linkgit:curl[1]).  This can be overridden\n \ton a per-remote basis; see remote.<name>.proxy\n \n+http.receivepack::\n+\tSee: linkgit:git-http-backend[1].\n+\n http.sslVerify::\n \tWhether to verify the SSL certificate when fetching or pushing\n \tover HTTPS. Can be overridden by the 'GIT_SSL_NO_VERIFY' environment\n@@ -1150,6 +1166,9 @@ http.noEPSV::\n \tsupport EPSV mode. Can be overridden by the 'GIT_CURL_FTP_NO_EPSV'\n \tenvironment variable. Default is false (curl will use EPSV).\n \n+http.uploadpack::\n+\tSee: linkgit:git-http-backend[1].\n+\n http.useragent::\n \tThe HTTP USER_AGENT string presented to an HTTP server.  The default\n \tvalue represents the version of the client git such as git/1.7.1.\n@@ -1174,6 +1193,17 @@ imap::\n \tThe configuration variables in the 'imap' section are described\n \tin linkgit:git-imap-send[1].\n \n+imap.user::\n+imap.tunnel::\n+imap.sslverify::\n+imap.preformattedHTML::\n+imap.port::\n+imap.pass::\n+imap.host::\n+imap.folder::\n+imap.authMethod::\n+\tSee: linkgit:git-imap-send[1].\n+\n init.templatedir::\n \tSpecify the directory from which templates will be copied.\n \t(See the \"TEMPLATE DIRECTORY\" section of linkgit:git-init[1].)\n@@ -1249,6 +1279,10 @@ man.<tool>.path::\n \n include::merge-config.txt[]\n \n+merge.summary::\n+merge.log::\n+\tSee: linkgit:git-fmt-merge-msg[1].\n+\n mergetool.<tool>.path::\n \tOverride the path for the given tool.  This is useful in case\n \tyour tool is not in the PATH.\n@@ -1688,6 +1722,13 @@ submodule.<name>.ignore::\n \tboth settings can be overridden on the command line by using the\n \t\"--ignore-submodules\" option.\n \n+svn.useSvnsyncProps::\n+svn.useSvmProps::\n+svn.pathnameencoding::\n+svn.noMetadata::\n+svn.brokenSymlinkWorkaround::\n+\tSee: linkgit:git-svn[1].\n+\n tar.umask::\n \tThis variable can be used to restrict the permission bits of\n \ttar archive entries.  The default is 0002, which turns off the\n\n\ndiff --git a/Documentation/Makefile b/Documentation/Makefile\nindex 747b849..8ce75d2 100644\n--- a/Documentation/Makefile\n+++ b/Documentation/Makefile\n@@ -125,7 +125,7 @@ endif\n \n SHELL_PATH ?= $(SHELL)\n # Shell quote;\n-SHELL_PATH_SQ = $(subst ','\\'',$(SHELL_PATH)) #'\n+SHELL_PATH_SQ = $(subst ','\\'',$(SHELL_PATH))\n \n #\n # Please note that there is a minor bug in asciidoc.\n@@ -320,12 +320,10 @@ howto-index.txt: howto-index.sh $(wildcard howto/*.txt)\n \t'$(SHELL_PATH_SQ)' ./howto-index.sh $(wildcard howto/*.txt) >$@+ && \\\n \tmv $@+ $@\n \n-config-vars.txt: config-vars-src.txt $(MAN1_TXT) $(MAN5_TXT) $(MAN7_TXT)\n-\t./make-config-list.perl --mainlist=config-vars-src.txt \\\n-\t\t--ignore=config-vars.txt \\\n-\t\t$(MAN1_TXT) $(MAN5_TXT) $(MAN7_TXT) \\\n-\t\t> config-vars.txt+ && \\\n-\tmv config-vars.txt+ config-vars.txt\n+config-vars.txt: config-vars-src.txt $(MAN_TXT) $(cmds_txt)\n+\t$(QUIET_GEN)$(PERL_PATH) ./make-config-list.perl \\\n+\t\t--mainlist=$< --ignore=$@ --ignore=merge-config.txt $(MAN_TXT) >$@+ && \\\n+\tmv $@+ $@\n \n $(patsubst %,%.html,$(ARTICLES)) : %.html : %.txt\n \t$(QUIET_ASCIIDOC)$(ASCIIDOC) $(ASCIIDOC_EXTRA) -b xhtml11 $*.txt\ndiff --git a/Documentation/config-vars-src.txt b/Documentation/config-vars-src.txt\nindex 949259c..a8d37a7 100644\n--- a/Documentation/config-vars-src.txt\n+++ b/Documentation/config-vars-src.txt\n@@ -936,7 +936,7 @@ gitcvs.dbname::\n \n gitcvs.dbdriver::\n \tUsed Perl DBI driver. You can specify any available driver\n-\tfor this here, but it might not work. git-cvsserver is tested\n+        for this here, but it might not work. git-cvsserver is tested\n \twith 'DBD::SQLite', reported to work with 'DBD::Pg', and\n \treported *not* to work with 'DBD::mysql'. Experimental feature.\n \tMay not contain double colons (`:`). Default: 'SQLite'.\ndiff --git a/Documentation/make-config-list.perl b/Documentation/make-config-list.perl\nindex f086867..2894d96 100755\n--- a/Documentation/make-config-list.perl\n+++ b/Documentation/make-config-list.perl\n@@ -4,128 +4,165 @@ use strict;\n use warnings;\n use Getopt::Long;\n \n+\n my %ignore;\n-\n my $rc = GetOptions(\n \t\"mainlist=s\" => \\my $mainlistfile,\n \t\"ignore=s\" => sub { $ignore{$_[1]} = 1 },\n-\t\"no-sort\" => \\my $no_sort,\n-\t);\n+);\n \n-if (!$rc or (!-r $mainlistfile)) {\n+if (!$rc || !defined $mainlistfile) {\n \tprint \"$0 --mainlist=<mainlist> [--ignore=<ignore>...] <asciidoc_manpage>...\\n\";\n \texit 1;\n }\n \n+my %var_manpages;\n+my %manpage_section;\n+\n+foreach my $name (@ARGV) {\n+\tread_man_txt($name);\n+}\n+\n+my ($mainlist, $mainvars) = read_varlist($mainlistfile);\n+\n+my @missing_vars =\n+\tgrep { !exists $mainlist->{lc($_)} } keys %var_manpages;\n+my %missing_vars =\n+\tmap { $_ => $var_manpages{$_} } @missing_vars;\n+\n+my %insert = find_insertion_points($mainlist, \\%missing_vars);\n+\n+open my $fh, '<', $mainlistfile\n+\tor die \"Couldn't open '$mainlistfile' for reading: $!\";\n+while (<$fh>) {\n+\tif (exists $insert{$.}) {\n+\t\tprint vars_documentation($insert{$.}, \\%missing_vars);\n+\t\tprint \"\\n\";\n+\t}\n+\tprint;\n+}\n+# special case: insertion after last line in $mainlistfile\n+print vars_documentation($insert{-1}, \\%missing_vars)\n+\tif exists $insert{-1};\n+close $fh\n+\tor die \"Couldn't close '$mainlistfile': $!\";\n+\n+exit 0;\n+\n+# ----------------------------------------------------------------------\n+# ----------------------------------------------------------------------\n+# ----------------------------------------------------------------------\n+\n sub read_varlist {\n-\tmy ($file) = @_;\n+\tmy ($filename) = @_;\n+\n+\topen my $fh, '<', $filename\n+\t\tor die \"Couldn't open '$filename' for reading: $!\";\n \n-\topen my $fh, \"<\", $file or die \"cannot open $file: $!\";\n \tmy (%mainlist, @mainvars);\n-\n-\tmy ($v, $last_v);\n-\tmy $in_block = 0;\n \twhile (<$fh>) {\n \t\tif (/^(\\S+)::/) {\n-\t\t\t$v = lc $1;\n-\t\t\t$in_block = 0;\n-\t\t\tpush @{$mainlist{$v}}, $_;\n+\t\t\tmy $v = $1;\n \t\t\tpush @mainvars, $v;\n-\t\t} elsif (/^$/ && !$in_block) {\n-\t\t\tif (defined $last_v && !$#{$mainlist{$last_v}}) {\n-\t\t\t\t$mainlist{$last_v} = $mainlist{$v};\n-\t\t\t}\n-\t\t\t$last_v = $v;\n-\t\t} elsif (defined $v) {\n-\t\t\tpush @{$mainlist{$v}}, $_;\n-\t\t\t$in_block = !$in_block if /^--$/;\n+\t\t\t$mainlist{lc($v)} = $.;\n \t\t}\n \t}\n \n-\tclose $fh or die \"eh? close failed: $!\";\n+\tclose $fh\n+\t\tor die \"Couldn't close '$filename': $!\";\n \n \treturn \\%mainlist, \\@mainvars;\n }\n \n-my %vars;\n-my %sections;\n-\n-sub read_file {\n-\tmy ($name, $main_name) = @_;\n-\tif (!defined $main_name) {\n-\t\t$main_name = $name;\n+sub read_man_txt {\n+\tmy ($filename, $manpage) = @_;\n+\tif (!defined $manpage) {\n+\t\t$manpage = $filename;\n+\t\t$manpage =~ s/\\.txt//;\n \t}\n-\tmy $manpage_name = $main_name;\n-\t$manpage_name =~ s/\\.txt//;\n-\tmy $fp;\n-\topen $fp, '<', $name or die \"open $name failed: $!\";\n-\twhile (<$fp>) {\n-\t\tif ($. < 5 && /^$manpage_name\\((\\d+)\\)/) {\n-\t\t\t$sections{$manpage_name} = $1;\n+\n+\topen my $fh, '<', $filename\n+\t\tor die \"Couldn't open '$filename' for reading: $!\";\n+\twhile (<$fh>) {\n+\t\tif ($. < 5 && /^$manpage\\((\\d+)\\)/) {\n+\t\t\t$manpage_section{$manpage} = $1;\n \t\t}\n-\t\tif (/^([a-z0-9]+\\.[a-z<>0-9.]+)::/) {\n-\t\t\tpush @{$vars{$1}}, $manpage_name;\n+\t\tif (/^([a-z0-9]+\\.[a-zA-Z<>0-9.]+)::/) {\n+\t\t\tpush @{$var_manpages{$1}}, $manpage;\n \t\t}\n-\t\tif (/^include::\\s*(\\S+)\\s*\\[\\]/\n-\t\t    && !exists $ignore{$1}) {\n-\t\t\tread_file($1, $main_name);\n+\t\tif (/^include::\\s*(\\S+)\\s*\\[\\]/ &&\n+\t\t    !exists $ignore{$1}) {\n+\t\t\tread_man_txt($1, $manpage);\n \t\t}\n \t}\n-\tclose $fp or die \"close $name failed: $!\";\n-}\n-\n-foreach my $name (@ARGV) {\n-\tread_file($name);\n+\tclose $fh\n+\t\tor die \"Couldn't close '$filename': $!\";\n }\n \n-my ($mainlist, $mainvars) = read_varlist($mainlistfile);\n-\n-my @all_keys = @$mainvars;\n-foreach my $k (keys %vars) {\n-\tif (!exists $mainlist->{$k}) {\n-\t\tpush @all_keys, $k;\n-\t}\n-}\n+sub find_insertion_points {\n+\tmy ($mainlist, $missing_vars) = @_;\n+\tmy %insert;\n \n-@all_keys = sort @all_keys unless $no_sort;\n+\tmy %all_vars = (%$mainlist, %$missing_vars);\n+\tmy $lineno = -1; # means after last line\n \n-my %out;\n-foreach my $k (@all_keys) {\n-\tif (exists $mainlist->{$k}) {\n-\t\tpush @{$out{$k}}, @{$mainlist->{$k}}, \"\\n\";\n-\t} elsif (exists $vars{$k}) {\n-\t\tpush @{$out{$k}}, $k . \"::\\n\";\n-\t\tpush @{$out{$k}}, \"\\tSee \";\n-\t\tmy $sep = \" \";\n-\t\tforeach my $p (sort @{$vars{$k}}) {\n-\t\t\tnext if ($p =~ /$mainlistfile/);\n-\t\t\tif (!exists $sections{$p}) {\n-\t\t\t\twarn \"section for $p unknown\";\n-\t\t\t\t$sections{$p} = 1;\n+\t# reverse order because we want to find a place before which to insert\n+\t# generated documentation; it is easy to find where description\n+\t# of variable begins, but in general harder to find where it ends.\n+\tmy @sorted_vars = reverse sort { lc($a) cmp lc($b) } keys %all_vars;\n+\tforeach my $key (@sorted_vars) {\n+\t\tmy $val = $all_vars{$key};\n+\t\tif (ref $val) {\n+\t\t\t# this came from %$missing_vars\n+\t\t\tpush @{$insert{$lineno}}, $key;\n+\t\t} else {\n+\t\t\t# this came from %$mainlist\n+\t\t\tif ($lineno < 0) {\n+\t\t\t\t# $lineno < 0 means after end of file (special case)\n+\t\t\t\t$lineno = $val;\n+\t\t\t} else {\n+\t\t\t\t# this is in case of unsorted entries in $mainlistfile\n+\t\t\t\t$lineno = $val < $lineno ? $val : $lineno; # min($val, $lineno)\n \t\t\t}\n-\t\t\tpush @{$out{$k}}, $sep . \"linkgit:\" . $p . \"[\" . $sections{$p} . \"]\";\n-\t\t\t$sep = \", \";\n \t\t}\n-\t\tpush @{$out{$k}}, \".\\n\\n\";\n-\t} else {\n-\t\tdie \"can't happen: $k not in any source\";\n \t}\n+\treturn %insert;\n }\n \n-for (my $i = 0; $i < $#all_keys; $i++) {\n-\tnext if $#{$out{$all_keys[$i]}} != $#{$out{$all_keys[$i+1]}};\n-\tmy $same = 1;\n-\tfor (my $j = 1; $j <= $#{$out{$all_keys[$i]}}; $j++) {\n-\t\tif ($out{$all_keys[$i]}[$j] ne $out{$all_keys[$i+1]}[$j]) {\n-\t\t\t$same = 0;\n-\t\t\tlast;\n-\t\t}\n+sub vars_documentation {\n+\tmy ($keylist, $vars) = @_;\n+\tmy @keys = sort @$keylist;\n+\tmy %out;\n+\n+\t# generate output for each key now, because it is easier to compare\n+\t# strings than arrays; comparing which is needed for compacting output\n+\tforeach my $k (@keys) {\n+\t\t$out{$k} = \"\\tSee: \".gen_links($vars->{$k}).\".\\n\";\n \t}\n-\tif ($same) {\n-\t\t$out{$all_keys[$i]} = [$out{$all_keys[$i]}[0]];\n+\n+\tmy $output = '';\n+\twhile (my $k = pop @keys) {\n+\t\t$output .= $k.\"::\\n\";\n+\t\tunless (@keys && $out{$k} eq $out{$keys[0]}) {\n+\t\t\t$output .= $out{$k};\n+\t\t}\n \t}\n+\treturn $output;\n }\n \n-foreach my $k (@all_keys) {\n-\tprint @{$out{$k}};\n+sub gen_links {\n+\tmy $manpages = shift;\n+\treturn join(\", \", map { linkgit($_) } @$manpages);\n }\n+\n+sub linkgit {\n+\tmy $manpage = shift;\n+\n+\tif (!exists $manpage_section{$manpage}) {\n+\t\twarn \"section for $manpage unknown, assuming '1'\\n\";\n+\t\t$manpage_section{$manpage} = 1;\n+\t}\n+\treturn \"linkgit:${manpage}[$manpage_section{$manpage}]\";\n+}\n+\n+__END__\n"},{"id":"154347","messageId":"201010242255.14379.jnareb@gmail.com","threadId":"25517","inReplyTo":"201010242244.24326.jnareb@gmail.com","subject":"[RFC PATCH v3 2/3 (amend)] Documentation: complete config list from other manpages","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2010-10-24T20:55:13Z","receivedAt":"2010-10-24T20:55:13Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"From: Thomas Rast <trast@student.ethz.ch>\n\nAdd an autogeneration script Documentation/make-config-list.perl\nthat complete list of config variables with missing variables\nfrom other manpages.\n\nThis script generates minimal documentation for those missing config\nvariables at appropriate place in Documentation/config-vars.txt,\nusing the following form:\n\n    foo.bar::\n    foo.baz::\n        See linkgit:git-foo[1].\n\n\nIt does that as follows:\n\n* parse config-vars-src.txt (was config-vars.txt, which is now generated)\n  to find out config variables it contains\n\n* parse each manpage source (following includes) for config variable\n  headers\n\n* assemble a new config-vars.txt that completes the original list with\n  \"See linkgit:git-foo[1]\" entries for all variables that were not in\n  it config-vars-src.txt\n\nSigned-off-by: Thomas Rast <trast@student.ethz.ch>\nSigned-off-by: Jakub Narebski <jnareb@gmail.com>\n---\nThis version has removed stray commented out remains of debugging the\nmake-config-list.perl script, and has it slightly reordered for better\nreadibility.\n\nI have accidentally included old version of a patch.  I am very sorry.\n\nBelow there comments from previous email (without references to\nattachements, which are not included in this email)\n...\n\nThe differences from v2 by Thomas Rast:\n* Removed stray changes to Documentation/Makefile and \n  Documentation/config-vars-src.txt\n\n* The config-vars.txt target now depends on $(cmds_txt), which are \n  included by git.txt (without it, and without 'make doc' ran, the\n  generation of \"make -C Documentation config-vars.txt\" failed because\n  it couldn't find IIRC cmds-mainporcelain.txt).  See below.\n\n* The config-vars.txt target now uses $(QUIET_GEN) and $(PERL_PATH),\n  and makes use of make's automatic variables ($@, $<), like other\n  targets that run *.perl scripts.  It uses $(MAN_TXT) in place of\n  its definition, i.e. '$(MAN1_TXT) $(MAN5_TXT) $(MAN7_TXT)'\n\n* The make-config-vars.perl invocation in config-vars.txt target\n  now has extra '--ignore=merge-config.txt' because config-vars.src.txt\n  contains 'include::merge-config.txt[]'.  See below.\n\n* The make-config-vars.perl got rewritten according to proposals in\n  parent email.  In general this means that instead of decomposing\n  config-vars-src.txt, adding documentation of missing variables,\n  and then recomposing it into config-vars.txt (with side-effects\n  such as lowercasing variable names, and sorting variables), it\n  simply finds places where to insert missing documentation, and\n  generates and inserts it there.\n\n  This means that read_varlist() got simplified, and main code got\n  rewritten.\n\n\nIssues to be solved (aka why this is an RFC):\n* Dependencies for config-vars.txt target; probably just needs \n  modification to build-docdep.perl script.\n\n* read_varlist does not follow includes, and that is why we had to\n  manually ignore merge-config.txt\n\n* Either sorting or inserting generated documentation could be\n  improved; as can be seen in attached config-vars.txt the variables\n  from manpage for git-http-backend got split.\n\n Documentation/Makefile                             |    5 +\n .../{config-vars.txt => config-vars-src.txt}       |    0\n Documentation/make-config-list.perl                |  168 ++++++++++++++++++++\n 3 files changed, 173 insertions(+), 0 deletions(-)\n rename Documentation/{config-vars.txt => config-vars-src.txt} (100%)\n create mode 100755 Documentation/make-config-list.perl\n\ndiff --git a/Documentation/Makefile b/Documentation/Makefile\nindex e117bc4..8ce75d2 100644\n--- a/Documentation/Makefile\n+++ b/Documentation/Makefile\n@@ -320,6 +320,11 @@ howto-index.txt: howto-index.sh $(wildcard howto/*.txt)\n \t'$(SHELL_PATH_SQ)' ./howto-index.sh $(wildcard howto/*.txt) >$@+ && \\\n \tmv $@+ $@\n \n+config-vars.txt: config-vars-src.txt $(MAN_TXT) $(cmds_txt)\n+\t$(QUIET_GEN)$(PERL_PATH) ./make-config-list.perl \\\n+\t\t--mainlist=$< --ignore=$@ --ignore=merge-config.txt $(MAN_TXT) >$@+ && \\\n+\tmv $@+ $@\n+\n $(patsubst %,%.html,$(ARTICLES)) : %.html : %.txt\n \t$(QUIET_ASCIIDOC)$(ASCIIDOC) $(ASCIIDOC_EXTRA) -b xhtml11 $*.txt\n \ndiff --git a/Documentation/config-vars.txt b/Documentation/config-vars-src.txt\nsimilarity index 100%\nrename from Documentation/config-vars.txt\nrename to Documentation/config-vars-src.txt\ndiff --git a/Documentation/make-config-list.perl b/Documentation/make-config-list.perl\nnew file mode 100755\nindex 0000000..2894d96\n--- /dev/null\n+++ b/Documentation/make-config-list.perl\n@@ -0,0 +1,168 @@\n+#!/usr/bin/perl\n+\n+use strict;\n+use warnings;\n+use Getopt::Long;\n+\n+\n+my %ignore;\n+my $rc = GetOptions(\n+\t\"mainlist=s\" => \\my $mainlistfile,\n+\t\"ignore=s\" => sub { $ignore{$_[1]} = 1 },\n+);\n+\n+if (!$rc || !defined $mainlistfile) {\n+\tprint \"$0 --mainlist=<mainlist> [--ignore=<ignore>...] <asciidoc_manpage>...\\n\";\n+\texit 1;\n+}\n+\n+my %var_manpages;\n+my %manpage_section;\n+\n+foreach my $name (@ARGV) {\n+\tread_man_txt($name);\n+}\n+\n+my ($mainlist, $mainvars) = read_varlist($mainlistfile);\n+\n+my @missing_vars =\n+\tgrep { !exists $mainlist->{lc($_)} } keys %var_manpages;\n+my %missing_vars =\n+\tmap { $_ => $var_manpages{$_} } @missing_vars;\n+\n+my %insert = find_insertion_points($mainlist, \\%missing_vars);\n+\n+open my $fh, '<', $mainlistfile\n+\tor die \"Couldn't open '$mainlistfile' for reading: $!\";\n+while (<$fh>) {\n+\tif (exists $insert{$.}) {\n+\t\tprint vars_documentation($insert{$.}, \\%missing_vars);\n+\t\tprint \"\\n\";\n+\t}\n+\tprint;\n+}\n+# special case: insertion after last line in $mainlistfile\n+print vars_documentation($insert{-1}, \\%missing_vars)\n+\tif exists $insert{-1};\n+close $fh\n+\tor die \"Couldn't close '$mainlistfile': $!\";\n+\n+exit 0;\n+\n+# ----------------------------------------------------------------------\n+# ----------------------------------------------------------------------\n+# ----------------------------------------------------------------------\n+\n+sub read_varlist {\n+\tmy ($filename) = @_;\n+\n+\topen my $fh, '<', $filename\n+\t\tor die \"Couldn't open '$filename' for reading: $!\";\n+\n+\tmy (%mainlist, @mainvars);\n+\twhile (<$fh>) {\n+\t\tif (/^(\\S+)::/) {\n+\t\t\tmy $v = $1;\n+\t\t\tpush @mainvars, $v;\n+\t\t\t$mainlist{lc($v)} = $.;\n+\t\t}\n+\t}\n+\n+\tclose $fh\n+\t\tor die \"Couldn't close '$filename': $!\";\n+\n+\treturn \\%mainlist, \\@mainvars;\n+}\n+\n+sub read_man_txt {\n+\tmy ($filename, $manpage) = @_;\n+\tif (!defined $manpage) {\n+\t\t$manpage = $filename;\n+\t\t$manpage =~ s/\\.txt//;\n+\t}\n+\n+\topen my $fh, '<', $filename\n+\t\tor die \"Couldn't open '$filename' for reading: $!\";\n+\twhile (<$fh>) {\n+\t\tif ($. < 5 && /^$manpage\\((\\d+)\\)/) {\n+\t\t\t$manpage_section{$manpage} = $1;\n+\t\t}\n+\t\tif (/^([a-z0-9]+\\.[a-zA-Z<>0-9.]+)::/) {\n+\t\t\tpush @{$var_manpages{$1}}, $manpage;\n+\t\t}\n+\t\tif (/^include::\\s*(\\S+)\\s*\\[\\]/ &&\n+\t\t    !exists $ignore{$1}) {\n+\t\t\tread_man_txt($1, $manpage);\n+\t\t}\n+\t}\n+\tclose $fh\n+\t\tor die \"Couldn't close '$filename': $!\";\n+}\n+\n+sub find_insertion_points {\n+\tmy ($mainlist, $missing_vars) = @_;\n+\tmy %insert;\n+\n+\tmy %all_vars = (%$mainlist, %$missing_vars);\n+\tmy $lineno = -1; # means after last line\n+\n+\t# reverse order because we want to find a place before which to insert\n+\t# generated documentation; it is easy to find where description\n+\t# of variable begins, but in general harder to find where it ends.\n+\tmy @sorted_vars = reverse sort { lc($a) cmp lc($b) } keys %all_vars;\n+\tforeach my $key (@sorted_vars) {\n+\t\tmy $val = $all_vars{$key};\n+\t\tif (ref $val) {\n+\t\t\t# this came from %$missing_vars\n+\t\t\tpush @{$insert{$lineno}}, $key;\n+\t\t} else {\n+\t\t\t# this came from %$mainlist\n+\t\t\tif ($lineno < 0) {\n+\t\t\t\t# $lineno < 0 means after end of file (special case)\n+\t\t\t\t$lineno = $val;\n+\t\t\t} else {\n+\t\t\t\t# this is in case of unsorted entries in $mainlistfile\n+\t\t\t\t$lineno = $val < $lineno ? $val : $lineno; # min($val, $lineno)\n+\t\t\t}\n+\t\t}\n+\t}\n+\treturn %insert;\n+}\n+\n+sub vars_documentation {\n+\tmy ($keylist, $vars) = @_;\n+\tmy @keys = sort @$keylist;\n+\tmy %out;\n+\n+\t# generate output for each key now, because it is easier to compare\n+\t# strings than arrays; comparing which is needed for compacting output\n+\tforeach my $k (@keys) {\n+\t\t$out{$k} = \"\\tSee: \".gen_links($vars->{$k}).\".\\n\";\n+\t}\n+\n+\tmy $output = '';\n+\twhile (my $k = pop @keys) {\n+\t\t$output .= $k.\"::\\n\";\n+\t\tunless (@keys && $out{$k} eq $out{$keys[0]}) {\n+\t\t\t$output .= $out{$k};\n+\t\t}\n+\t}\n+\treturn $output;\n+}\n+\n+sub gen_links {\n+\tmy $manpages = shift;\n+\treturn join(\", \", map { linkgit($_) } @$manpages);\n+}\n+\n+sub linkgit {\n+\tmy $manpage = shift;\n+\n+\tif (!exists $manpage_section{$manpage}) {\n+\t\twarn \"section for $manpage unknown, assuming '1'\\n\";\n+\t\t$manpage_section{$manpage} = 1;\n+\t}\n+\treturn \"linkgit:${manpage}[$manpage_section{$manpage}]\";\n+}\n+\n+__END__\n-- \n1.7.3\n"},{"id":"154404","messageId":"201010251444.08780.jnareb@gmail.com","threadId":"25517","inReplyTo":"20101022155307.GB5554@sigill.intra.peff.net","subject":"Re: [RFC PATCH v2 0/3] Documentation: refactor config variable descriptions","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2010-10-25T12:44:06Z","receivedAt":"2010-10-25T12:44:06Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"On Fri, 22 Oct 2010, Jeff King wrote:\n> On Fri, Oct 22, 2010 at 07:02:28AM +0200, Thomas Rast wrote:\n> \n> > This resurrects (finally) the earlier attempt at\n> > \n> >   http://mid.gmane.org/cover.1280169048.git.trast@student.ethz.ch\n> > \n> > It tries the inverse approach: teaching the script how to find config\n> > variable blocks in each manpage, and then linking them from the main\n> > list.  (Obviously just inserting them into the main list could also\n> > work.)\n> > \n> > In other words, it attempts to push out the \"original\" documentation\n> > of each variable from the main list to the individual manpage, which\n> > is exactly opposite from v1.\n> \n> Thanks for working on this.\n \n[...]\n\n> I have two comments on the approach:\n> \n>   1. It looks like you're more or less just parsing \"::\" list keys from\n>      all of the manpages. This seems somewhat fragile, as there could be\n>      other non-config lists. Can we at least restrict it to\n>      CONFIGURATION sections? It would be nice if we could put in some\n>      kind of semantic markup, but I'm not sure how painful that would be\n>      with asciidoc (we could always resort to comments in the source,\n>      but that would probably get unreadable quickly).\n\nThe regexp for catching config variables is quite strict, but tests\ndone with my version of script modifier further to check for \nCONFIGURATION-like sections (matching /^Config/) shown that we have\nproblems either way.\n\n1. Without checking for CONFIGURATION sections, we have what are \n   probably false positives from gitmodules.txt:\n\n     submodule.<name>.path::\n     submodule.<name>.url::\n     submodule.<name>.update::\n     submodule.<name>.ignore::\n\n   I say *probably* because while gitmodules manpage describes those \n   variables as going into .gitmodules, if I understand it correctly\n   those variables can got to .git/config as an override.\n\n2. With checking for CONFIGURATION-like, we would miss the following\n   configuration variables:\n\n     http.getanyfile:: (for git-http-backend, in 'SERVICES')\n     http.uploadpack:: (for git-http-backend, in 'SERVICES')\n     http.receivepack:: (for git-http-backend, in 'SERVICES')\n\n   These are in git-http-backend manpage, in 'SERVICES' section, which \n   probably should be named then 'CONFIGURING SERVICES'.\n\n   BTW, CONFIGURATION-like means:\n\n    * Configuration\n    * CONFIGURATION\n   \n  but also\n\n    * CONFIG FILE-ONLY OPTIONS\n    * CONFIGURATION FILE\n    * Configuration Mechanism\n    * CONFIG VARIABLES\n    * CONFIGURATION VARIABLES\n    * Configuring database backend\n\n> \n>   2. You recursively follow includes via include::. This means that the\n>      make rule is not accurate. E.g., try:\n> \n>        rm cmds-mainporcelain.txt config-vars.txt\n>        make config-vars.txt\n> \n>      which should fail, as we actually depend on cmds-mainporcelain.txt.\n>      Doing it accurately and automatically would mean making .depend\n>      files for make.\n\nWe do that: see 'doc.dep' target in Documentation/Makefile.  We just\nneed for this target to also add dependencies for config-vars.txt\n(perhaps separate mode for make-config-list.perl, or perhaps \nbuild-docdep.perl should be config-vars-src.txt aware...).\n\n> \n>      But I wonder if the recursive lookup is really required. Some of\n>      the includes with config files can just go away (e.g.,\n>      merge-config.txt is included only by config-vars-src.txt and\n>      git-merge.txt; it can just be merged straight into git-merge.txt\n>      once this system exists).\n\nmerge-config.txt is the only included file with config variables.\nOther includes does not contain config variables.  And because \nmerge-config.txt is also included in config-vars-src.txt, therefore\nthe whole recursive lookup is not necessary.\n\nNote however that make-config-list.perl only creates minimal documentation,\njust link(s) to appropriate mapage(s).  Include-ing merge-config.txt both\nin git-merge.txt and config-vars-src.txt means that we have merg config\nvariables defined in git-config(1) manpage, which I think is nice to have.\n\n>      Others, like pretty-formats.txt, should, \n>      IMHO, get their own user-visible page. Right now with your script\n>      you get[1]:\n> \n>        format.pretty::\n>                The default pretty format for log/show/whatchanged command,\n>                See linkgit:git-log[1], linkgit:git-show[1],\n>                linkgit:git-whatchanged[1].\n> \n>      but I would rather see[2]:\n> \n>        format.pretty::\n>                See linkgit:gitpretty[7].\n\nActually the above block describing `format.pretty` is from beginning in\nconfig-vars-src.txt, and is not added / created by said script.\n\n> \n>      [1]: I assume the single line of block description is an error in\n>           your script.\n\nHmmm?\n\n-- \nJakub Narebski\nPoland\n"},{"id":"154412","messageId":"20101025150405.GC28278@sigill.intra.peff.net","threadId":"25517","inReplyTo":"201010240324.42721.trast@student.ethz.ch","subject":"Re: [RFC PATCH v2 0/3] Documentation: refactor config variable descriptions","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2010-10-25T15:04:05Z","receivedAt":"2010-10-25T15:04:05Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Sun, Oct 24, 2010 at 03:24:42AM +0200, Thomas Rast wrote:\n\n> Jeff King wrote:\n> >   1. It looks like you're more or less just parsing \"::\" list keys from\n> >      all of the manpages. This seems somewhat fragile, as there could be\n> >      other non-config lists. Can we at least restrict it to\n> >      CONFIGURATION sections? It would be nice if we could put in some\n> >      kind of semantic markup, but I'm not sure how painful that would be\n> >      with asciidoc (we could always resort to comments in the source,\n> >      but that would probably get unreadable quickly).\n> \n> I figured for consistency and ease of lookup *all* configuration docs\n> should name the variables in the same format.  It can still be helpful\n> to mention them elsewhere, e.g. in the option documentations, but the\n> main docs should be a CONFIGURATION section formatted like this.\n> \n> Or do you think that would be a bad thing?\n\nNo, I think everything should be in a CONFIGURATION section. So checking\nfor that is probably enough. I was more concerned about false positives\ncreeping in. Checking just the CONFIGURATION section would probably make\nthat unlikely, though.\n\n-Peff\n"},{"id":"154414","messageId":"20101025151125.GD28278@sigill.intra.peff.net","threadId":"25517","inReplyTo":"201010251444.08780.jnareb@gmail.com","subject":"Re: [RFC PATCH v2 0/3] Documentation: refactor config variable descriptions","fromName":"Jeff King","fromEmail":"peff@peff.net","sentAt":"2010-10-25T15:11:25Z","receivedAt":"2010-10-25T15:11:25Z","isPatch":true,"sender":{"key":"peff@peff.net","avatar":"https://avatars.githubusercontent.com/u/45925?v=4"},"body":"On Mon, Oct 25, 2010 at 02:44:06PM +0200, Jakub Narebski wrote:\n\n> 2. With checking for CONFIGURATION-like, we would miss the following\n>    configuration variables:\n> \n>      http.getanyfile:: (for git-http-backend, in 'SERVICES')\n>      http.uploadpack:: (for git-http-backend, in 'SERVICES')\n>      http.receivepack:: (for git-http-backend, in 'SERVICES')\n> \n>    These are in git-http-backend manpage, in 'SERVICES' section, which \n>    probably should be named then 'CONFIGURING SERVICES'.\n\nI would argue those should probably go in a CONFIGURATION section for\nconsistency with the rest of the manpages.\n\n>    BTW, CONFIGURATION-like means:\n> \n>     * Configuration\n>     * CONFIGURATION\n>    \n>   but also\n> \n>     * CONFIG FILE-ONLY OPTIONS\n>     * CONFIGURATION FILE\n>     * Configuration Mechanism\n>     * CONFIG VARIABLES\n>     * CONFIGURATION VARIABLES\n>     * Configuring database backend\n\nAgain, I think for consistency for the reader, it may make sense to\nswitch them all to CONFIGURATION. I'd have to look at each page and see\nhow appropraite that is, though.\n\n> >   2. You recursively follow includes via include::. This means that the\n> >      make rule is not accurate. E.g., try:\n> [...]\n> We do that: see 'doc.dep' target in Documentation/Makefile.  We just\n> need for this target to also add dependencies for config-vars.txt\n> (perhaps separate mode for make-config-list.perl, or perhaps \n> build-docdep.perl should be config-vars-src.txt aware...).\n\nYeah, that would definitely work.\n\n> Note however that make-config-list.perl only creates minimal documentation,\n> just link(s) to appropriate mapage(s).  Include-ing merge-config.txt both\n> in git-merge.txt and config-vars-src.txt means that we have merg config\n> variables defined in git-config(1) manpage, which I think is nice to have.\n\nI disagree. I think one of the benefits of this exercise is generating a\nmore concise list. That being said, I don't think there's any reason we\ncan't have a terse list in gitconfig(7) and a much larger one in\ngitconfigfull(7) or something like that (or even put it later in the\nmanpage of gitconfig(7), or whatever).\n\nIf you're going to do that, though, there's no point in having\nmerge-options separate. make-config-list should just generate both\nlists.\n\n> >        format.pretty::\n> >                The default pretty format for log/show/whatchanged command,\n> >                See linkgit:git-log[1], linkgit:git-show[1],\n> >                linkgit:git-whatchanged[1].\n> [...]\n> \n> Actually the above block describing `format.pretty` is from beginning in\n> config-vars-src.txt, and is not added / created by said script.\n\nOh, you're right. I was browsing the output and just assumed it was\ncreated by the script, since it is of a similar form.\n\n> >      [1]: I assume the single line of block description is an error in\n> >           your script.\n> \n> Hmmm?\n\nThe comma at the end made it look to me like a sentence had been cut off\nduring parsing. But looking at config.txt, it is simply a typo.  The\ncomma should be a period.\n\n-Peff\n"},{"id":"154418","messageId":"201010251749.04784.jnareb@gmail.com","threadId":"25517","inReplyTo":"20101025151125.GD28278@sigill.intra.peff.net","subject":"Re: [RFC PATCH v2 0/3] Documentation: refactor config variable descriptions","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2010-10-25T15:49:02Z","receivedAt":"2010-10-25T15:49:02Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"On Mon, 25 Oct 2010, Jeff King wrote:\n> On Mon, Oct 25, 2010 at 02:44:06PM +0200, Jakub Narebski wrote:\n> \n> > 2. With checking for CONFIGURATION-like, we would miss the following\n> >    configuration variables:\n> > \n> >      http.getanyfile:: (for git-http-backend, in 'SERVICES')\n> >      http.uploadpack:: (for git-http-backend, in 'SERVICES')\n> >      http.receivepack:: (for git-http-backend, in 'SERVICES')\n> > \n> >    These are in git-http-backend manpage, in 'SERVICES' section, which \n> >    probably should be named then 'CONFIGURING SERVICES'.\n> \n> I would argue those should probably go in a CONFIGURATION section for\n> consistency with the rest of the manpages.\n\nWhat consistency ;-)?  But I agree, if we can switch all the following \nvariants to 'CONFIGURATION', it should also go in 'CONFIGURATION'\nsection.  If we cannot, then 'CONFIGURING SERVICES' as section name,\nand /^Config/i as a regexp detecting if we are in relevant section.\n\n> >    BTW, CONFIGURATION-like means:\n> > \n> >     * Configuration\n> >     * CONFIGURATION\n> >    \n> >   but also\n> > \n> >     * CONFIG FILE-ONLY OPTIONS\n> >     * CONFIGURATION FILE\n> >     * Configuration Mechanism\n> >     * CONFIG VARIABLES\n> >     * CONFIGURATION VARIABLES\n> >     * Configuring database backend\n> \n> Again, I think for consistency for the reader, it may make sense to\n> switch them all to CONFIGURATION. I'd have to look at each page and see\n> how appropriate that is, though.\n\nRight.\n\n> > >   2. You recursively follow includes via include::. This means that the\n> > >      make rule is not accurate. E.g., try:\n> > [...]\n> > We do that: see 'doc.dep' target in Documentation/Makefile.  We just\n> > need for this target to also add dependencies for config-vars.txt\n> > (perhaps separate mode for make-config-list.perl, or perhaps \n> > build-docdep.perl should be config-vars-src.txt aware...).\n> \n> Yeah, that would definitely work.\n\nThough simpler would be just to not use or turn off following includes,\nas it turned out that it doesn't matter to follow includes in manpages:\nif we include with config variables, it is to also include it in \nconfig-vars-src.txt.\n\nWell, assuming that we don't have to follow includes in config-vars-src.txt;\notherwise we have to generate line in doc.dep for that include anyway.\n\n> > Note however that make-config-list.perl only creates minimal documentation,\n> > just link(s) to appropriate mapage(s).  Include-ing merge-config.txt both\n> > in git-merge.txt and config-vars-src.txt means that we have merg config\n> > variables defined in git-config(1) manpage, which I think is nice to have.\n> \n> I disagree. I think one of the benefits of this exercise is generating a\n> more concise list. \n\nI can agree with eliminating those blocks that consist only of list of\nvariables and reference to main page, like the following[1]\n\n  sendemail.<identity>.*::\n        Identity-specific versions of the 'sendemail.*' parameters\n        found below, taking precedence over those when the this\n        identity is selected, through command-line or\n        'sendemail.identity'.\n\n  sendemail.aliasesfile::\n  sendemail.aliasfiletype::\n  sendemail.bcc::\n  sendemail.cc::\n  [...]\n  sendemail.thread::\n  sendemail.validate::\n        See linkgit:git-send-email[1] for description.\n\n\nand perhaps also this block\n\n  imap::\n        The configuration variables in the 'imap' section are described\n        in linkgit:git-imap-send[1].\n\n[1] Though only if we can ensure that they are added below \n'sendemail.<identity>.*', which refers to them.\n\n> That being said, I don't think there's any reason we\n> can't have a terse list in gitconfig(7) and a much larger one in\n> gitconfigfull(7) or something like that (or even put it later in the\n> manpage of gitconfig(7), or whatever).\n\nYou can mechanically move or copy description of config variables from\nconfig-vars-src.txt to individual manpages.  Moving in reverse direction,\nlike in your autogenerated gitconfigfull(7) proposal, is not that easy:\ndescription of config variables in individual manpages can refer to\nother parts of said manpage (and barring AI you cannot reliably detect\nsuch situation).\n\n-- \nJakub Narebski\nPoland\n"},{"id":"154487","messageId":"201010271256.16836.jnareb@gmail.com","threadId":"25517","inReplyTo":"201010251749.04784.jnareb@gmail.com","subject":"Re: [RFC PATCH v2 0/3] Documentation: refactor config variable descriptions","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2010-10-27T10:56:15Z","receivedAt":"2010-10-27T10:56:15Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"On Mon, 25 Oct 2010, Jakub Narebski wrote:\n> On Mon, 25 Oct 2010, Jeff King wrote:\n>> On Mon, Oct 25, 2010 at 02:44:06PM +0200, Jakub Narebski wrote:\n\n>>>>   2. You recursively follow includes via include::. This means that the\n>>>>      make rule is not accurate. E.g., try:\n>>> [...]\n>>> We do that: see 'doc.dep' target in Documentation/Makefile.  We just\n>>> need for this target to also add dependencies for config-vars.txt\n>>> (perhaps separate mode for make-config-list.perl, or perhaps \n>>> build-docdep.perl should be config-vars-src.txt aware...).\n>> \n>> Yeah, that would definitely work.\n\nThe part of patch (commit) touching Documentation/Makefile could look\nlike this:\n\n-- 8< --\ndiff --git a/Documentation/Makefile b/Documentation/Makefile\nindex e117bc4..351aa9c 100644\n--- a/Documentation/Makefile\n+++ b/Documentation/Makefile\n@@ -212,9 +212,12 @@ install-html: html\n #\n # Determine \"include::\" file references in asciidoc files.\n #\n-doc.dep : $(wildcard *.txt) build-docdep.perl\n+doc.dep : $(wildcard *.txt) build-docdep.perl make-config-list.perl\n \t$(QUIET_GEN)$(RM) $@+ $@ && \\\n \t$(PERL_PATH) ./build-docdep.perl >$@+ $(QUIET_STDERR) && \\\n+\t$(PERL_PATH) ./make-config-list.perl --deps=config-vars.txt \\\n+\t\t--mainlist=config-vars-src.txt $(MAN_TXT) \\\n+\t\t>>$@+ $(QUIET_STDERR) && \\\n \tmv $@+ $@\n \n -include doc.dep\n@@ -320,6 +323,11 @@ howto-index.txt: howto-index.sh $(wildcard howto/*.txt)\n \t'$(SHELL_PATH_SQ)' ./howto-index.sh $(wildcard howto/*.txt) >$@+ && \\\n \tmv $@+ $@\n \n+config-vars.txt: config-vars-src.txt $(MAN_TXT) make-config-list.perl\n+\t$(PERL_PATH) ./make-config-list.perl \\\n+\t\t--mainlist=$< --ignore=$@ $(MAN_TXT) >$@+ && \\\n+\tmv $@+ $@\n+\n $(patsubst %,%.html,$(ARTICLES)) : %.html : %.txt\n \t$(QUIET_ASCIIDOC)$(ASCIIDOC) $(ASCIIDOC_EXTRA) -b xhtml11 $*.txt\n \n-- >8 --\n\nNote that while in rule for config-vars.txt target we can use automatic\nvariables, we have to spell filenames in full in the part of doc.dep\nrules that generate dependency for config-vars.txt.  Note also that we\nhave to keep those explicit and implicit filenames in sync across those\ntwo rules.\n \n> Though simpler would be just to not use or turn off following includes,\n> as it turned out that it doesn't matter to follow includes in manpages:\n> if we include with config variables, it is to also include it in \n> config-vars-src.txt.\n> \n> Well, assuming that we don't have to follow includes in config-vars-src.txt;\n> otherwise we have to generate line in doc.dep for that include anyway.\n\nDecision time!!!\n\nThere are two possible approaches:\n\n1. Don't follow includes in manpages (in manpage sources), and don't follow\n   includes in config-vars-src.txt\n\n   Advantages:\n   * Less code to write and maintain\n   * No need to keep filenames in rule for config-vars.txt and for doc.dep\n     in sync.\n\n   Disadvantages:\n   * Theoretically fragile: it depends on two assumptions:\n\n     A. If file included in manpage contains description of config vars,\n        then this file would be included also in config-vars-src.txt\n\n     B. For config variables inside file(s) included by config-vars-src.txt,\n        if they are present in individual manpage, it is done by inclusion\n        of said file.\n\n     Those assumptions are two sides of the same coin, and can be written\n     as: file included in manpagee can contain config variables if and only\n     if it is included in config-vars-src.txt\n\n2. Follow includes both in manpages and in config-vars-src.txt, and\n   generate dependencies for config-vars.txt\n\n   Advantages:\n   * More generic solution\n\n   Disadvantages:\n   * Need to keep rules for doc.dep and for config-vars.txt in sync, as\n     described above\n   * config-vars.txt rule has more dependencies.\n\nNow, which one to choose?\n-- \nJakub Narebski\nPoland\n"},{"id":"154966","messageId":"4CD01558.7030701@web.de","threadId":"25517","inReplyTo":"201010251444.08780.jnareb@gmail.com","subject":"Re: [RFC PATCH v2 0/3] Documentation: refactor config variable descriptions","fromName":"Jens Lehmann","fromEmail":"jens.lehmann@web.de","sentAt":"2010-11-02T13:42:48Z","receivedAt":"2010-11-02T13:42:48Z","isPatch":true,"sender":{"key":"jens.lehmann@web.de","avatar":"https://avatars.githubusercontent.com/u/135220?v=4"},"body":"Am 25.10.2010 14:44, schrieb Jakub Narebski:\n> 1. Without checking for CONFIGURATION sections, we have what are \n>    probably false positives from gitmodules.txt:\n> \n>      submodule.<name>.path::\n>      submodule.<name>.url::\n>      submodule.<name>.update::\n>      submodule.<name>.ignore::\n> \n>    I say *probably* because while gitmodules manpage describes those \n>    variables as going into .gitmodules, if I understand it correctly\n>    those variables can got to .git/config as an override.\n\nAFAICS only 'path' won't show up in .git/config. 'url' and 'update'\nare copied into .git/config by \"git submodule init\", 'ignore' might\nbe added by a developer to override the setting from .gitmodules.\n"}]}