Merge "Support BuildFlags: nocumulaterpms" into devel
[tools/build.git] / createrepomddeps
1 #!/usr/bin/perl -w
2
3 ################################################################
4 #
5 # Copyright (c) 1995-2014 SUSE Linux Products GmbH
6 #
7 # This program is free software; you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License version 2 or 3 as
9 # published by the Free Software Foundation.
10 #
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 # GNU General Public License for more details.
15 #
16 # You should have received a copy of the GNU General Public License
17 # along with this program (see the file COPYING); if not, write to the
18 # Free Software Foundation, Inc.,
19 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
20 #
21 ################################################################
22
23 BEGIN {
24   unshift @INC, ($::ENV{'BUILD_DIR'} || '/usr/lib/build');
25 }
26
27 use strict;
28 use Data::Dumper;
29 use Getopt::Long;
30 use Build ':rpm';
31 use Build::Rpm;
32 use Build::Rpmmd;
33 use Digest::MD5 ();
34 use File::Path qw(mkpath rmtree);
35 use File::Basename;
36 use File::Copy qw(move);
37 use IPC::SysV qw(IPC_PRIVATE S_IRUSR S_IWUSR IPC_CREAT IPC_EXCL SEM_UNDO);
38 use IPC::Semaphore;
39
40 Getopt::Long::Configure("no_ignore_case");
41
42 my $opt_dump;
43 my $opt_old;
44 my $opt_nosrc;
45 my $opt_bc;
46 my $opt_zypp;
47 my $cachedir = "/var/cache/build";
48
49 sub printold {
50   my ($pkg, $baseurl, $old_seen) = @_;
51
52   my $arch = $pkg->{'arch'};
53   $arch = 'src' if $pkg->{'arch'} eq 'nosrc';
54   return if $arch eq 'src' && $opt_nosrc;
55   my $evr = $pkg->{'version'}.'-'.$pkg->{'release'};
56   $evr = "$pkg->{'epoch'}:$evr" if $pkg->{'epoch'};
57   my $loc = $baseurl . $pkg->{'location'};
58   if ($old_seen->{$pkg->{'name'}}->{$arch}) {
59     my $vv = Build::Rpm::verscmp($old_seen->{$pkg->{'name'}}->{$arch}->{'evr'}, $evr, 0);
60     if ($vv >= 0) {
61       print "$loc\n";
62       return;
63     }
64     print $old_seen->{$pkg->{'name'}}->{$arch}->{'loc'}."\n";
65   }
66   $old_seen->{$pkg->{'name'}}->{$arch}->{'evr'} = $evr;
67   $old_seen->{$pkg->{'name'}}->{$arch}->{'loc'} = $loc;
68 }
69
70 GetOptions (
71   "nosrc"   => \$opt_nosrc,
72   "dump"   => \$opt_dump,
73   "old"   => \$opt_old,
74   "zypp=s"   => \$opt_zypp,
75   "cachedir=s"  => \$cachedir,
76   ) or exit(1);
77
78 $opt_bc = 1 unless $opt_dump || $opt_old;
79
80 my $old_seen = {};      # for opt_old
81 my @packages;           # for opt_dump
82
83 for my $url (@ARGV) {
84   my $dir;
85   my $baseurl = $url;
86   if ($opt_zypp) {
87     $dir = $opt_zypp;
88   } elsif ($url =~ /^(?:ftps?|https?):\/\/([^\/]*)\/?/) {
89     my $repoid = Digest::MD5::md5_hex($url);
90     $dir = "$cachedir/$repoid/";
91     $baseurl .= '/' unless $baseurl =~ /\/$/;
92     mkpath("${dir}repodata");
93     #my $sem;
94         #my $key = IPC::SysV::ftok($dir, '1');
95         #if ($sem = IPC::Semaphore->new($key, 1, S_IRUSR | S_IWUSR | IPC_CREAT | IPC_EXCL)) {
96         #  $sem->setval(0, 1);
97         #} else {
98         #  $sem = IPC::Semaphore->new($key, 1, S_IRUSR | S_IWUSR | IPC_CREAT);
99         #}
100         #
101         #$sem->op(0, -1, SEM_UNDO);
102         #if (!-f "${dir}repodata/repomd.xml") {
103           system($INC[0].'/download', "${dir}repodata", "${baseurl}repodata/repomd.xml");
104       #}
105       #$sem->op(0, 1, SEM_UNDO);
106           #$sem->remove();
107   } else {
108     $dir = $url;
109   }
110   $dir .= '/' unless $dir =~ /\/$/;
111   $baseurl .= '/' unless $baseurl =~ /\/$/;
112
113   if (! -s "${dir}repodata/repomd.xml") {
114     die("zypp repo $url is not up to date, please refresh first\n") if $opt_zypp;
115     die("repo $url does not contain a repomd.xml file\n");
116   }
117
118   my @primaryfiles;
119   Build::Rpmmd::parse_repomd("${dir}repodata/repomd.xml", \@primaryfiles);
120   @primaryfiles = grep {$_->{'type'} eq 'primary' && defined($_->{'location'})} @primaryfiles;
121 #  print Dumper(\@primaryfiles);
122
123   for my $f (@primaryfiles) {
124     my $u = "$dir$f->{'location'}";
125     if ($] > 5.007) {
126       require Encode;
127       utf8::downgrade($u);
128     }
129     my $cached;
130         #my $sem;
131         #my $key = IPC::SysV::ftok("${dir}repodata/", '1');
132         #if ($sem = IPC::Semaphore->new($key, 1, S_IRUSR | S_IWUSR | IPC_CREAT | IPC_EXCL)) {
133         #  $sem->setval(0, 1);
134         #} else {
135         #  $sem = IPC::Semaphore->new($key, 1, S_IRUSR | S_IWUSR | IPC_CREAT);
136         #}
137         #$sem->op(0, -1, SEM_UNDO);
138     if (-e $u) {
139       $cached = 1;
140       $cached = 0 if exists($f->{'size'}) && $f->{'size'} != (-s _);
141       $cached = 0 if !exists($f->{'size'}) && $u !~ /[0-9a-f]{32}-primary/;
142     }
143     if (!$cached) {
144       die("zypp repo $url is not up to date, please refresh first\n") if $opt_zypp;
145       if ($url =~ /^(?:ftps?|https?):\/\/([^\/]*)\/?/) {
146         if (system("$INC[0]/download", "${dir}repodata/", "${baseurl}repodata/" . basename($u))) {
147           die("download failed\n");
148         }
149       } else {
150        die("inconsistent repodata in $url\n");
151       }
152     }
153         #$sem->op(0, 1, SEM_UNDO);
154         #$sem->remove();
155
156     my $fh;
157     open($fh, '<', $u) or die "Error opening $u: $!\n";
158     if ($u =~ /\.gz$/) {
159       use IO::Uncompress::Gunzip qw($GunzipError);
160       $fh = new IO::Uncompress::Gunzip $fh or die "Error opening $u: $GunzipError\n";
161     }
162     Build::Rpmmd::parse($fh, sub {
163       if ($opt_dump) {
164         $_[0]->{'baseurl'} = $baseurl;
165         push @packages, $_[0] if $opt_dump;
166       }
167       if ($opt_bc) {
168         Build::writedeps(\*STDOUT, $_[0], $baseurl);
169       } elsif ($opt_old) {
170         printold($_[0], $baseurl, $old_seen);
171       }
172     }, 'addselfprovides' => 1);
173     close($fh);
174   }
175 }
176
177 if ($opt_dump) {
178   print Data::Dumper->Dump([\@packages], ['packages']); # caution: excessive memory consumption!
179 }
180