1
#!/usr/bin/perl
2
# vim: set ts=3 sw=3 ai et nu:
3
#
4
# Verifies repository URLs and updates repository configuration files
5
# accordingly (removes failed URLs).
6
#
7
# by Pascal Bleser <pascal.bleser@opensuse.org>
8
#
9
#     This library is free software; you can redistribute it and/or modify it
10
#     under the terms of the GNU Lesser General Public License as published by
11
#     the Free Software Foundation; either version 2.1 of the License, or (at
12
#     your option) any later version.
13
#                 
14
#     This library is distributed in the hope that it will be useful, but
15
#     WITHOUT ANY WARRANTY; without even the implied warranty of
16
#     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17
#     Lesser General Public License for more details.
18
#      
19
#     You should have received a copy of the GNU Lesser General Public
20
#     License along with this library; if not, write to the Free Software
21
#     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307,
22
#     USA.
23
24
use strict;
25
use warnings;
26
use Term::ProgressBar;
27
use LWP::UserAgent;
28
use Getopt::Long;
29
30
my $repos = "./repos.d";
31
my $cache_dir = "./cache.d";
32
my $verbose = undef;
33
34
GetOptions(
35
   'v|verbose' => \$verbose,
36
);
37
38
my @repos = ();
39
{
40
   my @rfiles = ();
41
   if (scalar(@ARGV) > 0) {
42
      push(@rfiles, @ARGV);
43
   } else {
44
      @rfiles = grep { -f } glob($repos.'/*.conf');
45
   }
46
47
   foreach my $rfile (@rfiles) {
48
      open(my $fh, '<', $rfile) or die "failed to open $rfile: $!";
49
      while (<$fh>) {
50
         chomp;
51
         s/#.*$//;
52
         s/^\s*//;
53
         s/\s*//;
54
         next if /^$/;
55
         my ($repoid, $distname, $distversion, $baseurl) = split(/\s+/);
56
         push(@repos, {
57
            repoid         => $repoid,
58
            distname       => $distname,
59
            distversion    => $distversion,
60
            baseurl        => $baseurl,
61
            file           => $rfile,
62
         });
63
      }
64
      close($fh);
65
   }
66
}
67
68
my $ua = LWP::UserAgent->new(
69
   timeout      => 10,
70
   agent        => "webpin-repomanager/1.0",
71
   max_redirect => 4,
72
);
73
$ua->env_proxy();
74
75
my $progress = undef;
76
if ($verbose) {
77
   print "Checking ", scalar(@repos), " URLs", "\n";
78
   $progress = Term::ProgressBar->new({
79
      count => scalar(@repos),
80
      name  => "checking",
81
      ETA   => 'linear',
82
   });
83
   $progress->minor(0);
84
}
85
86
my $count = 0;
87
my @failed = ();
88
foreach my $r (@repos) {
89
   $count++;
90
   $progress->update($count) if defined $progress;
91
92
   my $url = $r->{baseurl}.'/repodata/repomd.xml';
93
   my $resp = $ua->head($url);
94
   next if $resp->is_success;
95
   $r->{code} = $resp->code;
96
   $r->{status} = $resp->status_line;
97
   $r->{url} = $url;
98
   push(@failed, $r);
99
}
100
101
if ($verbose) {
102
   print "\n", scalar(@failed), "/", scalar(@repos), " failed", "\n";
103
   foreach my $r (@failed) {
104
      print $r->{repoid},"\t", $r->{status}, "\t", $r->{url}, "\n";
105
   }
106
}
107
my %failed_repoids = map { $_->{repoid} => 1 } @failed;
108
my @failed_files = ();
109
{
110
   my %failed_files_h = map { $_->{file} => 1 } @failed;
111
   push(@failed_files, keys %failed_files_h);
112
}
113
114
foreach my $f (@failed_files) {
115
   my @lines = ();
116
   {
117
      open(my $fh, '<', $f) or die "failed to read $f: $!";
118
      while (<$fh>) {
119
         chomp;
120
         my ($repoid, $distname, $distversion, $baseurl) = split(/\s+/);
121
         push(@lines, $_) unless exists $failed_repoids{$repoid};
122
      }
123
      close($fh);
124
   }
125
   if (scalar(@lines) < 1) {
126
      unlink($f) or die "failed to delete file $f: $!";
127
   } else {
128
      open(my $fh, '>', $f) or die "failed to write $f: $!";
129
      foreach (@lines) {
130
         print $fh $_, "\n";
131
      }
132
      close($fh);
133
   }
134
}