{"thread":{"id":"8503","subject":"[PATCH 0/6] gitweb: 'commitdiff' view improvements","startedAt":"2007-06-08T11:24:13Z","lastAt":"2007-06-11T00:36:06Z","messageCount":8,"participants":["Jakub Narebski","Junio C Hamano"],"isPatch":true,"patchVersion":1,"patchTotal":6},"messages":[{"id":"44338","messageId":"20070608112337.3594.93976.stgit@roke.D-201","threadId":"8503","inReplyTo":null,"subject":"[PATCH 0/6] gitweb: 'commitdiff' view improvements","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2007-06-08T11:24:13Z","receivedAt":"2007-06-08T11:24:13Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"The following series makes a few improvements to 'commitdiff' view.\nThe final goal of the series is to use '--cc' (compact combined)\nformat for merge commits in gitweb, as requested by Linus Torvalds\nin\n  Message-ID: <Pine.LNX.4.64.0610061202060.3952@g5.osdl.org>\nwith a few other improvements.\n\nTable of contents:\n------------------\n gitweb: Provide links to commitdiff to each parent in 'commitdiff' view\n gitweb: Improve \"next\" link in commitdiff view\n gitweb: Split git_patchset_body into separate subroutines\n gitweb: Create special from-file/to-file header for combined diff\n gitweb: Add links to blobdiffs in from-file/to-file header for merges\n gitweb: '--cc' for merges in 'commitdiff' view\n\nThe first two patches are totally independent of other patches, and\nare not required by anu patches.\n\nThe \"Split git_patchset_body\" is required for all subsequent patches;\nthose patches shows why it was needed. The last patch is conceptually\nindepenent on the \"improve from-file/to-file header for merges\"\npatches.\n\nDiffstat:\n---------\n gitweb/gitweb.css  |    5 +\n gitweb/gitweb.perl |  481 ++++++++++++++++++++++++++++++++++++++--------------\n 2 files changed, 362 insertions(+), 124 deletions(-)\n\n-- \nJakub Narebski\nShadeHawk on #git\nPoland\n"},{"id":"44339","messageId":"20070608112419.3594.94911.stgit@roke.D-201","threadId":"8503","inReplyTo":"20070608112337.3594.93976.stgit@roke.D-201","subject":"[PATCH 1/6] gitweb: Provide links to commitdiff to each parent in 'commitdiff' view","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2007-06-08T11:24:56Z","receivedAt":"2007-06-08T11:24:56Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Since commit-fb1dde4a we show combined diff for merges in 'commitdiff'\nview, and since commit-208ecb2e also in 'commit' view. Sometimes\nthough one would want to see diff to one of merge commit parents. It\nis easy in 'commit' view: in the commit header part there are \"diff\"\nlinks for each of parent header. This commit adds such links also for\n'commitdiff' view.\n\nAdd to difftree / whatchanged table row with \"1\", \"2\", ... links to\n'commitdiff' view for diff with n-th parent for merge commits, as a\ntable header.  This is visible only in 'comitdiff' view, and only for\na merge commit (comit with more than one parent).\n\nTo save space links are shown as \"n\", where \"n\" is number of a parent,\nand not as for example shortened (to 7 characters) sha1 of a parent\ncommit.  To make it easier to discover what links is for, each link\nhas 'title' attribute explaining the link.\n\nNote that one would need to remember that difftree table in 'commit'\nview has one less column (it doesn't have \"patch\" link column), if one\nwould want to add such table header also in 'commit' view.\n\nExample output:\n                          1       2       3 \n  Makefile      patch | diff1 | diff2 | diff3 | blob | history\n  cache.h       patch | diff1 | diff2 | diff3 | blob | history\n\nSigned-off-by: Jakub Narebski <jnareb@gmail.com>\n---\n gitweb/gitweb.css  |    5 +++++\n gitweb/gitweb.perl |   21 +++++++++++++++++++++\n 2 files changed, 26 insertions(+), 0 deletions(-)\n\ndiff --git a/gitweb/gitweb.css b/gitweb/gitweb.css\nindex 9f0822f..7908fe3 100644\n--- a/gitweb/gitweb.css\n+++ b/gitweb/gitweb.css\n@@ -181,10 +181,15 @@ table.diff_tree {\n \tfont-family: monospace;\n }\n \n+table.combined.diff_tree th {\n+\ttext-align: center;\n+}\n+\n table.combined.diff_tree td {\n \tpadding-right: 24px;\n }\n \n+table.combined.diff_tree th.link,\n table.combined.diff_tree td.link {\n \tpadding: 0px 2px;\n }\ndiff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl\nindex e92596c..e2d5222 100755\n--- a/gitweb/gitweb.perl\n+++ b/gitweb/gitweb.perl\n@@ -2401,6 +2401,26 @@ sub git_difftree_body {\n \tprint \"<table class=\\\"\" .\n \t      (@parents > 1 ? \"combined \" : \"\") .\n \t      \"diff_tree\\\">\\n\";\n+\n+\t# header only for combined diff in 'commitdiff' view\n+\tmy $has_header = @parents > 1 && $action eq 'commitdiff';\n+\tif ($has_header) {\n+\t\t# table header\n+\t\tprint \"<thead><tr>\\n\" .\n+\t\t       \"<th></th><th></th>\\n\"; # filename, patchN link\n+\t\tfor (my $i = 0; $i < @parents; $i++) {\n+\t\t\tmy $par = $parents[$i];\n+\t\t\tprint \"<th>\" .\n+\t\t\t      $cgi->a({-href => href(action=>\"commitdiff\",\n+\t\t\t                             hash=>$hash, hash_parent=>$par),\n+\t\t\t               -title => 'commitdiff to parent number ' .\n+\t\t\t                          ($i+1) . ': ' . substr($par,0,7)},\n+\t\t\t              $i+1) .\n+\t\t\t      \"&nbsp;</th>\\n\";\n+\t\t}\n+\t\tprint \"</tr></thead>\\n<tbody>\\n\";\n+\t}\n+\n \tmy $alternate = 1;\n \tmy $patchno = 0;\n \tforeach my $line (@{$difftree}) {\n@@ -2673,6 +2693,7 @@ sub git_difftree_body {\n \t\t} # we should not encounter Unmerged (U) or Unknown (X) status\n \t\tprint \"</tr>\\n\";\n \t}\n+\tprint \"</tbody>\" if $has_header;\n \tprint \"</table>\\n\";\n }\n \n"},{"id":"44340","messageId":"20070608112502.3594.68102.stgit@roke.D-201","threadId":"8503","inReplyTo":"20070608112337.3594.93976.stgit@roke.D-201","subject":"[PATCH 2/6] gitweb: Improve \"next\" link in commitdiff view","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2007-06-08T11:26:31Z","receivedAt":"2007-06-08T11:26:31Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Check if 'hp' (hash_parent) parameter to 'commitdiff' view is one of\n'h' (hash) commit parents, i.e. if commitdiff is of the form\n\"<commit>^<n> <commit>\", and mark it as such in the bottom part of\nnavigation bar. The \"next\" link in commitdiff view was introduced\nin commit 151602df00b8e5c5b4a8193f59a94b85f9b5aebc\n\nIf 'hb' is n-th parent of 'h', show the following at the bottom\nof navigation bar:\n  (from parent n: _commit_)\n\nSigned-off-by: Jakub Narebski <jnareb@gmail.com>\n---\nThis is sort of companion to previous commit, meaning thatI'd like to\nsee if I came from link to diff to one of parents in a merge commit.\nPurely decoration, but I think it is nice.\n\n gitweb/gitweb.perl |    9 ++++++++-\n 1 files changed, 8 insertions(+), 1 deletions(-)\n\ndiff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl\nindex e2d5222..4561d4e 100755\n--- a/gitweb/gitweb.perl\n+++ b/gitweb/gitweb.perl\n@@ -4479,7 +4479,14 @@ sub git_commitdiff {\n \t\t\t\t$hash_parent_short = substr($hash_parent, 0, 7);\n \t\t\t}\n \t\t\t$formats_nav .=\n-\t\t\t\t' (from: ' .\n+\t\t\t\t' (from';\n+\t\t\tfor (my $i = 0; $i < @{$co{'parents'}}; $i++) {\n+\t\t\t\tif ($co{'parents'}[$i] eq $hash_parent) {\n+\t\t\t\t\t$formats_nav .= ' parent ' . ($i+1);\n+\t\t\t\t\tlast;\n+\t\t\t\t}\n+\t\t\t}\n+\t\t\t$formats_nav .= ': ' .\n \t\t\t\t$cgi->a({-href => href(action=>\"commitdiff\",\n \t\t\t\t                       hash=>$hash_parent)},\n \t\t\t\t        esc_html($hash_parent_short)) .\n"},{"id":"44341","messageId":"20070608112636.3594.1340.stgit@roke.D-201","threadId":"8503","inReplyTo":"20070608112337.3594.93976.stgit@roke.D-201","subject":"[PATCH 3/6] gitweb: Split git_patchset_body into separate subroutines","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2007-06-08T11:27:42Z","receivedAt":"2007-06-08T11:27:42Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"This commit makes git_patchset_body easier to read, and reduces level of\nnesting and indent level. It adds more lines that it removes because of\nextra parameter passing in subroutines, and subroutine calls in\ngit_patchset_body. Also because there are few added comments.\n\n\nBelow there are descriptions of all split-off subroutines:\n\nSeparate formatting \"git diff\" header into format_git_diff_header_line.\nWhile at it fix it so it always escapes pathname. It would be even more\nuseful if we decide to use `--cc' for merges, and need to generate by\nhand empty patches for anchors.\n\nSeparate formatting extended (git) diff header lines into\nformat_extended_diff_header_line. This one is copied without changes.\n\nSeparate formatting two-lines from-file/to-file diff header into\nformat_diff_from_to_header subroutine. While at it fix it so it always\nescapes pathname. Beware calling convention: it takes _two_ lines.\n\nSeparate generating %from and %to hashes (with info used among others to\ngenerate hyperlinks) into parse_from_to_diffinfo subroutine. This one is\ncopied without changes.\n\nSeparate checking if file was deleted (and among others therefore does\nnot have link to the result file) into is_deleted subroutine. This would\nallow us to easily change the algotithm to find if file is_deleted in\nthe result.\n\nSigned-off-by: Jakub Narebski <jnareb@gmail.com>\n---\nPerhaps only first paragraph (and signoff line) should be in the\ncommit message, although I think those comments are useful. \n\n gitweb/gitweb.perl |  313 ++++++++++++++++++++++++++++++++++------------------\n 1 files changed, 202 insertions(+), 111 deletions(-)\n\ndiff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl\nindex 4561d4e..aee4f23 100755\n--- a/gitweb/gitweb.perl\n+++ b/gitweb/gitweb.perl\n@@ -954,7 +954,149 @@ sub format_subject_html {\n \t}\n }\n \n-# format patch (diff) line (rather not to be used for diff headers)\n+# format git diff header line, i.e. \"diff --(git|combined|cc) ...\"\n+sub format_git_diff_header_line {\n+\tmy $line = shift;\n+\tmy $diffinfo = shift;\n+\tmy ($from, $to) = @_;\n+\n+\tif ($diffinfo->{'nparents'}) {\n+\t\t# combined diff\n+\t\t$line =~ s!^(diff (.*?) )\"?.*$!$1!;\n+\t\tif ($to->{'href'}) {\n+\t\t\t$line .= $cgi->a({-href => $to->{'href'}, -class => \"path\"},\n+\t\t\t                 esc_path($to->{'file'}));\n+\t\t} else { # file was deleted (no href)\n+\t\t\t$line .= esc_path($to->{'file'});\n+\t\t}\n+\t} else {\n+\t\t# \"ordinary\" diff\n+\t\t$line =~ s!^(diff (.*?) )\"?a/.*$!$1!;\n+\t\tif ($from->{'href'}) {\n+\t\t\t$line .= $cgi->a({-href => $from->{'href'}, -class => \"path\"},\n+\t\t\t                 'a/' . esc_path($from->{'file'}));\n+\t\t} else { # file was added (no href)\n+\t\t\t$line .= 'a/' . esc_path($from->{'file'});\n+\t\t}\n+\t\t$line .= ' ';\n+\t\tif ($to->{'href'}) {\n+\t\t\t$line .= $cgi->a({-href => $to->{'href'}, -class => \"path\"},\n+\t\t\t                 'b/' . esc_path($to->{'file'}));\n+\t\t} else { # file was deleted\n+\t\t\t$line .= 'b/' . esc_path($to->{'file'});\n+\t\t}\n+\t}\n+\n+\treturn \"<div class=\\\"diff header\\\">$line</div>\\n\";\n+}\n+\n+# format extended diff header line, before patch itself\n+sub format_extended_diff_header_line {\n+\tmy $line = shift;\n+\tmy $diffinfo = shift;\n+\tmy ($from, $to) = @_;\n+\n+\t# match <path>\n+\tif ($line =~ s!^((copy|rename) from ).*$!$1! && $from->{'href'}) {\n+\t\t$line .= $cgi->a({-href=>$from->{'href'}, -class=>\"path\"},\n+\t\t                       esc_path($from->{'file'}));\n+\t}\n+\tif ($line =~ s!^((copy|rename) to ).*$!$1! && $to->{'href'}) {\n+\t\t$line .= $cgi->a({-href=>$to->{'href'}, -class=>\"path\"},\n+\t\t                 esc_path($to->{'file'}));\n+\t}\n+\t# match single <mode>\n+\tif ($line =~ m/\\s(\\d{6})$/) {\n+\t\t$line .= '<span class=\"info\"> (' .\n+\t\t         file_type_long($1) .\n+\t\t         ')</span>';\n+\t}\n+\t# match <hash>\n+\tif ($line =~ m/^index [0-9a-fA-F]{40},[0-9a-fA-F]{40}/) {\n+\t\t# can match only for combined diff\n+\t\t$line = 'index ';\n+\t\tfor (my $i = 0; $i < $diffinfo->{'nparents'}; $i++) {\n+\t\t\tif ($from->{'href'}[$i]) {\n+\t\t\t\t$line .= $cgi->a({-href=>$from->{'href'}[$i],\n+\t\t\t\t                  -class=>\"hash\"},\n+\t\t\t\t                 substr($diffinfo->{'from_id'}[$i],0,7));\n+\t\t\t} else {\n+\t\t\t\t$line .= '0' x 7;\n+\t\t\t}\n+\t\t\t# separator\n+\t\t\t$line .= ',' if ($i < $diffinfo->{'nparents'} - 1);\n+\t\t}\n+\t\t$line .= '..';\n+\t\tif ($to->{'href'}) {\n+\t\t\t$line .= $cgi->a({-href=>$to->{'href'}, -class=>\"hash\"},\n+\t\t\t                 substr($diffinfo->{'to_id'},0,7));\n+\t\t} else {\n+\t\t\t$line .= '0' x 7;\n+\t\t}\n+\n+\t} elsif ($line =~ m/^index [0-9a-fA-F]{40}..[0-9a-fA-F]{40}/) {\n+\t\t# can match only for ordinary diff\n+\t\tmy ($from_link, $to_link);\n+\t\tif ($from->{'href'}) {\n+\t\t\t$from_link = $cgi->a({-href=>$from->{'href'}, -class=>\"hash\"},\n+\t\t\t                     substr($diffinfo->{'from_id'},0,7));\n+\t\t} else {\n+\t\t\t$from_link = '0' x 7;\n+\t\t}\n+\t\tif ($to->{'href'}) {\n+\t\t\t$to_link = $cgi->a({-href=>$to->{'href'}, -class=>\"hash\"},\n+\t\t\t                   substr($diffinfo->{'to_id'},0,7));\n+\t\t} else {\n+\t\t\t$to_link = '0' x 7;\n+\t\t}\n+\t\tmy ($from_id, $to_id) = ($diffinfo->{'from_id'}, $diffinfo->{'to_id'});\n+\t\t$line =~ s!$from_id\\.\\.$to_id!$from_link..$to_link!;\n+\t}\n+\n+\treturn $line . \"<br/>\\n\";\n+}\n+\n+# format from-file/to-file diff header\n+sub format_diff_from_to_header {\n+\tmy ($from_line, $to_line, $diffinfo, $from, $to) = @_;\n+\tmy $line;\n+\tmy $result = '';\n+\n+\t$line = $from_line;\n+\t#assert($line =~ m/^---/) if DEBUG;\n+\t# no extra formatting \"^--- /dev/null\"\n+\tif ($line =~ m!^--- \"?a/!) {\n+\t\tif (!$diffinfo->{'nparents'} && # multiple 'from'\n+\t\t    $from->{'href'}) {\n+\t\t\t$line = '--- a/' .\n+\t\t\t        $cgi->a({-href=>$from->{'href'}, -class=>\"path\"},\n+\t\t\t                esc_path($from->{'file'}));\n+\t\t} else {\n+\t\t\t$line = '--- a/' .\n+\t\t\t        esc_path($from->{'file'});\n+\t\t}\n+\t}\n+\t$result .= qq!<div class=\"diff from_file\">$line</div>\\n!;\n+\n+\t$line = $to_line;\n+\t#assert($line =~ m/^\\+\\+\\+/) if DEBUG;\n+\t# no extra formatting for \"^+++ /dev/null\"\n+\tif ($line =~ m!^\\+\\+\\+ \"?b/!) {\n+\t\tif ($to->{'href'}) {\n+\t\t\t$line = '+++ b/' .\n+\t\t\t        $cgi->a({-href=>$to->{'href'}, -class=>\"path\"},\n+\t\t\t                esc_path($to->{'file'}));\n+\t\t} else {\n+\t\t\t$line = '+++ b/' .\n+\t\t\t        esc_path($to->{'file'});\n+\t\t}\n+\t}\n+\t$result .= qq!<div class=\"diff to_file\">$line</div>\\n!;\n+\n+\treturn $result;\n+}\n+\n+# format patch (diff) line (not to be used for diff headers)\n sub format_diff_line {\n \tmy $line = shift;\n \tmy ($from, $to) = @_;\n@@ -1680,6 +1822,48 @@ sub parse_ls_tree_line ($;%) {\n \treturn wantarray ? %res : \\%res;\n }\n \n+# generates _two_ hashes, references to which are passed as 2 and 3 argument\n+sub parse_from_to_diffinfo {\n+\tmy ($diffinfo, $from, $to, @parents) = @_;\n+\n+\tif ($diffinfo->{'nparents'}) {\n+\t\t# combined diff\n+\t\t$from->{'file'} = [];\n+\t\t$from->{'href'} = [];\n+\t\tfill_from_file_info($diffinfo, @parents)\n+\t\t\tunless exists $diffinfo->{'from_file'};\n+\t\tfor (my $i = 0; $i < $diffinfo->{'nparents'}; $i++) {\n+\t\t\t$from->{'file'}[$i] = $diffinfo->{'from_file'}[$i] || $diffinfo->{'to_file'};\n+\t\t\tif ($diffinfo->{'status'}[$i] ne \"A\") { # not new (added) file\n+\t\t\t\t$from->{'href'}[$i] = href(action=>\"blob\",\n+\t\t\t\t                           hash_base=>$parents[$i],\n+\t\t\t\t                           hash=>$diffinfo->{'from_id'}[$i],\n+\t\t\t\t                           file_name=>$from->{'file'}[$i]);\n+\t\t\t} else {\n+\t\t\t\t$from->{'href'}[$i] = undef;\n+\t\t\t}\n+\t\t}\n+\t} else {\n+\t\t$from->{'file'} = $diffinfo->{'from_file'} || $diffinfo->{'file'};\n+\t\tif ($diffinfo->{'status'} ne \"A\") { # not new (added) file\n+\t\t\t$from->{'href'} = href(action=>\"blob\", hash_base=>$hash_parent,\n+\t\t\t                       hash=>$diffinfo->{'from_id'},\n+\t\t\t                       file_name=>$from->{'file'});\n+\t\t} else {\n+\t\t\tdelete $from->{'href'};\n+\t\t}\n+\t}\n+\n+\t$to->{'file'} = $diffinfo->{'to_file'} || $diffinfo->{'file'};\n+\tif (!is_deleted($diffinfo)) { # file exists in result\n+\t\t$to->{'href'} = href(action=>\"blob\", hash_base=>$hash,\n+\t\t                     hash=>$diffinfo->{'to_id'},\n+\t\t                     file_name=>$to->{'file'});\n+\t} else {\n+\t\tdelete $to->{'href'};\n+\t}\n+}\n+\n ## ......................................................................\n ## parse to array of hashes functions\n \n@@ -2387,6 +2571,11 @@ sub from_ids_eq {\n \t}\n }\n \n+sub is_deleted {\n+\tmy $diffinfo = shift;\n+\n+\treturn $diffinfo->{'to_id'} eq ('0' x 40);\n+}\n \n sub git_difftree_body {\n \tmy ($difftree, $hash, @parents) = @_;\n@@ -2444,7 +2633,7 @@ sub git_difftree_body {\n \t\t\tfill_from_file_info($diff, @parents)\n \t\t\t\tunless exists $diff->{'from_file'};\n \n-\t\t\tif ($diff->{'to_id'} ne ('0' x 40)) {\n+\t\t\tif (!is_deleted($diff)) {\n \t\t\t\t# file exists in the result (child) commit\n \t\t\t\tprint \"<td>\" .\n \t\t\t\t      $cgi->a({-href => href(action=>\"blob\", hash=>$diff->{'to_id'},\n@@ -2765,6 +2954,8 @@ sub git_patchset_body {\n \t\t\t} else {\n \t\t\t\t$diffinfo = parse_difftree_raw_line($difftree->[$patch_idx]);\n \t\t\t}\n+\t\t\t# modifies %from, %to hashes\n+\t\t\tparse_from_to_diffinfo($diffinfo, \\%from, \\%to, @hash_parents);\n \t\t\tif ($diffinfo->{'nparents'}) {\n \t\t\t\t# combined diff\n \t\t\t\t$from{'file'} = [];\n@@ -2794,7 +2985,7 @@ sub git_patchset_body {\n \t\t\t}\n \n \t\t\t$to{'file'} = $diffinfo->{'to_file'} || $diffinfo->{'file'};\n-\t\t\tif ($diffinfo->{'to_id'} ne ('0' x 40)) { # file exists in result\n+\t\t\tif (!is_deleted($diffinfo)) { # file exists in result\n \t\t\t\t$to{'href'} = href(action=>\"blob\", hash_base=>$hash,\n \t\t\t\t                   hash=>$diffinfo->{'to_id'},\n \t\t\t\t                   file_name=>$to{'file'});\n@@ -2808,105 +2999,15 @@ sub git_patchset_body {\n \n \t\t# print \"git diff\" header\n \t\t$patch_line = shift @diff_header;\n-\t\tif ($diffinfo->{'nparents'}) {\n-\n-\t\t\t# combined diff\n-\t\t\t$patch_line =~ s!^(diff (.*?) )\"?.*$!$1!;\n-\t\t\tif ($to{'href'}) {\n-\t\t\t\t$patch_line .= $cgi->a({-href => $to{'href'}, -class => \"path\"},\n-\t\t\t\t                       esc_path($to{'file'}));\n-\t\t\t} else { # file was deleted\n-\t\t\t\t$patch_line .= esc_path($to{'file'});\n-\t\t\t}\n-\n-\t\t} else {\n-\n-\t\t\t$patch_line =~ s!^(diff (.*?) )\"?a/.*$!$1!;\n-\t\t\tif ($from{'href'}) {\n-\t\t\t\t$patch_line .= $cgi->a({-href => $from{'href'}, -class => \"path\"},\n-\t\t\t\t                       'a/' . esc_path($from{'file'}));\n-\t\t\t} else { # file was added\n-\t\t\t\t$patch_line .= 'a/' . esc_path($from{'file'});\n-\t\t\t}\n-\t\t\t$patch_line .= ' ';\n-\t\t\tif ($to{'href'}) {\n-\t\t\t\t$patch_line .= $cgi->a({-href => $to{'href'}, -class => \"path\"},\n-\t\t\t\t                       'b/' . esc_path($to{'file'}));\n-\t\t\t} else { # file was deleted\n-\t\t\t\t$patch_line .= 'b/' . esc_path($to{'file'});\n-\t\t\t}\n-\n-\t\t}\n-\t\tprint \"<div class=\\\"diff header\\\">$patch_line</div>\\n\";\n+\t\tprint format_git_diff_header_line($patch_line, $diffinfo,\n+\t\t                                  \\%from, \\%to);\n \n \t\t# print extended diff header\n \t\tprint \"<div class=\\\"diff extended_header\\\">\\n\" if (@diff_header > 0);\n \tEXTENDED_HEADER:\n \t\tforeach $patch_line (@diff_header) {\n-\t\t\t# match <path>\n-\t\t\tif ($patch_line =~ s!^((copy|rename) from ).*$!$1! && $from{'href'}) {\n-\t\t\t\t$patch_line .= $cgi->a({-href=>$from{'href'}, -class=>\"path\"},\n-\t\t\t\t                       esc_path($from{'file'}));\n-\t\t\t}\n-\t\t\tif ($patch_line =~ s!^((copy|rename) to ).*$!$1! && $to{'href'}) {\n-\t\t\t\t$patch_line .= $cgi->a({-href=>$to{'href'}, -class=>\"path\"},\n-\t\t\t\t                       esc_path($to{'file'}));\n-\t\t\t}\n-\t\t\t# match single <mode>\n-\t\t\tif ($patch_line =~ m/\\s(\\d{6})$/) {\n-\t\t\t\t$patch_line .= '<span class=\"info\"> (' .\n-\t\t\t\t               file_type_long($1) .\n-\t\t\t\t               ')</span>';\n-\t\t\t}\n-\t\t\t# match <hash>\n-\t\t\tif ($patch_line =~ m/^index [0-9a-fA-F]{40},[0-9a-fA-F]{40}/) {\n-\t\t\t\t# can match only for combined diff\n-\t\t\t\t$patch_line = 'index ';\n-\t\t\t\tfor (my $i = 0; $i < $diffinfo->{'nparents'}; $i++) {\n-\t\t\t\t\tif ($from{'href'}[$i]) {\n-\t\t\t\t\t\t$patch_line .= $cgi->a({-href=>$from{'href'}[$i],\n-\t\t\t\t\t\t                        -class=>\"hash\"},\n-\t\t\t\t\t\t                       substr($diffinfo->{'from_id'}[$i],0,7));\n-\t\t\t\t\t} else {\n-\t\t\t\t\t\t$patch_line .= '0' x 7;\n-\t\t\t\t\t}\n-\t\t\t\t\t# separator\n-\t\t\t\t\t$patch_line .= ',' if ($i < $diffinfo->{'nparents'} - 1);\n-\t\t\t\t}\n-\t\t\t\t$patch_line .= '..';\n-\t\t\t\tif ($to{'href'}) {\n-\t\t\t\t\t$patch_line .= $cgi->a({-href=>$to{'href'}, -class=>\"hash\"},\n-\t\t\t\t\t                       substr($diffinfo->{'to_id'},0,7));\n-\t\t\t\t} else {\n-\t\t\t\t\t$patch_line .= '0' x 7;\n-\t\t\t\t}\n-\n-\t\t\t} elsif ($patch_line =~ m/^index [0-9a-fA-F]{40}..[0-9a-fA-F]{40}/) {\n-\t\t\t\t# can match only for ordinary diff\n-\t\t\t\tmy ($from_link, $to_link);\n-\t\t\t\tif ($from{'href'}) {\n-\t\t\t\t\t$from_link = $cgi->a({-href=>$from{'href'}, -class=>\"hash\"},\n-\t\t\t\t\t                     substr($diffinfo->{'from_id'},0,7));\n-\t\t\t\t} else {\n-\t\t\t\t\t$from_link = '0' x 7;\n-\t\t\t\t}\n-\t\t\t\tif ($to{'href'}) {\n-\t\t\t\t\t$to_link = $cgi->a({-href=>$to{'href'}, -class=>\"hash\"},\n-\t\t\t\t\t                   substr($diffinfo->{'to_id'},0,7));\n-\t\t\t\t} else {\n-\t\t\t\t\t$to_link = '0' x 7;\n-\t\t\t\t}\n-\t\t\t\t#affirm {\n-\t\t\t\t#\tmy ($from_hash, $to_hash) =\n-\t\t\t\t#\t\t($patch_line =~ m/^index ([0-9a-fA-F]{40})..([0-9a-fA-F]{40})/);\n-\t\t\t\t#\tmy ($from_id, $to_id) =\n-\t\t\t\t#\t\t($diffinfo->{'from_id'}, $diffinfo->{'to_id'});\n-\t\t\t\t#\t($from_hash eq $from_id) && ($to_hash eq $to_id);\n-\t\t\t\t#} if DEBUG;\n-\t\t\t\tmy ($from_id, $to_id) = ($diffinfo->{'from_id'}, $diffinfo->{'to_id'});\n-\t\t\t\t$patch_line =~ s!$from_id\\.\\.$to_id!$from_link..$to_link!;\n-\t\t\t}\n-\t\t\tprint $patch_line . \"<br/>\\n\";\n+\t\t\tprint format_extended_diff_header_line($patch_line, $diffinfo,\n+\t\t\t                                       \\%from, \\%to);\n \t\t}\n \t\tprint \"</div>\\n\"  if (@diff_header > 0); # class=\"diff extended_header\"\n \n@@ -2918,24 +3019,14 @@ sub git_patchset_body {\n \t\t}\n \t\tnext PATCH if ($patch_line =~ m/^diff /);\n \t\t#assert($patch_line =~ m/^---/) if DEBUG;\n-\t\tif (!$diffinfo->{'nparents'} && # not from-file line for combined diff\n-\t\t    $from{'href'} && $patch_line =~ m!^--- \"?a/!) {\n-\t\t\t$patch_line = '--- a/' .\n-\t\t\t              $cgi->a({-href=>$from{'href'}, -class=>\"path\"},\n-\t\t\t                      esc_path($from{'file'}));\n-\t\t}\n-\t\tprint \"<div class=\\\"diff from_file\\\">$patch_line</div>\\n\";\n+\t\t#assert($patch_line eq $last_patch_line) if DEBUG;\n \n \t\t$patch_line = <$fd>;\n \t\tchomp $patch_line;\n+\t\t#assert($patch_line =~ m/^\\+\\+\\+/) if DEBUG;\n \n-\t\t#assert($patch_line =~ m/^+++/) if DEBUG;\n-\t\tif ($to{'href'} && $patch_line =~ m!^\\+\\+\\+ \"?b/!) {\n-\t\t\t$patch_line = '+++ b/' .\n-\t\t\t              $cgi->a({-href=>$to{'href'}, -class=>\"path\"},\n-\t\t\t                      esc_path($to{'file'}));\n-\t\t}\n-\t\tprint \"<div class=\\\"diff to_file\\\">$patch_line</div>\\n\";\n+\t\tprint format_diff_from_to_header($last_patch_line, $patch_line,\n+\t\t                                 $diffinfo, \\%from, \\%to);\n \n \t\t# the patch itself\n \tLINE:\n"},{"id":"44342","messageId":"20070608112747.3594.81616.stgit@roke.D-201","threadId":"8503","inReplyTo":"20070608112337.3594.93976.stgit@roke.D-201","subject":"[PATCH 4/6] gitweb: Create special from-file/to-file header for combined diff","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2007-06-08T11:29:49Z","receivedAt":"2007-06-08T11:29:49Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Instead of using default, diff(1) like from-file/to-file header for\ncombined diff (for a merge commit), which looks like:\n\n  --- a/git-gui/git-gui.sh\n  +++ b/_git-gui/git-gui.sh_\n\n(where _link_ denotes [hidden] hyperlink), create from-file(n)/to-file\nheader, using \"--- <n>/_<filename>_\" for each of parents, e.g.:\n\n  --- 1/_git-gui/git-gui.sh_\n  --- 2/_git-gui.sh_\n  +++ b/_git-gui/git-gui.sh_\n\nTest it on one of merge commits involving rename, e.g.\n  95f97567c1887d77f3a46b42d8622c76414d964d (rename at top)\n  5bac4a671907604b5fb4e24ff682d5b0e8431931 (file from one branch)\n\nThis is mainly meant to easier see renames in a merge commit.\n\nSigned-off-by: Jakub Narebski <jnareb@gmail.com>\n---\nJunio and Pasky likes this, and were source of inspiration for\nthe next patch.\n\n gitweb/gitweb.perl |   38 +++++++++++++++++++++++++++-----------\n 1 files changed, 27 insertions(+), 11 deletions(-)\n\ndiff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl\nindex aee4f23..13114bc 100755\n--- a/gitweb/gitweb.perl\n+++ b/gitweb/gitweb.perl\n@@ -1064,19 +1064,35 @@ sub format_diff_from_to_header {\n \n \t$line = $from_line;\n \t#assert($line =~ m/^---/) if DEBUG;\n-\t# no extra formatting \"^--- /dev/null\"\n-\tif ($line =~ m!^--- \"?a/!) {\n-\t\tif (!$diffinfo->{'nparents'} && # multiple 'from'\n-\t\t    $from->{'href'}) {\n-\t\t\t$line = '--- a/' .\n-\t\t\t        $cgi->a({-href=>$from->{'href'}, -class=>\"path\"},\n-\t\t\t                esc_path($from->{'file'}));\n-\t\t} else {\n-\t\t\t$line = '--- a/' .\n-\t\t\t        esc_path($from->{'file'});\n+\t# no extra formatting for \"^--- /dev/null\"\n+\tif (! $diffinfo->{'nparents'}) {\n+\t\t# ordinary (single parent) diff\n+\t\tif ($line =~ m!^--- \"?a/!) {\n+\t\t\tif ($from->{'href'}) {\n+\t\t\t\t$line = '--- a/' .\n+\t\t\t\t        $cgi->a({-href=>$from->{'href'}, -class=>\"path\"},\n+\t\t\t\t                esc_path($from->{'file'}));\n+\t\t\t} else {\n+\t\t\t\t$line = '--- a/' .\n+\t\t\t\t        esc_path($from->{'file'});\n+\t\t\t}\n+\t\t}\n+\t\t$result .= qq!<div class=\"diff from_file\">$line</div>\\n!;\n+\n+\t} else {\n+\t\t# combined diff (merge commit)\n+\t\tfor (my $i = 0; $i < $diffinfo->{'nparents'}; $i++) {\n+\t\t\tif ($from->{'href'}[$i]) {\n+\t\t\t\t$line = '--- ' .\n+\t\t\t\t        ($i+1) . \"/\" .\n+\t\t\t\t        $cgi->a({-href=>$from->{'href'}[$i], -class=>\"path\"},\n+\t\t\t\t                esc_path($from->{'file'}[$i]));\n+\t\t\t} else {\n+\t\t\t\t$line = '--- /dev/null';\n+\t\t\t}\n+\t\t\t$result .= qq!<div class=\"diff from_file\">$line</div>\\n!;\n \t\t}\n \t}\n-\t$result .= qq!<div class=\"diff from_file\">$line</div>\\n!;\n \n \t$line = $to_line;\n \t#assert($line =~ m/^\\+\\+\\+/) if DEBUG;\n"},{"id":"44343","messageId":"20070608113000.3594.74677.stgit@roke.D-201","threadId":"8503","inReplyTo":"20070608112337.3594.93976.stgit@roke.D-201","subject":"[PATCH 5/6] gitweb: Add links to blobdiffs in from-file/to-file header for merges","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2007-06-08T11:32:44Z","receivedAt":"2007-06-08T11:32:44Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Add links to diff to file ('blobdiff' view) for each of individual\nversions of the file in a merge commit to the from-file/to-file header\nin the patch part of combined 'commitdiff' view for merges.\n\nThe from-file/to-file header for combined diff now looks like:\n\n  --- _1_/_git-gui/git-gui.sh_\n  --- _2_/_git-gui.sh_\n  +++ b/_git-gui/git-gui.sh_\n\nwhere _<filename>_ link is link to appropriate version of a file\n('blob' view), and _<n>_ is link to respective diff to mentioned\nversion of a file ('blobdiff' view). There is even hint provided in\nthe form of title attribute.\n\nSigned-off-by: Jakub Narebski <jnareb@gmail.com>\n---\nAs requested by Junio C Hamano and Petr \"Pasky\" Baudis in:\n  Message-ID: <7v1wh1en8k.fsf@assigned-by-dhcp.cox.net>\n  Message-ID: <20070528132959.GT4489@pasky.or.cz>\n\nI don't know if the link placement is best possible; I tried for\ncombined diff output be similar to ordinary diff output, but also\nprovide reqeusted additional functionality (which does not make\nsense for ordinary diff). You have to know ehere to search for\nthe link.\n\n gitweb/gitweb.perl |   17 ++++++++++++++---\n 1 files changed, 14 insertions(+), 3 deletions(-)\n\ndiff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl\nindex 13114bc..c7acfad 100755\n--- a/gitweb/gitweb.perl\n+++ b/gitweb/gitweb.perl\n@@ -1058,7 +1058,7 @@ sub format_extended_diff_header_line {\n \n # format from-file/to-file diff header\n sub format_diff_from_to_header {\n-\tmy ($from_line, $to_line, $diffinfo, $from, $to) = @_;\n+\tmy ($from_line, $to_line, $diffinfo, $from, $to, @parents) = @_;\n \tmy $line;\n \tmy $result = '';\n \n@@ -1084,7 +1084,17 @@ sub format_diff_from_to_header {\n \t\tfor (my $i = 0; $i < $diffinfo->{'nparents'}; $i++) {\n \t\t\tif ($from->{'href'}[$i]) {\n \t\t\t\t$line = '--- ' .\n-\t\t\t\t        ($i+1) . \"/\" .\n+\t\t\t\t        $cgi->a({-href=>href(action=>\"blobdiff\",\n+\t\t\t\t                             hash_parent=>$diffinfo->{'from_id'}[$i],\n+\t\t\t\t                             hash_parent_base=>$parents[$i],\n+\t\t\t\t                             file_parent=>$from->{'file'}[$i],\n+\t\t\t\t                             hash=>$diffinfo->{'to_id'},\n+\t\t\t\t                             hash_base=>$hash,\n+\t\t\t\t                             file_name=>$to->{'file'}),\n+\t\t\t\t                 -class=>\"path\",\n+\t\t\t\t                 -title=>\"diff\" . ($i+1)},\n+\t\t\t\t                $i+1) .\n+\t\t\t\t        '/' .\n \t\t\t\t        $cgi->a({-href=>$from->{'href'}[$i], -class=>\"path\"},\n \t\t\t\t                esc_path($from->{'file'}[$i]));\n \t\t\t} else {\n@@ -3042,7 +3052,8 @@ sub git_patchset_body {\n \t\t#assert($patch_line =~ m/^\\+\\+\\+/) if DEBUG;\n \n \t\tprint format_diff_from_to_header($last_patch_line, $patch_line,\n-\t\t                                 $diffinfo, \\%from, \\%to);\n+\t\t                                 $diffinfo, \\%from, \\%to,\n+\t\t                                 @hash_parents);\n \n \t\t# the patch itself\n \tLINE:\n"},{"id":"44344","messageId":"20070608113249.3594.65410.stgit@roke.D-201","threadId":"8503","inReplyTo":"20070608112337.3594.93976.stgit@roke.D-201","subject":"[PATCH 6/6] gitweb: '--cc' for merges in 'commitdiff' view","fromName":"Jakub Narebski","fromEmail":"jnareb@gmail.com","sentAt":"2007-06-08T11:33:28Z","receivedAt":"2007-06-08T11:33:28Z","isPatch":true,"sender":{"key":"jnareb@gmail.com","avatar":"https://avatars.githubusercontent.com/u/2706?v=4"},"body":"Allow choosing between '-c' (combined diff) and '--cc' (compact\ncombined) diff format in 'commitdiff' view for merge (multiparent)\ncommits.  Default is now '--cc'.\n\nIn the bottom part of navigation bar there is link allowing to change\ndiff format: \"combined\" for '-c' (when using '--cc') and \"compact\" for\n'--cc' (when using '-c'), just on the right of \"raw\" link to\n'commitdiff_plain\" view. \n\nAbout patchset part of diff --cc output: the difftree (whatchanged\ntable) has \"patch\" links to anchors to individual patches (on the same\npage). The --cc option further compresses the patch output by\nomitting some hunks; when this optimization makes all hunks disappear,\nthe patch is not shown (like in any other \"empty diff\" case). But the\nfact that patch has been simplified out is not reflected in the raw\n(difftree) part of diff output; the raw part is the same for '-c' and\n'--cc' options. As correcting difftree is rather out of the question,\nas it would require scanning patchset part before writing out\ndifftree, we add \"Simple merge\" empty diffs as a place to have anchor\nto in place of those simplified out and removed patches.\n\nSigned-off-by: Jakub Narebski <jnareb@gmail.com>\n---\nLinus wanted '--cc' for merges as it is more compact. Here it is.\n\n gitweb/gitweb.perl |  111 ++++++++++++++++++++++++++++++++++++++++++++++------\n 1 files changed, 99 insertions(+), 12 deletions(-)\n\ndiff --git a/gitweb/gitweb.perl b/gitweb/gitweb.perl\nindex c7acfad..a6383dc 100755\n--- a/gitweb/gitweb.perl\n+++ b/gitweb/gitweb.perl\n@@ -1122,6 +1122,31 @@ sub format_diff_from_to_header {\n \treturn $result;\n }\n \n+# create note for patch simplified by combined diff\n+sub format_diff_cc_simplified {\n+\tmy ($diffinfo, @parents) = @_;\n+\tmy $result = '';\n+\n+\t$result .= \"<div class=\\\"diff header\\\">\" .\n+\t           \"diff --cc \";\n+\tif (!is_deleted($diffinfo)) {\n+\t\t$result .= $cgi->a({-href => href(action=>\"blob\",\n+\t\t                                  hash_base=>$hash,\n+\t\t                                  hash=>$diffinfo->{'to_id'},\n+\t\t                                  file_name=>$diffinfo->{'to_file'}),\n+\t\t                    -class => \"path\"},\n+\t\t                   esc_path($diffinfo->{'to_file'}));\n+\t} else {\n+\t\t$result .= esc_path($diffinfo->{'to_file'});\n+\t}\n+\t$result .= \"</div>\\n\" . # class=\"diff header\"\n+\t           \"<div class=\\\"diff nodifferences\\\">\" .\n+\t           \"Simple merge\" .\n+\t           \"</div>\\n\"; # class=\"diff nodifferences\"\n+\n+\treturn $result;\n+}\n+\n # format patch (diff) line (not to be used for diff headers)\n sub format_diff_line {\n \tmy $line = shift;\n@@ -2973,13 +2998,33 @@ sub git_patchset_body {\n \t\t\t# advance raw git-diff output if needed\n \t\t\t$patch_idx++ if defined $diffinfo;\n \n-\t\t\t# read and prepare patch information\n-\t\t\tif (ref($difftree->[$patch_idx]) eq \"HASH\") {\n-\t\t\t\t# pre-parsed (or generated by hand)\n-\t\t\t\t$diffinfo = $difftree->[$patch_idx];\n-\t\t\t} else {\n-\t\t\t\t$diffinfo = parse_difftree_raw_line($difftree->[$patch_idx]);\n+\t\t\t# compact combined diff output can have some patches skipped\n+\t\t\t# find which patch (using pathname of result) we are at now\n+\t\t\tmy $to_name;\n+\t\t\tif ($diff_header[0] =~ m!^diff --cc \"?(.*)\"?$!) {\n+\t\t\t\t$to_name = $1;\n \t\t\t}\n+\n+\t\t\tdo {\n+\t\t\t\t# read and prepare patch information\n+\t\t\t\tif (ref($difftree->[$patch_idx]) eq \"HASH\") {\n+\t\t\t\t\t# pre-parsed (or generated by hand)\n+\t\t\t\t\t$diffinfo = $difftree->[$patch_idx];\n+\t\t\t\t} else {\n+\t\t\t\t\t$diffinfo = parse_difftree_raw_line($difftree->[$patch_idx]);\n+\t\t\t\t}\n+\n+\t\t\t\t# check if current raw line has no patch (it got simplified)\n+\t\t\t\tif (defined $to_name && $to_name ne $diffinfo->{'to_file'}) {\n+\t\t\t\t\tprint \"<div class=\\\"patch\\\" id=\\\"patch\". ($patch_idx+1) .\"\\\">\\n\" .\n+\t\t\t\t\t      format_diff_cc_simplified($diffinfo, @hash_parents) .\n+\t\t\t\t\t      \"</div>\\n\";  # class=\"patch\"\n+\n+\t\t\t\t\t$patch_idx++;\n+\t\t\t\t\t$patch_number++;\n+\t\t\t\t}\n+\t\t\t} until (!defined $to_name || $to_name eq $diffinfo->{'to_file'} ||\n+\t\t\t         $patch_idx > $#$difftree);\n \t\t\t# modifies %from, %to hashes\n \t\t\tparse_from_to_diffinfo($diffinfo, \\%from, \\%to, @hash_parents);\n \t\t\tif ($diffinfo->{'nparents'}) {\n@@ -3069,6 +3114,27 @@ sub git_patchset_body {\n \t\tprint \"</div>\\n\"; # class=\"patch\"\n \t}\n \n+\t# for compact combined (--cc) format, with chunk and patch simpliciaction\n+\t# patchset might be empty, but there might be unprocessed raw lines\n+\tfor ($patch_idx++ if $patch_number > 0;\n+\t     $patch_idx < @$difftree;\n+\t     $patch_idx++) {\n+\t\t# read and prepare patch information\n+\t\tif (ref($difftree->[$patch_idx]) eq \"HASH\") {\n+\t\t\t# pre-parsed (or generated by hand)\n+\t\t\t$diffinfo = $difftree->[$patch_idx];\n+\t\t} else {\n+\t\t\t$diffinfo = parse_difftree_raw_line($difftree->[$patch_idx]);\n+\t\t}\n+\n+\t\t# generate anchor for \"patch\" links in difftree / whatchanged part\n+\t\tprint \"<div class=\\\"patch\\\" id=\\\"patch\". ($patch_idx+1) .\"\\\">\\n\" .\n+\t\t      format_diff_cc_simplified($diffinfo, @hash_parents) .\n+\t\t      \"</div>\\n\";  # class=\"patch\"\n+\n+\t\t$patch_number++;\n+\t}\n+\n \tif ($patch_number == 0) {\n \t\tif (@hash_parents > 1) {\n \t\t\tprint \"<div class=\\\"diff nodifferences\\\">Trivial merge</div>\\n\";\n@@ -4582,7 +4648,11 @@ sub git_commitdiff {\n \t\tdie_error(undef, \"Unknown commit object\");\n \t}\n \n-\t# we need to prepare $formats_nav before any parameter munging\n+\t# choose format for commitdiff for merge\n+\tif (! defined $hash_parent && @{$co{'parents'}} > 1) {\n+\t\t$hash_parent = '--cc';\n+\t}\n+\t# we need to prepare $formats_nav before almost any parameter munging\n \tmy $formats_nav;\n \tif ($format eq 'html') {\n \t\t$formats_nav =\n@@ -4590,7 +4660,8 @@ sub git_commitdiff {\n \t\t\t                       hash=>$hash, hash_parent=>$hash_parent)},\n \t\t\t        \"raw\");\n \n-\t\tif (defined $hash_parent) {\n+\t\tif (defined $hash_parent &&\n+\t\t    $hash_parent ne '-c' && $hash_parent ne '--cc') {\n \t\t\t# commitdiff with two commits given\n \t\t\tmy $hash_parent_short = $hash_parent;\n \t\t\tif ($hash_parent =~ m/^[0-9a-fA-F]{40}$/) {\n@@ -4622,6 +4693,17 @@ sub git_commitdiff {\n \t\t\t\t')';\n \t\t} else {\n \t\t\t# merge commit\n+\t\t\tif ($hash_parent eq '--cc') {\n+\t\t\t\t$formats_nav .= ' | ' .\n+\t\t\t\t\t$cgi->a({-href => href(action=>\"commitdiff\",\n+\t\t\t\t\t                       hash=>$hash, hash_parent=>'-c')},\n+\t\t\t\t\t        'combined');\n+\t\t\t} else { # $hash_parent eq '-c'\n+\t\t\t\t$formats_nav .= ' | ' .\n+\t\t\t\t\t$cgi->a({-href => href(action=>\"commitdiff\",\n+\t\t\t\t\t                       hash=>$hash, hash_parent=>'--cc')},\n+\t\t\t\t\t        'compact');\n+\t\t\t}\n \t\t\t$formats_nav .=\n \t\t\t\t' (merge: ' .\n \t\t\t\tjoin(' ', map {\n@@ -4634,9 +4716,10 @@ sub git_commitdiff {\n \t}\n \n \tmy $hash_parent_param = $hash_parent;\n-\tif (!defined $hash_parent) {\n+\tif (!defined $hash_parent_param) {\n+\t\t# --cc for multiple parents, --root for parentless\n \t\t$hash_parent_param =\n-\t\t\t@{$co{'parents'}} > 1 ? '-c' : $co{'parent'} || '--root';\n+\t\t\t@{$co{'parents'}} > 1 ? '--cc' : $co{'parent'} || '--root';\n \t}\n \n \t# read commitdiff\n@@ -4713,10 +4796,14 @@ TEXT\n \n \t# write patch\n \tif ($format eq 'html') {\n-\t\tgit_difftree_body(\\@difftree, $hash, $hash_parent || @{$co{'parents'}});\n+\t\tmy $use_parents = !defined $hash_parent ||\n+\t\t\t$hash_parent eq '-c' || $hash_parent eq '--cc';\n+\t\tgit_difftree_body(\\@difftree, $hash,\n+\t\t                  $use_parents ? @{$co{'parents'}} : $hash_parent);\n \t\tprint \"<br/>\\n\";\n \n-\t\tgit_patchset_body($fd, \\@difftree, $hash, $hash_parent || @{$co{'parents'}});\n+\t\tgit_patchset_body($fd, \\@difftree, $hash,\n+\t\t                  $use_parents ? @{$co{'parents'}} : $hash_parent);\n \t\tclose $fd;\n \t\tprint \"</div>\\n\"; # class=\"page_body\"\n \t\tgit_footer_html();\n"},{"id":"44679","messageId":"7vlker49ah.fsf@assigned-by-dhcp.cox.net","threadId":"8503","inReplyTo":"20070608112337.3594.93976.stgit@roke.D-201","subject":"Re: [PATCH 0/6] gitweb: 'commitdiff' view improvements","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2007-06-11T00:36:06Z","receivedAt":"2007-06-11T00:36:06Z","isPatch":true,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Overall it makes the view of merge commit much more pleasant.\nGood job.\n\n[1/6]\nJakub Narebski <jnareb@gmail.com> writes:\n\n> To save space links are shown as \"n\", where \"n\" is number of a parent,\n> and not as for example shortened (to 7 characters) sha1 of a parent\n> commit.  To make it easier to discover what links is for, each link\n> has 'title' attribute explaining the link.\n\nNice; this is a good way to give \"diff $it^$n $it\".  The 'title'\ndoes not feel that useful but it does not add much to the weight\nof the payload so it probably is Ok.\n\n> Example output:\n>                           1       2       3 \n>   Makefile      patch | diff1 | diff2 | diff3 | blob | history\n>   cache.h       patch | diff1 | diff2 | diff3 | blob | history\n\nIt is now tempting to change diff[1234...] for each path to\n\"diff\", isn't it?\n\n[3/6]\nJakub Narebski <jnareb@gmail.com> writes:\n\n> This commit makes git_patchset_body easier to read, and reduces level of\n> nesting and indent level. It adds more lines that it removes because of\n> extra parameter passing in subroutines, and subroutine calls in\n> git_patchset_body. Also because there are few added comments.\n\nVery nice.  That gigantic loop in patchset_body has always been\nan eyesore.  The main loop is much easier to follow now.\n"}]}