Author: sparky
Date: Fri Sep 11 18:51:20 2009
New Revision: 10562

Modified:
   toys/rsget.pl/RSGet/FileList.pm
Log:
- mostly rewritten to allow new syntax and use ListManager


Modified: toys/rsget.pl/RSGet/FileList.pm
==============================================================================
--- toys/rsget.pl/RSGet/FileList.pm     (original)
+++ toys/rsget.pl/RSGet/FileList.pm     Fri Sep 11 18:51:20 2009
@@ -4,222 +4,235 @@
 use warnings;
 use URI::Escape;
 use RSGet::Tools;
-our $file = 'get.list';
-my $file_swp = '.get.list.swp';
-our $reread = 1;
-our %uri_options; # options to be saved
+
+my $file;
+my $file_swp;
+
+my $update = 1;
+# $uri => { cmd => "CMD", globals => {...}, options => {...} }
+
+# commands:
+# GET - download
+# DONE - stop, fully downloaded
+# STOP - stop, partially downloaded
+# ADD - add as clone if possible, new link otherwise
+
+our @actual;
+our @added;
 
 sub set_file
 {
-       my $file = shift;
+       $file = shift;
        die "Can't read '$file'\n" unless -r $file;
        p "Using '$file' file list\n";
-       my $make_swp = $settings{make_swp} || '.${file}.swp';
+       my $make_swp = $settings{list_lock};
        $file_swp = eval "\"$make_swp\"";
        p "Using '$file_swp' as file lock\n";
 }
-sub need_update
+
+sub update
 {
-       $reread = 1;
+       $update = 1;
 }
 
