diff options
-rw-r--r-- | qarepo.pl | 196 |
1 files changed, 137 insertions, 59 deletions
@@ -20,12 +20,12 @@ use strict; use warnings; -use File::Temp qw(tmpnam); use Glib qw(TRUE FALSE); use Gtk3 '-init'; use MDK::Common; +use URPM; -my $release = 'v1.2'; +my $release = 'v1.3'; ############################################################################### # States and Status @@ -51,6 +51,7 @@ my $sudo = $> ? 'sudo' : ''; my %config; +# Settings are stored in the config file in key=value format. my $config_file = "$home/.qareporc"; if (open(my $f, '<', $config_file)) { while (my $line = <$f>) { @@ -61,10 +62,13 @@ if (open(my $f, '<', $config_file)) { close($f); } -my $mirror = $config{MIRROR} || 'rsync://mirrors.kernel.org/mirrors/mageia'; -my $version = $config{VERSION} || '6'; -my $arch = $config{ARCH} || 'x86_64'; -my $qa_repo = $config{QA_REPO} || "$home/qa-testing"; +# Use sensible defaults for settings not in the config file. +my $mirror = $config{MIRROR} // 'rsync://mirrors.kernel.org/mirrors/mageia'; +my $version = $config{VERSION} // '6'; +my $arch = $config{ARCH} // 'x86_64'; +my $nonfree = $config{NONFREE} // 1; +my $tainted = $config{TAINTED} // 1; +my $qa_repo = $config{QA_REPO} // "$home/qa-testing"; my $qa_repo_name = 'QA Testing'; @@ -84,35 +88,41 @@ my $last_arch = $arch; # GUI Main Window ############################################################################### -my $window = Gtk3::Window->new('toplevel'); +my $window = Gtk3::Window->new('toplevel'); -my $grid = Gtk3::Grid->new(); +my $grid = Gtk3::Grid->new(); -my $label1 = Gtk3::Label->new('Mirror:'); -my $entry1 = Gtk3::Entry->new(); +my $label1 = Gtk3::Label->new('Mirror:'); +my $entry1 = Gtk3::Entry->new(); -my $label2 = Gtk3::Label->new('Version:'); -my $entry2 = Gtk3::Entry->new(); +my $label2 = Gtk3::Label->new('Version:'); +my $entry2 = Gtk3::Entry->new(); -my $label3 = Gtk3::Label->new('Arch:'); -my $entry3 = Gtk3::ComboBoxText->new(); +my $label3 = Gtk3::Label->new('Arch:'); +my $entry3 = Gtk3::ComboBoxText->new(); -my $label4 = Gtk3::Label->new('QA Repo:'); -my $entry4 = Gtk3::Entry->new(); +my $label4 = Gtk3::Label->new('QA Repo:'); +my $entry4 = Gtk3::Entry->new(); -my $label5 = Gtk3::Label->new('RPMs:'); -my $entry5 = Gtk3::TextView->new(); +my $label5 = Gtk3::Label->new('RPMs:'); +my $entry5 = Gtk3::TextView->new(); -my $scroll = Gtk3::ScrolledWindow->new(); +my $scroll = Gtk3::ScrolledWindow->new(); -my $label6 = Gtk3::Label->new('Status:'); -my $status = Gtk3::Label->new(''); +my $label6 = Gtk3::Label->new('Status:'); +my $status = Gtk3::Label->new(''); my $button1 = Gtk3::Button->new('Quit'); my $button2 = Gtk3::Button->new('Disable'); my $button3 = Gtk3::Button->new('Enable'); my $button4 = Gtk3::Button->new('Clear'); +my $check1 = Gtk3::CheckButton->new_with_label("nonfree"); +my $check2 = Gtk3::CheckButton->new_with_label("tainted"); + +my $check3 = Gtk3::CheckButton->new_with_label("fuzzy\nversion"); +my $check4 = Gtk3::CheckButton->new_with_label("add\ndeps"); + $window->set_title("QA Repo $release"); $window->set_default_size(600, 400); $window->set_border_width(10); @@ -130,7 +140,8 @@ $entry1->signal_connect(changed => \&changed); $label2->set_halign('GTK_ALIGN_END'); $entry2->set_text($version); -$entry2->set_hexpand(FALSE); +$entry2->set_width_chars(2); +$entry2->set_hexpand(TRUE); $entry2->signal_connect(changed => \&changed); $label3->set_halign('GTK_ALIGN_END'); @@ -169,28 +180,46 @@ $button1->signal_connect(clicked => \&quit); $button2->signal_connect(clicked => \&disable); $button3->signal_connect(clicked => \&enable); -$button3->set_valign('GTK_ALIGN_START'); -$button4->signal_connect(clicked => \&clear); +$button4->set_vexpand(TRUE); $button4->set_valign('GTK_ALIGN_END'); +$button4->signal_connect(clicked => \&clear); + +$check1->signal_connect(clicked => \&changed); +$check1->set_active($nonfree); + +$check2->signal_connect(clicked => \&changed); +$check2->set_active($tainted); + +$check3->signal_connect(clicked => \&changed); +$check3->set_active(FALSE); + +$check4->signal_connect(clicked => \&changed); +$check4->set_active(FALSE); $grid->attach($label1, 0, 0, 1, 1); -$grid->attach($entry1, 1, 0, 4, 1); +$grid->attach($entry1, 1, 0, 6, 1); + $grid->attach($label2, 1, 1, 1, 1); $grid->attach($entry2, 2, 1, 1, 1); $grid->attach($label3, 3, 1, 1, 1); $grid->attach($entry3, 4, 1, 1, 1); +$grid->attach($check1, 5, 1, 1, 1); +$grid->attach($check2, 6, 1, 1, 1); + $grid->attach($label4, 0, 2, 1, 1); -$grid->attach($entry4, 1, 2, 4, 1); +$grid->attach($entry4, 1, 2, 6, 1); $grid->attach($label5, 0, 3, 1, 1); -$grid->attach($scroll, 1, 3, 4, 2); -$grid->attach($label6, 0, 5, 1, 1); -$grid->attach($status, 1, 5, 4, 1); +$grid->attach($scroll, 1, 3, 6, 4); +$grid->attach($label6, 0, 7, 1, 1); +$grid->attach($status, 1, 7, 6, 1); -$grid->attach($button1, 5, 0, 1, 1); -$grid->attach($button2, 5, 2, 1, 1); -$grid->attach($button3, 5, 3, 1, 1); -$grid->attach($button4, 5, 4, 1, 1); +$grid->attach($button1, 7, 0, 1, 1); +$grid->attach($button2, 7, 2, 1, 1); +$grid->attach($button3, 7, 3, 1, 1); +$grid->attach($check3, 7, 4, 1, 1); +$grid->attach($check4, 7, 5, 1, 1); +$grid->attach($button4, 7, 6, 1, 1); $window->add($grid); @@ -261,10 +290,12 @@ sub changed { sub quit { get_settings(); if (open(my $f, '>', $config_file)) { - print $f "MIRROR=$mirror\n"; - print $f "VERSION=$version\n"; - print $f "ARCH=$arch\n"; - print $f "QA_REPO=$qa_repo\n"; + printf $f "MIRROR=%s\n", $mirror; + printf $f "VERSION=%s\n", $version; + printf $f "ARCH=%s\n", $arch; + printf $f "NONFREE=%d\n", $nonfree; + printf $f "TAINTED=%d\n", $tainted; + printf $f "QA_REPO=%s\n", $qa_repo; close($f); } Gtk3->main_quit; @@ -332,20 +363,28 @@ sub get_settings { $mirror = trim($entry1->get_text()); $version = trim($entry2->get_text()); $arch = trim($entry3->get_active_text()); + $nonfree = $check1->get_active(); + $tainted = $check2->get_active(); $qa_repo = trim($entry4->get_text()); if ($active_qa_repo && $active_qa_repo ne $qa_repo) { disable_repo(); } } -sub get_required_rpms { +sub get_requested_rpms { my $buffer = $entry5->get_buffer(); my $start = $buffer->get_start_iter(); my $end = $buffer->get_end_iter(); + my $fuzzy_version = $check3->get_active(); + my @lines = split("\n", $buffer->get_text($start, $end, FALSE)); - s/^\s+// foreach @lines; # skip leading white space - s/\s+$// foreach @lines; # skip leading white space + if ($fuzzy_version) { + # replace version-release with wildcard + s/-\d.*-.+(\.mga$version(?:(?:\.$arch|\.noarch)(?:\.rpm)?)?)$/-\\d*$1/ foreach @lines; + } + s/^\s+// foreach @lines; # trim leading white space + s/\s+$// foreach @lines; # trim trailing white space grep { $_ ne '' } @lines; # and discard blank lines } @@ -384,7 +423,8 @@ sub update_repo { } sub clear_repo { - my @existing_rpms = get_existing_rpms(); + my ($type) = @_; + my @existing_rpms = grep { $_ =~ /$type/ } get_existing_rpms(); if (@existing_rpms) { if (!unlink(map { "$qa_repo/$_" } @existing_rpms)) { my $message = "couldn't delete existing RPMs in the QA repo"; @@ -422,20 +462,41 @@ sub sync_repo { gtk_update(); } + my $add_dependencies = $check4->get_active(); + my $remote_repo = "$mirror/distrib/$version/$arch/media"; + my @mediatypes = ( 'core' ); + push @mediatypes, 'nonfree' if $nonfree; + push @mediatypes, 'tainted' if $tainted; + my $download_dir = "$qa_repo/.download"; mkdir_p($download_dir); - my @available_rpms = (); - foreach my $media_type (qw(core nonfree tainted)) { + my %rpm_dependencies; + foreach my $media_type (@mediatypes) { my $synthesis = 'synthesis.hdlist.cz'; my $remote_dir = "$remote_repo/$media_type/updates_testing/media_info"; &$sync_file("$remote_dir/$synthesis", $download_dir) or next; - my @package_list = split("\n", `urpmq --synthesis $download_dir/$synthesis --list -f`); - foreach my $package (@package_list) { - push(@available_rpms, "$package.rpm"); - } + gtk_update(); + + my $urpm = new URPM; + $urpm->parse_synthesis("$download_dir/$synthesis"); + $urpm->traverse(sub { + my ($pkg) = @_; + my $name = $pkg->fullname(); + my $rpm = "$name.rpm"; + %{$rpm_dependencies{$rpm}} = (); + if ($add_dependencies) { + my @requires = ( $pkg->requires_nosense(), $pkg->recommends_nosense ); + $urpm->traverse_tag('whatprovides', \@requires, sub { + my ($pkg) = @_; + my $name = $pkg->fullname(); + ${$rpm_dependencies{$rpm}}{"$name.rpm"} = 1; + }); + } + }); + if (!unlink("$download_dir/$synthesis")) { my $message = "couldn't delete $download_dir/$synthesis in the QA repo.\n"; show_error_dialogue($message); @@ -444,21 +505,34 @@ sub sync_repo { gtk_update(); } - my @required_rpms = (); - foreach my $request (get_required_rpms()) { - my $pattern = wildcard_to_regexp($request); - my $matched = 0; - foreach my $candidate (@available_rpms) { - if ($candidate =~ /^$pattern/) { - push(@required_rpms, $candidate) if !member($candidate, @required_rpms); - $matched = 1; + my %selection; + my @requests = get_requested_rpms(); + while (@requests) { + foreach my $request (@requests) { + my $pattern = wildcard_to_regexp($request); + my $matched = 0; + foreach my $candidate (keys %rpm_dependencies) { + if ($candidate =~ /^$pattern/) { + $selection{$candidate} = 1; + $selection{$_} ||= 2 foreach keys %{$rpm_dependencies{$candidate}}; + $matched = 1; + } } + $matched or sync_error("$request not found in the remote repository"); } - $matched or sync_error("$request not found in the remote repository"); + # avoid infinite loop if we haven't found a match + last if @sync_errors; + # recurse through any new dependencies + @requests = grep { $selection{$_} == 2 } keys %selection; } - my @existing_rpms = get_existing_rpms(); + if (@sync_errors) { + show_error_dialogue(@sync_errors); + return 0; + } + my @required_rpms = keys %selection; + my @existing_rpms = get_existing_rpms(); my @unwanted_rpms = difference2(\@existing_rpms, \@required_rpms); if (@unwanted_rpms) { if (!unlink(map { "$qa_repo/$_" } @unwanted_rpms)) { @@ -499,10 +573,14 @@ sub sync_repo { or sync_error("failed to update hdlist"); } else { print "ERROR: failed to download all the files.\n"; + } + + if (@sync_errors) { show_error_dialogue(@sync_errors); + return 0; } - @sync_errors == 0; + 1; } sub sync_file_rsync { @@ -533,7 +611,7 @@ sub sync_file_link { sub sync_error { my ($message) = @_; - push(@sync_errors, $message); + push @sync_errors, $message; print "ERROR: $message.\n"; 0; } |