source: server/trunk/web/lib/Sophie/Scan/RpmsPath.pm @ 333

Last change on this file since 333 was 333, checked in by nanardon, 13 years ago
  • massive rework of the base updater
File size: 5.8 KB
Line 
1package Sophie::Scan::RpmsPath;
2
3use strict;
4use warnings;
5use Sophie::Base::Header;
6use RPM4;
7use File::Temp;
8use File::Copy;
9use Archive::Cpio;
10use Encode::Guess;
11use Encode;
12use Time::HiRes;
13use DBD::Pg qw(:pg_types);
14
15sub new {
16    my ($class, $pathkey, $db) = @_;
17
18    bless({ key => $pathkey, db => $db }, $class);
19}
20
21sub key { $_[0]->{key} } 
22sub db { 
23    $_[0]->{db}
24} 
25
26sub path {
27    my ($self) = @_;
28   
29    $self->db->base->resultset('Paths')->find(
30        { d_path_key => $self->key }
31    )->path;
32}
33
34sub ls_rpms {
35    my ($self) = @_;
36
37    my %list;
38    foreach ($self->db->base->resultset('RpmFile')->search(
39        { d_path => $self->key }
40    )->get_column('filename')->all) {
41        $list{$_} = 1;
42    }
43    return \%list;
44}
45
46sub local_ls_rpms {
47    my ($self) = @_;
48
49    if (opendir(my $dh, $self->path)) {
50        my %list;
51        while (my $entry = readdir($dh)) {
52            $entry eq '.' and next;
53            $entry eq '..' and next;
54            $list{$entry} = 1;
55        }
56        closedir($dh);
57        return \%list;
58    } else {
59        return;
60    }
61}
62
63sub find_delta {
64    my ($self) = @_;
65
66    warn "$$ " . $self->path;
67
68    my @delta;
69    my $localrpms = $self->local_ls_rpms;
70    my $baserpms  = $self->ls_rpms;
71
72    if ($localrpms) {
73        push(@delta, { delta => 'DE' });
74    } else {
75        push(@delta, { delta => 'DM' });
76    }
77
78
79    my %list;
80    foreach (keys %{ $localrpms || {} }, keys %{ $baserpms }) {
81        $list{$_} = 1;
82    }
83
84    foreach my $rpm (sort { $b cmp $a } keys %list) {
85        if ($localrpms->{$rpm} && $baserpms->{$rpm}) {
86            # nothing to do
87        } elsif ($localrpms->{$rpm}) {
88            push(@delta, { rpm => $rpm, delta => 'A' });
89        } elsif ($baserpms->{$rpm}) {
90            push(@delta, { rpm => $rpm, delta => 'R' });
91        }
92    }
93    @delta;
94}
95
96sub update_content {
97    my ($self, @delta) = @_;
98    foreach (@delta) {
99        if (!$_->{delta}) {
100        }
101        elsif ($_->{delta} eq 'A') {
102            $self->add_rpm($_->{rpm});
103            #sleep(1);
104            #Time::HiRes::usleep(750);
105        }
106        elsif ($_->{delta} eq 'R') {
107            $self->remove_rpm($_->{rpm});
108        } elsif ($_->{delta} eq 'DM') {
109            $self->set_exists(0);
110        } elsif ($_->{delta} eq 'DE') {
111            $self->set_exists(1);
112        }
113    }
114}
115
116sub set_exists {
117    my ($self, $exists) = @_;
118    $self->db->base->resultset('Paths')->find(
119        { d_path_key => $self->key }
120    )->update({ 'exists' => ($exists ? 1 : 0) });
121    $self->db->commit;
122}
123
124sub set_updated {
125    my ($self) = @_;
126    warn "$$ UPD";
127    $self->db->base->resultset('Paths')->find(
128        { d_path_key => $self->key }
129    )->update({ 'updated' => \'now()' });
130    $self->db->commit;
131}
132
133sub remove_rpm {
134    my ($self, $rpm) = @_;
135    warn "$$ deleting $rpm";
136    $self->db->base->storage->txn_do(
137        sub {
138
139            $self->db->base->resultset('RpmFile')->search(
140                { d_path => $self->key, filename => $rpm }
141            )->delete;
142        }
143    );
144}
145
146sub add_rpm {
147    my ($self, $rpm) = @_;
148
149    warn "$$ adding $rpm";
150    eval {
151    my ($pkgid, $new) = $self->db->base->storage->txn_do(
152        sub {
153            my ($pkgid, $new) = $self->_add_header($rpm);
154            if (defined($pkgid)) {
155                $pkgid or return;
156                $self->db->base->resultset('RpmFile')->create(
157                    {
158                        d_path => $self->key,
159                        filename => $rpm,
160                        pkgid => $pkgid,
161                    }
162                ); 
163                return $pkgid, $new;
164            }
165        },
166    );
167    foreach my $plugins (qw'sources') {
168        my $mod = ucfirst(lc($plugins));
169        eval "require Sophie::Scan::RpmParser::$mod;";
170        warn $@ if($@);
171        eval {
172            my $parser = "Sophie::Scan::RpmParser::$mod"->new($self->db);
173            $parser->run($self->path . '/' . $rpm, $pkgid, $new);
174        }
175    }
176    }
177}
178
179sub _add_header {
180    my ($self, $rpm) = @_;
181
182    my $header;
183    eval {
184        $header = RPM4::Header->new($self->path . '/' . $rpm, $self->{db}) 
185    };
186    $header or do {
187        warn "$$ Cannot read " . $self->path . '/' . $rpm;
188        return "";
189    };
190
191    {
192        my $find = $self->db->base->resultset('Rpms')->search(
193            { pkgid => $header->queryformat('%{PKGID}') }
194        )->get_column('pkgid')->all;
195        if ($find) {
196            warn "$$ Find";
197            return($header->queryformat('%{PKGID}'), 0);
198        }
199    }
200    my $tmp = File::Temp->new( UNLINK => 1, SUFFIX => '.hdr' );
201    unlink($tmp->filename);
202    $header->write($tmp, 0);
203    seek($tmp, 0, 0);
204    my $string = '';
205    while (read($tmp, my $str, 1024)) { $string .= $str }
206    $tmp = undef;
207    my $description = $header->queryformat('%{DESCRIPTION}');
208    {
209        my $enc = guess_encoding($description, qw/latin1/);
210        $description = $enc->decode($description) if ($enc && ref $enc);
211    }
212    my $summary = $header->queryformat('%{SUMMARY}');
213    {
214        my $enc = guess_encoding($summary, qw/latin1/);
215        $summary = $enc->decode($summary) if ($enc && ref $enc);
216    }
217
218    $self->db->base->resultset('Rpms')->create({
219        pkgid  => $header->queryformat('%{PKGID}'),
220        name   => $header->queryformat('%{name}'),
221        header => \sprintf(qq{rpmheader_in(decode('%s', 'hex')::bytea)}, unpack('H*', $string)),
222        evr    => $header->queryformat('%|EPOCH?{%{EPOCH}:}:{}|%{VERSION}-%{RELEASE}'),
223        arch   => $header->queryformat('%{ARCH}'),
224        issrc  => $header->hastag('SOURCERPM') ? 'f' : 't',
225        description => $description,
226        summary => $summary,
227    });
228    my $index_tag = $self->db->base->storage->dbh->prepare_cached(
229        q{
230        select index_rpms(?);
231        }
232    );
233    $index_tag->execute($header->queryformat('%{PKGID}')) or return;
234    $index_tag->finish;
235
236    return($header->queryformat('%{PKGID}'), 1);
237}
238
2391;
Note: See TracBrowser for help on using the repository browser.