source: server/trunk/web/lib/Sophie/Base/RpmsPath.pm @ 24

Last change on this file since 24 was 18, checked in by nanardon, 14 years ago
  • improve database error management
  • add options to command line
File size: 5.1 KB
Line 
1package Sophie::Base::RpmsPath;
2
3use strict;
4use warnings;
5use base qw(Sophie::Base);
6use Sophie::Base::Header;
7use RPM4;
8use File::Temp;
9use File::Copy;
10use Archive::Cpio;
11use Encode::Guess;
12use Encode;
13
14sub new {
15    my ($class, $pathkey) = @_;
16
17    bless(\$pathkey, $class);
18}
19
20sub path {
21    my ($self) = @_;
22   
23    my $sth = $self->db->prepare_cached(
24        q{select path from d_path where d_path_key = ?}
25    );
26    $sth->execute($$self);
27    my $res = $sth->fetchrow_hashref;
28    $sth->finish;
29    return $res->{path}
30}
31
32sub ls_rpms {
33    my ($self) = @_;
34
35    my $sth = $self->db->prepare_cached(
36        q{select * from rpmfiles where d_path = ?}
37    );
38    $sth->execute($$self);
39    $sth->fetchall_hashref([ 'filename' ]);
40}
41
42sub local_ls_rpms {
43    my ($self) = @_;
44
45    if (opendir(my $dh, $self->path)) {
46        my %list;
47        while (my $entry = readdir($dh)) {
48            $entry eq '.' and next;
49            $entry eq '..' and next;
50            $list{$entry} = 1;
51        }
52        closedir($dh);
53        return \%list;
54    } else {
55        return;
56    }
57}
58
59sub find_delta {
60    my ($self) = @_;
61
62    warn $self->path;
63
64    my $localrpms = $self->local_ls_rpms || {};
65    my $baserpms  = $self->ls_rpms;
66
67    my %list;
68    foreach (keys %{ $localrpms }, keys %{ $baserpms }) {
69        $list{$_} = 1;
70    }
71    my @delta;
72
73    foreach my $rpm (sort { $b cmp $a } keys %list) {
74        if ($localrpms->{$rpm} && $baserpms->{$rpm}) {
75            # nothing to do
76        } elsif ($localrpms->{$rpm}) {
77            push(@delta, { rpm => $rpm, delta => 'A' });
78        } elsif ($baserpms->{$rpm}) {
79            push(@delta, { rpm => $rpm, delta => 'R' });
80        }
81    }
82    @delta;
83}
84sub update_content {
85    my ($self, @delta) = @_;
86    foreach (@delta) {
87        if (!$_->{delta}) {
88        }
89        elsif ($_->{delta} eq 'A') {
90            $self->add_rpm($_->{rpm});
91        }
92        elsif ($_->{delta} eq 'R') {
93            $self->remove_rpm($_->{rpm});
94        }
95    }
96}
97
98sub set_updated {
99    my ($self) = @_;
100    warn "UPD";
101    $self->db->prepare_cached(q{
102        update d_path set updated = now() where d_path_key = ?
103        })->execute($$self);
104    $self->db->commit;
105}
106
107
108sub remove_rpm {
109    my ($self, $rpm) = @_;
110    my $remove = $self->db->prepare_cached(
111        q{
112        DELETE FROM rpmfiles where d_path = ? and filename = ?
113        }
114    );
115    for (1 .. 3) {
116        if ($remove->execute($$self, $rpm)) { 
117            warn "deleting $rpm";
118            $self->db->commit;
119            return 1;
120        }
121        $self->db->rollback;
122    }
123}
124
125sub add_rpm {
126    my ($self, $rpm) = @_;
127
128    for (1 .. 3) {
129        if (defined(my $pkgid = $self->_add_header($rpm))) {
130            $pkgid or return;
131            my $register = $self->db->prepare_cached(
132                q{
133                INSERT INTO rpmfiles (d_path, filename, pkgid)
134                values (?,?,?)
135                }
136            );
137            if ($register->execute($$self, $rpm, $pkgid)) {
138                warn "adding $rpm";
139                $self->db->commit;
140                return;
141            }
142
143        }
144        $self->db->rollback;
145    }
146}
147
148sub _add_header {
149    my ($self, $rpm) = @_;
150
151    my $header;
152    eval {
153        $header = RPM4::Header->new($self->path . '/' . $rpm) 
154    };
155    $header or do {
156        warn "Cannot read " . $self->path . '/' . $rpm;
157        return "";
158    };
159
160    {
161        my $find = $self->db->prepare_cached(q{
162            select pkgid from rpms where pkgid = ?
163        });
164        $find->execute($header->queryformat('%{PKGID}'));
165        my $rows = $find->rows;
166        $find->finish;
167        if ($rows) {
168            warn "Find";
169            return $header->queryformat('%{PKGID}');
170        }
171    }
172    my $tmp = File::Temp->new( UNLINK => 1, SUFFIX => '.hdr' );
173    unlink($tmp->filename);
174    $header->write($tmp, 0);
175    seek($tmp, 0, 0);
176    my $string = '';
177    while (read($tmp, my $str, 1024)) { $string .= $str }
178    $tmp = undef;
179    my $add_header = $self->db->prepare_cached(
180        q{
181        INSERT into rpms (pkgid, header, evr, issrc, description, summary)
182        values (?,rpmheader_in(decode(?, 'hex')::bytea),?,?,?,?)
183        }
184    );
185    my $description = $header->queryformat('%{DESCRIPTION}');
186    {
187        my $enc = guess_encoding($description, qw/latin1/);
188        $description = $enc->decode($description) if ($enc && ref $enc);
189    }
190    my $summary = $header->queryformat('%{SUMMARY}');
191    {
192        my $enc = guess_encoding($summary, qw/latin1/);
193        $summary = $enc->decode($summary) if ($enc && ref $enc);
194    }
195
196    $add_header->execute(
197        $header->queryformat('%{PKGID}'),
198        unpack('H*', $string),
199        $header->queryformat('%|EPOCH?{%{EPOCH}:}:{}|%{VERSION}-%{RELEASE}'),
200        $header->hastag('SOURCERPM') ? 'f' : 't',
201        $description,
202        $summary,
203    );
204    my $index_tag = $self->db->prepare_cached(
205        q{
206        select index_rpms(?);
207        }
208    );
209    $index_tag->execute($header->queryformat('%{PKGID}')) or return;
210    $index_tag->finish;
211    Sophie::Base::Header->new($header->queryformat('%{PKGID}'))
212        ->addfiles_content({ path => $self->path, filename => $rpm}) or return;
213
214    $header->queryformat('%{PKGID}');
215}
216
2171;
Note: See TracBrowser for help on using the repository browser.