+sub add_debinfo {
+ my ($options,$opts,$p,$config,$argv) = @_;
+
+ my @files = @{$argv};
+ if (exists $opts->{debinfo_dir} and not @files) {
+ find(sub {
+ if (-f $_ and /\.debinfo$/) {
+ push @files, $File::Find::name;
+ }
+ },
+ $opts->{debinfo_dir}
+ );
+ }
+ if (not @files) {
+ {
+ local $/ = "\n";
+ local $/ = "\0" if $opts->{0};
+ while (<STDIN>) {
+ s/\n$// unless $opts->{0};
+ s/\0$// if $opts->{0};
+ push @files, $_;
+ }
+ }
+ }
+ return unless @files;
+ my $s = db_connect($options);
+ $p->target(scalar @files) if $p;
+ my $it = natatime 100, @files;
+ while (my @v = $it->()) {
+ my %cache;
+ my @debinfos;
+FILE: 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);
+ my @file_debinfos;
+ 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 =~ /_([a-z0-9-]+)\.debinfo/;
+ }
+ # It turns out that there are debinfo files which are horribly
+ # screwed up, and have junk in them. We need to discard them
+ # completely
+ if (not defined $srcname or
+ not defined $srcver or
+ not defined $binname or
+ not defined $binver or
+ not defined $binarch or
+ $srcname !~ /^$config{package_name_re}$/o or
+ $binname !~ /^$config{package_name_re}$/o or
+ $srcver !~ /^$config{package_version_re}$/o or
+ $binver !~ /^$config{package_version_re}$/o
+ ) {
+ print STDERR "malformed debinfo: $file\n$_\n";
+ next FILE;
+ }
+ push @file_debinfos,
+ [$binname,$binver,$binarch,$srcname,$srcver,$ct_date];
+ }
+ push @debinfos,
+ @file_debinfos;
+ }
+ $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;
+}
+
+sub add_maintainers {
+ my ($options,$opts,$p,$config,$argv) = @_;
+
+ my $s = db_connect($options);
+ my $maintainers = getsourcemaintainers() // {};
+ $p->target(2) if $p;
+ ## get all of the maintainers, and add the missing ones
+ my $maints = $s->resultset('Maintainer')->
+ get_maintainers(values %{$maintainers});
+ $p->update() if $p;
+ my @svs = $s->resultset('SrcVer')->
+ search({maintainer => undef
+ },
+ {join => 'src_pkg',
+ group_by => 'me.src_pkg, src_pkg.pkg',
+ result_class => 'DBIx::Class::ResultClass::HashRefInflator',
+ columns => [qw(me.src_pkg src_pkg.pkg)],
+ }
+ )->all();
+ $p->target(2+@svs) if $p;
+ $p->update() if $p;
+ for my $sv (@svs) {
+ if (exists $maintainers->{$sv->{src_pkg}{pkg}}) {
+ my $pkg = $sv->{src_pkg}{pkg};
+ my $maint = $maints->
+ {$maintainers->{$pkg}};
+ $s->txn_do(sub {$s->resultset('SrcVer')->
+ search({maintainer => undef,
+ 'src_pkg.pkg' => $pkg
+ },
+ {join => 'src_pkg'}
+ )->update({maintainer => $maint})
+ });
+ }
+ $p->update() if $p;
+ }
+ $p->remove() if $p;
+}
+
+sub add_configuration {
+ my ($options,$opts,$p,$config,$argv) = @_;
+
+ my $s = db_connect($options);
+
+ # 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 = -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->ordering($order);
+ $sev->update();
+ $order++;
+ $sev_names{$sev_name} = 1;
+ }
+ # mark obsolete severities
+ for my $sev ($s->resultset('Severity')->search_rs()->all()) {
+ next if exists $sev_names{$sev->severity()};
+ $sev->obsolete(1);
+ $sev->update();
+ }
+}
+
+sub add_suite {
+ my ($options,$opts,$p,$config,$argv) = @_;
+ # suites
+
+ my $s = db_connect($options);
+ my $dist_dir = IO::Dir->new($opts->{ftpdists});
+ my @dist_names =
+ grep { $_ !~ /^\./ and
+ -d $opts->{ftpdists}.'/'.$_ and
+ not -l $opts->{ftpdists}.'/'.$_
+ } $dist_dir->read;
+ while (my $dist = shift @dist_names) {
+ my $dist_dir = $opts->{ftpdists}.'/'.$dist;
+ my ($dist_info,$package_files) =
+ read_release_file($dist_dir.'/Release');
+ load_suite($s,$dist_info);
+ }
+}
+
+sub add_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);
+
+ walk_bugs(dirs => [(@{$argv}?@{$argv} : $initialdir)],
+ progress_bar => $p,
+ bug_file => 'log',
+ $verbose?(logging => \*STDERR):(),
+ callback =>
+ sub {
+ my $bug = shift;
+ 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$@";
+ }
+ });
+}