Update with latest fixes 0.14
wreis [Thu, 10 Mar 2011 17:13:42 +0000 (14:13 -0300)]
19 files changed:
lib/BackPAN/Index.pm
lib/BackPAN/Web.pm
root/html/about.html
root/html/error_404.html
root/html/error_500.html
root/html/layout.html
root/static/html/about.html [new file with mode: 0644]
root/static/html/dist.html [new file with mode: 0644]
root/static/html/error_404.html [new file with mode: 0644]
root/static/html/error_500.html [new file with mode: 0644]
root/static/html/index.html [new file with mode: 0644]
root/static/html/layout.html [new file with mode: 0644]
root/static/html/listing.html [new file with mode: 0644]
root/static/static/arrow-down.gif [new file with mode: 0644]
root/static/static/arrow-up.gif [new file with mode: 0644]
root/static/static/favicon.ico [new file with mode: 0644]
root/static/static/main.css [new file with mode: 0644]
root/static/static/searchbtn.png [new file with mode: 0644]
t/leaktrace.t [new file with mode: 0644]

index bb76563..6b7d0e8 100644 (file)
@@ -96,8 +96,6 @@ sub _update_database {
         $should_update_db = 1 if $db_mtime < $archive_mtime;
     }
 
-    unlink $db_file if -e $db_file and $should_update_db;
-
     $self->schema( BackPAN::Index::Schema->connect("dbi:SQLite:dbname=$db_file") );
     return unless $should_update_db;
 
@@ -269,10 +267,16 @@ CREATE TABLE IF NOT EXISTS dists (
 )
 SQL
 );
+    my %delete_for = (
+        files => 'DELETE FROM files',
+        releases => 'DELETE FROM releases',
+        dists => 'DELETE FROM dists',
+    );
 
     my $dbh = $self->_dbh;
