X-Git-Url: https://git.donarmstrong.com/?a=blobdiff_plain;f=bin%2Fdebbugs-loadsql;h=f452431d3bc8b34dc01f53dcd91dc1e8cc2029de;hb=5a7f0c77d7d30a0b9052f42796c8fead5202670a;hp=c91826677ffb5d666019ab85c3ef37ff0c7f8e98;hpb=d7bda9dac45d437e0f5297e0f09be5f70269c9c3;p=debbugs.git diff --git a/bin/debbugs-loadsql b/bin/debbugs-loadsql index c918266..f452431 100755 --- a/bin/debbugs-loadsql +++ b/bin/debbugs-loadsql @@ -17,10 +17,13 @@ debbugs-loadsql -- load debbugs sql database =head1 SYNOPSIS -debbugs-loadsql [options] +debbugs-loadsql [options] [subcommand] + Subcommands: + bugs help versions configuration + suites logs packages debinfo Options: - --quick, -q only load changed bugs + --quick, -q only load changed things --progress Show progress bar --service, -s service name --sysconfdir, -c postgresql service config dir @@ -37,15 +40,45 @@ Display this manual =head2 bugs -Add bugs +Add bugs (subject, number, etc) to the database + + --preload create all bugs first, then add information =head2 versions -Add versions +Add version descendant information (which version is based on which version) to +the database =head2 maintainers -Add source maintainers +Add source maintainers to the BTS + +=head2 configuration + +Add debbugs configuration information (tags, severity, etc) + +=head2 suites + +Add suite information from ftp distribution + + --ftpdists location of FTP mirror + +=head2 logs + +Add bug logs + +=head2 packages + +Add package information from the ftp archive + + --ftpdists location of FTP mirror + --suites Suite to operate on + +=head2 debinfo + +Add package information from a debinfo file + + --null -0 names of debinfo files are null separated =head1 OPTIONS @@ -99,12 +132,12 @@ Display this manual. use vars qw($DEBUG); use Debbugs::Common (qw(checkpid lockpid get_hashname getparsedaddrs getbugcomponent make_list getsourcemaintainers), - qw(hash_slice)); + qw(hash_slice open_compressed_file),); use Debbugs::Config qw(:config); use Debbugs::Status qw(read_bug split_status_fields); use Debbugs::Log; use Debbugs::DB; -use Debbugs::DB::Load qw(load_bug handle_load_bug_queue :load_package :load_suite); +use Debbugs::DB::Load qw(:load_bug :load_package :load_suite); use DateTime; use File::stat; use File::Basename; @@ -113,6 +146,7 @@ use IO::Dir; use IO::File; use IO::Uncompress::AnyUncompress; use Encode qw(decode_utf8); +use List::MoreUtils qw(natatime); my %options = (debug => 0, @@ -161,6 +195,8 @@ my %subcommands = }, 'logs' => {function => \&add_logs, }, + 'bugs_and_logs' => {function => \&add_bugs_and_logs, + }, 'packages' => {function => \&add_packages, arguments => {'ftpdists=s' => 1, 'suites=s@' => 0, @@ -244,8 +280,10 @@ sub add_bugs { 'summary', undef, sub { - push @bugs,shift; - }); + push @bugs,@_; + }, + 10000 + ); $s->resultset('Bug')->quick_insert_bugs(@bugs); } walk_bugs([(@{$argv}?@{$argv} : $initialdir)], @@ -253,31 +291,30 @@ sub add_bugs { 'summary', $verbose, sub { - my $bug = shift; - my $stat = stat(getbugcomponent($bug,'summary',$initialdir)); - if (not defined $stat) { - print STDERR "Unable to stat $bug $!\n"; - next; - } - if ($options{quick}) { - my $rs = $s->resultset('Bug')->search({bug=>$bug})->single(); - next if defined $rs and $stat->mtime < $rs->last_modified()->epoch(); - } - my $data = read_bug(bug => $bug, - location => $initialdir); - eval { - load_bug(db => $s, - data => split_status_fields($data), - tags => \%tags, - severities => \%severities, - queue => \%queue); - }; - if ($@) { - use Data::Dumper; - print STDERR Dumper($data) if $DEBUG; - die "failure while trying to load bug $bug\n$@"; - } - } + my @bugs = @_; + my @bugs_to_update; + if ($options{quick}) { + @bugs_to_update = + bugs_to_update($s,$initialdir,@bugs); + } else { + @bugs_to_update = @bugs; + } + eval { + $s->txn_do(sub { + for my $bug (@bugs_to_update) { + load_bug(db => $s, + bug => $bug, + tags => \%tags, + severities => \%severities, + queue => \%queue); + } + }); + }; + if ($@) { + die "failure while trying to load bug: $@"; + } + }, + 50 ); handle_load_bug_queue(db => $s, queue => \%queue); @@ -308,19 +345,21 @@ sub add_versions { my $sp; if (not defined $src_pkgs{$versions[$i][0]}) { $src_pkgs{$versions[$i][0]} = - $s->resultset('SrcPkg')->find_or_create({pkg => $versions[$i][0]}); + $s->resultset('SrcPkg')-> + get_src_pkg_id($versions[$i][0]); } $sp = $src_pkgs{$versions[$i][0]}; # There's probably something wrong if the source package # doesn't exist, but we'll skip it for now - next unless defined $sp; - my $sv = $s->resultset('SrcVer')->find({src_pkg=>$sp->id(), + last if not defined $sp; + my $sv = $s->resultset('SrcVer')->find({src_pkg=>$sp, ver => $versions[$i][1], }); + last if not defined $sv; if (defined $ancestor_sv and defined $sv and not defined $sv->based_on()) { - $sv->update({based_on => $ancestor_sv->id()}) + $sv->update({based_on => $ancestor_sv}) } - $ancestor_sv = $sv; + $ancestor_sv = $sv->id(); } $p->update() if $p; } @@ -333,63 +372,54 @@ sub add_debinfo { my @files = @{$argv}; if (not @files) { { - if ($opts->{0}) { - local $/ = "\0"; - } + local $/ = "\n"; + local $/ = "\0" if $opts->{0}; while () { + s/\n$// unless $opts->{0}; + s/\0$// if $opts->{0}; push @files, $_; } } } return unless @files; my $s = db_connect($options); - my %arch; $p->target(scalar @files) if $p; - for my $file (@files) { - my $fh = IO::File->new($file,'r') or - die "Unable to open $file for reading: $!"; - my $f_stat = stat($file); - while (<$fh>) { - chomp; - next unless length $_; - my ($binname, $binver, $binarch, $srcname, $srcver) = split; - # if $srcver is not defined, this is probably a broken - # .debinfo file [they were causing #686106, see commit - # 49c85ab8 in dak.] Basically, $binarch didn't get put into - # the file, so we'll fudge it from the filename. - if (not defined $srcver) { - ($srcname,$srcver) = ($binarch,$srcname); - ($binarch) = $file =~ /_([^\.]+)\.debinfo/; - } - my $sp = $s->resultset('SrcPkg')->find_or_create({pkg => $srcname}); - # update the creation date if the data we have is earlier - my $ct_date = DateTime->from_epoch(epoch => $f_stat->ctime); - if ($ct_date < $sp->creation) { - $sp->creation($ct_date); - $sp->last_modified(DateTime->now); - $sp->update; - } - my $sv = $s->resultset('SrcVer')->find_or_create({src_pkg =>$sp->id(), - ver => $srcver}); - if (not defined $sv->upload_date() or $ct_date < $sv->upload_date()) { - $sv->upload_date($ct_date); - $sv->update; - } - my $arch; - if (defined $arch{$binarch}) { - $arch = $arch{$binarch}; - } else { - $arch = $s->resultset('Arch')->find_or_create({arch => $binarch}); - $arch{$binarch} = $arch; - } - my $bp = $s->resultset('BinPkg')->find_or_create({pkg => $binname}); - $s->resultset('BinVer')->find_or_create({bin_pkg => $bp->id(), - src_ver => $sv->id(), - arch => $arch->id(), - ver => $binver, - }); - } - $p->update() if $p; + my $it = natatime 100, @files; + while (my @v = $it->()) { + my %cache; + my @debinfos; + for my $file (@v) { + my $fh = IO::File->new($file,'r') or + die "Unable to open $file for reading: $!"; + my $f_stat = stat($file); + my $ct_date = DateTime->from_epoch(epoch => $f_stat->ctime); + while (<$fh>) { + chomp; + next unless length $_; + my ($binname, $binver, $binarch, $srcname, $srcver) = split; + # if $srcver is not defined, this is probably a broken + # .debinfo file [they were causing #686106, see commit + # 49c85ab8 in dak.] Basically, $binarch didn't get put into + # the file, so we'll fudge it from the filename. + if (not defined $srcver) { + ($srcname,$srcver) = ($binarch,$srcname); + ($binarch) = $file =~ /_([^\.]+)\.debinfo/; + } + if (not defined $srcver) { + print STDERR "malformed debinfo (no srcver): $file\n"; + next; + } + push @debinfos, + [$binname,$binver,$binarch,$srcname,$srcver,$ct_date]; + } + } + $s->txn_do( + sub { + for my $di (@debinfos) { + Debbugs::DB::Load::load_debinfo($s,@{$di}[0..5],\%cache); + } + }); + $p->update($p->last_update()+@v) if $p; } $p->remove() if $p; } @@ -440,25 +470,35 @@ sub add_configuration { # tags # add all tags + my %tags; + for my $tag (@{$config{tags}}) { + $tags{$tag} = 1; + $s->resultset('Tag')->find_or_create({tag => $tag}); + } # mark obsolete tags + for my $tag ($s->resultset('Tag')->search_rs()->all()) { + next if exists $tags{$tag->tag}; + $tag->obsolete(1); + $tag->update; + } # severities my %sev_names; - my $order = 0; - for my $sev_name (@{$config{severities}}) { + my $order = -1; + for my $sev_name (($config{default_severity},@{$config{severity_list}})) { # add all severitites my $sev = $s->resultset('Severity')->find_or_create({severity => $sev_name}); # mark strong severities if (grep {$_ eq $sev_name} @{$config{strong_severities}}) { $sev->strong(1); } - $sev->order($order); + $sev->ordering($order); $sev->update(); $order++; $sev_names{$sev_name} = 1; } # mark obsolete severities - for my $sev ($s->resultset('Severity')->find()) { + for my $sev ($s->resultset('Severity')->search_rs()->all()) { next if exists $sev_names{$sev->severity()}; $sev->obsolete(1); $sev->update(); @@ -509,7 +549,18 @@ sub add_logs { $verbose, sub { my $bug = shift; - eval { + my $stat = stat(getbugcomponent($bug,'log',$initialdir)); + if (not defined $stat) { + print STDERR "Unable to stat $bug $!\n"; + next; + } + if ($options{quick}) { + my $rs = $s->resultset('Bug')-> + search({id=>$bug})->single(); + return if defined $rs and + $stat->mtime <= $rs->last_modified()->epoch(); + } + eval { load_bug_log(db => $s, bug => $bug); }; @@ -519,6 +570,81 @@ sub add_logs { }); } +sub add_bugs_and_logs { + my ($options,$opts,$p,$config,$argv) = @_; + + chdir($config->{spool_dir}) or + die "chdir $config->{spool_dir} failed: $!"; + + my $verbose = $options->{debug}; + + my $initialdir = "db-h"; + + if (defined $argv->[0] and $argv->[0] eq "archive") { + $initialdir = "archive"; + } + my $s = db_connect($options); + + my %tags; + my %severities; + my %queue; + + walk_bugs([(@{$argv}?@{$argv} : $initialdir)], + $p, + 'summary', + $verbose, + sub { + my @bugs = @_; + my @bugs_to_update; + if ($options{quick}) { + @bugs_to_update = + bugs_to_update($s,$initialdir,@bugs); + } else { + @bugs_to_update = @bugs; + } + eval { + $s->txn_do(sub { + for my $bug (@bugs_to_update) { + load_bug(db => $s, + bug => $bug, + tags => \%tags, + severities => \%severities, + queue => \%queue); + } + }); + }; + if ($@) { + die "failure while trying to load bug: $@"; + } + for my $bug (@bugs) { + my $stat = stat(getbugcomponent($bug,'log',$initialdir)); + if (not defined $stat) { + print STDERR "Unable to stat $bug $!\n"; + next; + } + if ($options{quick}) { + my $rs = $s->resultset('Bug')-> + search({id=>$bug})->single(); + return if defined $rs and + $stat->mtime <= $rs->last_modified()->epoch(); + } + eval { + load_bug_log(db => $s, + bug => $bug); + }; + if ($@) { + die "failure while trying to load bug log $bug\n$@"; + } + } + }, + 50 + ); + handle_load_bug_queue(db=>$s, + queue => \%queue, + ); + +} + sub add_packages { my ($options,$opts,$p,$config,$argv) = @_; @@ -630,27 +756,6 @@ sub db_connect { die "Unable to connect to database: "; } -sub open_compressed_file { - my ($file) = @_; - my $fh; - my $mode = '<:encoding(UTF-8)'; - my @opts; - if ($file =~ /\.gz$/) { - $mode = '-|:encoding(UTF-8)'; - push @opts,'gzip','-dc'; - } - if ($file =~ /\.xz$/) { - $mode = '-|:encoding(UTF-8)'; - push @opts,'xz','-dc'; - } - if ($file =~ /\.bz2$/) { - $mode = '-|:encoding(UTF-8)'; - push @opts,'bzip2','-dc'; - } - open($fh,$mode,@opts,$file); - return $fh; -} - sub read_release_file { my ($file) = @_; # parse release @@ -682,12 +787,13 @@ sub read_release_file { } sub walk_bugs { - my ($dirs,$p,$what,$verbose,$sub) = @_; + my ($dirs,$p,$what,$verbose,$sub,$n) = @_; my @dirs = @{$dirs}; my $tot_dirs = @dirs; my $done_dirs = 0; my $avg_subfiles = 0; my $completed_files = 0; + $n //= 1; while (my $dir = shift @dirs) { printf "Doing dir %s ...\n", $dir if $verbose; @@ -707,16 +813,34 @@ sub walk_bugs { $avg_subfiles = ($avg_subfiles * $done_dirs + @list) / ($done_dirs+1); $done_dirs += 1; - for my $bug (@list) { - $completed_files++; - $p->update($completed_files) if $p; - print "Up to $completed_files bugs...\n" if ($completed_files % 100 == 0 && $verbose); - $sub->($bug); + my $it = natatime $n,@list; + while (my @bugs = $it->()) { + $sub->(@bugs); + $completed_files += scalar @bugs; + $p->update($completed_files) if $p; + print "Up to $completed_files bugs...\n" + if ($completed_files % 100 == 0 && $verbose); } } $p->remove() if $p; } +sub bugs_to_update { + my ($s,$initialdir,@bugs) = @_; + my @bugs_to_update; + for my $bug (@bugs) { + my $stat = stat(getbugcomponent($bug,'summary',$initialdir)); + if (not defined $stat) { + print STDERR "Unable to stat $bug $!\n"; + next; + } + my $rs = $s->resultset('Bug')->search({id=>$bug})->single(); + next if defined $rs and $stat->mtime <= $rs->last_modified()->epoch(); + push @bugs_to_update, $bug; + } + @bugs_to_update; +} + __END__