Module: tools Branch: master Commit: 0d60762f674e42035b8ad788b2a26f49a8b97fe5 URL: http://source.winehq.org/git/tools.git/?a=commit;h=0d60762f674e42035b8ad788b...
Author: Alexandre Julliard julliard@winehq.org Date: Wed Nov 8 10:17:12 2017 +0100
patches: Display replies under the main patch.
Signed-off-by: Alexandre Julliard julliard@winehq.org
---
patches/patches.css | 5 +++- patches/update | 84 ++++++++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 75 insertions(+), 14 deletions(-)
diff --git a/patches/patches.css b/patches/patches.css index c1ef34f..f7bb560 100644 --- a/patches/patches.css +++ b/patches/patches.css @@ -132,15 +132,18 @@ div.buglist { border: 1px solid #601919; } table.main, table.legend { width: 100%; } +table.main { border-collapse: collapse; }
table.legend ul { margin: 2px 0; }
tr.even { background-color: #fff8f8; } tr.odd { background-color: #f8e8e8; } +.indent { padding: 0 2em; }
.id, .status, .testbot { text-align: center; } -.id, .status, .author { white-space: nowrap; padding: 0 3px; } +.id, .status, .author { white-space: nowrap; padding: 2px 3px; } .checkmark { text-align: center; color:green; } +.arrow { text-align: center; padding: 0 0; } .failmark { text-align: center; color: red; } .signoffextra { color: #A50D0D; border: 1px solid #601919; } .sha1 { white-space: nowrap; font-family: monospace; padding: 2px 12px; } diff --git a/patches/update b/patches/update index cdc172d..9e12c4b 100755 --- a/patches/update +++ b/patches/update @@ -90,6 +90,7 @@ my @legend = my $dir = $ARGV[0] || "$ENV{HOME}/patches"; my $dest = "/home/winehq/opt/source/patches"; my %patches; +my %messages;
sub format_author($) { @@ -126,7 +127,7 @@ print INDEX "<div id="logo_blurb">Wine source repository – Patch status< print INDEX "<div id="main_content"><div id="content"><div class="main">\n"; print INDEX "<table id="main_table" class="main"><thead><tr><th class="id">ID</th>", "<th class="status">Status</th>", - "<th class="author">Author</th>", + "<th colspan="2" class="author">Author</th>", "<th class="subject">Subject</th>", "<th class="author">Reviewer</th>", "<th class="status">Sign</th>", @@ -144,6 +145,8 @@ foreach my $file (readdir DIR) utf8::decode($_); if (/^Subject: (.*)$/) { $patch{"subject"} = $1; } elsif (/^From: (.*)$/) { $patch{"author"} = format_author($1); } + elsif (/^Message-Id: (.*)$/) { $patch{"msgid"} = $1; } + elsif (/^In-Reply-To: (.*)$/) { $patch{"reply"} = $1; } last if (/^$/); } while (<PATCH>) @@ -152,8 +155,14 @@ foreach my $file (readdir DIR) if (/^\s*Signed-off-by: (.*)$/) { push @{$patch{"signoff"}}, format_author($1); } last if (/^---$/); } + while (<PATCH>) + { + utf8::decode($_); + if (/^diff --git a//) { $patch{"has_patch"} = 1; last; } + } close PATCH;
+ $patch{"id"} = $file; $patch{"status"} = "nil"; if (open STATUS, "<$dir/$file.status") { @@ -208,19 +217,52 @@ foreach my $file (readdir DIR) { $patch{"testbot"} = "Failed"; } + if (defined $patch{"msgid"}) + { + $messages{$patch{"msgid"}} = %patch; + } $patches{$file} = %patch; } closedir DIR;
+# build mail threads + +foreach my $file (sort keys %patches) +{ + my $patch = $patches{$file}; + next if defined $patch->{"has_patch"}; + next unless defined $patch->{"reply"}; + next unless defined $messages{$patch->{"reply"}}; + my $parent = $messages{$patch->{"reply"}}; + # find top parent + while (!defined($parent->{"has_patch"}) && defined($parent->{"reply"})) + { + $parent = $messages{$parent->{"reply"}}; + } + next unless defined $parent; + # add it to the parent's children and remove it from the list + $patch->{"parent"} = $parent; + push @{$parent->{"children"}}, $patch; + delete $patches{$file}; +} + my $row = 0; foreach my $file (sort { $patches{$b}->{"order"} <=> $patches{$a}->{"order"} } keys %patches) { my $patch = $patches{$file}; - printf INDEX "<tr class="%s %s"><td class="id">%s</td><td class="status"><a href="#legend">%s</a></td><td class="author">%s</td>", - $row & 1 ? "odd" : "even", $patch->{"status"}, $file, $status_descr{$patch->{"status"}} || $patch->{"status"}, - escapeHTML($patch->{"author"}); - printf INDEX "<td class="subject"><a href="data/$file">%s</a></td>", - escapeHTML($patch->{"subject"}); + + printf INDEX "<tr class="%s %s"><td class="id">%s</td><td class="status"><a href="#legend">%s</a></td>", + $row & 1 ? "odd" : "even", $patch->{"status"}, $file, $status_descr{$patch->{"status"}} || $patch->{"status"}; + if (defined $patch->{"children"}) + { + printf INDEX "<td class="author">%s</td>", escapeHTML($patch->{"author"}); + printf INDEX "<td class="arrow" onclick="toggle_display('$file.reply')">▼</td>"; + } + else + { + printf INDEX "<td colspan="2" class="author">%s</td>", escapeHTML($patch->{"author"}); + } + printf INDEX "<td class="subject"><a href="data/$file">%s</a></td>", escapeHTML($patch->{"subject"}); if ($patch->{"review"}) { printf INDEX "<td class="author">%s</td>", escapeHTML($patch->{"review"}); @@ -259,9 +301,17 @@ foreach my $file (sort { $patches{$b}->{"order"} <=> $patches{$a}->{"order"} } k if (defined($patch->{"signoff"})) { printf INDEX "<tr class="%s" id="$file.signoff" style="display: none;" onclick="toggle_display('$file.signoff')">" . - "<td colspan="4" /><td colspan="4" class="signoffextra author">%s</td></tr>\n", + "<td colspan="5" /><td colspan="4" class="signoffextra author">%s</td></tr>\n", $row & 1 ? "odd" : "even", join("", map { "Signed-off-by: " . escapeHTML($_) . "<br/>"; } @{$patch->{"signoff"}}); } + foreach my $child (@{$patch->{"children"}}) + { + printf INDEX "<tr class="%s" id="$file.reply" style="display: none;" onclick="toggle_display('$file.reply')">" . + "<td colspan="2" /><td colspan="2" class="reply author"><span class="indent" />%s</td> " . + "<td class="reply author"><span class="indent" /><a href="data/%s">%s</a></td> " . + "<td colspan="4" /></tr>\n", + $row & 1 ? "odd" : "even", escapeHTML($child->{"author"}), $child->{"id"}, escapeHTML($child->{"subject"}); + } $row++; } print INDEX "</tbody></table></div>\n"; @@ -284,7 +334,7 @@ my $sorter = <<END; tbody = table.children[1], ths = thead.getElementsByTagName('th'), trs = tbody.getElementsByTagName('tr'), - i, do_reverse, th, sort_func; + i, j, k, id, do_reverse, th, sort_func;
for (i = 0; i < ths.length; i++) ths[i].onclick = sort_table; @@ -307,13 +357,20 @@ my $sorter = <<END; do_reverse = 1; th.setAttribute('data-order', do_reverse)
- for (j = 0, i = trs.length - 1; i != -1; i--) + for (j = 0, k = 0, i = trs.length - 1; i != -1; i--) { - tr = tbody.removeChild(trs[i]) + tr = tbody.removeChild(trs[0]) if (!tr.getAttribute('id')) + { clone_trs[j++] = tr; - else - sign_trs[text_content(trs[i - 1].children[0])] = tr; /* based on the patch ID */ + id = text_content(tr.children[0]); + k = 0; + } + else if (id) /* based on the patch ID */ + { + if (!k) sign_trs[id] = []; + sign_trs[id][k++] = tr; + } } clone_trs.sort(sorter);
@@ -323,7 +380,8 @@ my $sorter = <<END; tbody.appendChild(clone_trs[i]); j = text_content(clone_trs[i].children[0]); if (sign_trs[j]) - tbody.appendChild(sign_trs[j]); + for (k = 0; k < sign_trs[j].length; k++) + tbody.appendChild(sign_trs[j][k]); } }