aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMartin Whitaker <mageia@martin-whitaker.me.uk>2018-03-30 19:09:35 +0100
committerNeal Gompa <ngompa13@gmail.com>2018-03-30 14:15:14 -0400
commitd7e77fdefb37e2b1244c7c38b544d6c893a671ed (patch)
tree4def6486ac8fa79132d7087487fdf4a2434acbed
parent654a14c7d32f5cde599329936e9675caa8834016 (diff)
downloadqarepo-d7e77fdefb37e2b1244c7c38b544d6c893a671ed.tar
qarepo-d7e77fdefb37e2b1244c7c38b544d6c893a671ed.tar.gz
qarepo-d7e77fdefb37e2b1244c7c38b544d6c893a671ed.tar.bz2
qarepo-d7e77fdefb37e2b1244c7c38b544d6c893a671ed.tar.xz
qarepo-d7e77fdefb37e2b1244c7c38b544d6c893a671ed.zip
New release
I've added a couple of extra options: 1. "fuzzy version" will automatically replace the package version/release in each requested package with a wildcard. If there are multiple versions in the remote repository, you'll get them all (and MageiaUpdate will then select the newest). Note this only happens if the requested package name includes the Mageia release (e.g. mga6) and if the package version starts with a digit, to avoid false matches. 2. "add deps" will automatically add all dependencies of the requested packages that can be satisfied from the updates_testing repositories. If you want to see what's actually been selected, either quit the app. and restart it, or use urpmq --list --media 'QA Testing' I would only use these options whilst things are in a state of flux. You really want to test against a definitive package list before you finally validate an update. I've also added a couple of check boxes to let you enable/disable use of the nonfree and tainted repositories.
-rw-r--r--qarepo.pl196
1 files changed, 137 insertions, 59 deletions
diff --git a/qarepo.pl b/qarepo.pl
index fe623dd..c7d5947 100644
--- a/qarepo.pl
+++ b/qarepo.pl
@@ -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;
}