From 87af55faa7a169572abd62c52df4b4aa5a43b3c3 Mon Sep 17 00:00:00 2001 From: Martin Whitaker Date: Sat, 24 Mar 2018 23:37:16 +0000 Subject: Initial code --- qarepo.pl | 361 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 361 insertions(+) create mode 100644 qarepo.pl diff --git a/qarepo.pl b/qarepo.pl new file mode 100644 index 0000000..877602c --- /dev/null +++ b/qarepo.pl @@ -0,0 +1,361 @@ +#!/usr/bin/perl + +use strict; +use Gtk3 '-init'; +use Glib qw(TRUE FALSE); +use MDK::Common; + +my $home = $ENV{HOME} or die "ERROR: the HOME environment variable is not set.\n"; + +my $sudo = $> ? 'sudo' : ''; + +my %config; + +my $config_file = $home . '/.qareporc'; +if (open(my $f, '<', $config_file)) { + while (my $line = <$f>) { + chomp($line); + my ($key, $value) = split(/=/, $line); + $config{$key} = $value if $key; + } + 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'; + +my $qa_repo_name = 'QA Testing'; + +my $list_url = `urpmq --list-url | grep '$qa_repo_name'`; +chomp($list_url); + +my $active_qa_repo = $list_url =~ s/$qa_repo_name +//r; +if ($list_url && $active_qa_repo ne $qa_repo) { + disable_repo(); +} +my $last_version = $version; +my $last_arch = $arch; + +my $window = Gtk3::Window->new('toplevel'); + +my $grid = Gtk3::Grid->new(); + +my $label1 = Gtk3::Label->new('Mirror:'); +my $entry1 = 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 $label4 = Gtk3::Label->new('QA Repo:'); +my $entry4 = Gtk3::Entry->new(); + +my $label5 = Gtk3::Label->new('RPMs:'); +my $entry5 = Gtk3::TextView->new(); + +my $scroll = Gtk3::ScrolledWindow->new(); + +my $button1 = Gtk3::Button->new('Quit'); +my $button2 = Gtk3::Button->new($active_qa_repo ? 'Disable' : 'Enable'); +my $button3 = Gtk3::Button->new('Update'); +my $button4 = Gtk3::Button->new('Clear'); + +$window->set_title('QA Repo'); +$window->set_default_size(500, 300); +$window->set_border_width(10); +$window->signal_connect(delete_event => \&quit); + +$grid->set_row_spacing(10); +$grid->set_column_spacing(10); + +$label1->set_halign('GTK_ALIGN_END'); + +$entry1->set_text($mirror); +$entry1->set_hexpand(TRUE); +$entry1->signal_connect(changed => \&changed); + +$label2->set_halign('GTK_ALIGN_END'); + +$entry2->set_text($version); +$entry2->set_hexpand(FALSE); +$entry2->signal_connect(changed => \&changed); + +$label3->set_halign('GTK_ALIGN_END'); + +$entry3->append_text('i586'); +$entry3->append_text('x86_64'); +if ($arch eq 'x86_64') { + $entry3->set_active(1); +} else { + $entry3->set_active(0); +} +$entry3->signal_connect(changed => \&changed); + +$label4->set_halign('GTK_ALIGN_END'); + +$entry4->set_text($qa_repo); +$entry4->set_hexpand(TRUE); +$entry4->signal_connect(changed => \&changed); + +$label5->set_valign('GTK_ALIGN_START'); +$label5->set_halign('GTK_ALIGN_END'); + +$entry5->get_buffer->set_text(join("\n", get_existing_rpms())); +$entry5->get_buffer->signal_connect(changed => \&changed); + +$scroll->set_hexpand(TRUE); +$scroll->set_vexpand(TRUE); + +$scroll->add($entry5); + +$button1->signal_connect(clicked => \&quit); + +$button2->signal_connect(clicked => \&enable_disable); + +$button3->signal_connect(clicked => \&update); +$button3->set_valign('GTK_ALIGN_START'); +$button3->set_sensitive(FALSE); + +$button4->signal_connect(clicked => \&clear); +$button4->set_valign('GTK_ALIGN_END'); + +$grid->attach($label1, 0, 0, 1, 1); +$grid->attach($entry1, 1, 0, 4, 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($label4, 0, 2, 1, 1); +$grid->attach($entry4, 1, 2, 4, 1); +$grid->attach($label5, 0, 3, 1, 1); +$grid->attach($scroll, 1, 3, 4, 2); + +$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); + +$window->add($grid); +$window->show_all; + +Gtk3->main; + +my $ignore_change; + +sub changed() { + if ($ignore_change) { + $ignore_change = 0; + } else { + $button3->set_sensitive(TRUE); + } +} + +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"; + close($f); + } + Gtk3->main_quit; +} + +sub enable_disable() { + disable_buttons(); + if ($active_qa_repo) { + disable_repo(); + } else { + get_settings(); + if (sync_repo()) { + enable_repo(); + } + } + enable_buttons(); +} + +sub update() { + disable_buttons(); + get_settings(); + if (sync_repo()) { + if ($active_qa_repo) { + update_repo(); + } else { + enable_repo(); + } + } else { + if ($active_qa_repo) { + disable_repo(); + } + } + enable_buttons(); +} + +my $clear_pending; + +sub clear() { + disable_buttons(); + get_settings(); + clear_repo(); + if ($active_qa_repo) { + disable_repo(); + } + my $buffer = $entry5->get_buffer(); + $ignore_change = $buffer->get_char_count() > 0; + $buffer->set_text(""); + enable_buttons(); +} + +sub disable_buttons() { + $button1->set_sensitive(FALSE); + $button2->set_sensitive(FALSE); + $button3->set_sensitive(FALSE); + $button4->set_sensitive(FALSE); +} + +sub enable_buttons() { + $button1->set_sensitive(TRUE); + $button2->set_sensitive(TRUE); + $button4->set_sensitive(TRUE); +} + +sub get_settings() { + $mirror = $entry1->get_text(); + $version = $entry2->get_text(); + $arch = $entry3->get_active_text(); + $qa_repo = $entry4->get_text(); + if ($active_qa_repo && $active_qa_repo ne $qa_repo) { + disable_repo(); + } +} + +sub get_required_rpms() { + my $buffer = $entry5->get_buffer(); + my $start = $buffer->get_start_iter(); + my $end = $buffer->get_end_iter(); + + grep { $_ ne '' } split("\n", $buffer->get_text($start, $end, FALSE)); +} + +sub get_existing_rpms() { + map { basename($_) } glob("$qa_repo/*.rpm"); +} + +sub disable_repo() { + system("$sudo urpmi.removemedia '$qa_repo_name'") == 0 + or die "ERROR: couldn't disable the $qa_repo_name media.\n"; + $button2->set_label('Enable'); + $active_qa_repo = ''; +} + +sub enable_repo() { + if (system("$sudo urpmi.addmedia --update '$qa_repo_name' $qa_repo") == 0) { + $button2->set_label('Disable'); + $active_qa_repo = $qa_repo; + } else { + $active_qa_repo = ''; + } +} + +sub update_repo() { + if (system("$sudo urpmi.update '$qa_repo_name'") != 0) { + print "ERROR: couldn't update the $qa_repo_name media.\n"; + disable_repo(); + } +} + +sub clear_repo() { + my @existing_rpms = get_existing_rpms(); + if (@existing_rpms) { + unlink(map { "$qa_repo/$_" } @existing_rpms) + or die "ERROR: couldn't delete/unlink existing RPMs in the QA repo.\n"; + } +} + +my $sync_ok; + +sub sync_repo() { + my $sync_file; + if ($mirror =~ /^rsync:/) { + $sync_file = \&sync_file_rsync; + } elsif ($mirror =~ /^ftp:/ || $mirror =~ /^http:/) { + $sync_file = \&sync_file_aria2; + } elsif ($mirror !~ /^\w+:/) { + $sync_file = \&sync_file_link; + } else { + sync_error("unsupported mirror URL type"); + return 0; + } + + if ($version ne $last_version || $arch ne $last_arch) { + clear_repo(); + } + + my @required_rpms = get_required_rpms(); + my @existing_rpms = get_existing_rpms(); + my @unwanted_rpms = difference2(\@existing_rpms, \@required_rpms); + if (@unwanted_rpms) { + unlink(map { "$qa_repo/$_" } @unwanted_rpms) + or die "ERROR: couldn't delete/unlink unwanted RPMs in the QA repo.\n"; + } + my $old_pubkey = "$qa_repo/media_info/pubkey"; + if (-e $old_pubkey) { + unlink($old_pubkey) + or die "ERROR: couldn't delete/unlink old pubkey in the QA repo.\n"; + } + + mkdir_p("$qa_repo/media_info/"); + + $sync_ok = 1; + my $remote_repo = $mirror . '/distrib/' . $version . '/' . $arch . '/media'; + foreach my $rpm (difference2(\@required_rpms, \@existing_rpms)) { + my $remote_url = $remote_repo; + if ($rpm =~ /tainted/) { + $remote_url .= '/tainted/updates_testing/' . $rpm; + } elsif ($rpm =~ /nonfree/) { + $remote_url .= '/nonfree/updates_testing/' . $rpm; + } else { + $remote_url .= '/core/updates_testing/' . $rpm; + } + &$sync_file($remote_url, $qa_repo); + } + &$sync_file($remote_repo . '/core/updates_testing/media_info/pubkey', $qa_repo . '/media_info'); + + if ($sync_ok) { + system("genhdlist2 $qa_repo") == 0 + or sync_error("failed to update hdlist"); + } + + $sync_ok; +} + +sub sync_file_rsync { + my ($src_url, $dst_dir) = @_; + print "fetching $src_url\n"; + system("rsync -q $src_url $dst_dir") == 0 + or sync_error("failed to download $src_url"); +} + +sub sync_file_aria2 { + my ($src_url, $dst_dir) = @_; + print "fetching $src_url\n"; + system("aria2c -q -d $dst_dir $src_url") == 0 + or sync_error("failed to download $src_url"); +} + +sub sync_file_link { + my ($src_file, $dst_dir) = @_; + -e $src_file && symlink($src_file, $dst_dir . '/' . basename($src_file)) + or sync_error("failed to link $src_file"); +} + +sub sync_error { + my ($message) = @_; + print "ERROR: $message.\n"; + $sync_ok = 0; +} -- cgit v1.2.1