[Bps-public-commit] r18260 - in Net-Trac/trunk: .

jesse at bestpractical.com jesse at bestpractical.com
Thu Feb 5 19:59:31 EST 2009


Author: jesse
Date: Thu Feb  5 19:59:31 2009
New Revision: 18260

Modified:
   Net-Trac/trunk/TODO
   Net-Trac/trunk/lib/Net/Trac/Ticket.pm
   Net-Trac/trunk/lib/Net/Trac/TicketHistory.pm
   Net-Trac/trunk/lib/Net/Trac/TicketHistoryEntry.pm
   Net-Trac/trunk/lib/Net/Trac/TicketSearch.pm

Log:
* Better caching of ticket history. Properish handling of the keywords filed

Modified: Net-Trac/trunk/TODO
==============================================================================
--- Net-Trac/trunk/TODO	(original)
+++ Net-Trac/trunk/TODO	Thu Feb  5 19:59:31 2009
@@ -1,8 +1,13 @@
+KNOWN ISSUES
+
+    * reverse engineering a proper history of trac's "Description" field is hard. 
+    * Patches welcome
+
+
 Samples of failed parses from the Parrot Trac 
 
 
 
-My ticket id is 31 at /Users/jesse/git/bps/sd.git/lib/App/SD/Replica/trac/PullEncoder.pm line 165.
 could not  parse <strong>description</strong>
               modified (<a href="/parrot/ticket/35?action=diff&version=1">diff</a>)
 

Modified: Net-Trac/trunk/lib/Net/Trac/Ticket.pm
==============================================================================
--- Net-Trac/trunk/lib/Net/Trac/Ticket.pm	(original)
+++ Net-Trac/trunk/lib/Net/Trac/Ticket.pm	Thu Feb  5 19:59:31 2009
@@ -42,6 +42,21 @@
     is  => 'rw'
 );
 
+
+has history => (
+    isa     => 'Net::Trac::TicketHistory',
+    is => 'rw',
+    default => sub {
+        my $self = shift;
+        my $hist = Net::Trac::TicketHistory->new( { connection => $self->connection } );
+        $hist->load($self);
+        return $hist;
+    },
+    lazy => 1
+);
+
+
+
 has _attachments            => ( isa => 'ArrayRef', is => 'rw' );
 
 class_has _loaded_new_metadata    => ( isa => 'Bool',     is => 'rw' );
@@ -106,10 +121,23 @@
 
     return unless @{ $search->results };
 
-    my $tid = $self->load_from_hashref( $search->results->[0] );
+    my $ticket_data = $search->results->[0];
+    $self->_tweak_ticket_data_for_load($ticket_data);
+
+    my $tid = $self->load_from_hashref( $ticket_data);
     return $tid;
 }
 
+# We force an order on the keywords prop since trac doesn't let us
+# really know what the order used to be
+sub _tweak_ticket_data_for_load {
+    my $self = shift;
+    my $ticket = shift;
+    $ticket->{keywords} = join(' ', sort ( split ( /\s+/,$ticket->{keywords})));
+
+}
+
+
 =head2 load_from_hashref HASHREF [SKIP]
 
 You should never need to use this method yourself.  Loads a ticket from a hashref
@@ -302,9 +330,9 @@
         form_number => $form_num,
         fields => { %form, submit => 1 }
     );
-
     my $reply = $self->connection->mech->response;
     if ( $reply->is_success ) {
+        delete $self->{history}; # ICK. I really want a Moose "reset to default"
         return $self->load($self->id);
     }
     else {
@@ -330,12 +358,6 @@
 
 =cut
 
-sub history {
-    my $self = shift;
-    my $hist = Net::Trac::TicketHistory->new({ connection => $self->connection });
-    $hist->load( $self->id );
-    return $hist;
-}
 
 =head2 comments
 
@@ -393,6 +415,7 @@
 
     my $reply = $self->connection->mech->response;
     $self->connection->_warn_on_error( $reply->base->as_string ) and return;
+    delete $self->{history}; # ICK. I really want a Moose "reset to default"
 
     return $self->attachments->[-1];
 }

Modified: Net-Trac/trunk/lib/Net/Trac/TicketHistory.pm
==============================================================================
--- Net-Trac/trunk/lib/Net/Trac/TicketHistory.pm	(original)
+++ Net-Trac/trunk/lib/Net/Trac/TicketHistory.pm	Thu Feb  5 19:59:31 2009
@@ -45,7 +45,7 @@
     is  => 'ro'
 );
 
-has ticket  => ( isa => 'Int',      is => 'rw' );
+has ticket  => ( isa => 'Net::Trac::Ticket',      is => 'rw', weak_ref => 1);
 has entries => ( isa => 'ArrayRef', is => 'rw' );
 
 =head1 METHODS