-    for my $sql (values %create_for) {
-        $dbh->do($sql);
+    for my $table_name (keys %create_for) {
+        $dbh->do($create_for{$table_name});
+        $dbh->do($delete_for{$table_name});
     }
 
     $self->schema->rescan;
index 87c332c..2aa5bbc 100644 (file)
@@ -375,6 +375,7 @@ sub search {
 dispatch {
     subdispatch sub () {
         $self->_build_request_obj_from($_[+PSGI_ENV]);
+        my $base_title = 'BackPAN.org';
         [
             sub (/) {
                 $self->html_response({ body => $self->index_page_content });
@@ -396,7 +397,8 @@ dispatch {
                 my $release_rs = $self->releases($_[1]);
                 if ( $release_rs->count ) {
                     my $body = $self->releases_page_content($release_rs)
-                        ->select('#nav-releases')->add_to_attribute(class => 'active');
+                        ->select('#nav-releases')->add_to_attribute(class => 'active')
+                       ->select('title')->replace_content(join q{ - }, 'Releases', $base_title);
                     return $self->html_response({ body => $body });
                 }
                 else {
@@ -411,7 +413,8 @@ dispatch {
                 my $dist_rs = $self->dists($_[1]);
                 if ( $dist_rs->count ) {
                     my $body = $self->dists_page_content($dist_rs)
-                        ->select('#nav-dists')->add_to_attribute(class => 'active');
+                        ->select('#nav-dists')->add_to_attribute(class => 'active')
+                       ->select('title')->replace_content(join q{ - }, 'Distributions', $base_title);
                     return $self->html_response({ body => $body });
                 }
                 else {
@@ -424,7 +427,8 @@ dispatch {
 
             sub ( /distribution/*|/distribution/*/ + ?* ) {
                 if ( my $dist = $self->get_dist($_[1]) ) {
-                    my $body = $self->dist_info_page_content($dist, $_[2]);
+                    my $body = $self->dist_info_page_content($dist, $_[2])
+                       ->select('title')->replace_content(join q{ - }, $self->format_dist_name($dist->name), $base_title);
                     return $self->html_response({ body => $body });
                 }
                 else {
@@ -438,7 +442,8 @@ dispatch {
             sub ( /authors|/authors/ + ?* ) {
                 if ( my $authors = $self->authors($_[1]) ) {
                     my $body = $self->authors_page_content($authors)
-                        ->select('#nav-authors')->add_to_attribute(class => 'active');
+                        ->select('#nav-authors')->add_to_attribute(class => 'active')
+                       ->select('title')->replace_content(join q{ - }, 'Authors', $base_title);
                     return $self->html_response({ body => $body });
                 }
                 else {
@@ -456,7 +461,8 @@ dispatch {
                     my $body = $self->dists_page_content($dist_rs)
                         ->select('#q')->add_to_attribute(
                             value => $query_str
-                        );
+                        )
+                       ->select('title')->replace_content(join q{ - }, 'Search', $base_title);
                     return $self->html_response({ body => $body });
                 }
                 else {
@@ -495,10 +501,10 @@ sub as_psgi_app {
             404 => 'root/html/error_404.html';
         enable 'HTTPExceptions';
         enable 'Head';
-        enable 'AccessLog',
-            format => 'combined',
-            logger => sub { get_logger('accesslog')->info(@_) };
-        enable 'Log4perl', conf => 'log/log.conf';
+        #enable 'AccessLog',
+        #    format => 'combined',
+        #    logger => sub { get_logger('accesslog')->info(@_) };
+        #enable 'Log4perl', conf => 'log/log.conf';
         $app;
     };
 }
index b9b5083..62ab513 100644 (file)
@@ -1,7 +1,7 @@
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 <html>
        <head>
-               <title>BackPAN</title>
+               <title>About - BackPAN.org</title>
                <meta http-equiv="content-type" content="text/html;charset=UTF-8" />
                <link rel="shortcut icon" href="/static/favicon.ico" />
                <link rel="stylesheet" href="/static/main.css" type="text/css" />
index dd543f1..2137193 100644 (file)
@@ -1,7 +1,7 @@
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 <html>
         <head>
-                <title>BackPAN</title>
+                <title>Not found - BackPAN.org</title>
                 <meta http-equiv="content-type" content="text/html;charset=UTF-8" />
                <link rel="shortcut icon" href="/static/favicon.ico" />
                 <link rel="stylesheet" href="/static/main.css" type="text/css" />
index 2d36760..ad103ca 100644 (file)
@@ -1,7 +1,7 @@
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 <html>
        <head>
-               <title>BackPAN</title>
+               <title>Ooooops! - BackPAN.org</title>
                <meta http-equiv="content-type" content="text/html;charset=UTF-8" />
                <link rel="shortcut icon" href="/static/favicon.ico" />
                <link rel="stylesheet" href="/static/main.css" type="text/css" />
index bc6bae6..1f128e1 100644 (file)
@@ -1,7 +1,7 @@
 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
 <html>
        <head>
-               <title>BackPAN</title>
+               <title>BackPAN.org</title>
                <meta http-equiv="content-type" content="text/html;charset=UTF-8" />
                <link rel="shortcut icon" href="/static/favicon.ico" />
                <link rel="stylesheet" href="/static/main.css" type="text/css" />
diff --git a/root/static/html/about.html b/root/static/html/about.html
new file mode 100644 (file)
index 0000000..ae7254d
--- /dev/null
@@ -0,0 +1,53 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+       <head>
+               <title>BackPAN</title>
+               <meta http-equiv="content-type" content="text/html;charset=UTF-8" />
+               <link rel="stylesheet" href="/static/main.css" type="text/css" />
+       </head>
+<body>
+<div class="container">
+       <div id="search">
+                <form action="/search" method="GET">
+                        <input type="text" id="q" name="q" />
+                       <input type="submit" id="searchbtn" value="Search" />
+                </form>
+        </div>
+       <div id="logo">
+               <a href="/"><h1>BackPAN.org</h1><a>
+       </div>
+       <div id="menu">
+               <div class="nav">
+                       <ul>
+                               <li><a id="nav-releases" href="/releases">Releases</a></li>
+                               <li><a id="nav-dists" href="/dists">Distributions</a></li>
+                               <li><a id="nav-authors" href="/authors">Authors</a></li>
+                               <li><a id="nav-about" class="active" href="/about">About</a></li>
+                       </ul>
+               </div>
+       </div>
+       <div id="header">
+               <p>A Complete History of CPAN.</p>
+       </div>
+       <div id="content">
+               <div id="plain-text">
+                       <p>The <a href="http://cpan.org" target="_blank">Comprehensive Perl Archive Network (CPAN)</a> is a very useful
+                       collection of Perl code. However, authors of modules can delete older versions of modules to only
+                       let CPAN have the latest version of a module and BackPAN is where these deleted modules are backed up.</p>
+                       <p>BackPAN.org is a project created by <a href="http://search.cpan.org/~wreis/" target="_blank">Wallace Reis</a>
+                       using <a href="http://search.cpan.org/perldoc?Web::Simple" target="_blank">Web::Simple</a> and
+                       <a href="http://search.cpan.org/perldoc?HTML::Zoom" target="_blank">HTML::Zoom</a>. Kindly hosted by
+                       <a href="http://shadowcat.co.uk" target="_blank">Shadowcat Systems</a>. Website design developed by
+                       <a href="http://paulovitor.com" target="_blank">Paulo Vitor</a>.</p>
+                       <p>Please send any corrections, suggestions or comments to wreis at cpan.org.</p>
+                       <p>You can check out the source code from: git://git.shadowcat.co.uk/catagits/BackPAN-Web.git</p>
+                       <p>IRC channel: irc.perl.org #backpan-web</p>
+               </div>
+       </div>
+</div>
+<div id="footer">
+       <p>Created by <a href="http://search.cpan.org/~wreis/" target="_blank">Wallace Reis</a></p>
+       <p>Hosted by <a href="http://shadowcat.co.uk" target="_blank">Shadowcat Systems</a></p>
+</div>
+</body>
+</html>
diff --git a/root/static/html/dist.html b/root/static/html/dist.html
new file mode 100644 (file)
index 0000000..fbd2d03
--- /dev/null
@@ -0,0 +1,25 @@
+<div id="content">
+       <div id="dist">
+               <span>Name: [% name %]</span><br />
+               <span>Number of releases: [% num_releases %]</span><br />
+               <span>Maintainers:</span><br />
+               <ul class="maintainer-list">
+                       <li><a>Name</a></li>
+               </ul><br />
+               <span>First release: <a class="f_rel_link">[% f_release_label %]</a></span><br />
+               <span>Latest release: <a class="l_rel_link">[% l_release_label %]</a></span><br />
+       </div>
+       <div id="list">
+               <span>Releases:</span><br />
+               <ul class="main-list">
+                       <li><a>Name</a></li>
+               </ul>
+               <div id="paging">
+                       <div id="pages">
+                               <span><a>Page Number</a></span>
+                       </div>
+                       <span class="paging-desc" />
+                       <span class="entries" />
+               </div>
+       </div>
+</div>
diff --git a/root/static/html/error_404.html b/root/static/html/error_404.html
new file mode 100644 (file)
index 0000000..4dbbaa9
--- /dev/null
@@ -0,0 +1,45 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+        <head>
+                <title>BackPAN</title>
+                <meta http-equiv="content-type" content="text/html;charset=UTF-8" />
+                <link rel="stylesheet" href="/static/main.css" type="text/css" />
+        </head>
+<body>
+<div class="container">
+        <div id="search">
+                <form action="/search" method="GET">
+                        <input type="text" id="q" name="q" />
+                        <input type="submit" id="searchbtn" value="Search" />
+                </form>
+        </div>
+        <div id="logo">
+                <a href="/"><h1>BackPAN.org</h1><a>
+        </div>
+        <div id="menu">
+                <div class="nav">
+                        <ul>
+                                <li><a id="nav-releases" href="/releases">Releases</a></li>
+                                <li><a id="nav-dists" href="/dists">Distributions</a></li>
+                                <li><a id="nav-authors" href="/authors">Authors</a></li>
+                                <li><a id="nav-about" href="/about">About</a></li>
+                        </ul>
+                </div>
+        </div>
+        <div id="header">
+                <p>A Complete History of CPAN.</p>
+        </div>
+       <div id="content">
+               <div id="plain-text">
+                       <p>Sorry, not found!</p>
+                       <p>Whatever it was you were looking for, it's not here.</p>
+                       <p>Please send any corrections, suggestions or comments to wreis at cpan.org.</p>
+               </div>
+       </div>
+</div>
+<div id="footer">
+        <p>Created by <a href="http://search.cpan.org/~wreis/" target="_blank">Wallace Reis</a></p>
+        <p>Hosted by <a href="http://shadowcat.co.uk" target="_blank">Shadowcat Systems</a></p>
+</div>
+</body>
+</html>
diff --git a/root/static/html/error_500.html b/root/static/html/error_500.html
new file mode 100644 (file)
index 0000000..a5ddf83
--- /dev/null
@@ -0,0 +1,41 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+       <head>
+               <title>BackPAN</title>
+               <meta http-equiv="content-type" content="text/html;charset=UTF-8" />
+               <link rel="stylesheet" href="/static/main.css" type="text/css" />
+       </head>
+<body>
+<div class="container">
+       <div id="search">
+                <form action="/search" method="GET">
+                        <input type="text" id="q" name="q" />
+                       <input type="submit" id="searchbtn" value="Search" />
+                </form>
+        </div>
+       <div id="logo">
+               <a href="/"><h1>BackPAN.org</h1><a>
+       </div>
+       <div id="menu">
+               <div class="nav">
+                       <ul>
+                               <li><a id="nav-releases" href="/releases">Releases</a></li>
+                               <li><a id="nav-dists" href="/dists">Distributions</a></li>
+                               <li><a id="nav-authors" href="/authors">Authors</a></li>
+                               <li><a id="nav-about" href="/about">About</a></li>
+                       </ul>
+               </div>
+       </div>
+       <div id="header">
+               <p>A Complete History of CPAN.</p>
+       </div>
+       <div id="content">
+               <div id="plain-text"><p>Ooooops! Sorry, we couldn't process your request.</p></div>
+       </div>
+</div>
+<div id="footer">
+       <p>Created by <a href="http://search.cpan.org/~wreis/" target="_blank">Wallace Reis</a></p>
+       <p>Hosted by <a href="http://shadowcat.co.uk" target="_blank">Shadowcat Systems</a></p>
+</div>
+</body>
+</html>
diff --git a/root/static/html/index.html b/root/static/html/index.html
new file mode 100644 (file)
index 0000000..3872765
--- /dev/null
@@ -0,0 +1,8 @@
+<div id="content">
+       <span>New releases</p>
+       <div id="list">
+               <ul class="main-list">
+                       <li><a>Name</a></li>
+               </ul>
+       </div>
+</div>
diff --git a/root/static/html/layout.html b/root/static/html/layout.html
new file mode 100644 (file)
index 0000000..d375747
--- /dev/null
@@ -0,0 +1,40 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html>
+       <head>
+               <title>BackPAN</title>
+               <meta http-equiv="content-type" content="text/html;charset=UTF-8" />
+               <link rel="stylesheet" href="/static/main.css" type="text/css" />
+       </head>
+<body>
+<div class="container">
+       <div id="search">
+               <form action="/search" method="GET">
+                       <input type="text" id="q" name="q" />
+                       <input type="submit" id="searchbtn" value="Search" />
+               </form>
+       </div>
+       <div id="logo">
+               <a href="/"><h1>BackPAN.org</h1><a>
+       </div>
+       <div id="menu">
+               <div class="nav">
+                       <ul>
+                               <li><a id="nav-releases" href="/releases">Releases</a></li>
+                               <li><a id="nav-dists" href="/dists">Distributions</a></li>
+                               <li><a id="nav-authors" href="/authors">Authors</a></li>
+                               <li><a id="nav-about" href="/about">About</a></li>
+                       </ul>
+               </div>
+       </div>
+       <div id="header">
+               <p>A Complete History of CPAN.</p>
+       </div>
+       <div id="content">
+       </div>
+</div>
+<div id="footer">
+       <p>Created by <a href="http://search.cpan.org/~wreis/" target="_blank">Wallace Reis</a></p>
+       <p>Hosted by <a href="http://shadowcat.co.uk" target="_blank">Shadowcat Systems</a></p>
+</div>
+</body>
+</html>
diff --git a/root/static/html/listing.html b/root/static/html/listing.html
new file mode 100644 (file)
index 0000000..4f33502
--- /dev/null
@@ -0,0 +1,26 @@
+<div id="content">
+       <div id="page-size">
+               <span>Page Size:</span>
+               <div class="page-size-options">
+                       <span><a>Page Size</a></span>
+               </div>
+       </div>
+       <div id="ordering">
+               <span>Sort by:</span>
+               <div class="ordering-options">
+                       <span><a>Name</a></span>
+               </div>
+       </div>
+       <div id="list">
+               <ul class="main-list">
+                       <li><a>Name</a></li>
+               </ul>
+       </div>
+       <div id="paging">
+               <div id="pages">
+                       <span><a>Page Number</a></span>
+               </div>
+               <span class="paging-desc" />
+               <span class="entries" />
+       </div>
+</div>
diff --git a/root/static/static/arrow-down.gif b/root/static/static/arrow-down.gif
new file mode 100644 (file)
index 0000000..4d29cc7
Binary files /dev/null and b/root/static/static/arrow-down.gif differ
diff --git a/root/static/static/arrow-up.gif b/root/static/static/arrow-up.gif
new file mode 100644 (file)
index 0000000..5555b2d
Binary files /dev/null and b/root/static/static/arrow-up.gif differ
diff --git a/root/static/static/favicon.ico b/root/static/static/favicon.ico
new file mode 100644 (file)
index 0000000..b710021
Binary files /dev/null and b/root/static/static/favicon.ico differ
diff --git a/root/static/static/main.css b/root/static/static/main.css
new file mode 100644 (file)
index 0000000..a701748
--- /dev/null
@@ -0,0 +1,149 @@
+* {
+margin:0;
+padding:0;
+list-style: none;
+}
+
+body {
+text-align: center;
+font-family: Arial, sans-serif;
+color: #333;
+}
+
+a { color:#004065; }
+
+.container {
+margin: 20px auto 40px auto;
+text-align: left;
+width: 900px;
+}
+
+#ordering, #header, #paging, #list { float: left; }
+#menu, #page-size, #search { float: right; }
+
+#search input#q {
+float: right;
+border: 1px solid #004065;
+padding: 1px 25px 1px 5px;
+font-size: 14px;
+background: url(searchbtn.png) no-repeat right;
+}
+
+#header {
+font-size: 12px;
+color: #999;
+}
+
+.nav ul li {
+display: inline;
+}
+
+.nav ul li a {
+font-size: 14px;
+padding: 0 15px;
+text-decoration: none;
+color: #004065;
+height: 30px;
+line-height: 30px;
+display: block;
+float: left;
+}
+
+.nav ul li a:hover {
+background: #004065;
+color: #FFF;
+text-shadow: 1px 1px 1px #333;
+}
+
+#content, #list, #footer { width: 100%; overflow: auto; }
+
+#content {
+margin-top: 30px;
+border-top: 5px solid #004065;
+}
+
+#page-size, #ordering { width: 245px; }
+#page-size span, #ordering span {
+float: left; 
+font-size: 14px;
+padding-top: 6px;
+}
+
+.page-size-options span a, .ordering-options span a {
+text-decoration: none;
+margin-left: 2px;
+padding: 0 4px;
+margin-top: -6px;
+display: block;
+height: 28px;
+line-height: 28px;
+float: left;
+}
+.page-size-options span a:hover, .ordering-options span a:hover {
+background: url(arrow-down.gif) no-repeat center top;
+}
+
+a.active {
+background: url(arrow-up.gif) no-repeat center bottom;
+}
+
+.main-list {
+border-top: 1px solid #004065;
+border-bottom: 1px solid #004065;
+margin-top: 5px;
+}
+/* IExpression to the horror */
+.main-list li {
+display: table;
+width: 900px;
+}
+/* I Love IExplorer! */
+
+.main-list li a {
+display: block;
+font-size: 15px;
+color: #333;
+text-decoration: none;
+padding: 5px 30px;
+}
+.main-list li a:hover {
+color: #FFF;
+background: #004065;
+}
+.main-list li.even a { background: #eaeaea;  }
+.main-list li.even a:hover {
+color: #FFF;
+background: #004065;
+}
+
+#paging span {
+font-size: 12px;
+}
+#pages span a {
+margin-left: 2px;
+padding: 2px;
+color: #004065;
+font-size: 14px;
+text-decoration: none;
+}
+
+#plain-text {
+min-height: 518px;
+}
+#plain-text a { text-decoration: none }
+#plain-text a:hover { text-decoration: underline }
+#plain-text p {
+padding: 20px 20px 5px 20px;
+}
+
+#footer {
+min-height: 40px;
+background: #004065;
+color: #fff;
+}
+#footer a {
+text-decoration: none;
+text-shadow: 1px 1px 1px #333;
+color: #FFF;
+}
+#footer a:hover { text-decoration: underline }
diff --git a/root/static/static/searchbtn.png b/root/static/static/searchbtn.png
new file mode 100644 (file)
index 0000000..0fcf85c
Binary files /dev/null and b/root/static/static/searchbtn.png differ
diff --git a/t/leaktrace.t b/t/leaktrace.t
new file mode 100644 (file)
index 0000000..3d6ac7b
--- /dev/null
@@ -0,0 +1,57 @@
+use strict;
+use warnings;
+use lib 'lib';
+use BackPAN::Web;
+use Plack::Test;
+use HTTP::Request::Common;
+use Test::More;
+use Devel::Cycle;
+use Data::Dumper;
+use Devel::Events::Handler::ObjectTracker;
+use Devel::Events::Filter::RemoveFields;
+use Devel::Events::Generator::Objects;
+
+my $tracker = Devel::Events::Handler::ObjectTracker->new();
+
+my $gen = Devel::Events::Generator::Objects->new(
+    handler => Devel::Events::Filter::RemoveFields->new(
+    fields => [qw/generator/], # don't need to have a ref to $gen in each event
+    handler => $tracker,
+),
+);
+
+
+my $app = BackPAN::Web->as_psgi_app;
+
+my $run = sub {
+    $gen->enable(); # start generating events
+    test_psgi app => $app,
+        client => sub {
+            my $cb = shift;
+            foreach my $path (qw{/ /releases /dists /authors /about}) {
+                for (1..1000) {
+                    my $res = $cb->(GET $path);
+                    ok($res->code == 200) or diag($res->code);
+                }
+            }
+        };
+    $gen->disable();
+};
+$run->();
+
+# live_objects is a Tie::RefHash::Weak hash
+
+my @leaked_objects = keys %{ $tracker->live_objects };
+
+print "leaked ", scalar(@leaked_objects), " objects\n";
+
+foreach my $object ( @leaked_objects ) {
+    print "Leaked object: $object\n";
+
+    # the event that generated it
+    #print Dumper( $object, $tracker->live_objects->{$object} );
+
+    find_cycle( $object );
+}
+
+done_testing();