* [PATCH 09/37] view: wire up diff and vcs viewers with solver
2019-01-21 20:52 7% [PATCH 00/37] viewvcs: diff highlighting and more Eric Wong
@ 2019-01-21 20:52 3% ` Eric Wong
0 siblings, 0 replies; 2+ results
From: Eric Wong @ 2019-01-21 20:52 UTC (permalink / raw)
To: meta
---
MANIFEST | 2 +
lib/PublicInbox/Config.pm | 59 ++++++++++++++-
lib/PublicInbox/View.pm | 47 +++++++++---
lib/PublicInbox/ViewDiff.pm | 147 ++++++++++++++++++++++++++++++++++++
lib/PublicInbox/ViewVCS.pm | 87 +++++++++++++++++++++
lib/PublicInbox/WWW.pm | 18 ++++-
6 files changed, 345 insertions(+), 15 deletions(-)
create mode 100644 lib/PublicInbox/ViewDiff.pm
create mode 100644 lib/PublicInbox/ViewVCS.pm
diff --git a/MANIFEST b/MANIFEST
index 95ad0c6..5e980fe 100644
--- a/MANIFEST
+++ b/MANIFEST
@@ -109,6 +109,8 @@ lib/PublicInbox/SpawnPP.pm
lib/PublicInbox/Unsubscribe.pm
lib/PublicInbox/V2Writable.pm
lib/PublicInbox/View.pm
+lib/PublicInbox/ViewDiff.pm
+lib/PublicInbox/ViewVCS.pm
lib/PublicInbox/WWW.pm
lib/PublicInbox/WWW.pod
lib/PublicInbox/WatchMaildir.pm
diff --git a/lib/PublicInbox/Config.pm b/lib/PublicInbox/Config.pm
index bea2617..355e64b 100644
--- a/lib/PublicInbox/Config.pm
+++ b/lib/PublicInbox/Config.pm
@@ -2,12 +2,19 @@
# License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt>
#
# Used throughout the project for reading configuration
+#
+# Note: I hate camelCase; but git-config(1) uses it, but it's better
+# than alllowercasewithoutunderscores, so use lc('configKey') where
+# applicable for readability
+
package PublicInbox::Config;
use strict;
use warnings;
require PublicInbox::Inbox;
use PublicInbox::Spawn qw(popen_rd);
+sub _array ($) { ref($_[0]) eq 'ARRAY' ? $_[0] : [ $_[0] ] }
+
# returns key-value pairs of config directives in a hash
# if keys may be multi-value, the value is an array ref containing all values
sub new {
@@ -22,6 +29,7 @@ sub new {
$self->{-by_newsgroup} ||= {};
$self->{-no_obfuscate} ||= {};
$self->{-limiters} ||= {};
+ $self->{-code_repos} ||= {}; # nick => PublicInbox::Git object
if (my $no = delete $self->{'publicinbox.noobfuscate'}) {
$no = [ $no ] if ref($no) ne 'ARRAY';
@@ -169,6 +177,41 @@ sub valid_inbox_name ($) {
1;
}
+# parse a code repo
+# Only git is supported at the moment, but SVN and Hg are possibilities
+sub _fill_code_repo {
+ my ($self, $nick) = @_;
+ my $pfx = "coderepo.$nick";
+
+ my $dir = $self->{"$pfx.dir"}; # aka "GIT_DIR"
+ unless (defined $dir) {
+ warn "$pfx.repodir unset";
+ return;
+ }
+
+ my $git = PublicInbox::Git->new($dir);
+ foreach my $t (qw(blob commit tree tag)) {
+ $git->{$t.'_url_format'} =
+ _array($self->{lc("$pfx.${t}UrlFormat")});
+ }
+
+ if (my $cgits = $self->{lc("$pfx.cgitUrl")}) {
+ $git->{cgit_url} = $cgits = _array($cgits);
+
+ # cgit supports "/blob/?id=%s", but it's only a plain-text
+ # display and requires an unabbreviated id=
+ foreach my $t (qw(blob commit tag)) {
+ $git->{$t.'_url_format'} ||= map {
+ "$_/$t/?id=%s"
+ } @$cgits;
+ }
+ }
+ # TODO: support gitweb and other repository viewers?
+ # TODO: parse cgitrc
+
+ $git;
+}
+
sub _fill {
my ($self, $pfx) = @_;
my $rv = {};
@@ -192,9 +235,9 @@ sub _fill {
}
# TODO: more arrays, we should support multi-value for
# more things to encourage decentralization
- foreach my $k (qw(address altid nntpmirror)) {
+ foreach my $k (qw(address altid nntpmirror coderepo)) {
if (defined(my $v = $self->{"$pfx.$k"})) {
- $rv->{$k} = ref($v) eq 'ARRAY' ? $v : [ $v ];
+ $rv->{$k} = _array($v);
}
}
@@ -224,6 +267,18 @@ sub _fill {
$rv->{-no_obfuscate_re} = $self->{-no_obfuscate_re};
each_inbox($self, sub {}); # noop to populate -no_obfuscate
}
+
+ if (my $ibx_code_repos = $rv->{coderepo}) {
+ my $code_repos = $self->{-code_repos};
+ my $repo_objs = $rv->{-repo_objs} = [];
+ foreach my $nick (@$ibx_code_repos) {
+ valid_inbox_name($nick) or next;
+ my $repo = $code_repos->{$nick} ||=
+ _fill_code_repo($self, $nick);
+ push @$repo_objs, $repo if $repo;
+ }
+ }
+
$rv
}
diff --git a/lib/PublicInbox/View.pm b/lib/PublicInbox/View.pm
index 470e3ab..0187ec3 100644
--- a/lib/PublicInbox/View.pm
+++ b/lib/PublicInbox/View.pm
@@ -14,6 +14,7 @@ use PublicInbox::MsgIter;
use PublicInbox::Address;
use PublicInbox::WwwStream;
use PublicInbox::Reply;
+use PublicInbox::ViewDiff qw(flush_diff);
require POSIX;
use Time::Local qw(timegm);
@@ -28,7 +29,7 @@ sub msg_html {
my ($ctx, $mime, $more, $smsg) = @_;
my $hdr = $mime->header_obj;
my $ibx = $ctx->{-inbox};
- my $obfs_ibx = $ctx->{-obfs_ibx} = $ibx->{obfuscate} ? $ibx : undef;
+ $ctx->{-obfs_ibx} = $ibx->{obfuscate} ? $ibx : undef;
my $tip = _msg_html_prepare($hdr, $ctx, $more, 0);
my $end = 2;
PublicInbox::WwwStream->response($ctx, 200, sub {
@@ -36,7 +37,7 @@ sub msg_html {
if ($nr == 1) {
# $more cannot be true w/o $smsg being defined:
my $upfx = $more ? '../'.mid_escape($smsg->mid).'/' : '';
- $tip . multipart_text_as_html($mime, $upfx, $obfs_ibx) .
+ $tip . multipart_text_as_html($mime, $upfx, $ibx) .
'</pre><hr>'
} elsif ($more && @$more) {
++$end;
@@ -81,15 +82,15 @@ sub msg_html_more {
my $str = eval {
my ($id, $prev, $smsg) = @$more;
my $mid = $ctx->{mid};
- $smsg = $ctx->{-inbox}->smsg_mime($smsg);
+ my $ibx = $ctx->{-inbox};
+ $smsg = $ibx->smsg_mime($smsg);
my $next = $ctx->{srch}->next_by_mid($mid, \$id, \$prev);
@$more = $next ? ($id, $prev, $next) : ();
if ($smsg) {
my $mime = $smsg->{mime};
my $upfx = '../' . mid_escape($smsg->mid) . '/';
_msg_html_prepare($mime->header_obj, $ctx, $more, $nr) .
- multipart_text_as_html($mime, $upfx,
- $ctx->{-obfs_ibx}) .
+ multipart_text_as_html($mime, $upfx, $ibx) .
'</pre><hr>'
} else {
'';
@@ -260,7 +261,8 @@ sub index_entry {
$rv .= "\n";
# scan through all parts, looking for displayable text
- msg_iter($mime, sub { $rv .= add_text_body($mhref, $obfs_ibx, $_[0]) });
+ my $ibx = $ctx->{-inbox};
+ msg_iter($mime, sub { $rv .= add_text_body($mhref, $ibx, $_[0]) });
# add the footer
$rv .= "\n<a\nhref=#$id_m\nid=e$id>^</a> ".
@@ -488,11 +490,11 @@ sub thread_html {
}
sub multipart_text_as_html {
- my ($mime, $upfx, $obfs_ibx) = @_;
+ my ($mime, $upfx, $ibx) = @_;
my $rv = "";
# scan through all parts, looking for displayable text
- msg_iter($mime, sub { $rv .= add_text_body($upfx, $obfs_ibx, $_[0]) });
+ msg_iter($mime, sub { $rv .= add_text_body($upfx, $ibx, $_[0]) });
$rv;
}
@@ -545,7 +547,8 @@ sub attach_link ($$$$;$) {
}
sub add_text_body {
- my ($upfx, $obfs_ibx, $p) = @_;
+ my ($upfx, $ibx, $p) = @_;
+ my $obfs_ibx = $ibx->{obfuscate} ? $ibx : undef;
# $p - from msg_iter: [ Email::MIME, depth, @idx ]
my ($part, $depth) = @$p; # attachment @idx is unused
my $ct = $part->content_type || 'text/plain';
@@ -554,6 +557,19 @@ sub add_text_body {
return attach_link($upfx, $ct, $p, $fn) unless defined $s;
+ my ($diff, $spfx);
+ if ($ibx->{-repo_objs} && $s =~ /^(?:diff|---|\+{3}) /ms) {
+ $diff = [];
+ my $n_slash = $upfx =~ tr!/!/!;
+ if ($n_slash == 0) {
+ $spfx = '../';
+ } elsif ($n_slash == 1) {
+ $spfx = '';
+ } else { # nslash == 2
+ $spfx = '../../';
+ }
+ };
+
my @lines = split(/^/m, $s);
$s = '';
if (defined($fn) || $depth > 0 || $err) {
@@ -568,19 +584,26 @@ sub add_text_body {
# show the previously buffered quote inline
flush_quote(\$s, $l, \@quot) if @quot;
- # regular line, OK
- $l->linkify_1($cur);
- $s .= $l->linkify_2(ascii_html($cur));
+ if ($diff) {
+ push @$diff, $cur;
+ } else {
+ # regular line, OK
+ $l->linkify_1($cur);
+ $s .= $l->linkify_2(ascii_html($cur));
+ }
} else {
+ flush_diff(\$s, $spfx, $l, $diff) if $diff && @$diff;
push @quot, $cur;
}
}
if (@quot) { # ugh, top posted
flush_quote(\$s, $l, \@quot);
+ flush_diff(\$s, $spfx, $l, $diff) if $diff && @$diff;
obfuscate_addrs($obfs_ibx, $s) if $obfs_ibx;
$s;
} else {
+ flush_diff(\$s, $spfx, $l, $diff) if $diff && @$diff;
obfuscate_addrs($obfs_ibx, $s) if $obfs_ibx;
if ($s =~ /\n\z/s) { # common, last line ends with a newline
$s;
diff --git a/lib/PublicInbox/ViewDiff.pm b/lib/PublicInbox/ViewDiff.pm
new file mode 100644
index 0000000..ee450fa
--- /dev/null
+++ b/lib/PublicInbox/ViewDiff.pm
@@ -0,0 +1,147 @@
+# Copyright (C) 2019 all contributors <meta@public-inbox.org>
+# License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt>
+#
+# used by PublicInbox::View
+package PublicInbox::ViewDiff;
+use strict;
+use warnings;
+use base qw(Exporter);
+our @EXPORT_OK = qw(flush_diff);
+
+use PublicInbox::Hval qw(ascii_html);
+use PublicInbox::Git qw(git_unquote);
+
+sub DSTATE_INIT () { 0 }
+sub DSTATE_STAT () { 1 } # TODO
+sub DSTATE_HEAD () { 2 } # /^diff --git /, /^index /, /^--- /, /^\+\+\+ /
+sub DSTATE_HUNK () { 3 } # /^@@ /
+sub DSTATE_CTX () { 4 } # /^ /
+sub DSTATE_ADD () { 5 } # /^\+/
+sub DSTATE_DEL () { 6 } # /^\-/
+
+my $OID_NULL = '0{7,40}';
+my $OID_BLOB = '[a-f0-9]{7,40}';
+my $PATH_A = '"?a/.+|/dev/null';
+my $PATH_B = '"?b/.+|/dev/null';
+
+sub to_html ($$) {
+ $_[0]->linkify_1($_[1]);
+ $_[0]->linkify_2(ascii_html($_[1]));
+}
+
+# link to line numbers in blobs
+sub diff_hunk ($$$$) {
+ my ($dctx, $spfx, $ca, $cb) = @_;
+ my $oid_a = $dctx->{oid_a};
+ my $oid_b = $dctx->{oid_b};
+
+ (defined($oid_a) && defined($oid_b)) or return "@@ $ca $cb @@";
+
+ my ($n) = ($ca =~ /^-(\d+)/);
+ $n = defined($n) ? do { ++$n; "#n$n" } : '';
+
+ my $rv = qq(@@ <a\nhref=$spfx$oid_a/s$n>$ca</a>);
+
+ ($n) = ($cb =~ /^\+(\d+)/);
+ $n = defined($n) ? do { ++$n; "#n$n" } : '';
+
+ $rv .= qq( <a\nhref=$spfx$oid_b/s$n>$cb</a> @@);
+}
+
+sub flush_diff ($$$$) {
+ my ($dst, $spfx, $linkify, $diff) = @_;
+ my $state = DSTATE_INIT;
+ my $dctx; # {}, keys: oid_a, oid_b, path_a, path_b
+
+ foreach my $s (@$diff) {
+ if ($s =~ /^ /) {
+ if ($state == DSTATE_HUNK || $state == DSTATE_ADD ||
+ $state == DSTATE_DEL || $state == DSTATE_HEAD) {
+ $$dst .= "</span><span\nclass=ctx>";
+ $state = DSTATE_CTX;
+ }
+ $$dst .= to_html($linkify, $s);
+ } elsif ($s =~ /^-- $/) { # email signature begins
+ if ($state != DSTATE_INIT) {
+ $state = DSTATE_INIT;
+ $$dst .= '</span>';
+ }
+ $$dst .= $s;
+ } elsif ($s =~ m!^diff --git ($PATH_A) ($PATH_B)$!x) {
+ if ($state != DSTATE_HEAD) {
+ my ($pa, $pb) = ($1, $2);
+ $$dst .= '</span>' if $state != DSTATE_INIT;
+ $$dst .= "<span\nclass=head>";
+ $state = DSTATE_HEAD;
+ $pa = (split('/', git_unquote($pa), 2))[1];
+ $pb = (split('/', git_unquote($pb), 2))[1];
+ $dctx = { path_a => $pa, path_b => $pb };
+ }
+ $$dst .= to_html($linkify, $s);
+ } elsif ($s =~ s/^(index $OID_NULL\.\.)($OID_BLOB)\b//o) {
+ $$dst .= qq($1<a\nhref=$spfx$2/s>$2</a>);
+ $$dst .= to_html($linkify, $s) ;
+ } elsif ($s =~ s/^index ($OID_NULL)(\.\.$OID_BLOB)\b//o) {
+ $$dst .= 'index ';
+ $$dst .= qq(<a\nhref=$spfx$1/s>$1</a>$2);
+ $$dst .= to_html($linkify, $s);
+ } elsif ($s =~ /^index ($OID_BLOB)\.\.($OID_BLOB)/o) {
+ $dctx->{oid_a} = $1;
+ $dctx->{oid_b} = $2;
+ $$dst .= to_html($linkify, $s);
+ } elsif ($s =~ s/^@@ (\S+) (\S+) @@//) {
+ my ($ca, $cb) = ($1, $2);
+ if ($state == DSTATE_HEAD || $state == DSTATE_CTX ||
+ $state == DSTATE_ADD || $state == DSTATE_DEL) {
+ $$dst .= "</span><span\nclass=hunk>";
+ $state = DSTATE_HUNK;
+ $$dst .= diff_hunk($dctx, $spfx, $ca, $cb);
+ } else {
+ $$dst .= to_html($linkify, "@@ $ca $cb @@");
+ }
+ $$dst .= to_html($linkify, $s);
+ } elsif ($s =~ m!^--- $PATH_A!) {
+ if ($state == DSTATE_INIT) { # color only (no oid link)
+ $state = DSTATE_HEAD;
+ $$dst .= "<span\nclass=head>";
+ }
+ $$dst .= to_html($linkify, $s);
+ } elsif ($s =~ m!^\+{3} $PATH_B!) {
+ if ($state == DSTATE_INIT) { # color only (no oid link)
+ $state = DSTATE_HEAD;
+ $$dst .= "<span\nclass=head>";
+ }
+ $$dst .= to_html($linkify, $s);
+ } elsif ($s =~ /^\+/) {
+ if ($state != DSTATE_ADD && $state != DSTATE_INIT) {
+ $$dst .= "</span><span\nclass=add>";
+ $state = DSTATE_ADD;
+ }
+ $$dst .= to_html($linkify, $s);
+ } elsif ($s =~ /^-/) {
+ if ($state != DSTATE_DEL && $state != DSTATE_INIT) {
+ $$dst .= "</span><span\nclass=del>";
+ $state = DSTATE_DEL;
+ }
+ $$dst .= to_html($linkify, $s);
+ # ignore the following lines in headers:
+ } elsif ($s =~ /^(?:dis)similarity index/ ||
+ $s =~ /^(?:old|new) mode/ ||
+ $s =~ /^(?:deleted|new) file mode/ ||
+ $s =~ /^(?:copy|rename) (?:from|to) / ||
+ $s =~ /^(?:dis)?similarity index /) {
+ $$dst .= to_html($linkify, $s);
+ } else {
+ if ($state != DSTATE_INIT) {
+ $$dst .= '</span>';
+ $state = DSTATE_INIT;
+ }
+ $$dst .= to_html($linkify, $s);
+ }
+ }
+ @$diff = ();
+ $$dst .= '</span>' if $state != DSTATE_INIT;
+ undef;
+}
+
+1;
diff --git a/lib/PublicInbox/ViewVCS.pm b/lib/PublicInbox/ViewVCS.pm
new file mode 100644
index 0000000..49fb1c5
--- /dev/null
+++ b/lib/PublicInbox/ViewVCS.pm
@@ -0,0 +1,87 @@
+# Copyright (C) 2019 all contributors <meta@public-inbox.org>
+# License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt>
+
+# show any VCS object, similar to "git show"
+package PublicInbox::ViewVCS;
+use strict;
+use warnings;
+use Encode qw(find_encoding);
+use PublicInbox::SolverGit;
+use PublicInbox::WwwStream;
+use PublicInbox::Linkify;
+use PublicInbox::Hval qw(ascii_html);
+my %QP_MAP = ( A => 'oid_a', B => 'oid_b', a => 'path_a', b => 'path_b' );
+my $max_size = 1024 * 1024; # TODO: configurable
+my $enc_utf8 = find_encoding('UTF-8');
+
+sub html_page ($$$) {
+ my ($ctx, $code, $strref) = @_;
+ $ctx->{-upfx} = '../'; # from "/$INBOX/$OID/s"
+ PublicInbox::WwwStream->response($ctx, $code, sub {
+ my ($nr, undef) = @_;
+ $nr == 1 ? $$strref : undef;
+ });
+}
+
+sub show ($$;$) {
+ my ($ctx, $oid_b, $fn) = @_;
+ my $ibx = $ctx->{-inbox};
+ my $inboxes = [ $ibx ];
+ my $solver = PublicInbox::SolverGit->new($ibx->{-repo_objs}, $inboxes);
+ my $qp = $ctx->{qp};
+ my $hints = {};
+ while (my ($from, $to) = each %QP_MAP) {
+ defined(my $v = $qp->{$from}) or next;
+ $hints->{$to} = $v;
+ }
+
+ open my $log, '+>', undef or die "open: $!";
+ my $res = $solver->solve($log, $oid_b, $hints);
+
+ seek($log, 0, 0) or die "seek: $!";
+ $log = do { local $/; <$log> };
+
+ my $l = PublicInbox::Linkify->new;
+ $l->linkify_1($log);
+ $log = '<pre>debug log:</pre><hr /><pre>' .
+ $l->linkify_2(ascii_html($log)) . '</pre>';
+
+ $res or return html_page($ctx, 404, \$log);
+
+ my ($git, $oid, $type, $size, $di) = @$res;
+ if ($size > $max_size) {
+ # TODO: stream the raw file if it's gigantic, at least
+ $log = '<pre><b>Too big to show</b></pre>' . $log;
+ return html_page($ctx, 500, \$log);
+ }
+
+ my $blob = $git->cat_file($oid);
+ if (!$blob) { # WTF?
+ my $e = "Failed to retrieve generated blob ($oid)";
+ $ctx->{env}->{'psgi.errors'}->print("$e ($git->{git_dir})\n");
+ $log = "<pre><b>$e</b></pre>" . $log;
+ return html_page($ctx, 500, \$log);
+ }
+
+ if (index($$blob, "\0") >= 0) {
+ $log = "<pre>$oid $type $size bytes (binary)</pre>" . $log;
+ return html_page($ctx, 200, \$log);
+ }
+
+ $$blob = $enc_utf8->decode($$blob);
+ my $nl = ($$blob =~ tr/\n/\n/);
+ my $pad = length($nl);
+
+ # using some of the same CSS class names and ids as cgit
+ $log = "<pre>$oid $type $size bytes</pre><hr /><table\nclass=blob>".
+ "<tr><td\nclass=linenumbers><pre>" . join('', map {
+ sprintf("<a id=n$_ href=#n$_>% ${pad}u</a>\n", $_)
+ } (1..$nl)) . '</pre></td>' .
+ '<td><pre> </pre></td>'. # pad for non-CSS users
+ "<td\nclass=lines><pre><code>" . ascii_html($$blob) .
+ '</pre></td></tr></table>' . $log;
+
+ html_page($ctx, 200, \$log);
+}
+
+1;
diff --git a/lib/PublicInbox/WWW.pm b/lib/PublicInbox/WWW.pm
index 3562e46..c73370f 100644
--- a/lib/PublicInbox/WWW.pm
+++ b/lib/PublicInbox/WWW.pm
@@ -25,6 +25,7 @@ our $INBOX_RE = qr!\A/([\w\-][\w\.\-]*)!;
our $MID_RE = qr!([^/]+)!;
our $END_RE = qr!(T/|t/|t\.mbox(?:\.gz)?|t\.atom|raw|)!;
our $ATTACH_RE = qr!(\d[\.\d]*)-([[:alnum:]][\w\.-]+[[:alnum:]])!i;
+our $OID_RE = qr![a-f0-9]{7,40}!;
sub new {
my ($class, $pi_config) = @_;
@@ -117,7 +118,10 @@ sub call {
r301($ctx, $1, $2);
} elsif ($path_info =~ m!$INBOX_RE/_/text(?:/(.*))?\z!o) {
get_text($ctx, $1, $2);
-
+ } elsif ($path_info =~ m!$INBOX_RE/($OID_RE)/s\z!o) {
+ get_vcs_object($ctx, $1, $2);
+ } elsif ($path_info =~ m!$INBOX_RE/($OID_RE)/_([\w\.\-]+)\z!o) {
+ get_vcs_object($ctx, $1, $2, $3);
# convenience redirects order matters
} elsif ($path_info =~ m!$INBOX_RE/([^/]{2,})\z!o) {
r301($ctx, $1, $2);
@@ -259,6 +263,18 @@ sub get_text {
PublicInbox::WwwText::get_text($ctx, $key);
}
+# show git objects (blobs and commits)
+# /$INBOX/_/$OBJECT_ID/show
+# /$INBOX/_/${OBJECT_ID}_${FILENAME}
+# KEY may contain slashes
+sub get_vcs_object ($$$;$) {
+ my ($ctx, $inbox, $oid, $filename) = @_;
+ my $r404 = invalid_inbox($ctx, $inbox);
+ return $r404 if $r404;
+ require PublicInbox::ViewVCS;
+ PublicInbox::ViewVCS::show($ctx, $oid, $filename);
+}
+
sub ctx_get {
my ($ctx, $key) = @_;
my $val = $ctx->{$key};
--
EW
^ permalink raw reply related [relevance 3%]
* [PATCH 00/37] viewvcs: diff highlighting and more
@ 2019-01-21 20:52 7% Eric Wong
2019-01-21 20:52 3% ` [PATCH 09/37] view: wire up diff and vcs viewers with solver Eric Wong
0 siblings, 1 reply; 2+ results
From: Eric Wong @ 2019-01-21 20:52 UTC (permalink / raw)
To: meta
Still working on VCS integration and I'm not comfortable deploying
this on the main public-inbox.org because of performance/fairness
concerns, yet.
But, perfect is the enemy of good and I figure it's worth
publishing at the moment. It's also on a Tor mirror:
http://hjrcffqmbrq6wope.onion/meta/
http://hjrcffqmbrq6wope.onion/git/
It looks great to me in Netsurf and dillo :>
People with machines powerful enough to run Firefox
(or Tor Browser Bundle) can use "View -> Page Style" to adjust
colors.
Performance considerations:
* diff highlighting alone adds 10-20% overhead to message rendering
Maybe I can speed it up with some less-readable Perl...
* blob reconstruction is horribly unfair to other clients at the
moment. Fixing this is a priority for me.
I haven't hooked up highlight to blob viewing, yet; but that's
coming; too.
Thinking about it more, the blob lookups is so specific to git
that I'm not sure other VCSes can be supported...
The following changes since commit 55db8a2a51c13aec813ac56bbaac1505791fd262:
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
TODO: autolinkify that(!)
t/git.t: do not pass "-b" to git-repack(1) (2019-01-18 22:00:33 +0000)
are available in the Git repository at:
https://public-inbox.org/ viewvcs
for you to fetch changes up to c440c879d38e67f62bdbb74f616dc84d20899c33:
t/check-www-inbox: trap SIGINT for File::Temp destruction (2019-01-21 06:53:35 +0000)
----------------------------------------------------------------
Eric Wong (37):
view: disable bold in topic display
hval: force monospace for <form> elements, too
t/perf-msgview: add test to check msg_html performance
solver: initial Perl implementation
git: support multiple URL endpoints
git: add git_quote
git: check saves error on disambiguation
solver: various bugfixes and cleanups
view: wire up diff and vcs viewers with solver
git: disable abbreviations with cat-file hints
solver: operate directly on git index
view: enable naming hints for raw blob downloads
git: support 'ambiguous' result from --batch-check
solver: more verbose blob resolution
solver: break up patch application steps
solver: switch patch application to use a callback
solver: simplify control flow for initial loop
solver: break @todo loop into a callback
solver: note the synchronous nature of index preparation
solver: add a TODO note about making this fully evented
view: enforce trailing slash for /$INBOX/$OID/s/ endpoints
solver: restore diagnostics and deal with CRLF
www: admin-configurable CSS via "publicinbox.css"
$INBOX/_/text/color/ and sample user-side CSS
viewdiff: support diff-highlighting w/o coderepo
viewdiff: cleanup state transitions a bit
viewdiff: quote attributes for Atom feed
t/check-www-inbox: use xmlstarlet to validate Atom if available
viewdiff: do not link to 0{7,40} blobs (again)
viewvcs: disable white-space prewrap in blob view
solver: force quoted-printable bodies to LF
solver: remove extra "^index $OID..$OID" line
config: each_inbox iteration preserves config order
t/check-www-inbox: warn on missing Content-Type
highlight: initial wrapper and PSGI service
hval: split out escape sequences to a separate table
t/check-www-inbox: trap SIGINT for File::Temp destruction
Documentation/design_www.txt | 6 +-
MANIFEST | 15 +
Makefile.PL | 3 +
TODO | 2 -
contrib/css/216dark.css | 26 ++
contrib/css/216light.css | 25 ++
contrib/css/README | 41 +++
examples/highlight.psgi | 13 +
examples/public-inbox.psgi | 2 +-
lib/PublicInbox/Config.pm | 96 +++++-
lib/PublicInbox/Git.pm | 87 ++++-
lib/PublicInbox/HlMod.pm | 126 ++++++++
lib/PublicInbox/Hval.pm | 38 +--
lib/PublicInbox/SolverGit.pm | 454 +++++++++++++++++++++++++++
lib/PublicInbox/UserContent.pm | 78 +++++
lib/PublicInbox/View.pm | 51 ++-
lib/PublicInbox/ViewDiff.pm | 161 ++++++++++
lib/PublicInbox/ViewVCS.pm | 110 +++++++
lib/PublicInbox/WWW.pm | 152 ++++++++-
lib/PublicInbox/WwwHighlight.pm | 73 +++++
lib/PublicInbox/WwwStream.pm | 4 +-
lib/PublicInbox/WwwText.pm | 35 +++
script/public-inbox-httpd | 2 +-
t/check-www-inbox.perl | 26 +-
t/config.t | 19 ++
t/git.t | 7 +-
t/hl_mod.t | 54 ++++
t/perf-msgview.t | 50 +++
t/solve/0001-simple-mod.patch | 20 ++
t/solve/0002-rename-with-modifications.patch | 37 +++
t/solver_git.t | 91 ++++++
t/view.t | 2 +
32 files changed, 1841 insertions(+), 65 deletions(-)
create mode 100644 contrib/css/216dark.css
create mode 100644 contrib/css/216light.css
create mode 100644 contrib/css/README
create mode 100644 examples/highlight.psgi
create mode 100644 lib/PublicInbox/HlMod.pm
create mode 100644 lib/PublicInbox/SolverGit.pm
create mode 100644 lib/PublicInbox/UserContent.pm
create mode 100644 lib/PublicInbox/ViewDiff.pm
create mode 100644 lib/PublicInbox/ViewVCS.pm
create mode 100644 lib/PublicInbox/WwwHighlight.pm
create mode 100644 t/hl_mod.t
create mode 100644 t/perf-msgview.t
create mode 100644 t/solve/0001-simple-mod.patch
create mode 100644 t/solve/0002-rename-with-modifications.patch
create mode 100644 t/solver_git.t
Eric Wong (37):
view: disable bold in topic display
hval: force monospace for <form> elements, too
t/perf-msgview: add test to check msg_html performance
solver: initial Perl implementation
git: support multiple URL endpoints
git: add git_quote
git: check saves error on disambiguation
solver: various bugfixes and cleanups
view: wire up diff and vcs viewers with solver
git: disable abbreviations with cat-file hints
solver: operate directly on git index
view: enable naming hints for raw blob downloads
git: support 'ambiguous' result from --batch-check
solver: more verbose blob resolution
solver: break up patch application steps
solver: switch patch application to use a callback
solver: simplify control flow for initial loop
solver: break @todo loop into a callback
solver: note the synchronous nature of index preparation
solver: add a TODO note about making this fully evented
view: enforce trailing slash for /$INBOX/$OID/s/ endpoints
solver: restore diagnostics and deal with CRLF
www: admin-configurable CSS via "publicinbox.css"
$INBOX/_/text/color/ and sample user-side CSS
viewdiff: support diff-highlighting w/o coderepo
viewdiff: cleanup state transitions a bit
viewdiff: quote attributes for Atom feed
t/check-www-inbox: use xmlstarlet to validate Atom if available
viewdiff: do not link to 0{7,40} blobs (again)
viewvcs: disable white-space prewrap in blob view
solver: force quoted-printable bodies to LF
solver: remove extra "^index $OID..$OID" line
config: each_inbox iteration preserves config order
t/check-www-inbox: warn on missing Content-Type
highlight: initial wrapper and PSGI service
hval: split out escape sequences to a separate table
t/check-www-inbox: trap SIGINT for File::Temp destruction
Documentation/design_www.txt | 6 +-
MANIFEST | 15 +
Makefile.PL | 3 +
TODO | 2 -
contrib/css/216dark.css | 26 ++
contrib/css/216light.css | 25 +
contrib/css/README | 41 ++
examples/highlight.psgi | 13 +
examples/public-inbox.psgi | 2 +-
lib/PublicInbox/Config.pm | 96 +++-
lib/PublicInbox/Git.pm | 87 +++-
lib/PublicInbox/HlMod.pm | 126 +++++
lib/PublicInbox/Hval.pm | 38 +-
lib/PublicInbox/SolverGit.pm | 454 +++++++++++++++++++
lib/PublicInbox/UserContent.pm | 78 ++++
lib/PublicInbox/View.pm | 51 ++-
lib/PublicInbox/ViewDiff.pm | 161 +++++++
lib/PublicInbox/ViewVCS.pm | 110 +++++
lib/PublicInbox/WWW.pm | 152 ++++++-
lib/PublicInbox/WwwHighlight.pm | 73 +++
lib/PublicInbox/WwwStream.pm | 4 +-
lib/PublicInbox/WwwText.pm | 35 ++
script/public-inbox-httpd | 2 +-
t/check-www-inbox.perl | 26 +-
t/config.t | 19 +
t/git.t | 7 +-
t/hl_mod.t | 54 +++
t/perf-msgview.t | 50 ++
t/solve/0001-simple-mod.patch | 20 +
t/solve/0002-rename-with-modifications.patch | 37 ++
t/solver_git.t | 91 ++++
t/view.t | 2 +
32 files changed, 1841 insertions(+), 65 deletions(-)
create mode 100644 contrib/css/216dark.css
create mode 100644 contrib/css/216light.css
create mode 100644 contrib/css/README
create mode 100644 examples/highlight.psgi
create mode 100644 lib/PublicInbox/HlMod.pm
create mode 100644 lib/PublicInbox/SolverGit.pm
create mode 100644 lib/PublicInbox/UserContent.pm
create mode 100644 lib/PublicInbox/ViewDiff.pm
create mode 100644 lib/PublicInbox/ViewVCS.pm
create mode 100644 lib/PublicInbox/WwwHighlight.pm
create mode 100644 t/hl_mod.t
create mode 100644 t/perf-msgview.t
create mode 100644 t/solve/0001-simple-mod.patch
create mode 100644 t/solve/0002-rename-with-modifications.patch
create mode 100644 t/solver_git.t
^ permalink raw reply [relevance 7%]
Results 1-2 of 2 | reverse | options above
-- pct% links below jump to the message on this page, permalinks otherwise --
2019-01-21 20:52 7% [PATCH 00/37] viewvcs: diff highlighting and more Eric Wong
2019-01-21 20:52 3% ` [PATCH 09/37] view: wire up diff and vcs viewers with solver Eric Wong
Code repositories for project(s) associated with this public inbox
https://80x24.org/public-inbox.git
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).