@@ -58,19 +58,24 @@
 
 sub load {
     my $self = shift;
-    my ($id) = validate_pos( @_, { type => SCALAR } );
+    my ($ticket_obj) = validate_pos( @_, 1);
 
-    $self->ticket( $id );
+    $self->ticket( $ticket_obj );
 
-    my $feed = $self->connection->_fetch_feed( "/ticket/$id?format=rss" )
+    # Clone the ticket state so we can morph it backwards to reverse engineer
+    # keywords
+    my $temp_state = { %{ $ticket_obj->state()}};
+
+    my $feed = $self->connection->_fetch_feed( "/ticket/@{[$ticket_obj->id]}?format=rss" )
         or return;
 
-    my @entries = $feed->entries;
     my @history;
-    foreach my $entry (@entries) {
+    # Work on the newest entry first so we can back-calculate from the current state
+    foreach my $entry (reverse $feed->entries ) {
         my $e = Net::Trac::TicketHistoryEntry->new({ connection => $self->connection });
-        $e->parse_feed_entry($entry);
-        push @history, $e;
+        $e->parse_feed_entry($entry, $temp_state);
+        # newest entry should be at the front of the list in the history later
+        unshift @history, $e;
     }
 
     $self->entries( \@history );

Modified: Net-Trac/trunk/lib/Net/Trac/TicketHistoryEntry.pm
==============================================================================
--- Net-Trac/trunk/lib/Net/Trac/TicketHistoryEntry.pm	(original)
+++ Net-Trac/trunk/lib/Net/Trac/TicketHistoryEntry.pm	Thu Feb  5 19:59:31 2009
@@ -62,6 +62,12 @@
     my $self = shift;
     my $e    = shift;    # XML::Feed::Entry
 
+    # We use a reference to a copy of ticket state as it was after this feed 
+    # entry to interpret what "x added, y removed" meant for absolute values
+    # of keywords
+
+    my $ticket_state = shift; 
+    
     $self->author( $e->author );
     $self->date( $e->issued );
     $self->category( $e->category );
@@ -69,16 +75,17 @@
     my $desc = $e->content->body;
     if ( $desc =~ s|^\s*?<ul>(.*)</ul>||is) {
         my $props = $1;
-        $self->prop_changes( $self->_parse_props($props) );
+        $self->prop_changes( $self->_parse_props($props, $ticket_state) );
     }
 
     $self->content($desc);
-    return 1;
+
 }
 
 sub _parse_props {
     my $self       = shift;
     my $raw        = shift || '';
+    my $ticket_state = shift;
     # throw out the wrapping <li>
    $raw =~ s|^\s*?<li>(.*)</li>\s*?$|$1|is;
     my @prop_lines = split( m#</li>\s*<li>#s, $raw );
@@ -86,7 +93,33 @@
 
     foreach my $line (@prop_lines) {
         my ($prop, $old, $new);
-        if ( $line =~ m{<strong>(.*?)</strong>\s+changed\s+from\s+<em>(.*)</em>\s+to\s+<em>(.*)</em>}is ) {
+        if ($line =~ m{<strong>keywords</strong>(.*)$}is ) {
+            my $value_changes = $1;
+            $prop = 'keywords';
+            my (@added, @removed);
+            if ($value_changes =~ m{^\s*<em>(.*?)</em> added;?}is) {
+                    my $added = $1;
+                    @added = split(m{</em>\s*<em>}is, $added);
+                }  
+
+            if ($value_changes =~ m{(?:^|;)\s*<em>(.*)</em> removed}is) {
+                    my $removed = $1;
+                    @removed = split(m{</em>\s*<em>}is, $removed);
+
+            }
+          
+           my @before = (); 
+           my @after  =  grep defined && length, split (/\s+/,$ticket_state->{keywords});
+           for my $value  (@after) {
+                next if grep {$_ eq  $value} @added;
+                push @before, $value;
+            }
+
+            $old = join(' ', sort (@before, @removed));
+            $new = join(' ', sort (@after));
+            $ticket_state->{keywords} = $old;
+        }
+        elsif ( $line =~ m{<strong>(.*?)</strong>\s+changed\s+from\s+<em>(.*)</em>\s+to\s+<em>(.*)</em>}is ) {
             $prop = $1;
             $old  = $2;
             $new  = $3;
@@ -101,7 +134,8 @@
         } elsif ( $line =~ m{<strong>(.*?)</strong>\s+deleted}is ) {
             $prop = $1;
             $new  = '';
-        } else {
+        } 
+        else {
             warn "could not  parse ". $line;
         }
 

Modified: Net-Trac/trunk/lib/Net/Trac/TicketSearch.pm
==============================================================================
--- Net-Trac/trunk/lib/Net/Trac/TicketSearch.pm	(original)
+++ Net-Trac/trunk/lib/Net/Trac/TicketSearch.pm	Thu Feb  5 19:59:31 2009
@@ -97,9 +97,10 @@
 
     unless ( $no_objects ) {
         my @tickets = ();
-        for ( @{$data || []} ) {
+        for my $ticket_data ( @{$data || []} ) {
             my $ticket = Net::Trac::Ticket->new( connection => $self->connection );
-            my $id = $ticket->load_from_hashref( $_ );
+            $ticket->_tweak_ticket_data_for_load($ticket_data);
+            my $id = $ticket->load_from_hashref( $ticket_data );
             push @tickets, $ticket if $id;
         }
         return $self->results( \@tickets );



More information about the Bps-public-commit mailing list