diff options
-rw-r--r-- | cgi-bin/css/lxrng.css | 6 | ||||
-rw-r--r-- | cgi-bin/js/lxrng-funcs.js | 47 | ||||
-rwxr-xr-x | cgi-bin/lxr | 66 | ||||
-rw-r--r-- | lib/LXRng/Context.pm | 16 | ||||
-rw-r--r-- | lib/LXRng/Index/DBI.pm | 117 | ||||
-rw-r--r-- | lib/LXRng/Index/Pg.pm | 3 | ||||
-rw-r--r-- | lib/LXRng/Index/PgBatch.pm | 2 | ||||
-rw-r--r-- | lib/LXRng/Lang/C.pm | 3 | ||||
-rw-r--r-- | lib/LXRng/Markup/File.pm | 2 | ||||
-rw-r--r-- | lib/LXRng/Repo/Git.pm | 17 | ||||
-rw-r--r-- | lib/LXRng/Search/Xapian.pm | 29 | ||||
-rwxr-xr-x | lxr-genxref | 127 | ||||
-rw-r--r-- | lxrng.conf-dist | 2 | ||||
-rw-r--r-- | tmpl/header.tt2 | 18 | ||||
-rw-r--r-- | tmpl/prefs.tt2 | 13 | ||||
-rw-r--r-- | tmpl/search_result.tt2 | 6 |
16 files changed, 335 insertions, 139 deletions
diff --git a/cgi-bin/css/lxrng.css b/cgi-bin/css/lxrng.css index 9a47d80..637c774 100644 --- a/cgi-bin/css/lxrng.css +++ b/cgi-bin/css/lxrng.css @@ -273,6 +273,12 @@ div.progress { font-style: italic; } +div.error { + font-weight: bold; + font-style: italic; + color: #E04040; +} + form { display: inline; } diff --git a/cgi-bin/js/lxrng-funcs.js b/cgi-bin/js/lxrng-funcs.js index d7c9be8..614879e 100644 --- a/cgi-bin/js/lxrng-funcs.js +++ b/cgi-bin/js/lxrng-funcs.js @@ -74,12 +74,18 @@ var pending_ver; var pending_line; function ajax_nav() { - var file = this.href.replace(/^(http:.*?lxr\/[+]ajax\/|)/, ''); - // alert(loaded_file + ' - ' + file); + var file = this.href.replace(/^(http:.*?\/.*?[+][*]\/|)/, ''); load_file(loaded_tree, file, loaded_ver, ''); return false; } +function ajax_jumpto_line() { + location.hash = location.hash.replace(/\#L\d+$/, '') + + this.href.replace(/.*(\#L\d+)$/, '$1'); + check_hash_navigation(); + return false; +} + function ajax_prefs() { if (use_ajax_navigation) { var full_path = location.href.split(/#/)[0]; @@ -102,12 +108,14 @@ function check_hash_navigation() { if (location.hash.replace(/\#L\d+$/, '') == loaded_hash.replace(/\#L\d+$/, '')) { - var l = location.hash.replace(/.*(\#L\d+)$/, '$1'); + var l = location.hash.replace(/.*#(L\d+)$/, '$1'); var a = document.getElementById(l); if (l && a) { - a.name = location.hash; + a.name = location.hash.replace(/^\#/, ''); location.hash = a.name; + loaded_hash = location.hash; } + hash_check = setTimeout('check_hash_navigation()', 50); } else { // alert(location.hash + ' / ' + loaded_hash); @@ -150,6 +158,7 @@ function load_file(tree, file, ver, line) { function load_file_finalize(content) { var res = document.getElementById('content'); + res.innerHTML = 'Done'; res.innerHTML = content; var head = document.getElementById('current_path'); head.innerHTML = '<a class=\"fref\" href=\".\">' + pending_tree + '</a>'; @@ -165,11 +174,11 @@ function load_file_finalize(content) { } document.title = 'LXR ' + pending_tree + '/' + pending_file; - var full_path = pending_tree; + var full_tree = pending_tree; if (pending_ver) { - full_path = full_path + '+' + pending_ver; + full_tree = full_tree + '+' + pending_ver; } - full_path = full_path + '/' + pending_file.replace(/^\/?/, ''); + var full_path = full_tree + '/' + pending_file.replace(/^\/?/, ''); var pre = document.getElementById('file_contents'); if (pre && pre.className == 'partial') { @@ -178,6 +187,9 @@ function load_file_finalize(content) { [load_file_finalize]); } + if (hash_check) { + clearTimeout(hash_check); + } if (pending_line) { var anchor = document.getElementById('L' + pending_line); if (anchor) { @@ -197,18 +209,18 @@ function load_file_finalize(content) { loaded_tree = pending_tree; loaded_file = pending_file; loaded_ver = pending_ver; - if (hash_check) { - clearTimeout(hash_check); - } hash_check = setTimeout('check_hash_navigation()', 50); +// return; +// TODO: This really takes oodles of time. Consider coding into html. var i; for (i = 0; i < document.links.length; i++) { - if (document.links[i].className == 'fref' || - document.links[i].className == 'line') - { + if (document.links[i].className == 'fref') { document.links[i].onclick = ajax_nav; } + else if (document.links[i].className == 'line') { + document.links[i].onclick = ajax_jumpto_line; + } else if (document.links[i].className == 'sref' || document.links[i].className == 'falt') { @@ -243,8 +255,10 @@ function load_content_finalize(content) { function update_version(verlist, base_url, tree, defversion, path) { if (use_ajax_navigation) { var file = location.hash.replace(/^[^\/]*\//, ''); + var line = file.replace(/.*\#L(\d+)/, '$1'); + file = file.replace(/\#L\d+$/, ''); - load_file(loaded_tree, file, verlist.value, ''); + load_file(loaded_tree, file, verlist.value, line); return false; } else { @@ -279,7 +293,10 @@ function ajax_lookup_anchor(event, anchor) { if (!anchor) anchor = this; - lookup = anchor.href.replace(/^(http:.*?lxr\/[+]ajax\/|)/, ''); + // TODO: Fix +// lookup = anchor.href.replace(/^(http:.*?lxr\/[+]ajax\/|)/, ''); + lookup = anchor.href.replace(/^(http:.*?\/.*?[+][*]\/|)/, ''); + var lvar = document.getElementById('ajax_lookup'); lvar.value = lookup; diff --git a/cgi-bin/lxr b/cgi-bin/lxr index cda9179..a0c0f6e 100755 --- a/cgi-bin/lxr +++ b/cgi-bin/lxr @@ -4,7 +4,6 @@ use strict; use FindBin; use lib "$FindBin::Bin/../lib"; -use lib '/home/argggh/www/lxrng/_deps/share/perl/5.8.4'; use CGI::Carp qw(fatalsToBrowser); use IO::Handle; @@ -51,6 +50,11 @@ sub print_markedup_file { autoflush STDOUT 1; + unless ($node) { + print('<div class="error">File not found.</div>'); + return; + } + if ($node->isa('LXRng::Repo::Directory')) { my $markup = LXRng::Markup::Dir->new('context' => $context, 'node' => $node); @@ -126,29 +130,29 @@ sub print_release_list { } sub source { - my ($context, $template, $query) = @_; + my ($context, $template, $query, $template_extra_args) = @_; - my $pjx = CGI::Ajax->new('pjx_search' => 'lxr', - 'pjx_load_file' => 'lxr', - 'pjx_releases' => 'lxr'); + my $pjx = CGI::Ajax->new('pjx_search' => '', + 'pjx_load_file' => '', + 'pjx_releases' => ''); $pjx->js_encode_function('escape'); - + if ($context->prefs and $context->prefs->{'navmethod'} eq 'ajax') { - my $path = $query->path_info; - $path =~ s,^/[+ ],,; - if ($path ne '') { - $path =~ s,^/+,,; - print($query->redirect($query->url(-full => 1). - '#'.$path)); + if ($context->tree ne '') { + my $base = $context->base_url(1); + my $path = $context->vtree.'/'.$context->path; + print($query->redirect($base.'#'.$path)); } else { print($query->header(-type => 'text/html', -charset => 'utf-8')); - my $base = $query->url(-full => 1); + my $base = $context->base_url(1); + $base =~ s,/*$,/ajax+*/,; + $template->process('main.tt2', {'context' => $context, - 'base_url' => $base.'/+ajax/', + 'base_url' => $base, 'javascript' => $pjx->show_javascript(), 'is_ajax' => 1}) or die $template->error(); @@ -168,11 +172,13 @@ sub source { my $ver = $context->release; my $rep = $context->config->{'repository'}; - my $node = $rep->node($context->path, $ver); + die "No tree given" unless $rep; + my $node = $rep->node($context->path, $ver); die "Node not found: ".$context->path." ($ver)" unless $node; - my %template_args = ('context' => $context, + my %template_args = (%{$template_extra_args || {}}, + 'context' => $context, 'tree' => $context->tree, 'node' => $node, 'base_url' => $context->base_url, @@ -288,7 +294,7 @@ sub search { $$ident[5] &&= $LXRng::Lang::deftypes{$$ident[5]}; use Data::Dumper; - warn Dumper($symname, $symid, $ident, $refs); + # warn Dumper($symname, $symid, $ident, $refs); $template_args{'ident_res'} = {'query' => $symname, 'ident' => $ident, 'refs' => $refs}; @@ -326,26 +332,23 @@ sub search_result { 'search_res' => $result, 'base_url' => $context->base_url); - my $gzip = do_compress_response($query); + if ($context->prefs and $context->prefs->{'navmethod'} eq 'popup') { + my $gzip = do_compress_response($query); - print($query->header(-type => 'text/html', - -charset => 'utf-8', - $gzip ? (-content_encoding => 'gzip') : ())); + print($query->header(-type => 'text/html', + -charset => 'utf-8', + $gzip ? (-content_encoding => 'gzip') : ())); - binmode(\*STDOUT, ":gzip") if $gzip; + binmode(\*STDOUT, ":gzip") if $gzip; - if ($context->prefs and $context->prefs->{'navmethod'} eq 'popup') { $template->process('popup_main.tt2', {%template_args, 'is_popup' => 1}) or die $template->error(); } else { - $template->process('main.tt2', - {%template_args, - 'file_content' => '', - 'is_dir' => 0}) - or die $template->error(); + $context->path(''); + source($context, $template, $query, \%template_args); } } @@ -423,8 +426,13 @@ sub handle_preferences { print($query->header(-type => 'text/html', -charset => 'utf-8')); + my $nav = 'is_replace'; + $nav = 'is_'.$context->prefs->{'navmethod'} if + $context->prefs and $context->prefs->{'navmethod'} ne ''; + $template->process('prefs.tt2', - {'return' => $query->param('return')}) + {'return' => $query->param('return'), + $nav => 1}) or die $template->error(); } } diff --git a/lib/LXRng/Context.pm b/lib/LXRng/Context.pm index 46faa21..caaa473 100644 --- a/lib/LXRng/Context.pm +++ b/lib/LXRng/Context.pm @@ -9,7 +9,10 @@ sub new { $self = bless({}, $self); if ($args{'query'}) { - $$self{'req_url'} = $args{'query'}->url(); + # CGI::Simple appears to confuse '' with undef for SCRIPT_NAME. + # $$self{'req_url'} = $args{'query'}->url(); + $$self{'req_url'} = + $args{'query'}->url(-base => 1).'/'.$ENV{'SCRIPT_NAME'}; foreach my $p ($args{'query'}->param) { $$self{'params'}{$p} = [$args{'query'}->param($p)]; @@ -28,7 +31,7 @@ sub new { } if ($$self{'tree'} =~ s/[+](.*)$//) { - $$self{'release'} = $1; + $$self{'release'} = $1 if $1 ne '*'; } if ($$self{'tree'}) { @@ -137,7 +140,7 @@ sub path_elements { sub config { my ($self) = @_; - return $$self{'config'}; + return $$self{'config'} || {}; } sub prefs { @@ -147,7 +150,7 @@ sub prefs { } sub base_url { - my ($self) = @_; + my ($self, $notree) = @_; my $base = $self->config->{'base_url'}; unless ($base) { @@ -156,7 +159,10 @@ sub base_url { } $base =~ s,/+$,,; - $base .= '/lxr/'.$self->vtree.'/'; + + return $base if $notree; + + $base .= '/'.$self->vtree.'/'; $base =~ s,//+$,/,; return $base; diff --git a/lib/LXRng/Index/DBI.pm b/lib/LXRng/Index/DBI.pm index 602eac8..932202c 100644 --- a/lib/LXRng/Index/DBI.pm +++ b/lib/LXRng/Index/DBI.pm @@ -73,6 +73,110 @@ sub _get_tree { return $id; } +sub pending_files { + my ($self, $tree) = @_; + + my $tree_id = $self->_get_tree($tree); + return [] unless $tree_id; + + my $dbh = $self->dbh; + my $pre = $self->prefix; + + # Can be made more fine grained by consulting filestatus, but all + # hashed documents need to have their termlist updated... Just + # include all files participating in releases not yet fully + # indexed. + my $sth = $$self{'sth'}{'pending_files'} ||= + $dbh->prepare(qq{ + select rv.id, f.path, rv.revision + from ${pre}revisions rv, ${pre}files f + where rv.id_file = f.id + and rv.id in (select fr.id_rfile + from ${pre}releases r, ${pre}filereleases fr + where r.id = fr.id_release + and r.id_tree = ? + and r.is_indexed = 'f')}); + +# $dbh->prepare(qq{ +# select rv.id, f.path, rv.revision +# from ${pre}files f, ${pre}revisions rv +# where rv.id_file = f.id +# and not exists(select 1 from ${pre}filestatus fs +# where fs.id_rfile = rv.id +# and fs.indexed = 't' +# and fs.hashed = 't' +# and fs.referenced = 't') +# and exists(select 1 from ${pre}filereleases fr, ${pre}releases r +# where fr.id_rfile = rv.id +# and fr.id_release = r.id +# and r.id_tree = ?)}); + if ($sth->execute($tree_id) > 0) { + return $sth->fetchall_arrayref(); + } + else { + $sth->finish(); + return []; + } +} + +sub new_releases_by_file { + my ($self, $file_id) = @_; + + my $dbh = $self->dbh; + my $pre = $self->prefix; + my $sth = $$self{'sth'}{'releases_by_file'} ||= + $dbh->prepare(qq{ + select r.release_tag from ${pre}releases r, ${pre}filereleases f + where r.id = f.id_release and f.id_rfile = ? and r.is_indexed = 'f'}); + if ($sth->execute($file_id) > 0) { + return [map { $$_[0] } @{$sth->fetchall_arrayref()}]; + } + else { + $sth->finish(); + return []; + } +} + +sub update_indexed_releases { + my ($self, $tree) = @_; + + my $tree_id = $self->_get_tree($tree); + return [] unless $tree_id; + + my $dbh = $self->dbh; + my $pre = $self->prefix; + my $sth = $$self{'sth'}{'update_indexed_releases_find'} ||= + $dbh->prepare(qq{ + select r.id, r.release_tag + from ${pre}releases r + where is_indexed = 'f' + and not exists (select 1 + from ${pre}filereleases fr + left outer join ${pre}filestatus fs + on (fr.id_rfile = fs.id_rfile) + where fr.id_release = r.id + and (fs.id_rfile is null + or fs.indexed = 'f' + or fs.hashed = 'f' + or fs.referenced = 'f'))}); + + if ($sth->execute() > 0) { + my $rels = $sth->fetchall_arrayref(); + $sth->finish(); + $sth = $$self{'sth'}{'update_indexed_releases_set'} ||= + $dbh->prepare(qq{ + update ${pre}releases set is_indexed = 't' where id = ?}); + foreach my $r (@$rels) { + $sth->execute($$r[0]); + } + $sth->finish(); + return [map { $$_[1] } @$rels]; + } + else { + return []; + } +} + sub _get_release { my ($self, $tree_id, $release) = @_; @@ -345,14 +449,19 @@ sub get_symbol_usage { my $dbh = $self->dbh; my $pre = $self->prefix; - my $sth = $$self{'sth'}{'get_symbol_usage'} ||= + + # Postgres' query optimizer deals badly with placeholders and + # prepared statements in this case. + return undef unless $symid =~ /^\d+$/s; + my $sth = $dbh->prepare(qq{ select u.id_rfile, u.line from ${pre}usage u, ${pre}filereleases fr - where u.id_symbol = ? - and u.id_rfile = fr.id_rfile and fr.id_release = ?}); + where u.id_symbol = $symid + and u.id_rfile = fr.id_rfile and fr.id_release = ? + limit 1000}); - $sth->execute($symid, $rel_id); + $sth->execute($rel_id); my $res = $sth->fetchall_arrayref(); $sth->finish(); diff --git a/lib/LXRng/Index/Pg.pm b/lib/LXRng/Index/Pg.pm index 05fe3a0..1b905c0 100644 --- a/lib/LXRng/Index/Pg.pm +++ b/lib/LXRng/Index/Pg.pm @@ -179,6 +179,8 @@ sub init_db { or die($dbh->errstr); $dbh->do(qq{create index ${pre}file_idx1 on ${pre}files using btree (path)}) or die($dbh->errstr); + $dbh->do(qq{create index ${pre}filerel_idx1 on ${pre}filereleases using btree (id_release)}) + or die($dbh->errstr); $dbh->do(qq{grant select on ${pre}charsets to public}) or die($dbh->errstr); $dbh->do(qq{grant select on ${pre}trees to public}) or die($dbh->errstr); @@ -212,6 +214,7 @@ sub drop_db { $dbh->do(qq{drop index ${pre}usage_idx2}); $dbh->do(qq{drop index ${pre}include_idx1}); $dbh->do(qq{drop index ${pre}file_idx1}); + $dbh->do(qq{drop index ${pre}filerel_idx1}); $dbh->do(qq{drop table ${pre}usage}); $dbh->do(qq{drop table ${pre}identifiers}); diff --git a/lib/LXRng/Index/PgBatch.pm b/lib/LXRng/Index/PgBatch.pm index 8f8844c..19c9fa9 100644 --- a/lib/LXRng/Index/PgBatch.pm +++ b/lib/LXRng/Index/PgBatch.pm @@ -77,7 +77,7 @@ sub flush { } } $self->dbh->commit() unless $self->dbh->{AutoCommit}; - $self->dbh->do(q(analyze)) if $i > 100000; + $self->dbh->do(q(analyze)) if $i > 500000; $self->dbh->disconnect(); warn "\n*** index: flushed $i rows\n"; kill(9, $$); diff --git a/lib/LXRng/Lang/C.pm b/lib/LXRng/Lang/C.pm index c88f424..1a826bd 100644 --- a/lib/LXRng/Lang/C.pm +++ b/lib/LXRng/Lang/C.pm @@ -51,7 +51,8 @@ sub parsespec { 'comment', '//', "\$", 'string', '"', '"', 'string', "'", "'", - 'include', '#\s*include', "\$"]; + 'include', '#\s*include\s+"', '"', + 'include', '#\s*include\s+<', '>']; } sub typemap { diff --git a/lib/LXRng/Markup/File.pm b/lib/LXRng/Markup/File.pm index 406737c..abb763c 100644 --- a/lib/LXRng/Markup/File.pm +++ b/lib/LXRng/Markup/File.pm @@ -16,7 +16,7 @@ sub context { sub safe_html { my ($str) = @_; - return encode_entities($str, '^\n\r\t !\#\$\(-;=?-~'); + return encode_entities($str, '^\n\r\t !\#\$\(-;=?-~\200-\377'); } sub make_format_newline { diff --git a/lib/LXRng/Repo/Git.pm b/lib/LXRng/Repo/Git.pm index 2d6ea33..757da26 100644 --- a/lib/LXRng/Repo/Git.pm +++ b/lib/LXRng/Repo/Git.pm @@ -74,7 +74,7 @@ sub allversions { } sub node { - my ($self, $path, $release) = @_; + my ($self, $path, $release, $rev) = @_; $path =~ s,^/+,,; $path =~ s,/+$,,; @@ -88,14 +88,21 @@ sub node { return LXRng::Repo::Git::Directory->new($self, '', $ref); } - my $git = $self->_git_cmd('ls-tree', $release, $path); - my ($mode, $type, $ref, $gitpath) = split(" ", <$git>); + my $type; + if ($rev) { + $type = 'blob'; + } + else { + my $git = $self->_git_cmd('ls-tree', $release, $path); + my ($mode, $gitpath); + ($mode, $type, $rev, $gitpath) = split(" ", <$git>); + } if ($type eq 'tree') { - return LXRng::Repo::Git::Directory->new($self, $path, $ref, $release); + return LXRng::Repo::Git::Directory->new($self, $path, $rev, $release); } elsif ($type eq 'blob') { - return LXRng::Repo::Git::File->new($self, $path, $ref, $release); + return LXRng::Repo::Git::File->new($self, $path, $rev, $release); } else { return undef; diff --git a/lib/LXRng/Search/Xapian.pm b/lib/LXRng/Search/Xapian.pm index 42c7580..b6e28a0 100644 --- a/lib/LXRng/Search/Xapian.pm +++ b/lib/LXRng/Search/Xapian.pm @@ -32,9 +32,11 @@ sub new_document { } sub add_document { - my ($self, $doc, $rel_id) = @_; + my ($self, $doc, $rel_ids) = @_; - $doc->add_term('__@@LXRREL_'.$rel_id); + foreach my $r (@$rel_ids) { + $doc->add_term('__@@LXRREL_'.$r); + } my $doc_id = $self->wrdb->add_document($doc); $self->{'writes'}++; $self->flush() if $self->{'writes'} % 499 == 0; @@ -42,20 +44,25 @@ sub add_document { } sub add_release { - my ($self, $doc_id, $rel_id) = @_; + my ($self, $doc_id, $rel_ids) = @_; - my $reltag = '__@@LXRREL_'.$rel_id; my $doc = $self->wrdb->get_document($doc_id); - my $term = $doc->termlist_begin; my $termend = $doc->termlist_end; - $term->skip_to($reltag); - if ($term ne $termend) { - return 0 if $term->get_termname eq $reltag; + my $changes = 0; + foreach my $r (@$rel_ids) { + my $reltag = '__@@LXRREL_'.$r; + my $term = $doc->termlist_begin; + $term->skip_to($reltag); + if ($term ne $termend) { + next if $term->get_termname eq $reltag; + } + $doc->add_term($reltag); + $changes++; } - $doc->add_term($reltag); - $self->wrdb->replace_document($doc_id, $doc); - return 1; + + $self->wrdb->replace_document($doc_id, $doc) if $changes; + return $changes; } sub flush { diff --git a/lxr-genxref b/lxr-genxref index 79e98f5..9f055ae 100755 --- a/lxr-genxref +++ b/lxr-genxref @@ -86,15 +86,15 @@ sub make_add_ident { } sub index_file { - my ($context, $index, $tree, $rel, $file, $fileid) = @_; + my ($context, $index, $tree, $file, $fileid) = @_; my $lang = LXRng::Lang->new($file); - return unless $lang->doindex(); unless ($index->to_index($fileid)) { progress_mark("*"); return; } + return unless $lang->doindex(); my $add_ident = make_add_ident($index, $fileid); @@ -137,20 +137,18 @@ sub index_file { } sub reference_file { - my ($context, $index, $tree, $rel, $file, $fileid) = @_; + my ($context, $index, $tree, $file, $fileid) = @_; my $lang = LXRng::Lang->new($file); - return unless $lang->doindex(); - unless ($index->to_reference($fileid)) { progress_mark("."); return; } + return unless $lang->doindex(); -# sysopen(my $handle, $file->phys_path, O_RDONLY) or die($!); -# my $parse = new LXRng::Parse::Simple($handle, 8, @{$lang->parsespec}); - my $parse = new LXRng::Parse::Simple($file->handle, 8, @{$lang->parsespec}); + my $parse = new LXRng::Parse::Simple($file->handle, 8, + @{$lang->parsespec}); progress_info("referencing ".$file->name.", ". $file->size." bytes ($lang)..."); @@ -196,7 +194,7 @@ sub reference_file { } sub hash_file { - my ($context, $index, $hash, $tree, $rel, $file, $fileid) = @_; + my ($context, $index, $hash, $tree, $file, $fileid, $rels) = @_; my $docid; if ($index->to_hash($fileid)) { @@ -218,47 +216,19 @@ sub hash_file { $doc->add_posting($term, $.*100 + $pos++); } } - $docid = $hash->add_document($doc, $index->release_id($tree, $rel)); + + $docid = $hash->add_document($doc, [map { + $index->release_id($tree, $_) } @$rels]); $index->add_hashed_document($fileid, $docid); } else { $docid = $index->get_hashed_document($fileid); - if ($hash->add_release($docid, $index->release_id($tree, $rel))) { - progress_mark("+"); - } - else { - progress_mark("-"); - } + my $changed = $hash->add_release($docid, [map { + $index->release_id($tree, $_) } @$rels]); + progress_mark($changed ? "+" : "-"); } - # for all releases this fileid belongs to (that are not is_indexed) - # add_release to $docid. } -sub do_index { - my ($context, $index, $hash, $tree, $rel, $iter) = @_; - - my $node; - while (defined($node = $iter->next)) { - next if $node->name =~ /\.o$/; - my $fileid = $index->rfile_id($node, 1); - $index->add_filerelease($tree, $rel, $fileid); - index_file($context, $index, $tree, $rel, $node, $fileid); - hash_file($context, $index, $hash, $tree, $rel, $node, $fileid); - } -} - -sub do_reference { - my ($context, $index, $hash, $tree, $rel, $iter) = @_; - - my $node; - while (defined($node = $iter->next)) { - next if $node->name =~ /\.o$/; - my $fileid = $index->rfile_id($node, 1); - LXRng::Index::transaction { - reference_file($context, $index, $tree, $rel, $node, $fileid); - } $index; - } -} my $tree = shift(@ARGV); my @versions = @ARGV; @@ -269,33 +239,76 @@ my $index = $context->config->{'index'}; my $hash = $context->config->{'search'}; my $rep = $context->config->{'repository'}; -sub do_genxref { + +sub inventory_release { my ($tree, $version) = @_; - print("\nindexing release $version...\n"); - my $root = $rep->node('/', $version) or die "bad root"; - $context->release($version); - + print("\nrecording all files for $version...\n"); + + my $iter = $rep->iterator($version); + LXRng::Index::transaction { + my $root = $rep->node('/', $version) or die "bad root"; + + my $node; + while (defined($node = $iter->next)) { + next if $node->name =~ /\.o$/; + my $fileid = $index->rfile_id($node, 1); + $index->add_filerelease($tree, $version, $fileid); + } + } $index; +} + +sub index_pending { + my ($tree) = @_; + my $pending = $index->pending_files($tree); + + print("\nindexing ".(0+@$pending)." outstanding files...\n"); LXRng::Index::transaction { - do_index($context, $index, $hash, $tree, $version, $rep->iterator($version)); - do_reference($context, $index, $hash, $tree, $version, $rep->iterator($version)); + foreach my $p (@$pending) { + my ($fileid, $path, $rev) = @$p; + my $rels = $index->new_releases_by_file($fileid); + next unless @$rels; + my $node = $rep->node($path, $$rels[0], $rev); + next unless $node; + + hash_file($context, $index, $hash, $tree, $node, $fileid, $rels); + index_file($context, $index, $tree, $node, $fileid); + } } $index; - $hash->flush(); - # Mark release as is_indexed - progress_info("release $version done"); + print("\nreferencing ".(0+@$pending)." outstanding files...\n"); + LXRng::Index::transaction { + foreach my $p (@$pending) { + my ($fileid, $path, $rev) = @$p; + my $rels = $index->new_releases_by_file($fileid); + next unless @$rels; + $context->release($$rels[0]); # Needed for include resolution. + my $node = $rep->node($path, $$rels[0], $rev); + next unless $node; + + LXRng::Index::transaction { + reference_file($context, $index, $tree, $node, $fileid, $rels); + } $index; + } + } $index; + + my $done = $index->update_indexed_releases($tree); + + progress_info("releases ".join(", ", @$done)." done") if + @$done; } if (@versions) { foreach my $version (@versions) { - do_genxref($tree, $version); + inventory_release($tree, $version); } } else { - # Run pass over all un-indexed releases, record all files. - foreach my $version (reverse @{$context->all_releases}) { next if $index->_get_release($index->tree_id($tree), $version); - system($0, $tree, $version); + inventory_release($tree, $version); } } + +index_pending($tree); +$hash->flush(); diff --git a/lxrng.conf-dist b/lxrng.conf-dist index 80c35f5..27abb1b 100644 --- a/lxrng.conf-dist +++ b/lxrng.conf-dist @@ -24,7 +24,7 @@ return { 'index' => $index, 'search' => $search, - 'base_url' => 'http://lxr-test.linpro.no/', + 'base_url' => 'http://lxr-test.linpro.no/lxr', # Must be writable by httpd user: 'cache' => '/var/lib/lxrng/cache', diff --git a/tmpl/header.tt2 b/tmpl/header.tt2 index 0c5b6f6..0b07111 100644 --- a/tmpl/header.tt2 +++ b/tmpl/header.tt2 @@ -2,9 +2,22 @@ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en"> <head> - <base href="[% base_url %]" /> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> - + [% IF is_ajax %] + <script type="text/javascript"> + var tree = location.hash.match(/^#([^/+]+)([+][^/]*|)/); + if (tree) { + var base = '[% base_url %]'; + base = base.replace(/\/ajax[+][*]/, '/' + tree[1] + '+*'); + document.write('<base href="' + base + '" />'); + } + else { + document.write('<base href="[% base_url %]" />'); + } + </script> + [% ELSE %] + <base href="[% base_url %]" /> + [% END %] <script type="text/javascript" src="../../js/lxrng-funcs.js"></script> <link rel="stylesheet" href="../../css/lxrng.css" type="text/css" title="LXRng" /> @@ -36,6 +49,7 @@ END %] </span> <img src="../../gfx/rolldown.png" /> + <!-- TODO: appears to break w. ajax nav. --> [% IF node.name.match('[^/]$') %] <form action="+print=[% node.name %]" method="post"> <button type="submit" class="print"><img src="../../gfx/print.png"></button> diff --git a/tmpl/prefs.tt2 b/tmpl/prefs.tt2 index c7f6a6d..6246ac6 100644 --- a/tmpl/prefs.tt2 +++ b/tmpl/prefs.tt2 @@ -18,7 +18,7 @@ </span> <div class="lxr_menu"> - <span class="lxr_prefs"><a href="[% return || '.' %]">Back</a></span> + <span class="lxr_prefs"><a href="./[% return %]">Back</a></span> </div> <div class="headingbottom"></div> </div> @@ -30,10 +30,12 @@ <input type="hidden" name="return" value="[% return %]" /> Where do you want your search results to be displayed? <ol> - <li><input type="radio" name="resultloc" value="replace" /> + <li><input type="radio" name="resultloc" value="replace" + [% IF is_replace %]checked[% END %]/> Replace the active source browsing window</li> - <li><input type="radio" name="resultloc" value="popup" /> + <li><input type="radio" name="resultloc" value="popup" + [% IF is_popup %]checked[% END %]/> Show them in a popup window (requires JavaScript enabled)<br> <font size="-1"><em>If your browser limits the ability to @@ -41,9 +43,10 @@ Preferences -> Content -> Enable JavaScript -> Advanced -> Allow scripts to: Raise or lower windows), make sure you either close your search result windows or avoid hiding them - behing other windows after use.</em></font></li> + behind other windows after use.</em></font></li> - <li><input type="radio" name="resultloc" value="ajax" /> + <li><input type="radio" name="resultloc" value="ajax" + [% IF is_ajax %]checked[% END %]/> Show them inside the active source browsing window (requires JavaScript enabled) </li> diff --git a/tmpl/search_result.tt2 b/tmpl/search_result.tt2 index 639e951..1a38e22 100644 --- a/tmpl/search_result.tt2 +++ b/tmpl/search_result.tt2 @@ -56,7 +56,8 @@ at [% INCLUDE line_reference.tt2, file = file.1, line = file.2 %] <ul> [% FOREACH file = file_res.files %] <li><a href="[% file %]" onclick="return load_file('[% context.tree %]', - '[% file %][% context.args_url %]', '', '');" [% navtarget %]>[% file %]</a> + '[% file %][% context.args_url %]', '[% context.release %]', '');" + [% navtarget %]>[% file %]</a> </li> [% END %] </ul> @@ -67,7 +68,8 @@ at [% INCLUDE line_reference.tt2, file = file.1, line = file.2 %] <ul> [% FOREACH file = ambig_res.files %] <li><a href="[% file %]" onclick="return load_file('[% context.tree %]', - '[% file %][% context.args_url %]', '', '');" [% navtarget %]>[% file %]</a> + '[% file %][% context.args_url %]', '[% context.release %]', '');" + [% navtarget %]>[% file %]</a> </li> [% END %] </ul> |