882 lines
30 KiB
Python
882 lines
30 KiB
Python
#! /usr/bin/python3
|
|
# -*- coding:utf-8 -*-
|
|
|
|
import pyalpm
|
|
from gi.repository import Gtk
|
|
|
|
from pamac import config, common
|
|
|
|
# i18n
|
|
import gettext
|
|
import locale
|
|
locale.bindtextdomain('pamac', '/usr/share/locale')
|
|
gettext.bindtextdomain('pamac', '/usr/share/locale')
|
|
gettext.textdomain('pamac')
|
|
_ = gettext.gettext
|
|
|
|
interface = Gtk.Builder()
|
|
interface.set_translation_domain('pamac')
|
|
|
|
interface.add_from_file('/usr/share/pamac/gui/dialogs.ui')
|
|
ErrorDialog = interface.get_object('ErrorDialog')
|
|
WarningDialog = interface.get_object('WarningDialog')
|
|
InfoDialog = interface.get_object('InfoDialog')
|
|
#QuestionDialog = interface.get_object('QuestionDialog')
|
|
ConfDialog = interface.get_object('ConfDialog')
|
|
transaction_sum = interface.get_object('transaction_sum')
|
|
sum_top_label = interface.get_object('sum_top_label')
|
|
sum_bottom_label = interface.get_object('sum_bottom_label')
|
|
ChooseDialog = interface.get_object('ChooseDialog')
|
|
choose_list = interface.get_object('choose_list')
|
|
choose_label = interface.get_object('choose_label')
|
|
choose_renderertoggle = interface.get_object('choose_renderertoggle')
|
|
ProgressWindow = interface.get_object('ProgressWindow')
|
|
progress_bar = interface.get_object('progressbar2')
|
|
progress_label = interface.get_object('progresslabel2')
|
|
action_icon = interface.get_object('action_icon')
|
|
ProgressCancelButton = interface.get_object('ProgressCancelButton')
|
|
ProgressCloseButton = interface.get_object('ProgressCloseButton')
|
|
progress_textview = interface.get_object('progress_textview')
|
|
progress_expander = interface.get_object('progress_expander')
|
|
|
|
progress_buffer = progress_textview.get_buffer()
|
|
choose_only_one = False
|
|
|
|
def choose_provides(data):
|
|
global choose_only_one
|
|
choose_only_one = True
|
|
providers = data[0]
|
|
dep_to_provide = data[1]
|
|
choose_label.set_markup(_('<b>{pkgname} is provided by {number} packages.\nPlease choose the one you want to install:</b>').format(pkgname = dep_to_provide, number = str(len(providers))))
|
|
choose_list.clear()
|
|
choose_renderertoggle.set_radio(True)
|
|
for pkg in providers:
|
|
choose_list.append([False, pkg.name])
|
|
ChooseDialog.run()
|
|
index = 0
|
|
if to_provide:
|
|
for pkg in providers:
|
|
if to_provide[0] == pkg.name:
|
|
index = providers.index(pkg)
|
|
return index
|
|
|
|
def on_choose_renderertoggle_toggled(widget, line):
|
|
global choose_only_one
|
|
choose_list[line][0] = not choose_list[line][0]
|
|
if choose_only_one:
|
|
for row in choose_list:
|
|
if not row[1] == choose_list[line][1]:
|
|
row[0] = False
|
|
|
|
def on_ChooseButton_clicked(*arg):
|
|
ChooseDialog.hide()
|
|
line = 0
|
|
to_provide.clear()
|
|
while line < len(choose_list):
|
|
if choose_list[line][0] is True:
|
|
to_provide.append(choose_list[line][1])
|
|
line += 1
|
|
|
|
def on_progress_textview_size_allocate(*arg):
|
|
#auto-scrolling method
|
|
adj = progress_textview.get_vadjustment()
|
|
adj.set_value(adj.get_upper() - adj.get_page_size())
|
|
|
|
#~ def policykit_test(sender, connexion, action):
|
|
#~ bus = dbus.SystemBus()
|
|
#~ proxy_dbus = connexion.get_object('org.freedesktop.DBus','/org/freedesktop/DBus/Bus', False)
|
|
#~ dbus_info = dbus.Interface(proxy_dbus,'org.freedesktop.DBus')
|
|
#~ sender_pid = dbus_info.GetConnectionUnixProcessID(sender)
|
|
#~ proxy_policykit = bus.get_object('org.freedesktop.PolicyKit1','/org/freedesktop/PolicyKit1/Authority',False)
|
|
#~ policykit_authority = dbus.Interface(proxy_policykit,'org.freedesktop.PolicyKit1.Authority')
|
|
#~
|
|
#~ Subject = ('unix-process', {'pid': dbus.UInt32(sender_pid, variant_level=1),
|
|
#~ 'start-time': dbus.UInt64(0, variant_level=1)})
|
|
#~ (is_authorized,is_challenge,details) = policykit_authority.CheckAuthorization(Subject, action, {'': ''}, dbus.UInt32(1), '')
|
|
#~ return is_authorized
|
|
|
|
#~ def sort_pkgs_list(self, pkgs_list):
|
|
#~ result = []
|
|
#~ names_list = sorted([pkg.name for pkg in pkgs_list])
|
|
#~ for name in names_list:
|
|
#~ for pkg in pkgs_list:
|
|
#~ if name == pkg.name:
|
|
#~ result.append(pkg)
|
|
#~ return result
|
|
|
|
def remove_pkg_from_list(pkg, pkgs_list):
|
|
if pkgs_list:
|
|
for _pkg in pkgs_list:
|
|
if (pkg.name == _pkg.name and pkg.version == _pkg.version and pkg.arch == _pkg.arch):
|
|
target = _pkg
|
|
pkgs_list.remove(_pkg)
|
|
|
|
def pkg_in_list(pkg, pkgs_list):
|
|
result = False
|
|
if pkgs_list:
|
|
for _pkg in pkgs_list:
|
|
if (pkg.name == _pkg.name and pkg.version == _pkg.version and pkg.arch == _pkg.arch):
|
|
result = True
|
|
return result
|
|
|
|
class Transaction():
|
|
def __init__(self):
|
|
self.t = None
|
|
self.to_remove = []
|
|
self.to_add = []
|
|
self.to_load = []
|
|
self.to_provide = []
|
|
self.error = ''
|
|
self.warning = ''
|
|
self.previous_action = ''
|
|
self.previous_action_long = ''
|
|
self.previous_icon = ''
|
|
self.previous_target = ''
|
|
self.previous_percent = 0
|
|
self.total_size = 0
|
|
self.already_transferred = 0
|
|
self.handle = config.handle()
|
|
self.syncdbs = self.handle.get_syncdbs()
|
|
self.localdb = self.handle.get_localdb()
|
|
self.handle.dlcb = self.cb_dl
|
|
self.handle.totaldlcb = self.totaldlcb
|
|
self.handle.eventcb = self.cb_event
|
|
self.handle.questioncb = self.cb_question
|
|
self.handle.progresscb = self.cb_progress
|
|
self.handle.logcb = self.cb_log
|
|
|
|
def update_dbs(self):
|
|
self.handle = config.handle()
|
|
self.syncdbs = self.handle.get_syncdbs()
|
|
self.localdb = self.handle.get_localdb()
|
|
self.handle.dlcb = self.cb_dl
|
|
self.handle.totaldlcb = self.totaldlcb
|
|
self.handle.eventcb = self.cb_event
|
|
self.handle.questioncb = self.cb_question
|
|
self.handle.progresscb = self.cb_progress
|
|
self.handle.logcb = self.cb_log
|
|
|
|
def get_localpkg(self, name):
|
|
return self.localdb.get_pkg(name)
|
|
|
|
def get_syncpkg(self, name):
|
|
for repo in self.syncdbs:
|
|
pkg = repo.get_pkg(name)
|
|
if pkg:
|
|
return pkg
|
|
|
|
def cb_event(self, event, tupel):
|
|
global progress_buffer
|
|
action = self.previous_action
|
|
action_long = self.previous_action_long
|
|
icon = self.previous_icon
|
|
if event == 'ALPM_EVENT_CHECKDEPS_START':
|
|
action = _('Checking dependencies')+'...'
|
|
action_long = action+'\n'
|
|
icon = '/usr/share/pamac/icons/24x24/status/package-search.png'
|
|
elif event == 'ALPM_EVENT_CHECKDEPS_DONE':
|
|
if self.warning:
|
|
self.handle_warning(self.warning)
|
|
self.warning = ''
|
|
elif event == 'ALPM_EVENT_FILECONFLICTS_START':
|
|
action = _('Checking file conflicts')+'...'
|
|
action_long = action+'\n'
|
|
icon = '/usr/share/pamac/icons/24x24/status/package-search.png'
|
|
elif event == 'ALPM_EVENT_FILECONFLICTS_DONE':
|
|
pass
|
|
elif event == 'ALPM_EVENT_RESOLVEDEPS_START':
|
|
action = _('Resolving dependencies')+'...'
|
|
action_long = action+'\n'
|
|
icon = '/usr/share/pamac/icons/24x24/status/package-setup.png'
|
|
elif event == 'ALPM_EVENT_RESOLVEDEPS_DONE':
|
|
pass
|
|
elif event == 'ALPM_EVENT_INTERCONFLICTS_START':
|
|
action = _('Checking inter conflicts')+'...'
|
|
action_long = action+'\n'
|
|
icon = '/usr/share/pamac/icons/24x24/status/package-search.png'
|
|
elif event == 'ALPM_EVENT_INTERCONFLICTS_DONE':
|
|
if self.warning:
|
|
self.handle_warning(self.warning)
|
|
self.warning = ''
|
|
elif event == 'ALPM_EVENT_ADD_START':
|
|
string = _('Installing {pkgname}').format(pkgname = tupel[0].name)
|
|
action = string+'...'
|
|
action_long = '{} ({})\n'.format(string, tupel[0].version)
|
|
icon = '/usr/share/pamac/icons/24x24/status/package-add.png'
|
|
ProgressCancelButton.set_visible(False)
|
|
elif event == 'ALPM_EVENT_ADD_DONE':
|
|
formatted_event = 'Installed {pkgname} ({pkgversion})'.format(pkgname = tupel[0].name, pkgversion = tupel[0].version)
|
|
common.write_log_file(formatted_event)
|
|
elif event == 'ALPM_EVENT_REMOVE_START':
|
|
string = _('Removing {pkgname}').format(pkgname = tupel[0].name)
|
|
action = string+'...'
|
|
action_long = '{} ({})\n'.format(string, tupel[0].version)
|
|
icon = '/usr/share/pamac/icons/24x24/status/package-delete.png'
|
|
ProgressCancelButton.set_visible(False)
|
|
elif event == 'ALPM_EVENT_REMOVE_DONE':
|
|
formatted_event = 'Removed {pkgname} ({pkgversion})'.format(pkgname = tupel[0].name, pkgversion = tupel[0].version)
|
|
common.write_log_file(formatted_event)
|
|
elif event == 'ALPM_EVENT_UPGRADE_START':
|
|
string = _('Upgrading {pkgname}').format(pkgname = tupel[1].name)
|
|
action = string+'...'
|
|
action_long = '{} ({} -> {})\n'.format(string, tupel[1].version, tupel[0].version)
|
|
icon = '/usr/share/pamac/icons/24x24/status/package-update.png'
|
|
ProgressCancelButton.set_visible(False)
|
|
elif event == 'ALPM_EVENT_UPGRADE_DONE':
|
|
formatted_event = 'Upgraded {pkgname} ({oldversion} -> {newversion})'.format(pkgname = tupel[1].name, oldversion = tupel[1].version, newversion = tupel[0].version)
|
|
common.write_log_file(formatted_event)
|
|
elif event == 'ALPM_EVENT_DOWNGRADE_START':
|
|
string = _('Downgrading {pkgname}').format(pkgname = tupel[1].name)
|
|
action = string+'...'
|
|
action_long = '{} ({} -> {})'.format(string, tupel[1].version, tupel[0].version)
|
|
icon = '/usr/share/pamac/icons/24x24/status/package-add.png'
|
|
ProgressCancelButton.set_visible(False)
|
|
elif event == 'ALPM_EVENT_DOWNGRADE_DONE':
|
|
formatted_event = 'Downgraded {pkgname} ({oldversion} -> {newversion})'.format(pkgname = tupel[1].name, oldversion = tupel[1].version, newversion = tupel[0].version)
|
|
common.write_log_file(formatted_event)
|
|
elif event == 'ALPM_EVENT_REINSTALL_START':
|
|
string = _('Reinstalling {pkgname}').format(pkgname = tupel[0].name)
|
|
action = string+'...'
|
|
action_long = '{} ({})'.format(string, tupel[0].version)
|
|
icon = '/usr/share/pamac/icons/24x24/status/package-add.png'
|
|
ProgressCancelButton.set_visible(False)
|
|
elif event == 'ALPM_EVENT_REINSTALL_DONE':
|
|
formatted_event = 'Reinstalled {pkgname} ({pkgversion})'.format(pkgname = tupel[0].name, pkgversion = tupel[0].version)
|
|
common.write_log_file(formatted_event)
|
|
elif event == 'ALPM_EVENT_INTEGRITY_START':
|
|
action = _('Checking integrity')+'...'
|
|
action_long = action+'\n'
|
|
icon = '/usr/share/pamac/icons/24x24/status/package-search.png'
|
|
self.already_transferred = 0
|
|
elif event == 'ALPM_EVENT_INTEGRITY_DONE':
|
|
pass
|
|
elif event == 'ALPM_EVENT_LOAD_START':
|
|
action = _('Loading packages files')+'...'
|
|
action_long = action+'\n'
|
|
icon = '/usr/share/pamac/icons/24x24/status/package-search.png'
|
|
elif event == 'ALPM_EVENT_LOAD_DONE':
|
|
pass
|
|
elif event == 'ALPM_EVENT_DELTA_INTEGRITY_START':
|
|
action = _('Checking delta integrity')+'...'
|
|
action_long = action+'\n'
|
|
icon = '/usr/share/pamac/icons/24x24/status/package-search.png'
|
|
elif event == 'ALPM_EVENT_DELTA_INTEGRITY_DONE':
|
|
pass
|
|
elif event == 'ALPM_EVENT_DELTA_PATCHES_START':
|
|
action = _('Applying deltas')+'...'
|
|
action_long = action+'\n'
|
|
icon = '/usr/share/pamac/icons/24x24/status/package-setup.png'
|
|
elif event == 'ALPM_EVENT_DELTA_PATCHES_DONE':
|
|
pass
|
|
elif event == 'ALPM_EVENT_DELTA_PATCH_START':
|
|
action = _('Generating {} with {}').format(tupel[0], tupel[1])+'...'
|
|
action_long = action+'\n'
|
|
icon = '/usr/share/pamac/icons/24x24/status/package-setup.png'
|
|
elif event == 'ALPM_EVENT_DELTA_PATCH_DONE':
|
|
action = _('Generation succeeded!')
|
|
action_long = action+'\n'
|
|
elif event == 'ALPM_EVENT_DELTA_PATCH_FAILED':
|
|
action = _('Generation failed.')
|
|
action_long = action+'\n'
|
|
elif event == 'ALPM_EVENT_SCRIPTLET_INFO':
|
|
action =_('Configuring {pkgname}').format(pkgname = self.previous_target)+'...'
|
|
action_long = tupel[0]
|
|
icon = '/usr/share/pamac/icons/24x24/status/package-setup.png'
|
|
progress_bar.pulse()
|
|
progress_expander.set_expanded(True)
|
|
elif event == 'ALPM_EVENT_RETRIEVE_START':
|
|
# handled by download callback
|
|
ProgressCancelButton.set_visible(True)
|
|
elif event == 'ALPM_EVENT_DISKSPACE_START':
|
|
action = _('Checking available disk space')+'...'
|
|
action_long = action+'\n'
|
|
icon = '/usr/share/pamac/icons/24x24/status/package-search.png'
|
|
elif event == 'ALPM_EVENT_OPTDEP_REQUIRED':
|
|
print('Optionnal deps exist')
|
|
elif event == 'ALPM_EVENT_DATABASE_MISSING':
|
|
#action =_('Database file for {} does not exist').format(tupel[0])+'...'
|
|
#action_long = action
|
|
pass
|
|
elif event == 'ALPM_EVENT_KEYRING_START':
|
|
action = _('Checking keyring')+'...'
|
|
action_long = action+'\n'
|
|
icon = '/usr/share/pamac/icons/24x24/status/package-search.png'
|
|
ProgressCancelButton.set_visible(True)
|
|
elif event == 'ALPM_EVENT_KEYRING_DONE':
|
|
pass
|
|
elif event == 'ALPM_EVENT_KEY_DOWNLOAD_START':
|
|
action = _('Downloading required keys')+'...'
|
|
action_long = action+'\n'
|
|
elif event == 'ALPM_EVENT_KEY_DOWNLOAD_DONE':
|
|
pass
|
|
if action != self.previous_action:
|
|
self.previous_action = action
|
|
progress_label.set_text(action)
|
|
if action_long != self.previous_action_long:
|
|
self.previous_action_long != action_long
|
|
end_iter = progress_buffer.get_end_iter()
|
|
progress_buffer.insert(end_iter, action_long)
|
|
if icon != self.previous_icon:
|
|
self.previous_icon = icon
|
|
action_icon.set_from_file(icon)
|
|
while Gtk.events_pending():
|
|
Gtk.main_iteration()
|
|
print(event)
|
|
|
|
def cb_question(self, event, data_tupel, extra_data):
|
|
print('question', event, data_tupel, extra_data)
|
|
if event == 'ALPM_QUESTION_INSTALL_IGNOREPKG':
|
|
return 0 #Do not install package in IgnorePkg/IgnoreGroup
|
|
if event == 'ALPM_QUESTION_REPLACE_PKG':
|
|
self.warning += _('{pkgname1} will be replaced by {pkgname2}').format(pkgname1 = data_tupel[0].name, pkgname2 = data_tupel[1].name)+'\n'
|
|
return 1 #Auto-remove conflicts in case of replaces
|
|
if event == 'ALPM_QUESTION_CONFLICT_PKG':
|
|
self.warning += _('{pkgname1} conflicts with {pkgname2}').format(pkgname1 = data_tupel[0], pkgname2 = data_tupel[1])+'\n'
|
|
return 1 #Auto-remove conflicts
|
|
if event == 'ALPM_QUESTION_CORRUPTED_PKG':
|
|
return 1 #Auto-remove corrupted pkgs in cache
|
|
if event == 'ALPM_QUESTION_REMOVE_PKGS':
|
|
return 1 #Do not upgrade packages which have unresolvable dependencies
|
|
if event == 'ALPM_QUESTION_SELECT_PROVIDER':
|
|
return choose_provides(data_tupel)
|
|
if event == 'ALPM_QUESTION_IMPORT_KEY':
|
|
# data_tupel = (revoked(int), length(int), pubkey_algo(string), fingerprint(string), uid(string), created_time(int))
|
|
if data_tupel[0] is 0: # not revoked
|
|
return 1 #Auto import not revoked key
|
|
if data_tupel[0] is 1: # revoked
|
|
return 0 #Do not import revoked key
|
|
|
|
def cb_log(self, level, line):
|
|
global progress_buffer
|
|
_logmask = pyalpm.LOG_ERROR | pyalpm.LOG_WARNING
|
|
if not (level & _logmask):
|
|
return
|
|
if level & pyalpm.LOG_ERROR:
|
|
#self.error += line
|
|
_error = "ERROR: "+line
|
|
end_iter = progress_buffer.get_end_iter()
|
|
progress_buffer.insert(end_iter, _error)
|
|
progress_expander.set_expanded(True)
|
|
while Gtk.events_pending():
|
|
Gtk.main_iteration()
|
|
print(line)
|
|
elif level & pyalpm.LOG_WARNING:
|
|
self.warning += line
|
|
_warning = "WARNING: "+line
|
|
end_iter = progress_buffer.get_end_iter()
|
|
progress_buffer.insert(end_iter, _warning)
|
|
while Gtk.events_pending():
|
|
Gtk.main_iteration()
|
|
elif level & pyalpm.LOG_DEBUG:
|
|
line = "DEBUG: " + line
|
|
print(line)
|
|
elif level & pyalpm.LOG_FUNCTION:
|
|
line = "FUNC: " + line
|
|
print(line)
|
|
|
|
def totaldlcb(self, _total_size):
|
|
self.total_size = _total_size
|
|
|
|
def cb_dl(self, _target, _transferred, _total):
|
|
global progress_buffer
|
|
if _target.endswith('.db'):
|
|
action = _('Refreshing {repo}').format(repo = _target.rstrip('.db'))+'...'
|
|
action_long = ''
|
|
icon = '/usr/share/pamac/icons/24x24/status/refresh-cache.png'
|
|
else:
|
|
action = _('Downloading {pkgname}').format(pkgname = _target.rstrip('.pkg.tar.xz'))+'...'
|
|
action_long = action+'\n'
|
|
icon = '/usr/share/pamac/icons/24x24/status/package-download.png'
|
|
if self.total_size > 0:
|
|
percent = round((_transferred+self.already_transferred)/self.total_size, 2)
|
|
#~ target = '{transferred}/{size}'.format(transferred = common.format_size(_transferred+self.already_transferred), size = common.format_size(self.total_size))
|
|
else:
|
|
percent = round(_transferred/_total, 2)
|
|
#~ percent = 2.0
|
|
#~ target = ''
|
|
if action != self.previous_action:
|
|
self.previous_action = action
|
|
progress_label.set_text(action)
|
|
if action_long != self.previous_action_long:
|
|
self.previous_action_long = action_long
|
|
end_iter = progress_buffer.get_end_iter()
|
|
progress_buffer.insert(end_iter, action_long)
|
|
if icon != self.previous_icon:
|
|
self.previous_icon = icon
|
|
action_icon.set_from_file(icon)
|
|
#~ if target != self.previous_target:
|
|
#~ self.previous_target = target
|
|
#~ progress_bar.set_text(target)
|
|
#~ if percent == 2.0:
|
|
#~ progress_bar.pulse()
|
|
elif percent != self.previous_percent:
|
|
self.previous_percent = percent
|
|
if 0 <= percent <= 1:
|
|
progress_bar.set_fraction(percent)
|
|
else:
|
|
progress_bar.pulse()
|
|
elif _transferred == _total:
|
|
self.already_transferred += _total
|
|
#~ if self.already_transferred == self.total_size:
|
|
#~ progress_bar.set_text('')
|
|
while Gtk.events_pending():
|
|
Gtk.main_iteration()
|
|
|
|
def cb_progress(self, event, target, _percent, n, i):
|
|
if event in ('ALPM_PROGRESS_ADD_START', 'ALPM_PROGRESS_UPGRADE_START', 'ALPM_PROGRESS_DOWNGRADE_START', 'ALPM_PROGRESS_REINSTALL_START', 'ALPM_PROGRESS_REMOVE_START'):
|
|
percent = round(((i-1)/n)+(_percent/(100*n)), 2)
|
|
else:
|
|
percent = round(_percent/100, 2)
|
|
if target != self.previous_target:
|
|
self.previous_target = target.format()
|
|
if percent != self.previous_percent:
|
|
progress_bar.set_text('{}/{}'.format(str(i), str(n)))
|
|
self.previous_percent = percent
|
|
if 0 <= percent <= 1:
|
|
progress_bar.set_fraction(percent)
|
|
else:
|
|
progress_bar.pulse()
|
|
while Gtk.events_pending():
|
|
Gtk.main_iteration()
|
|
|
|
def refresh(self, force_update):
|
|
progress_label.set_text(_('Refreshing')+'...')
|
|
action_icon.set_from_file('/usr/share/pamac/icons/24x24/status/refresh-cache.png')
|
|
progress_bar.set_text('')
|
|
progress_bar.set_fraction(0)
|
|
ProgressCloseButton.set_visible(False)
|
|
ProgressCancelButton.set_visible(True)
|
|
ProgressWindow.show()
|
|
while Gtk.events_pending():
|
|
Gtk.main_iteration()
|
|
self.error = ''
|
|
for db in self.syncdbs:
|
|
try:
|
|
self.t = self.handle.init_transaction()
|
|
db.update(force = force_update)
|
|
self.t.release()
|
|
except pyalpm.error as e:
|
|
self.release()
|
|
self.error += str(e)+'\n'
|
|
break
|
|
self.update_dbs()
|
|
ProgressWindow.hide()
|
|
if self.error:
|
|
self.handle_error(self.error)
|
|
|
|
def get_updates(self):
|
|
do_syncfirst = False
|
|
list_first = set()
|
|
_ignorepkgs = set()
|
|
if self.handle:
|
|
for group in self.handle.ignoregrps:
|
|
db = self.handle.get_localdb()
|
|
grp = db.read_grp(group)
|
|
if grp:
|
|
name, pkg_list = grp
|
|
for pkg in pkg_list:
|
|
_ignorepkgs.add(pkg.name)
|
|
for name in self.handle.ignorepkgs:
|
|
if self.get_localpkg(name):
|
|
_ignorepkgs.add(name)
|
|
if config.syncfirst:
|
|
for name in config.syncfirst:
|
|
if self.get_localpkg(name):
|
|
candidate = pyalpm.sync_newversion(self.get_localpkg(name), self.syncdbs)
|
|
if candidate:
|
|
list_first.add(candidate)
|
|
if list_first:
|
|
do_syncfirst = True
|
|
return do_syncfirst, list_first
|
|
result = set()
|
|
for pkg in self.localdb.pkgcache:
|
|
candidate = pyalpm.sync_newversion(pkg, self.syncdbs)
|
|
if candidate:
|
|
if not candidate.name in _ignorepkgs:
|
|
result.add(candidate)
|
|
return do_syncfirst, result
|
|
|
|
def init(self, **options):
|
|
self.error = ''
|
|
try:
|
|
self.t = self.handle.init_transaction(**options)
|
|
except pyalpm.error as e:
|
|
self.error += str(e)+'\n'
|
|
finally:
|
|
if self.error:
|
|
self.handle_error(self.error)
|
|
return False
|
|
else:
|
|
return True
|
|
|
|
def sysupgrade(self, force_downgrade):
|
|
try:
|
|
self.t.sysupgrade(downgrade = force_downgrade)
|
|
except pyalpm.error as e:
|
|
self.error += str(e)+'\n'
|
|
self.t.release()
|
|
finally:
|
|
if self.error:
|
|
self.handle_error(self.error)
|
|
return False
|
|
else:
|
|
return True
|
|
|
|
def remove(self, pkg):
|
|
try:
|
|
self.t.remove_pkg(pkg)
|
|
except pyalpm.error as e:
|
|
self.error += str(e)+'\n'
|
|
self.t.release()
|
|
finally:
|
|
if self.error:
|
|
self.handle_error(self.error)
|
|
return False
|
|
else:
|
|
return True
|
|
|
|
def add(self, pkg):
|
|
try:
|
|
self.t.add_pkg(pkg)
|
|
except pyalpm.error as e:
|
|
# skip duplicate target error
|
|
if not 'pm_errno 25' in str(e):
|
|
self.error += str(e)+'\n'
|
|
self.t.release()
|
|
finally:
|
|
if self.error:
|
|
self.handle_error(self.error)
|
|
return False
|
|
else:
|
|
return True
|
|
|
|
def load(self, tarball_path):
|
|
try:
|
|
pkg = self.handle.load_pkg(tarball_path)
|
|
if pkg:
|
|
self.t.add_pkg(pkg)
|
|
else:
|
|
self.error += _('{pkgname} is not a valid path or package name').format(pkgname = tarball_path)
|
|
except pyalpm.error as e:
|
|
# skip duplicate target error
|
|
if not 'pm_errno 25' in str(e):
|
|
self.error += str(e)+'\n'
|
|
self.t.release()
|
|
finally:
|
|
if self.error:
|
|
self.handle_error(self.error)
|
|
return False
|
|
else:
|
|
return True
|
|
|
|
def prepare(self):
|
|
try:
|
|
self.t.prepare()
|
|
except pyalpm.error as e:
|
|
self.error += str(e)+'\n'
|
|
self.t.release()
|
|
else:
|
|
for pkg in self.t.to_remove:
|
|
if pkg.name in config.holdpkg:
|
|
self.error += _('The transaction cannot be performed because it needs to remove {pkgname1} which is a locked package').format(pkgname1 = pkg.name)
|
|
self.t.release()
|
|
break
|
|
finally:
|
|
if self.error:
|
|
self.handle_error(self.error)
|
|
return False
|
|
else:
|
|
return True
|
|
|
|
def commit(self):
|
|
try:
|
|
self.t.commit()
|
|
except pyalpm.error as e:
|
|
self.error += str(e)+'\n'
|
|
else:
|
|
global progress_buffer
|
|
ProgressCloseButton.set_visible(True)
|
|
action_icon.set_from_icon_name('dialog-information', Gtk.IconSize.BUTTON)
|
|
progress_label.set_text(_('Transaction successfully finished'))
|
|
progress_bar.set_text('')
|
|
end_iter = progress_buffer.get_end_iter()
|
|
progress_buffer.insert(end_iter, _('Transaction successfully finished'))
|
|
finally:
|
|
self.release()
|
|
if self.warning:
|
|
self.handle_warning(self.warning)
|
|
self.warning = ''
|
|
if self.error:
|
|
self.handle_error(self.error)
|
|
|
|
def interrupt(self):
|
|
try:
|
|
self.t.interrupt()
|
|
except:
|
|
pass
|
|
try:
|
|
self.t.release()
|
|
except:
|
|
pass
|
|
# Fix me, pyalpm don't stop so we inform and force quit to really interrupt the transaction
|
|
InfoDialog.format_secondary_text(_('The transaction was interrupted.\nNow Pamac will quit.'))
|
|
response = InfoDialog.run()
|
|
if response:
|
|
InfoDialog.hide()
|
|
common.rm_pid_file()
|
|
print('interrupted')
|
|
exit(0)
|
|
|
|
def set_transaction_sum(self, show_updates):
|
|
transaction_sum.clear()
|
|
sum_top_label.set_markup(_('<big><b>Transaction Summary</b></big>'))
|
|
_to_remove = self.t.to_remove
|
|
_to_install = []
|
|
_to_reinstall = []
|
|
_to_downgrade = []
|
|
_to_update = []
|
|
dsize = 0
|
|
for pkg in self.t.to_add:
|
|
dsize += pkg.download_size
|
|
installed = self.get_localpkg(pkg.name)
|
|
if not installed:
|
|
_to_install.append(pkg)
|
|
else:
|
|
comp = pyalpm.vercmp(pkg.version, installed.version)
|
|
if comp == 0:
|
|
_to_reinstall.append(pkg)
|
|
elif comp == -1:
|
|
_to_downgrade.append(pkg)
|
|
elif comp == 1:
|
|
_to_update.append(pkg)
|
|
if dsize == 0:
|
|
sum_bottom_label.set_markup('')
|
|
else:
|
|
sum_bottom_label.set_markup(_('<b>Total download size: </b>')+common.format_size(dsize))
|
|
i = 0
|
|
while i < len(_to_remove):
|
|
pkg = _to_remove[i]
|
|
if i == 0:
|
|
transaction_sum.append([_('To remove')+':', pkg.name+' '+pkg.version])
|
|
else:
|
|
transaction_sum.append(['', pkg.name+' '+pkg.version])
|
|
i += 1
|
|
i = 0
|
|
while i < len(_to_install):
|
|
pkg = _to_install[i]
|
|
if i == 0:
|
|
transaction_sum.append([_('To install')+':', pkg.name+' '+pkg.version])
|
|
else:
|
|
transaction_sum.append(['', pkg.name+' '+pkg.version])
|
|
i += 1
|
|
i = 0
|
|
while i < len(_to_reinstall):
|
|
pkg = _to_reinstall[i]
|
|
if i == 0:
|
|
transaction_sum.append([_('To reinstall')+':', pkg.name+' '+pkg.version])
|
|
else:
|
|
transaction_sum.append(['', pkg.name+' '+pkg.version])
|
|
i += 1
|
|
i = 0
|
|
while i < len(_to_downgrade):
|
|
pkg = _to_downgrade[i]
|
|
if i == 0:
|
|
transaction_sum.append([_('To downgrade')+':', pkg.name+' '+pkg.version])
|
|
else:
|
|
transaction_sum.append(['', pkg.name+' '+pkg.version])
|
|
i += 1
|
|
if show_updates:
|
|
i = 0
|
|
while i < len(_to_update):
|
|
pkg = _to_update[i]
|
|
if i == 0:
|
|
transaction_sum.append([_('To update')+':', pkg.name+' '+pkg.version])
|
|
else:
|
|
transaction_sum.append(['', pkg.name+' '+pkg.version])
|
|
i += 1
|
|
|
|
def handle_error(self, error):
|
|
ProgressWindow.hide()
|
|
print(error)
|
|
ErrorDialog.format_secondary_text(error)
|
|
response = ErrorDialog.run()
|
|
if response:
|
|
ErrorDialog.hide()
|
|
|
|
def handle_warning(self, warning):
|
|
WarningDialog.format_secondary_text(warning)
|
|
response = WarningDialog.run()
|
|
if response:
|
|
WarningDialog.hide()
|
|
|
|
def do_sysupgrade(self, show_updates):
|
|
do_syncfirst, to_update = self.get_updates()
|
|
if to_update:
|
|
self.to_add.clear()
|
|
self.to_remove.clear()
|
|
self.error = ''
|
|
if do_syncfirst:
|
|
if self.init(recurse = True):
|
|
for pkg in to_update:
|
|
self.add(pkg)
|
|
if self.prepare():
|
|
self.set_transaction_sum(show_updates)
|
|
if show_updates:
|
|
ConfDialog.show_all()
|
|
while Gtk.events_pending():
|
|
Gtk.main_iteration()
|
|
else:
|
|
if len(transaction_sum) != 0:
|
|
ConfDialog.show_all()
|
|
while Gtk.events_pending():
|
|
Gtk.main_iteration()
|
|
else:
|
|
self.finalize()
|
|
else:
|
|
if self.init():
|
|
if self.sysupgrade(False):
|
|
if self.prepare():
|
|
self.set_transaction_sum(show_updates)
|
|
if show_updates:
|
|
ConfDialog.show_all()
|
|
while Gtk.events_pending():
|
|
Gtk.main_iteration()
|
|
else:
|
|
if len(transaction_sum) != 0:
|
|
ConfDialog.show_all()
|
|
while Gtk.events_pending():
|
|
Gtk.main_iteration()
|
|
else:
|
|
self.finalize()
|
|
|
|
def finalize(self):
|
|
global progress_buffer
|
|
progress_label.set_text(_('Preparing')+'...')
|
|
action_icon.set_from_file('/usr/share/pamac/icons/24x24/status/package-setup.png')
|
|
progress_bar.set_text('')
|
|
progress_bar.set_fraction(0)
|
|
progress_buffer.delete(progress_buffer.get_start_iter(),progress_buffer.get_end_iter())
|
|
ProgressCloseButton.set_visible(False)
|
|
ProgressWindow.show()
|
|
while Gtk.events_pending():
|
|
Gtk.main_iteration()
|
|
self.commit()
|
|
self.to_add.clear()
|
|
self.to_remove.clear()
|
|
|
|
def run(self):
|
|
if self.to_add or self.to_load:
|
|
## check for kernel extra modules ##
|
|
to_check = [pkg for pkg in self.to_add] + [pkg for pkg in self.to_load]
|
|
already_checked = set(pkg.name for pkg in to_check)
|
|
depends = [to_check]
|
|
# get installed kernels
|
|
pkgs = self.localdb.search('linux3')
|
|
installed_linux = []
|
|
for pkg in pkgs:
|
|
if len(pkg.name) == 7 or len(pkg.name) == 8:
|
|
installed_linux.append(pkg.name)
|
|
for pkg in self.to_add:
|
|
if 'linux3' in pkg.name:
|
|
if len(pkg.name) == 7 or len(pkg.name) == 8:
|
|
installed_linux.append(pkg.name)
|
|
# start loops to check pkgs
|
|
i = 0
|
|
while depends[i]:
|
|
# add a empty list for new pkgs to check next loop
|
|
depends.append([])
|
|
# start to check one pkg
|
|
for pkg in depends[i]:
|
|
# check if the current pkg is a kernel and if so, check if a module is required to install
|
|
if 'linux3' in pkg.name:
|
|
for _pkg in self.localdb.pkgcache:
|
|
for depend in _pkg.depends:
|
|
if '-modules' in depend:
|
|
for db in self.syncdbs:
|
|
for __pkg in db.pkgcache:
|
|
if not self.get_localpkg(__pkg.name):
|
|
for provide in __pkg.provides:
|
|
for linux in installed_linux:
|
|
if linux in __pkg.name:
|
|
if common.format_pkg_name(depend) == common.format_pkg_name(provide):
|
|
if not pkg_in_list(__pkg, self.to_add):
|
|
if not __pkg.name in already_checked:
|
|
depends[i+1].append(__pkg)
|
|
already_checked.add(__pkg.name)
|
|
self.to_add.append(__pkg)
|
|
# check pkg deps
|
|
for depend in pkg.depends:
|
|
# check if dep is already installed
|
|
found_depend = pyalpm.find_satisfier(self.localdb.pkgcache, depend)
|
|
if found_depend:
|
|
# check if the dep is a kernel module to provide and if so, auto-select it
|
|
if found_depend.name != common.format_pkg_name(depend):
|
|
if ('-modules' in depend) or ('linux' in depend):
|
|
for db in self.syncdbs:
|
|
for _pkg in db.pkgcache:
|
|
if not self.get_localpkg(_pkg.name):
|
|
for name in _pkg.provides:
|
|
for linux in installed_linux:
|
|
if linux in _pkg.name:
|
|
if common.format_pkg_name(depend) == common.format_pkg_name(name):
|
|
if not pkg_in_list(_pkg, self.to_add):
|
|
if not _pkg.name in already_checked:
|
|
depends[i+1].append(_pkg)
|
|
already_checked.add(_pkg.name)
|
|
self.to_add.append(_pkg)
|
|
else:
|
|
# add the dep in list to check its deps in next loop
|
|
if not found_depend.name in already_checked:
|
|
depends[i+1].append(found_depend)
|
|
already_checked.add(found_depend.name)
|
|
else:
|
|
# found the dep in uninstalled pkgs
|
|
for db in self.syncdbs:
|
|
found_depend = pyalpm.find_satisfier(db.pkgcache, depend)
|
|
if found_depend:
|
|
if found_depend.name != common.format_pkg_name(depend):
|
|
# check if the dep is a kernel module to provide and if so, auto-select it
|
|
if ('-modules' in depend) or ('linux' in depend):
|
|
for db in self.syncdbs:
|
|
for _pkg in db.pkgcache:
|
|
if not self.get_localpkg(_pkg.name):
|
|
for name in _pkg.provides:
|
|
for linux in installed_linux:
|
|
if linux in _pkg.name:
|
|
if common.format_pkg_name(depend) == common.format_pkg_name(name):
|
|
if not pkg_in_list(_pkg, self.to_add):
|
|
if not _pkg.name in already_checked:
|
|
depends[i+1].append(_pkg)
|
|
already_checked.add(_pkg.name)
|
|
self.to_add.append(_pkg)
|
|
else:
|
|
# so the dep is not yet installed, add it in list to check its deps in next loop
|
|
if not found_depend.name in already_checked:
|
|
depends[i+1].append(found_depend)
|
|
already_checked.add(found_depend.name)
|
|
break
|
|
i += 1
|
|
# end of the loop
|
|
|
|
if self.to_add or self.to_remove or self.to_load:
|
|
if self.init(cascade = True):
|
|
for pkg in self.to_add:
|
|
self.add(pkg)
|
|
for pkg in self.to_remove:
|
|
self.remove(pkg)
|
|
for path in self.to_load:
|
|
self.load(path)
|
|
if self.prepare():
|
|
self.set_transaction_sum(True)
|
|
ConfDialog.show()
|
|
while Gtk.events_pending():
|
|
Gtk.main_iteration()
|
|
else:
|
|
self.handle_warning(_('Nothing to do'))
|
|
|
|
def release(self):
|
|
try:
|
|
self.t.release()
|
|
except:
|
|
pass
|