-sub words
+our %save; # options to be saved
+sub save
 {
-       my $pre = shift;
-       my $before = shift;
-       return () unless @_;
-       my $line = "";
-       my $lline = $pre . $before . shift;
-       foreach ( @_ ) {
-               if ( length $lline . $_ > 76 ) {
-                       $line .= "$lline \\\n";
-                       $lline = $pre;
+       my $uri = shift;
+       my %data = @_;
+       my $save_uri = $save{ $uri } ||= {};
+       foreach my $key ( keys %data ) {
+               my $val = $data{ $key };
+               if ( $key =~ /^(options|globals|clones)/ ) {
+                       my $hash = $save_uri->{ $key } ||= {};
+                       hadd $hash, %{ $val };
+               } else {
+                       $save_uri->{ $key } = $val;
                }
-               $lline .= " " . $_;
        }
-
-       $lline = $line.$lline if $line;
-       return $lline."\n";
 }
 
 
+
 sub h2a($)
 {
        my $h = shift;
-       return map { $_ . "=" . uri_escape( $h->{$_} ) } sort keys %$h;
-}
-
-sub getter
-{
-       my $uri = shift;
-       my @g = grep { $uri =~ m/^http:\/\/(:?www\.)?$_->{uri}/ } values 
%getters;
-       return undef unless @g;
-       return $g[0];
+       return map { defined $h->{$_} ? ($_ . "=" . uri_escape( $h->{$_} )) : 
() } sort keys %$h;
 }
 
-my @added_text;
-sub add_text
-{
-       my $type = shift;
-       my $text = shift;
-
-       return unless $text;
-       if ( $type eq "links" ) {
-               my @words = split /\s/s, $text;
-
-               foreach ( @words ) {
-                       next unless m{^(http://)?(.*?)$};
-                       my $proto = $1 || "http://";;
-                       my $uri = $proto . $2;
-                       push @added_text, $uri . "\n" if getter($uri);
-               }
-
-               $reread = 2;
-       } elsif ( $type eq "text" ) {
-               foreach ( split /\n/, $text ) {
-                       s/\s+$//;
-                       push @added_text, $_."\n";
-               }
-       } elsif ( $type eq "comment" ) {
-               foreach ( split /\n/, $text ) {
-                       s/\s+$//;
-                       push @added_text, "# $_\n";
-               }
-       }
-       return \...@added_text;
-}
-
-my $listmtime = 0;
+our $listmtime = 0;
 sub readlist
 {
        return unless -r $file;
        my $mtime = (stat _)[9];
-       return unless $reread or $mtime != $listmtime;
+       return unless $update or $mtime != $listmtime;
        #p "readlist()";
 
-       my @getlist;
-       my @newlist;
        open my $list, '<', $file;
-       while ( my $line = <$list> ) {
+       my @list = <$list>;
+       close $list;
+
+       push @list, @added;
+
+       my @new;
+       my @end;
+
+       my @used_save;
+       my %all_uri;
+       @actual = ();
+       while ( my $line = shift @list ) {
                chomp $line;
+               if ( $line =~ /^__END__\s*$/ ) { # end of the list
+                       push @end, $line . "\n";
+                       push @actual, $line;
+                       push @end, @list;
+                       push @actual, @list;
+                       last;
+               }
                if ( $line =~ /^\s*(#.*)?$/ ) { # comments and empty lines
-                       push @newlist, $line . "\n";
+                       push @new, $line . "\n";
+                       push @actual, $line;
                        next;
-               } elsif ( $line =~ /^__END__\s*$/ ) { # end of list
-                       push @newlist, $line . "\n";
-                       push @newlist, <$list>;
-                       last;
                }
-               while ( $line =~ s/\\$/ / ) { # stitch broken lines together
-                       $line .= <$list>;
+               my $mline = $line;
+               while ( $mline =~ s/\s*\\$/ / or (@list and $list[0] =~ 
s/^\s*\+\s*/ /) ) { # stitch broken lines together
+                       $line = shift @list;
                        chomp $line;
+                       $mline .= $line;
                }
 
-               $line =~ s/^\s+//;
-               $line =~ s/\s+$//;
+               $mline =~ s/^\s+//s;
+               $mline =~ s/\s+$//s;
+               my @words = split /\s+/s, $mline;
 
 
-               my %uris;
-               my %options;
-               my @invalid;
-               my @invalid_uri;
+               my $cmd;
+               if ( $words[0] =~ /^(GET|DONE|STOP|ADD):$/ ) {
+                       $cmd = $1;
+                       shift @words;
+               }
+               my $globals = {};
+               my $options = $globals;
 
-               # split line into words
-               foreach ( split /\s+/, $line ) {
-                       if ( /^([a-z_]+)=(.*)$/ ) {
-                               $options{$1} = uri_unescape( $2 );
+               my %decoded;
+               my @invalid;
+               foreach ( @words ) {
+                       if ( /^([a-z0-9_]+)=(.*)$/ ) {
+                               $options->{$1} = uri_unescape( $2 );
+                               next;
                        } elsif ( m{^(http://)?(.*?)$} ) {
                                my $proto = $1 || "http://";;
                                my $uri = $proto . $2;
-                               if ( my $getter = getter($uri) ) {
-                                       $uris{ $uri } = $getter;
-                               } elsif ( $uri =~ m{.+\.[a-z]{2,4}/.+} ) {
-                                       push @invalid_uri, $uri;
-                               } else {
-                                       push @invalid, $_;
+                               if ( my $getter = RSGet::Dispatch::getter($uri) 
) {
+                                       $options = {};
+                                       $decoded{ $uri } = [ $getter, $options 
];
+                                       next;
                                }
-                       } else {
-                               push @invalid, $_;
                        }
+
+                       push @invalid, $_;
                }
 
-               if ( not scalar keys %uris ) {
-                       push @newlist, words(
-                               "# ", "invalid line: ",
-                               @invalid, @invalid_uri, h2a( \%options ),
-                       );
-                       next;
-               } elsif ( @invalid ) {
-                       push @newlist, words(
-                               "# ", "invalid words: ",
-                               @invalid, @invalid_uri
-                       );
-               } elsif ( @invalid_uri ) {
-                       push @newlist, words(
-                               "# ", "invalid uri: ",
-                               @invalid_uri,
-                       );
-               }
-
-               foreach my $uri ( sort keys %uris ) {
-                       my $error = RSGet::Dispatch::is_error( $uri );
-                       next unless $error;
-                       delete $uris{ $uri };
-                       push @newlist, "# $error:\n# $uri\n";
-               }
-
-               unless ( keys %uris ) {
-                       push @newlist, words(
-                               "#", "", h2a( \%options )
-                       ) if keys %options;
+               unless ( keys %decoded ) {
+                       my $line = '# invalid line: ' . (join " ", ($cmd ? 
"$cmd:" : ()), @words);
+                       push @new, $line . "\n";
+                       push @actual, $line;
                        next;
                }
+               if ( @invalid ) {
+                       my $line = '# invalid: ' . (join " ", @invalid);
+                       push @new, $line . "\n";
+                       push @actual, $line;
+               }
 
-               foreach my $uri ( sort keys %uris ) {
-                       hadd \%options, %{$uri_options{ $uri }} if 
$uri_options{ $uri };
+               $cmd ||= "GET";
+
+               foreach my $uri ( keys %decoded ) {
+                       next unless exists $save{ $uri };
+                       push @used_save, $uri;
+                       my $save = $save{ $uri };
+                       if ( not ref $save or ref $save ne "HASH" ) {
+                               warn "Invalid \$save{ $uri } => $save\n";
+                               next;
+                       }
+                       
+                       my $options = $decoded{ $uri }->[1];
+
+                       $cmd = $save->{cmd} if $save->{cmd};
+                       hadd $globals, %{$save->{globals}} if $save->{globals};
+                       hadd $options, %{$save->{options}} if $save->{options};
+
+                       if ( my $links = $save->{links} ) {
+                               push @new, map { "ADD: $_\n" } @$links;
+                               # don't bother with @actual, list will be 
reread shortly
+                               $update = 2;
+                       }
+
+                       if ( my $clones = $save->{clones} ) {
+                               hadd \%decoded, %{ $clones };
+                               $update = 2;
+                       }
+                       delete $decoded{ $uri } if $save->{delete};
                }
 
-               my $status;
-               foreach my $uri ( sort keys %uris ) {
-                       next unless $status = RSGet::Dispatch::done( $uri, 
$uris{ $uri } );
-                       $uri = "*" . $uri;
-                       if ( ref $status and ref $status eq "ARRAY" ) {
-                               push @newlist, words(
-                                       "#", " Link: ",
-                                       (sort keys %uris), h2a( \%options )
-                               );
-                               push @newlist, words( '', '', @$status );
+               foreach my $uri ( keys %decoded ) {
+                       if ( $all_uri{ $uri } ) {
+                               warn "URI: $uri repeated, removing second 
one\n";
+                               #hadd $options, %{ $all_uri{ $uri }->[1] };
+                               #$all_uri{ $uri }->[1] = $options;
+                               delete $decoded{ $uri };
                        } else {
-                               push @newlist, words(
-                                       "# ", "$status:\n# ",
-                                       (sort keys %uris), h2a( \%options )
-                               );
+                               $all_uri{ $uri } = $decoded{ $uri };
                        }
-                       $reread = 2;
-                       last;
                }
-               next if $status;
 
-               push @newlist, words( '', '', (sort keys %uris), h2a( \%options 
) );
+               next unless keys %decoded;
 
-               push @getlist, [ \%uris, \%options ];
+               my $all_error = 1;
+               foreach my $uri ( keys %decoded ) {
+                       my $options = $decoded{ $uri }->[1];
+                       unless ( $options->{error} ) {
+                               $all_error = 0;
+                               last;
+                       }
+               }
+               $cmd = "STOP" if $all_error and $cmd ne "DONE";
+
+               push @actual, {
+                       cmd => $cmd,
+                       globals => $globals,
+                       uris => \%decoded
+               };
+
+               {
+                       my @out = ( "$cmd:", h2a( $globals ) );
+                       push @new, (join " ", @out) . "\n";
+               }
+               foreach my $uri ( sort keys %decoded ) {
+                       my @out = ( $uri, h2a( $decoded{ $uri }->[1] ) );
+                       push @new, (join " ", '+', @out) . "\n";
+               }
        }
-       close $list;
+       
+       # we are forced to regenerate the list if there was something added
+       unlink $file_swp if @added or $update == 2;
 
        unless ( -e $file_swp ) {
                open my $newlist, '>', $file . ".tmp";
-               print $newlist @newlist;
-               print $newlist @added_text;
-               @added_text = ();
+               print $newlist @new;
                close $newlist || die "\nCannot update $file file: $!\n";
                unlink $file;
                rename $file . ".tmp", $file;
+               @added = ();
+               foreach my $uri ( @used_save ) {
+                       delete $save{ $uri };
+               }
        }
 
-       $reread = $reread == 2 ? 1 : 0;
+       $update = $update == 2 ? 1 : 0;
        $listmtime = (stat $file)[9];
 
-       return \...@getlist;
+       return \...@actual;
 }
 
 1;
_______________________________________________
pld-cvs-commit mailing list
[email protected]
http://lists.pld-linux.org/mailman/listinfo/pld-cvs-commit

Reply via email to