www: Include .so mans if found in the same package

Unfortunately, this can lead to slightly confusing scenarios, because
the exact package of the displayed man page is not very well defined.
It's possible that, when browsing from a package listing to a man page,
you may see an included file that does not come from the package you
browsed from.
E.g. https://manned.org/pwrite/5f2909f6 - that man page simply includes
pread.2, but from the URL it's unclear from which package or system it
should be included.

The only way to fix this is to add the package ID to the link format.
This commit is contained in:
Yorhel 2017-02-26 08:52:23 +01:00
parent 81e2c99503
commit 8e5fa1e165
2 changed files with 45 additions and 23 deletions

View file

@ -24,14 +24,6 @@ sub fmt {
$$output = ''; $$output = '';
@$errors = (); @$errors = ();
# tix comes with[1] a custom(?) macro package. But it looks okay even without
# loading that.
# [1] It actually doesn't, the tcllib package appears to have that file, but
# doesn't '.so' it.
$input =~ s/^\.so man.macros$//mg;
# Other .so's should be handled by html()
$input =~ s/^\.so (.+)$/.in -10\n.sp\n\[\[\[MANNEDINCLUDE$1\]\]\]/mg;
$input = $input =
# Disable hyphenation, since that screws up man page references. :-( # Disable hyphenation, since that screws up man page references. :-(
".hy 0\n.de hy\n..\n" ".hy 0\n.de hy\n..\n"

View file

@ -618,20 +618,49 @@ sub _normalizename {
} }
# Replace .so's in man source with the contents (if available in the same
# package) or with a reference to the other man page.
sub soelim {
my($self, $verid, $src) = @_;
# tix comes with[1] a custom(?) macro package. But it looks okay even without
# loading that.
# [1] It actually doesn't, the tcllib package appears to have that file, but
# doesn't '.so' it.
$src =~ s/^\.so man.macros$//mg;
# Other .so's should be handled by html()
$src =~ s{^\.so (.+)$}{
my $path = $1;
my $name = (reverse split /\//, $path)[0];
my($man) = $verid ? $self->dbManPrefName($name, pkgver => $verid) : ();
if($man) {
# Recursive soelim, but the second call gets $verid=0 so we don't keep checking the database
soelim($self, 0, $self->dbManContent($man->{hash}))
} else {
".in -10\n.sp\n\[\[\[MANNEDINCLUDE$path\]\]\]"
}
}emg;
return $src;
}
sub man { sub man {
my($self, $name, $hash) = @_; my($self, $name, $hash) = @_;
$name = _normalizename($name); $name = _normalizename($name);
my $man; # Unfortunately, even in the permalink format with the hash, we don't know
if($hash) { # from which package we're supposed to get the man page. This info is
$man = $self->dbManInfo(name => $name, shorthash => $hash)->[0]; # needed in order to do .so substitution, so we can substitute files from
} else { # the same package as the requested man page. Use the dbManPref logic here
($man, undef) = $self->dbManPrefName($name); # to deterministically select a good package.
} my($man, undef) = $hash
? $self->dbManPref(name => $name, shorthash => $hash)
: $self->dbManPrefName($name);
return $self->resNotFound() if !$man; return $self->resNotFound() if !$man;
my $fmt = ManUtils::html(ManUtils::fmt_block $self->dbManContent($man->{hash})); my $fmt = ManUtils::html(ManUtils::fmt_block soelim $self, $man->{verid}, $self->dbManContent($man->{hash}));
my @toc; my @toc;
$fmt =~ s{\n<b>(.+?)<\/b>\n}{ $fmt =~ s{\n<b>(.+?)<\/b>\n}{
push @toc, $1; push @toc, $1;
@ -884,7 +913,7 @@ sub dbManInfo {
$o{sort} eq 'syspkgname' ? 'ORDER BY s.name, s.relorder DESC, p.name, v.released DESC, m.name, m.locale NULLS FIRST, m.filename' : ''; $o{sort} eq 'syspkgname' ? 'ORDER BY s.name, s.relorder DESC, p.name, v.released DESC, m.name, m.locale NULLS FIRST, m.filename' : '';
my $select = $o{countonly} ? 'COUNT(*) as count' my $select = $o{countonly} ? 'COUNT(*) as count'
: "p.system, p.category, p.name AS package, v.version, v.released, m.name, m.section, m.filename, m.locale, encode(m.hash, 'hex') AS hash"; : "p.system, p.category, p.name AS package, v.version, v.released, v.id AS verid, m.name, m.section, m.filename, m.locale, encode(m.hash, 'hex') AS hash";
my($r, $np) = $s->dbPage(\%o, q{ my($r, $np) = $s->dbPage(\%o, q{
SELECT !s SELECT !s
@ -919,10 +948,11 @@ sub dbSearch {
# Get the preferred man page for the given filters. Returns a row with the same fields as dbManInfo(). # Get the preferred man page for the given filters. Returns a row with the same fields as dbManInfo().
sub dbManPref { sub dbManPref {
my($s, $name, $section, %o) = @_; my($s, %o) = @_;
my %where = ( my %where = (
'm.name = ?' => $name, $o{name} ? ('m.name = ?' => $o{name}) : (),
$section ? ('m.section LIKE ?' => escape_like($section).'%') : (), $o{shorthash} ? (q{substring(m.hash from 1 for 4) = decode(?, 'hex')} => $o{shorthash}) : (),
$o{section} ? ('m.section LIKE ?' => escape_like($o{section}).'%') : (),
$o{sysid} ? ('p.system = ?' => $o{sysid}) : (), $o{sysid} ? ('p.system = ?' => $o{sysid}) : (),
$o{package} ? ('p.id = ?' => $o{package}) : (), $o{package} ? ('p.id = ?' => $o{package}) : (),
$o{pkgver} ? ('v.id = ?' => $o{pkgver}) : (), $o{pkgver} ? ('v.id = ?' => $o{pkgver}) : (),
@ -962,10 +992,10 @@ sub dbManPref {
), f_secorder AS( ), f_secorder AS(
SELECT * FROM f_sysrel a WHERE NOT EXISTS(SELECT 1 FROM f_sysrel b WHERE (a.man).section > (b.man).section) SELECT * FROM f_sysrel a WHERE NOT EXISTS(SELECT 1 FROM f_sysrel b WHERE (a.man).section > (b.man).section)
) )
SELECT (pkg).system, (pkg).category, (pkg).name AS package, (ver).version, (ver).released, SELECT (pkg).system, (pkg).category, (pkg).name AS package, (ver).version, (ver).released, (ver).id AS verid,
(man).name, (man).section, (man).filename, (man).locale, encode((man).hash, 'hex') AS hash (man).name, (man).section, (man).filename, (man).locale, encode((man).hash, 'hex') AS hash
FROM f_secorder ORDER BY (man).hash LIMIT 1 FROM f_secorder ORDER BY (man).hash LIMIT 1
}, \%where, $section, $section)->[0]; }, \%where, $o{section}||'', $o{section}||'')->[0];
} }
@ -974,12 +1004,12 @@ sub dbManPref {
sub dbManPrefName { sub dbManPrefName {
my($s, $name, %o) = @_; my($s, $name, %o) = @_;
my $man = $s->dbManPref($name, '', %o); my $man = $s->dbManPref(%o, name => $name);
return ($man, '') if $man; return ($man, '') if $man;
return (undef, '') if $name !~ s/\.([^.]+)$//; return (undef, '') if $name !~ s/\.([^.]+)$//;
my $section = $1; my $section = $1;
$man = $s->dbManPref($name, $section, %o); $man = $s->dbManPref(%o, name => $name, section => $section);
return ($man, $section) if $man; return ($man, $section) if $man;
return (undef, ''); return (undef, '');
} }