From 7bbe3a50ba4528f740c0d00ca48bd8f17ae2bf1f Mon Sep 17 00:00:00 2001
From: guinux <nuxgui@gmail.com>
Date: Fri, 15 Nov 2013 14:37:12 +0100
Subject: [PATCH] rewrite of check updates, config parser improvements, AUR
 support improvements

---
 .gitignore           |   3 +-
 gui/dialogs.ui       |   5 +-
 gui/updater.ui       |   6 +-
 pamac-daemon.py      | 157 +++++++++++++++++-------------
 pamac-install.py     |  45 +++++----
 pamac-manager.py     |  59 ++++++++----
 pamac-refresh.py     |  17 ++--
 pamac-tray.py        |  13 ++-
 pamac-updater.py     |  48 ++++++----
 pamac/aur.py         |  47 +++++++--
 pamac/config.py      |  43 +++++----
 pamac/transaction.py | 222 +++++++++++++++++++++++++++----------------
 start-pamac-daemon   |   3 -
 13 files changed, 407 insertions(+), 261 deletions(-)
 delete mode 100755 start-pamac-daemon

diff --git a/.gitignore b/.gitignore
index ad74e522..3a95b05a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,2 @@
 __pycache__
-test*
-build
+refresh-sources.sh
diff --git a/gui/dialogs.ui b/gui/dialogs.ui
index b9be37d1..6c53771b 100644
--- a/gui/dialogs.ui
+++ b/gui/dialogs.ui
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.16.0 on Wed Oct 16 14:36:20 2013 -->
+<!-- Generated with glade 3.16.0 on Fri Nov 15 10:21:27 2013 -->
 <interface>
   <!-- interface-requires gtk+ 3.6 -->
   <object class="GtkDialog" id="ChooseDialog">
@@ -387,6 +387,7 @@
                 <property name="vexpand">True</property>
                 <property name="window_placement">bottom-left</property>
                 <property name="shadow_type">in</property>
+                <property name="min_content_width">400</property>
                 <property name="min_content_height">200</property>
                 <child>
                   <object class="GtkTextView" id="progress_textview">
@@ -409,7 +410,7 @@
             </child>
           </object>
           <packing>
-            <property name="expand">False</property>
+            <property name="expand">True</property>
             <property name="fill">True</property>
             <property name="position">2</property>
           </packing>
diff --git a/gui/updater.ui b/gui/updater.ui
index 4487344e..170f5b85 100644
--- a/gui/updater.ui
+++ b/gui/updater.ui
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.16.0 on Sun Oct 13 12:38:20 2013 -->
+<!-- Generated with glade 3.16.0 on Sat Nov  9 11:57:52 2013 -->
 <interface>
   <!-- interface-requires gtk+ 3.6 -->
   <object class="GtkListStore" id="transaction_add">
@@ -145,7 +145,9 @@
                 <property name="headers_clickable">False</property>
                 <property name="search_column">0</property>
                 <child internal-child="selection">
-                  <object class="GtkTreeSelection" id="treeview-selection1"/>
+                  <object class="GtkTreeSelection" id="treeview-selection1">
+                    <property name="mode">none</property>
+                  </object>
                 </child>
                 <child>
                   <object class="GtkTreeViewColumn" id="treeviewcolumn1">
diff --git a/pamac-daemon.py b/pamac-daemon.py
index 22aac018..363df5f7 100755
--- a/pamac-daemon.py
+++ b/pamac-daemon.py
@@ -17,14 +17,6 @@ gettext.bindtextdomain('pamac', '/usr/share/locale')
 gettext.textdomain('pamac')
 _ = gettext.gettext
 
-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 PamacDBusService(dbus.service.Object):
 	def __init__(self):
 		bus = dbus.SystemBus()
@@ -43,10 +35,16 @@ class PamacDBusService(dbus.service.Object):
 		self.total_size = 0
 		self.already_transferred = 0
 		self.handle = config.handle()
+		self.local_packages = set()
+		self.localdb = None
+		self.syncdbs = None
+		self.get_handle()
 
 	def get_handle(self):
 		print('daemon get handle')
 		self.handle = config.handle()
+		self.localdb = self.handle.get_localdb()
+		self.syncdbs = self.handle.get_syncdbs()
 		self.handle.dlcb = self.cb_dl
 		self.handle.totaldlcb = self.totaldlcb
 		self.handle.eventcb = self.cb_event
@@ -54,6 +52,24 @@ class PamacDBusService(dbus.service.Object):
 		self.handle.progresscb = self.cb_progress
 		self.handle.logcb = self.cb_log
 
+	def get_local_packages(self):
+		self.local_packages = set()
+		sync_pkg = None
+		for pkg in self.localdb.pkgcache:
+			for db in self.syncdbs:
+				sync_pkg = db.get_pkg(pkg.name)
+				if sync_pkg:
+					break
+			if not sync_pkg:
+				self.local_packages.add(pkg.name)
+
+	def check_finished_commit(self):
+		if self.task.is_alive():
+			return True
+		else:
+			self.get_handle()
+			return False
+
 	@dbus.service.signal('org.manjaro.pamac')
 	def EmitAction(self, action):
 		pass
@@ -86,8 +102,8 @@ class PamacDBusService(dbus.service.Object):
 	def EmitLogWarning(self, message):
 		pass
 
-	@dbus.service.signal('org.manjaro.pamac', signature = 'u')
-	def EmitAvailableUpdates(self, updates_nb):
+	@dbus.service.signal('org.manjaro.pamac', signature = '(ba(ssssu))')
+	def EmitAvailableUpdates(self, updates):
 		pass
 
 	@dbus.service.signal('org.manjaro.pamac')
@@ -143,7 +159,7 @@ class PamacDBusService(dbus.service.Object):
 		elif event == 'ALPM_EVENT_ADD_START':
 			string = _('Installing {pkgname}').format(pkgname = tupel[0].name)
 			action = string+'...'
-			action_long = '{} ({})\n'.format(string, tupel[0].version)
+			action_long = '{} ({})...\n'.format(string, tupel[0].version)
 			icon = '/usr/share/pamac/icons/24x24/status/package-add.png'
 		elif event == 'ALPM_EVENT_ADD_DONE':
 			formatted_event = 'Installed {pkgname} ({pkgversion})'.format(pkgname = tupel[0].name, pkgversion = tupel[0].version)
@@ -151,7 +167,7 @@ class PamacDBusService(dbus.service.Object):
 		elif event == 'ALPM_EVENT_REMOVE_START':
 			string = _('Removing {pkgname}').format(pkgname = tupel[0].name)
 			action = string+'...'
-			action_long = '{} ({})\n'.format(string, tupel[0].version)
+			action_long = '{} ({})...\n'.format(string, tupel[0].version)
 			icon = '/usr/share/pamac/icons/24x24/status/package-delete.png'
 		elif event == 'ALPM_EVENT_REMOVE_DONE':
 			formatted_event = 'Removed {pkgname} ({pkgversion})'.format(pkgname = tupel[0].name, pkgversion = tupel[0].version)
@@ -159,7 +175,7 @@ class PamacDBusService(dbus.service.Object):
 		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)
+			action_long = '{} ({} => {})...\n'.format(string, tupel[1].version, tupel[0].version)
 			icon = '/usr/share/pamac/icons/24x24/status/package-update.png'
 		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)
@@ -167,7 +183,7 @@ class PamacDBusService(dbus.service.Object):
 		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)
+			action_long = '{} ({} => {})...\n'.format(string, tupel[1].version, tupel[0].version)
 			icon = '/usr/share/pamac/icons/24x24/status/package-add.png'
 		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)
@@ -175,7 +191,7 @@ class PamacDBusService(dbus.service.Object):
 		elif event == 'ALPM_EVENT_REINSTALL_START':
 			string = _('Reinstalling {pkgname}').format(pkgname = tupel[0].name)
 			action = string+'...'
-			action_long = '{} ({})'.format(string, tupel[0].version)
+			action_long = '{} ({})...\n'.format(string, tupel[0].version)
 			icon = '/usr/share/pamac/icons/24x24/status/package-add.png'
 		elif event == 'ALPM_EVENT_REINSTALL_DONE':
 			formatted_event = 'Reinstalled {pkgname} ({pkgversion})'.format(pkgname = tupel[0].name, pkgversion = tupel[0].version)
@@ -221,7 +237,9 @@ class PamacDBusService(dbus.service.Object):
 			icon = '/usr/share/pamac/icons/24x24/status/package-setup.png'
 			self.EmitNeedDetails(True)
 		elif event == 'ALPM_EVENT_RETRIEVE_START':
-			# handled by download callback
+			action = _('Downloading')+'...'
+			action_long = action+'\n'
+			icon = '/usr/share/pamac/icons/24x24/status/package-download.png'
 			self.EmitDownloadStart('')
 		elif event == 'ALPM_EVENT_DISKSPACE_START':
 			action = _('Checking available disk space')+'...'
@@ -337,8 +355,6 @@ class PamacDBusService(dbus.service.Object):
 		if percent != self.previous_percent:
 			self.previous_percent = percent
 			self.EmitPercent(percent)
-		if _transferred == 0:
-			self.EmitDownloadStart('')
 		elif _transferred == _total:
 			self.already_transferred += _total
 
@@ -368,46 +384,56 @@ class PamacDBusService(dbus.service.Object):
 		(is_authorized,is_challenge,details) = policykit_authority.CheckAuthorization(Subject, action, {'': ''}, dbus.UInt32(1), '')
 		return is_authorized
 
-	def CheckUpdates(self):
-		updates = 0
+	@dbus.service.method('org.manjaro.pamac', 'si', 's')
+	def SetPkgReason(self, pkgname, reason):
+		error = ''
+		try:
+			pkg = self.localdb.get_pkg(pkgname)
+			if pkg:
+				self.handle.set_pkgreason(pkg, reason)
+		except Exception as e:
+			error = str(e)
+		return error
+
+	@dbus.service.method('org.manjaro.pamac', '', 's', async_callbacks=('success', 'nosuccess'))
+	def CheckUpdates(self, success, nosuccess):
+		success('')
+		syncfirst = False
+		updates = []
 		_ignorepkgs = set()
+		self.get_local_packages()
 		for group in self.handle.ignoregrps:
-			db = self.handle.get_localdb()
+			db = self.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:
-			pkg = self.handle.get_localdb().get_pkg(name)
+			pkg = self.localdb.get_pkg(name)
 			if pkg:
 				_ignorepkgs.add(pkg.name)
 		if config.syncfirst:
 			for name in config.syncfirst:
-				pkg = self.handle.get_localdb().get_pkg(name)
+				pkg = self.localdb.get_pkg(name)
 				if pkg:
-					candidate = pyalpm.sync_newversion(pkg, self.handle.get_syncdbs())
+					candidate = pyalpm.sync_newversion(pkg, self.syncdbs)
 					if candidate:
-						updates += 1
+						syncfirst = True
+						updates.append((candidate.name, candidate.version, candidate.db.name, '', candidate.download_size))
 		if not updates:
-			for pkg in self.handle.get_localdb().pkgcache:
+			for pkg in self.localdb.pkgcache:
 				if not pkg.name in _ignorepkgs:
-					candidate = pyalpm.sync_newversion(pkg, self.handle.get_syncdbs())
+					candidate = pyalpm.sync_newversion(pkg, self.syncdbs)
 					if candidate:
-						updates += 1
-					else:
-						sync_pkg = None
-						for db in self.handle.get_syncdbs():
-							sync_pkg = db.get_pkg(pkg.name)
-							if sync_pkg:
-								break
-						if not sync_pkg:
-							aur_pkg = aur.infos(pkg.name)
-							if aur_pkg:
-								comp = pyalpm.vercmp(aur_pkg.version, pkg.version)
-								if comp == 1:
-									updates += 1
-		self.EmitAvailableUpdates(updates)
+						updates.append((candidate.name, candidate.version, candidate.db.name, '', candidate.download_size))
+						self.local_packages.discard(pkg.name)
+			aur_pkgs = aur.multiinfo(self.local_packages)
+			for aur_pkg in aur_pkgs:
+				comp = pyalpm.vercmp(aur_pkg.version, self.localdb.get_pkg(aur_pkg.name).version)
+				if comp == 1:
+					updates.append((aur_pkg.name, aur_pkg.version, aur_pkg.db.name, aur_pkg.tarpath, aur_pkg.download_size))
+		self.EmitAvailableUpdates((syncfirst, updates))
 
 	@dbus.service.method('org.manjaro.pamac', 'b', 's', async_callbacks=('success', 'nosuccess'))
 	def Refresh(self, force_update, success, nosuccess):
@@ -415,8 +441,7 @@ class PamacDBusService(dbus.service.Object):
 			self.target = ''
 			self.percent = 0
 			error = ''
-			self.get_handle()
-			for db in self.handle.get_syncdbs():
+			for db in self.syncdbs:
 				try:
 					self.t = self.handle.init_transaction()
 					db.update(force = bool(force_update))
@@ -427,17 +452,16 @@ class PamacDBusService(dbus.service.Object):
 			if error:
 				self.EmitTransactionError(error)
 			else:
-				self.CheckUpdates()
 				self.EmitTransactionDone('')
 		self.task = Process(target=refresh)
 		self.task.start()
+		GObject.timeout_add(500, self.check_finished_commit)
 		success('')
 
 	@dbus.service.method('org.manjaro.pamac', 'a{sb}', 's')
 	def Init(self, options):
 		error = ''
 		try:
-			self.get_handle()
 			self.t = self.handle.init_transaction(**options)
 			print('Init:',self.t.flags)
 		except pyalpm.error as e:
@@ -460,7 +484,7 @@ class PamacDBusService(dbus.service.Object):
 	def Remove(self, pkgname):
 		error = ''
 		try:
-			pkg = self.handle.get_localdb().get_pkg(pkgname)
+			pkg = self.localdb.get_pkg(pkgname)
 			if pkg is not None:
 				self.t.remove_pkg(pkg)
 		except pyalpm.error as e:
@@ -472,7 +496,7 @@ class PamacDBusService(dbus.service.Object):
 	def Add(self, pkgname):
 		error = ''
 		try:
-			for repo in self.handle.get_syncdbs():
+			for repo in self.syncdbs:
 				pkg = repo.get_pkg(pkgname)
 				if pkg:
 					self.t.add_pkg(pkg)
@@ -495,15 +519,13 @@ class PamacDBusService(dbus.service.Object):
 			return error
 
 	def check_extra_modules(self):
-		localdb = self.handle.get_localdb()
-		syncdbs = self.handle.get_syncdbs()
 		to_add = set(pkg.name for pkg in self.t.to_add)
 		to_remove = set(pkg.name for pkg in self.t.to_remove)
 		to_check = [pkg for pkg in self.t.to_add]
 		already_checked = set(pkg.name for pkg in to_check)
 		depends = [to_check]
 		# get installed kernels and modules
-		pkgs = localdb.search('linux')
+		pkgs = self.localdb.search('linux')
 		installed_kernels = set()
 		installed_modules =  set()
 		for pkg in pkgs:
@@ -528,7 +550,7 @@ class PamacDBusService(dbus.service.Object):
 						pkgname = match.group(1)+module
 						if not pkgname in to_remove:
 							to_remove.add(pkgname)
-							_pkg = localdb.get_pkg(pkgname)
+							_pkg = self.localdb.get_pkg(pkgname)
 							if _pkg:
 								self.t.remove_pkg(_pkg)
 		# start loops to check pkgs
@@ -544,8 +566,8 @@ class PamacDBusService(dbus.service.Object):
 					if not match.group(2): # match pkg is a kernel
 						for module in installed_modules:
 							pkgname = match.group(1) + module
-							if not localdb.get_pkg(pkgname):
-								for db in syncdbs:
+							if not self.localdb.get_pkg(pkgname):
+								for db in self.syncdbs:
 									_pkg = db.get_pkg(pkgname)
 									if _pkg:
 										if not _pkg.name in already_checked:
@@ -560,8 +582,8 @@ class PamacDBusService(dbus.service.Object):
 				if match:
 					for kernel in installed_kernels:
 						pkgname = kernel + match.group(2)
-						if not localdb.get_pkg(pkgname):
-							for db in syncdbs:
+						if not self.localdb.get_pkg(pkgname):
+							for db in self.syncdbs:
 								_pkg = db.get_pkg(pkgname)
 								if _pkg:
 									if not _pkg.name in already_checked:
@@ -572,9 +594,9 @@ class PamacDBusService(dbus.service.Object):
 											self.t.add_pkg(_pkg)
 									break
 				for depend in pkg.depends:
-					found_depend = pyalpm.find_satisfier(localdb.pkgcache, depend)
+					found_depend = pyalpm.find_satisfier(self.localdb.pkgcache, depend)
 					if not found_depend:
-						for db in syncdbs:
+						for db in self.syncdbs:
 							found_depend = pyalpm.find_satisfier(db.pkgcache, depend)
 							if found_depend:
 								break
@@ -603,8 +625,11 @@ class PamacDBusService(dbus.service.Object):
 					self.t.release()
 					break
 		finally:
-			print(self.t.to_add, self.t.to_remove)
-			if len(self.t.to_add) + len(self.t.to_remove) == 0:
+			try:
+				summ = len(self.t.to_add) + len(self.t.to_remove)
+			except alpm.error:
+				return [((), '')]
+			if summ == 0:
 				self.t.release()
 				return [((), _('Nothing to do'))]
 			elif error:
@@ -616,23 +641,23 @@ class PamacDBusService(dbus.service.Object):
 
 	@dbus.service.method('org.manjaro.pamac', '', 'a(ss)')
 	def To_Remove(self):
-		liste = []
+		_list = []
 		try:
 			for pkg in self.t.to_remove:
-				liste.append((pkg.name, pkg.version))
+				_list.append((pkg.name, pkg.version))
 		except:
 			pass
-		return liste
+		return _list
 
 	@dbus.service.method('org.manjaro.pamac', '', 'a(ssi)')
 	def To_Add(self):
-		liste = []
+		_list = []
 		try:
 			for pkg in self.t.to_add:
-				liste.append((pkg.name, pkg.version, pkg.download_size))
+				_list.append((pkg.name, pkg.version, pkg.download_size))
 		except:
 			pass
-		return liste
+		return _list
 
 	@dbus.service.method('org.manjaro.pamac', '', 's', async_callbacks=('success', 'nosuccess'))
 	def Interrupt(self, success, nosuccess):
@@ -663,7 +688,6 @@ class PamacDBusService(dbus.service.Object):
 				#pass
 			finally:
 				self.t.release()
-				self.CheckUpdates()
 				if self.warning:
 					self.EmitLogWarning(self.warning)
 					self.warning = ''
@@ -680,6 +704,7 @@ class PamacDBusService(dbus.service.Object):
 			if authorized:
 				self.task = Process(target=commit)
 				self.task.start()
+				GObject.timeout_add(500, self.check_finished_commit)
 			else :
 				self.t.release()
 				self.EmitTransactionError(_('Authentication failed'))
diff --git a/pamac-install.py b/pamac-install.py
index 60983f01..236eb854 100755
--- a/pamac-install.py
+++ b/pamac-install.py
@@ -1,7 +1,7 @@
 #! /usr/bin/python3
 # -*- coding:utf-8 -*-
 
-from gi.repository import GObject, Gtk
+from gi.repository import Gtk
 from sys import argv
 import dbus
 from os.path import abspath
@@ -19,7 +19,7 @@ def exiting(msg):
 	transaction.StopDaemon()
 	print(msg)
 	print('exiting')
-	loop.quit()
+	Gtk.main_quit()
 
 def handle_error(error):
 	transaction.ProgressWindow.hide()
@@ -41,6 +41,24 @@ def handle_reply(reply):
 	end_iter = transaction.progress_buffer.get_end_iter()
 	transaction.progress_buffer.insert(end_iter, str(reply))
 
+def handle_updates(update_data):
+	syncfirst, updates = update_data
+	transaction.ProgressWindow.hide()
+	while Gtk.events_pending():
+		Gtk.main_iteration()
+	if updates:
+		transaction.ErrorDialog.format_secondary_text(_('Some updates are available.\nPlease update your system first'))
+		response = transaction.ErrorDialog.run()
+		if response:
+			transaction.ErrorDialog.hide()
+		exiting('')
+	else:
+		common.write_pid_file()
+		transaction.interface.connect_signals(signals)
+		transaction.config_dbus_signals()
+		pkgs_to_install = argv[1:]
+		install(pkgs_to_install)
+
 def on_TransValidButton_clicked(*args):
 	transaction.ConfDialog.hide()
 	while Gtk.events_pending():
@@ -88,10 +106,10 @@ def get_pkgs(pkgs):
 def install(pkgs):
 	if get_pkgs(pkgs):
 		error = transaction.run()
+		while Gtk.events_pending():
+			Gtk.main_iteration()
 		if error:
 			handle_error(error)
-		else:
-			loop.run()
 
 signals = {'on_ChooseButton_clicked' : transaction.on_ChooseButton_clicked,
 		'on_progress_textview_size_allocate' : transaction.on_progress_textview_size_allocate,
@@ -105,6 +123,7 @@ def config_dbus_signals():
 	bus = dbus.SystemBus()
 	bus.add_signal_receiver(handle_reply, dbus_interface = "org.manjaro.pamac", signal_name = "EmitTransactionDone")
 	bus.add_signal_receiver(handle_error, dbus_interface = "org.manjaro.pamac", signal_name = "EmitTransactionError")
+	bus.add_signal_receiver(handle_updates, dbus_interface = "org.manjaro.pamac", signal_name = "EmitAvailableUpdates")
 
 if common.pid_file_exists():
 	transaction.ErrorDialog.format_secondary_text(_('Pamac is already running'))
@@ -115,18 +134,6 @@ else:
 	transaction.get_handle()
 	transaction.update_dbs()
 	transaction.get_dbus_methods()
-	do_syncfirst, updates = transaction.get_updates()
-	if updates:
-		transaction.ErrorDialog.format_secondary_text(_('Some updates are available.\nPlease update your system first'))
-		response = transaction.ErrorDialog.run()
-		if response:
-			transaction.ErrorDialog.hide()
-		transaction.StopDaemon()
-	else:
-		common.write_pid_file()
-		transaction.interface.connect_signals(signals)
-		transaction.config_dbus_signals()
-		config_dbus_signals()
-		loop = GObject.MainLoop()
-		pkgs_to_install = argv[1:]
-		install(pkgs_to_install)
+	config_dbus_signals()
+	transaction.get_updates()
+	Gtk.main()
diff --git a/pamac-manager.py b/pamac-manager.py
index ed1462b8..0322d308 100755
--- a/pamac-manager.py
+++ b/pamac-manager.py
@@ -403,6 +403,7 @@ def handle_error(error):
 	transaction.Release()
 	transaction.get_handle()
 	transaction.update_dbs()
+	transaction.mark_needed_pkgs_as_dep()
 	transaction.to_add.clear()
 	transaction.to_remove.clear()
 	transaction.to_update.clear()
@@ -413,7 +414,6 @@ def handle_reply(reply):
 	if transaction.to_build:
 		transaction.build_next() 
 	elif reply:
-		transaction.Release()
 		transaction.ProgressCloseButton.set_visible(True)
 		transaction.action_icon.set_from_icon_name('dialog-information', Gtk.IconSize.BUTTON)
 		transaction.progress_label.set_text(str(reply))
@@ -421,21 +421,18 @@ def handle_reply(reply):
 		end_iter = transaction.progress_buffer.get_end_iter()
 		transaction.progress_buffer.insert(end_iter, str(reply))
 	else:
-		transaction.ProgressWindow.hide()
-		while Gtk.events_pending():
-			Gtk.main_iteration()
-		error = transaction.sysupgrade()
-		ManagerWindow.get_window().set_cursor(None)
-		if error:
-			handle_error(error)
-			return
+		#~ transaction.ProgressWindow.hide()
+		#~ while Gtk.events_pending():
+			#~ Gtk.main_iteration()
+		transaction.get_updates()
+	transaction.Release()
 	transaction.get_handle()
 	transaction.update_dbs()
+	transaction.mark_needed_pkgs_as_dep()
 	transaction.to_add.clear()
 	transaction.to_remove.clear()
 	transaction.to_update.clear()
 	transaction.to_load.clear()
-	transaction.to_build.clear()
 	global search_dict
 	global groups_dict
 	global states_dict
@@ -447,6 +444,14 @@ def handle_reply(reply):
 	if current_filter[0]:
 		refresh_packages_list(current_filter[0](current_filter[1]))
 
+def handle_updates(updates):
+	ManagerWindow.get_window().set_cursor(None)
+	transaction.ProgressWindow.hide()
+	transaction.available_updates = updates
+	error = transaction.sysupgrade()
+	if error:
+		handle_error(error)
+
 def on_ManagerWindow_delete_event(*args):
 	transaction.StopDaemon()
 	common.rm_pid_file()
@@ -464,24 +469,25 @@ def on_TransCancelButton_clicked(*args):
 	while Gtk.events_pending():
 		Gtk.main_iteration()
 	transaction.Release()
+	transaction.to_add.clear()
+	transaction.to_remove.clear()
 	transaction.to_update.clear()
-	# do it because deps are also added in to_build when check_to_build
+	transaction.to_load.clear()
 	transaction.to_build.clear()
 	if current_filter[0]:
 		refresh_packages_list(current_filter[0](current_filter[1]))
 
 def on_ProgressCloseButton_clicked(*args):
-	transaction.ProgressWindow.hide()
-	while Gtk.events_pending():
-		Gtk.main_iteration()
+	#~ transaction.ProgressWindow.hide()
+	#~ while Gtk.events_pending():
+		#~ Gtk.main_iteration()
 	transaction.progress_buffer.delete(transaction.progress_buffer.get_start_iter(),transaction.progress_buffer.get_end_iter())
+	transaction.need_details_handler(False)
 	ManagerWindow.get_window().set_cursor(Gdk.Cursor(Gdk.CursorType.WATCH))
 	while Gtk.events_pending():
 		Gtk.main_iteration()
-	error = transaction.sysupgrade()
-	ManagerWindow.get_window().set_cursor(None)
-	if error:
-		handle_error(error)
+	transaction.to_build.clear()
+	transaction.get_updates()
 
 def on_ProgressCancelButton_clicked(*args):
 	ManagerWindow.get_window().set_cursor(Gdk.Cursor(Gdk.CursorType.WATCH))
@@ -493,7 +499,10 @@ def on_ProgressCancelButton_clicked(*args):
 		if transaction.build_proc.poll() is None:
 			transaction.build_proc.kill()
 			transaction.build_proc.wait()
-	# do it because deps are also added in to_build when check_to_build
+	transaction.to_add.clear()
+	transaction.to_remove.clear()
+	transaction.to_update.clear()
+	transaction.to_load.clear()
 	transaction.to_build.clear()
 	transaction.Interrupt()
 	ManagerWindow.get_window().set_cursor(None)
@@ -513,7 +522,10 @@ def on_search_entry_activate(widget):
 	refresh_packages_list(search_pkgs((search_entry.get_text(), search_aur_button.get_active())))
 
 def mark_to_install(widget, pkg):
-	transaction.to_add.add(pkg.name)
+	if pkg.db.name == 'AUR':
+		transaction.to_build.append(pkg)
+	else:
+		transaction.to_add.add(pkg.name)
 
 def mark_to_reinstall(widget, pkg):
 	transaction.to_add.add(pkg.name)
@@ -524,6 +536,8 @@ def mark_to_remove(widget, pkg):
 def mark_to_deselect(widget, pkg):
 	transaction.to_remove.discard(pkg.name)
 	transaction.to_add.discard(pkg.name)
+	if pkg in transaction.to_build:
+		transaction.to_build.remove(pkg)
 
 def select_optdeps(widget, pkg, optdeps):
 	transaction.choose_label.set_markup('<b>{}</b>'.format(_('{pkgname} has {number} uninstalled optional deps.\nPlease choose those you would like to install:').format(pkgname = pkg.name, number = str(len(optdeps)))))
@@ -548,7 +562,7 @@ def on_list_treeview_button_press_event(treeview, event):
 		if treeiter:
 			if liststore[treeiter][0] != _('No package found') and not liststore[treeiter][0].name in config.holdpkg:
 				right_click_menu = Gtk.Menu()
-				if liststore[treeiter][0].name in transaction.to_add | transaction.to_remove:
+				if liststore[treeiter][0].name in transaction.to_add or transaction.to_remove or transaction.to_build:
 					item = Gtk.ImageMenuItem(_('Deselect'))
 					item.set_image(Gtk.Image.new_from_stock('gtk-undo', Gtk.IconSize.MENU))
 					item.set_always_show_image(True)
@@ -726,6 +740,8 @@ def on_manager_valid_button_clicked(*args):
 def on_manager_cancel_button_clicked(*args):
 	transaction.to_add.clear()
 	transaction.to_remove.clear()
+	transaction.to_update.clear()
+	transaction.to_load.clear()
 	transaction.to_build.clear()
 	if current_filter[0]:
 		refresh_packages_list(current_filter[0](current_filter[1]))
@@ -856,6 +872,7 @@ def config_dbus_signals():
 	bus = dbus.SystemBus()
 	bus.add_signal_receiver(handle_reply, dbus_interface = "org.manjaro.pamac", signal_name = "EmitTransactionDone")
 	bus.add_signal_receiver(handle_error, dbus_interface = "org.manjaro.pamac", signal_name = "EmitTransactionError")
+	bus.add_signal_receiver(handle_updates, dbus_interface = "org.manjaro.pamac", signal_name = "EmitAvailableUpdates")
 
 if common.pid_file_exists():
 	transaction.ErrorDialog.format_secondary_text(_('Pamac is already running'))
diff --git a/pamac-refresh.py b/pamac-refresh.py
index c6a2703a..d1759c02 100755
--- a/pamac-refresh.py
+++ b/pamac-refresh.py
@@ -5,23 +5,28 @@ from gi.repository import GObject
 from pamac import common, transaction
 import dbus
 
-def reply(reply):
-	transaction.StopDaemon()
+
+def handle_reply(reply):
 	print('check updates done')
-	loop.quit()
+	transaction.CheckUpdates()
 
-def error(error):
+def handle_error(error):
 	transaction.StopDaemon()
 	print('check updates failed')
 	loop.quit()
 
+def handle_updates(updates):
+	transaction.StopDaemon()
+	loop.quit()
+
 loop = GObject.MainLoop()
 
 if not common.pid_file_exists():
 	print('checking updates')
 	bus = dbus.SystemBus()
-	bus.add_signal_receiver(reply, dbus_interface = "org.manjaro.pamac", signal_name = "EmitTransactionDone")
-	bus.add_signal_receiver(error, dbus_interface = "org.manjaro.pamac", signal_name = "EmitTransactionError")
+	bus.add_signal_receiver(handle_reply, dbus_interface = "org.manjaro.pamac", signal_name = "EmitTransactionDone")
+	bus.add_signal_receiver(handle_error, dbus_interface = "org.manjaro.pamac", signal_name = "EmitTransactionError")
+	bus.add_signal_receiver(handle_updates, dbus_interface = "org.manjaro.pamac", signal_name = "EmitAvailableUpdates")
 	transaction.get_dbus_methods()
 	try:
 		transaction.Refresh(False)
diff --git a/pamac-tray.py b/pamac-tray.py
index d3bfca6c..45a7f508 100644
--- a/pamac-tray.py
+++ b/pamac-tray.py
@@ -4,8 +4,9 @@
 from gi.repository import Gtk, GObject, Notify
 from subprocess import Popen
 import dbus
-from pamac import common, transaction
-from time import sleep
+from dbus.mainloop.glib import DBusGMainLoop
+
+from pamac import common
 
 # i18n
 import gettext
@@ -74,15 +75,16 @@ class Tray:
 def refresh():
 	Popen(['/usr/bin/pamac-refresh'])
 
-def set_icon(updates):
+def set_icon(update_data):
 	global icon
 	global info
+	syncfirst, updates = update_data
 	if updates:
 		icon = update_icon
-		if int(updates) == 1:
+		if len(updates) == 1:
 			info = one_update_info
 		else:
-			info = update_info.format(number = updates)
+			info = update_info.format(number = len(updates))
 		if not common.pid_file_exists():
 			Notify.Notification.new(_('Update Manager'), info, '/usr/share/pamac/icons/32x32/apps/pamac-updater.png').show()
 	else:
@@ -91,6 +93,7 @@ def set_icon(updates):
 	print(info)
 	tray.update_icon(icon, info)
 
+DBusGMainLoop(set_as_default = True)
 bus = dbus.SystemBus()
 bus.add_signal_receiver(set_icon, dbus_interface = "org.manjaro.pamac", signal_name = "EmitAvailableUpdates")
 tray = Tray()
diff --git a/pamac-updater.py b/pamac-updater.py
index 41d66058..05598072 100644
--- a/pamac-updater.py
+++ b/pamac-updater.py
@@ -34,9 +34,9 @@ def have_updates():
 	UpdaterWindow.get_window().set_cursor(Gdk.Cursor(Gdk.CursorType.WATCH))
 	while Gtk.events_pending():
 		Gtk.main_iteration()
-	do_syncfirst, updates = transaction.get_updates()
 	update_listore.clear()
 	update_top_label.set_justify(Gtk.Justification.CENTER)
+	updates = transaction.available_updates[1]
 	if not updates:
 		update_bottom_label.set_markup('')
 		update_top_label.set_markup('<big><b>{}</b></big>'.format(_('Your system is up-to-date')))
@@ -44,14 +44,13 @@ def have_updates():
 	else:
 		UpdaterApplyButton.set_sensitive(True)
 		dsize = 0
-		for pkg in updates:
-			pkgname = pkg.name+' '+pkg.version
-			if pkg.size:
-				size_str = common.format_size(pkg.size)
+		for name, version, db, tarpath, size in updates:
+			dsize += size
+			if size:
+				size_str = common.format_size(size)
 			else:
 				size_str = ''
-			update_listore.append([pkgname, size_str])
-			dsize += pkg.download_size
+			update_listore.append([name+' '+version, size_str])
 		if dsize == 0:
 			update_bottom_label.set_markup('')
 		else:
@@ -78,6 +77,8 @@ def handle_error(error):
 	transaction.update_dbs()
 
 def handle_reply(reply):
+	while Gtk.events_pending():
+		Gtk.main_iteration()
 	if transaction.to_build:
 		transaction.build_next() 
 	elif reply:
@@ -91,13 +92,18 @@ def handle_reply(reply):
 		transaction.get_handle()
 		transaction.update_dbs()
 	else:
-		transaction.ProgressWindow.hide()
-		while Gtk.events_pending():
-			Gtk.main_iteration()
+		#~ transaction.ProgressWindow.hide()
+		#~ while Gtk.events_pending():
+			#~ Gtk.main_iteration()
 		UpdaterWindow.get_window().set_cursor(None)
 		transaction.get_handle()
 		transaction.update_dbs()
-		have_updates()
+		transaction.get_updates()
+
+def handle_updates(updates):
+	transaction.ProgressWindow.hide()
+	transaction.available_updates = updates
+	have_updates()
 
 def on_UpdaterWindow_delete_event(*args):
 	transaction.StopDaemon()
@@ -118,20 +124,23 @@ def on_TransCancelButton_clicked(*args):
 	while Gtk.events_pending():
 		Gtk.main_iteration()
 	transaction.Release()
+	transaction.to_add.clear()
+	transaction.to_add_as_dep.clear()
 	transaction.to_update.clear()
-	# do it because deps are also added in to_build when check_to_build
 	transaction.to_build.clear()
 
 def on_ProgressCloseButton_clicked(*args):
 	UpdaterWindow.get_window().set_cursor(None)
-	transaction.ProgressWindow.hide()
-	while Gtk.events_pending():
-		Gtk.main_iteration()
+	#~ transaction.ProgressWindow.hide()
+	#~ while Gtk.events_pending():
+		#~ Gtk.main_iteration()
 	transaction.progress_buffer.delete(transaction.progress_buffer.get_start_iter(),transaction.progress_buffer.get_end_iter())
-	have_updates()
+	transaction.need_details_handler(False)
+	transaction.get_updates()
 
 def on_ProgressCancelButton_clicked(*args):
-	# do it because deps are also added in to_build when check_to_build
+	transaction.to_add.clear()
+	transaction.to_update.clear()
 	transaction.to_build.clear()
 	transaction.Interrupt()
 	UpdaterWindow.get_window().set_cursor(None)
@@ -140,16 +149,12 @@ def on_ProgressCancelButton_clicked(*args):
 		Gtk.main_iteration()
 
 def on_Updater_ApplyButton_clicked(*args):
-	while Gtk.events_pending():
-		Gtk.main_iteration()
 	UpdaterWindow.get_window().set_cursor(Gdk.Cursor(Gdk.CursorType.WATCH))
 	while Gtk.events_pending():
 		Gtk.main_iteration()
 	transaction.sysupgrade(show_updates = False)
 
 def on_Updater_RefreshButton_clicked(*args):
-	while Gtk.events_pending():
-		Gtk.main_iteration()
 	UpdaterWindow.get_window().set_cursor(Gdk.Cursor(Gdk.CursorType.WATCH))
 	while Gtk.events_pending():
 		Gtk.main_iteration()
@@ -176,6 +181,7 @@ def config_dbus_signals():
 	bus = dbus.SystemBus()
 	bus.add_signal_receiver(handle_reply, dbus_interface = "org.manjaro.pamac", signal_name = "EmitTransactionDone")
 	bus.add_signal_receiver(handle_error, dbus_interface = "org.manjaro.pamac", signal_name = "EmitTransactionError")
+	bus.add_signal_receiver(handle_updates, dbus_interface = "org.manjaro.pamac", signal_name = "EmitAvailableUpdates")
 
 if common.pid_file_exists():
 	transaction.ErrorDialog.format_secondary_text(_('Pamac is already running'))
diff --git a/pamac/aur.py b/pamac/aur.py
index 0b19f801..c16c925f 100644
--- a/pamac/aur.py
+++ b/pamac/aur.py
@@ -56,10 +56,10 @@ class AURPkg():
 			self.depends = pkginfo['orig_depends']
 		else:
 			self.depends = []
-		#~ if 'orig_optdepends' in keys:
-			#~ self.optdepends = pkginfo['orig_optdepends']
-		#~ else:
-			#~ self.optdepends = []
+		if 'orig_optdepends' in keys:
+			self.optdepends = pkginfo['orig_optdepends']
+		else:
+			self.optdepends = []
 		#~ if 'orig_provides' in keys:
 			#~ self.provides = pkginfo['orig_provides']
 		#~ else:
@@ -84,6 +84,12 @@ class AURPkg():
 	def __repr__(self):
 		return '{}-{}'.format(self.name, self.version)
 
+	def __eq__(self, other):
+		if hasattr(other, 'name') and hasattr(other, 'version'):
+			if self.name == other.name and self.version == other.version:
+				return True
+		return False
+
 class FakeDB():
 	def __init__(self):
 		self.name = 'AUR'
@@ -110,12 +116,14 @@ def search(args):
 		return []
 	else:
 		results_dict = r.json()
+		results = results_dict['results']
 		pkgs = []
-		for result in results_dict['results']:
-			pkgs.append(AURPkg(result))
+		if results:
+			for result in results:
+				pkgs.append(AURPkg(result))
 		return pkgs
 
-def infos(pkgname):
+def info(pkgname):
 	spec = {'type':'info', 'arg':pkgname}
 	try:
 		r = requests.get(rpc_url, params = spec)
@@ -133,6 +141,25 @@ def infos(pkgname):
 			print('failed to get infos about {} from AUR'.format(pkgname))
 			return None
 
+def multiinfo(pkgnames):
+	spec = {'type':'multiinfo', 'arg[]':pkgnames}
+	try:
+		r = requests.get(rpc_url, params = spec)
+		r.raise_for_status()
+	except Exception as e:
+		print(e)
+		return []
+	else:
+		results_dict = r.json()
+		results = results_dict['results']
+		pkgs = []
+		if results:
+			for result in results:
+				pkgs.append(AURPkg(result))
+		else:
+			print('failed to get infos about {} from AUR'.format(pkgnames))
+		return pkgs
+
 def get_extract_tarball(pkg):
 	try:
 		r = requests.get(aur_url + pkg.tarpath)
@@ -143,16 +170,16 @@ def get_extract_tarball(pkg):
 	else:
 		if not os.path.exists(srcpkgdir):
 			os.makedirs(srcpkgdir)
-		tarpath = os.path.join(srcpkgdir, os.path.basename(pkg.tarpath))
+		full_tarpath = os.path.join(srcpkgdir, os.path.basename(pkg.tarpath))
 		try:
-			with open(tarpath, 'wb') as f:
+			with open(full_tarpath, 'wb') as f:
 				f.write(r.content)
 		except Exception as e:
 			print(e)
 			return None
 		else:
 			try:
-				tar = tarfile.open(tarpath)
+				tar = tarfile.open(full_tarpath)
 				tar.extractall(path = srcpkgdir)
 			except Exception as e:
 				print(e)
diff --git a/pamac/config.py b/pamac/config.py
index 5a842d68..2953462d 100644
--- a/pamac/config.py
+++ b/pamac/config.py
@@ -1,10 +1,10 @@
 #! /usr/bin/python3
 # -*- coding:utf-8 -*-
 
-import io
+#import io
 import os
 import glob
-import sys
+#import sys
 import argparse
 import collections
 import warnings
@@ -69,13 +69,14 @@ def pacman_conf_enumerator(path):
 			continue
 
 		line = line.strip()
-		if len(line) == 0: continue
+		if len(line) == 0:
+			continue
 		if line[0] == '#':
 			continue
 		if line[0] == '[' and line[-1] == ']':
 			current_section = line[1:-1]
 			continue
-		if current_section is None:
+		if not current_section:
 			raise InvalidSyntax(f.name, 'statement outside of a section', line)
 		# read key, value
 		key, equal, value = [x.strip() for x in line.partition('=')]
@@ -103,11 +104,11 @@ def pacman_conf_enumerator(path):
 				warnings.warn(InvalidSyntax(f.name, 'unrecognized option', key))
 		else:
 			if key in BOOLEAN_OPTIONS:
-				yield (current_section, key, True)
+				yield (current_section, key, 1)
 			else:
 				warnings.warn(InvalidSyntax(f.name, 'unrecognized option', key))
 
-class PacmanConfig(object):
+class PacmanConfig:
 	def __init__(self, conf = None, options = None):
 		self.options = {}
 		self.repos = collections.OrderedDict()
@@ -116,9 +117,9 @@ class PacmanConfig(object):
 		self.options["GPGDir"]  = "/etc/pacman.d/gnupg/"
 		self.options["LogFile"] = "/var/log/pacman.log"
 		self.options["Architecture"] = os.uname()[-1]
-		if conf is not None:
+		if conf:
 			self.load_from_file(conf)
-		if options is not None:
+		if options:
 			self.load_from_options(options)
 
 	def load_from_file(self, filename):
@@ -134,27 +135,28 @@ class PacmanConfig(object):
 				servers = self.repos.setdefault(section, [])
 				if key == 'Server':
 					servers.append(value)
-		if "CacheDir" not in self.options:
+		if not "CacheDir" in self.options:
 			self.options["CacheDir"]= ["/var/cache/pacman/pkg"]
 
 	def load_from_options(self, options):
 		global _logmask
-		if options.root is not None:
+		if options.root:
 			self.options["RootDir"] = options.root
-		if options.dbpath is not None:
+		if options.dbpath:
 			self.options["DBPath"] = options.dbpath
-		if options.gpgdir is not None:
+		if options.gpgdir:
 			self.options["GPGDir"] = options.gpgdir
-		if options.arch is not None:
+		if options.arch:
 			self.options["Architecture"] = options.arch
-		if options.logfile is not None:
+		if options.logfile:
 			self.options["LogFile"] = options.logfile
-		if options.cachedir is not None:
+		if options.cachedir:
 			self.options["CacheDir"] = [option.cachedir]
 		if options.debug:
 			_logmask = 0xffff
 
-	def apply(self, h):
+	def initialize_alpm(self):
+		h = pyalpm.Handle(self.options["RootDir"], self.options["DBPath"])
 		h.arch = self.options["Architecture"]
 		h.logfile = self.options["LogFile"]
 		h.gpgdir = self.options["GPGDir"]
@@ -167,7 +169,10 @@ class PacmanConfig(object):
 			h.noextracts = self.options["NoExtract"]
 		if "NoUpgrade" in self.options:
 			h.noupgrades = self.options["NoUpgrade"]
-
+		if "UseSyslog" in self.options:
+			h.usesyslog = self.options["UseSyslog"]
+		if "CheckSpace" in self.options:
+			h.checkspace = self.options["CheckSpace"]
 		# set sync databases
 		for repo, servers in self.repos.items():
 			db = h.register_syncdb(repo, 0)
@@ -177,10 +182,6 @@ class PacmanConfig(object):
 				url = url.replace("$arch", self.options["Architecture"])
 				db_servers.append(url)
 			db.servers = db_servers
-
-	def initialize_alpm(self):
-		h = pyalpm.Handle(self.options["RootDir"], self.options["DBPath"])
-		self.apply(h)
 		return h
 
 	def __str__(self):
diff --git a/pamac/transaction.py b/pamac/transaction.py
index 567a5576..66f5fba7 100644
--- a/pamac/transaction.py
+++ b/pamac/transaction.py
@@ -16,8 +16,10 @@ from pamac import config, common, aur
 
 to_remove = set()
 to_add = set()
+to_add_as_dep = set()
 to_update = set()
 to_load = set()
+available_updates = (False, [])
 to_build = []
 cancel_download = False
 build_proc = None
@@ -72,6 +74,7 @@ bus = dbus.SystemBus()
 def get_dbus_methods():
 	proxy = bus.get_object('org.manjaro.pamac','/org/manjaro/pamac', introspect = False)
 	global Refresh
+	global CheckUpdates
 	global Init
 	global Sysupgrade
 	global Remove
@@ -84,7 +87,10 @@ def get_dbus_methods():
 	global Interrupt
 	global Release
 	global StopDaemon
+	global SetPkgReason
+	SetPkgReason = proxy.get_dbus_method('SetPkgReason','org.manjaro.pamac')
 	Refresh = proxy.get_dbus_method('Refresh','org.manjaro.pamac')
+	CheckUpdates = proxy.get_dbus_method('CheckUpdates','org.manjaro.pamac')
 	Init = proxy.get_dbus_method('Init','org.manjaro.pamac')
 	Sysupgrade = proxy.get_dbus_method('Sysupgrade','org.manjaro.pamac')
 	Remove = proxy.get_dbus_method('Remove','org.manjaro.pamac')
@@ -113,7 +119,7 @@ def config_dbus_signals():
 def write_to_buffer(fd, condition):
 	if condition == GObject.IO_IN: # if there's something interesting to read
 		line = fd.readline().decode(encoding='UTF-8')
-		print(line.rstrip('\n'))
+		#print(line.rstrip('\n'))
 		progress_buffer.insert_at_cursor(line)
 		progress_bar.pulse()
 		return True # FUNDAMENTAL, otherwise the callback isn't recalled
@@ -221,12 +227,16 @@ def get_syncpkg(name):
 			return pkg
 
 def refresh(force_update = False):
+	while Gtk.events_pending():
+		Gtk.main_iteration()
 	action_handler(_('Refreshing')+'...')
 	icon_handler('/usr/share/pamac/icons/24x24/status/refresh-cache.png')
 	target_handler('')
 	percent_handler(0)
 	ProgressCancelButton.set_visible(True)
 	ProgressCloseButton.set_visible(False)
+	progress_expander.set_visible(True)
+	ProgressWindow.show()
 	while Gtk.events_pending():
 		Gtk.main_iteration()
 	Refresh(force_update)
@@ -236,7 +246,7 @@ def init_transaction(**options):
 
 def check_to_build():
 	global to_build
-	global to_add
+	global to_add_as_dep
 	global make_depends
 	global build_depends
 	already_checked = set()
@@ -244,6 +254,8 @@ def check_to_build():
 	i = 0
 	error = ''
 	while i < len(to_build):
+		while Gtk.events_pending():
+			Gtk.main_iteration()
 		pkg = to_build[i]
 		# if current pkg is not in build_order add it at the end of the list
 		if not pkg.name in build_order:
@@ -254,43 +266,82 @@ def check_to_build():
 			# get PKGBUILD and parse it to create a new pkg object with makedeps and deps 
 			new_pkgs = aur.get_pkgs(srcdir + '/PKGBUILD')
 			for new_pkg in new_pkgs:
+				while Gtk.events_pending():
+					Gtk.main_iteration()
 				print('checking', new_pkg.name)
 				# check if some makedeps must be installed
 				for makedepend in new_pkg.makedepends:
+					while Gtk.events_pending():
+						Gtk.main_iteration()
 					if not makedepend in already_checked:
 						if not pyalpm.find_satisfier(localdb.pkgcache, makedepend):
 							print('found make dep:',makedepend)
 							for db in syncdbs:
-									provider = pyalpm.find_satisfier(db.pkgcache, makedepend)
-									if provider:
-										break
+								provider = pyalpm.find_satisfier(db.pkgcache, makedepend)
+								if provider:
+									break
 							if provider:
 								make_depends.add(provider.name)
 								already_checked.add(makedepend)
+							else:
+								# current makedep need to be built
+								raw_makedepend = common.format_pkg_name(makedepend)
+								if raw_makedepend in build_order:
+									# add it in build_order before pkg
+									build_order.remove(raw_makedepend)
+									index = build_order.index(pkg.name)
+									build_order.insert(index, raw_makedepend)
+								else:
+									# get infos about it
+									makedep_pkg = aur.info(raw_makedepend)
+									if makedep_pkg:
+										# add it in to_build so it will be checked 
+										to_build.append(makedep_pkg)
+										# add it in build_order before pkg
+										index = build_order.index(pkg.name)
+										build_order.insert(index, raw_makedepend)
+										# add it in already_checked and to_add_as_as_dep 
+										already_checked.add(raw_makedepend)
+										to_add_as_dep.add(raw_makedepend)
+									else:
+										if error:
+											error += '\n'
+										error += _('{pkgname} depends on {dependname} but it is not installable').format(pkgname = pkg.name, dependname = makedepend)
 				# check if some deps must be installed or built
 				for depend in new_pkg.depends:
+					while Gtk.events_pending():
+						Gtk.main_iteration()
 					if not depend in already_checked:
 						if not pyalpm.find_satisfier(localdb.pkgcache, depend):
 							print('found dep:',depend)
 							for db in syncdbs:
-									provider = pyalpm.find_satisfier(db.pkgcache, depend)
-									if provider:
-										break
+								provider = pyalpm.find_satisfier(db.pkgcache, depend)
+								if provider:
+									break
 							if provider:
 								# current dep need to be installed
 								build_depends.add(provider.name)
 								already_checked.add(depend)
 							else:
 								# current dep need to be built
-								if not depend in build_order:
+								raw_depend = common.format_pkg_name(depend)
+								if raw_depend in build_order:
+									# add it in build_order before pkg
+									build_order.remove(raw_depend)
+									index = build_order.index(pkg.name)
+									build_order.insert(index, raw_depend)
+								else:
 									# get infos about it
-									dep_pkg = aur.infos(depend)
+									dep_pkg = aur.info(raw_depend)
 									if dep_pkg:
 										# add it in to_build so it will be checked 
 										to_build.append(dep_pkg)
 										# add it in build_order before pkg
 										index = build_order.index(pkg.name)
-										build_order.insert(index, dep_pkg.name)
+										build_order.insert(index, raw_depend)
+										# add it in already_checked and to_add_as_as_dep 
+										already_checked.add(raw_depend)
+										to_add_as_dep.add(raw_depend)
 									else:
 										if error:
 											error += '\n'
@@ -302,11 +353,11 @@ def check_to_build():
 		i += 1
 	if error:
 		return error
-	# add pkgname in make_depends and build_depends in to_add
+	# add pkgname in make_depends and build_depends in to_add_as_dep
 	for name in make_depends:
-		to_add.add(name)
+		to_add_as_dep.add(name)
 	for name in build_depends:
-		to_add.add(name)
+		to_add_as_dep.add(name)
 	# reorder to_build following build_order
 	to_build.sort(key = lambda pkg: build_order.index(pkg.name))
 	print('order:', build_order)
@@ -317,16 +368,30 @@ def check_to_build():
 
 def run():
 	if to_add or to_remove or to_load or to_build:
+		global progress_buffer
+		action_handler(_('Preparing')+'...')
+		icon_handler('/usr/share/pamac/icons/24x24/status/package-setup.png')
+		target_handler('')
+		percent_handler(0)
+		progress_buffer.delete(progress_buffer.get_start_iter(), progress_buffer.get_end_iter())
+		ProgressCancelButton.set_visible(False)
+		ProgressCloseButton.set_visible(False)
+		progress_expander.set_visible(False)
+		ProgressWindow.show()
 		error = ''
+		while Gtk.events_pending():
+			Gtk.main_iteration()
 		if to_build:
 			# check if packages in to_build have deps or makedeps which need to be install first 
 			error += check_to_build()
+		while Gtk.events_pending():
+			Gtk.main_iteration()
 		if not error:
-			if to_add or to_remove or to_load:
+			if to_add or to_remove or to_load or to_add_as_dep:
 				trans_flags = {'cascade' : True}
 				error += init_transaction(**trans_flags)
 				if not error:
-					for name in to_add:
+					for name in to_add | to_add_as_dep:
 						error += Add(name)
 					for name in to_remove:
 						error += Remove(name)
@@ -336,10 +401,12 @@ def run():
 						error += prepare(**trans_flags)
 			if not error:
 				set_transaction_sum()
+				ProgressWindow.hide()
 				ConfDialog.show_all()
 				while Gtk.events_pending():
 					Gtk.main_iteration()
 		if error:
+			ProgressWindow.hide()
 			Release()
 			return(error)
 	else:
@@ -355,7 +422,7 @@ def prepare(**trans_flags):
 			choose_provides(item)
 		error += init_transaction(**trans_flags)
 		if not error:
-			for name in to_add:
+			for name in to_add | to_add_as_dep:
 				error += Add(name)
 			for name in to_remove:
 				error += Remove(name)
@@ -385,16 +452,14 @@ def check_finished_build(data):
 		for new_pkg in new_pkgs:
 			for item in os.listdir(path):
 				if os.path.isfile(os.path.join(path, item)):
-					if fnmatch.fnmatch(item, '{}-{}-*.pkg.tar*'.format(new_pkg.name, new_pkg.version)):
+					if fnmatch.fnmatch(item, '{}-{}-*.pkg.tar.?z'.format(new_pkg.name, new_pkg.version)):
 						built.append(os.path.join(path, item))
 						break
 		if built:
 			print('successfully built:', built)
 			build_proc = None
-			to_build_pkgs = to_build.copy()
-			for to_build_pkg in to_build_pkgs:
-				if pkg.name == to_build_pkg.name:
-					to_build.remove(pkg)
+			if pkg in to_build:
+				to_build.remove(pkg)
 			# install built packages
 			error = ''
 			error += init_transaction()
@@ -498,19 +563,21 @@ def build_next():
 	new_pkgs = aur.get_pkgs(path + '/PKGBUILD')
 	# sources are identicals for splitted packages
 	# (not complete) download(new_pkgs[0].source, path)
-	icon_handler('/usr/share/pamac/icons/24x24/status/package-setup.png')
-	target_handler('')
 	action = _('Building {pkgname}').format(pkgname = pkg.name)+'...'
 	action_handler(action)
 	action_long_handler(action+'\n')
+	icon_handler('/usr/share/pamac/icons/24x24/status/package-setup.png')
+	target_handler('')
+	percent_handler(0)
 	ProgressCancelButton.set_visible(True)
 	ProgressCloseButton.set_visible(False)
+	progress_expander.set_visible(True)
 	progress_expander.set_expanded(True)
 	ProgressWindow.show()
+	build_proc = subprocess.Popen(["makepkg", "-c"], cwd = path, stdout = subprocess.PIPE, stderr=subprocess.STDOUT)
+	GObject.io_add_watch(build_proc.stdout, GObject.IO_IN, write_to_buffer)
 	while Gtk.events_pending():
 		Gtk.main_iteration()
-	build_proc = subprocess.Popen(["makepkg", "-cf"], cwd = path, stdout = subprocess.PIPE, stderr=subprocess.STDOUT)
-	GObject.io_add_watch(build_proc.stdout, GObject.IO_IN, write_to_buffer)
 	GObject.timeout_add(500, check_finished_build, (path, pkg))
 
 def finalize():
@@ -523,57 +590,40 @@ def finalize():
 		progress_buffer.delete(progress_buffer.get_start_iter(), progress_buffer.get_end_iter())
 		ProgressCancelButton.set_visible(True)
 		ProgressCloseButton.set_visible(False)
+		progress_expander.set_visible(True)
 		try:
 			Commit()
 		except dbus.exceptions.DBusException as e:
 			Release()
-		while Gtk.events_pending():
-			Gtk.main_iteration()
 	elif to_build:
 		# packages in to_build have no deps or makedeps 
 		# so we build and install the first one
 		# the next ones will be built by the caller
 		build_next()
 
+def mark_needed_pkgs_as_dep():
+	global to_add_as_dep
+	for name in to_add_as_dep.copy():
+		error = SetPkgReason(name, pyalpm.PKG_REASON_DEPEND)
+		if error:
+			print(error)
+		else:
+			to_add_as_dep.discard(name)
+
 def get_updates():
-	do_syncfirst = False
-	list_first = []
-	_ignorepkgs = set()
-	if handle:
-		for group in handle.ignoregrps:
-			db = localdb
-			grp = db.read_grp(group)
-			if grp:
-				name, pkg_list = grp
-				for pkg in pkg_list:
-					_ignorepkgs.add(pkg.name)
-		for name in handle.ignorepkgs:
-			if get_localpkg(name):
-				_ignorepkgs.add(name)
-	if config.syncfirst:
-		for name in config.syncfirst:
-			pkg = get_localpkg(name)
-			if pkg:
-				candidate = pyalpm.sync_newversion(pkg, syncdbs)
-				if candidate:
-					list_first.append(candidate)
-		if list_first:
-			do_syncfirst = True
-			return do_syncfirst, list_first
-	result = []
-	for pkg in localdb.pkgcache:
-		if not pkg.name in _ignorepkgs:
-			candidate = pyalpm.sync_newversion(pkg, syncdbs)
-			if candidate:
-				result.append(candidate)
-			else:
-				if not get_syncpkg(pkg.name):
-					aur_pkg = aur.infos(pkg.name)
-					if aur_pkg:
-						comp = pyalpm.vercmp(aur_pkg.version, pkg.version)
-						if comp == 1:
-							result.append(aur_pkg)
-	return do_syncfirst, result
+	while Gtk.events_pending():
+		Gtk.main_iteration()
+	action_handler(_('Checking for updates')+'...')
+	icon_handler('/usr/share/pamac/icons/24x24/status/package-search.png')
+	target_handler('')
+	percent_handler(0)
+	ProgressCancelButton.set_visible(False)
+	ProgressCloseButton.set_visible(False)
+	progress_expander.set_visible(False)
+	ProgressWindow.show()
+	while Gtk.events_pending():
+		Gtk.main_iteration()
+	CheckUpdates()
 
 def get_transaction_sum():
 	transaction_dict = {'to_remove': [], 'to_build': [], 'to_install': [], 'to_update': [], 'to_reinstall': [], 'to_downgrade': []}
@@ -595,18 +645,18 @@ def get_transaction_sum():
 				transaction_dict['to_downgrade'].append((name+' '+version, dsize))
 		else:
 			transaction_dict['to_install'].append((name+' '+version, dsize))
-	if transaction_dict['to_build']:
-		print('To build:', [name for name in transaction_dict['to_build']])
-	if transaction_dict['to_install']:
-		print('To install:', [name for name, size in transaction_dict['to_install']])
-	if transaction_dict['to_reinstall']:
-		print('To reinstall:', [name for name, size in transaction_dict['to_reinstall']])
-	if transaction_dict['to_downgrade']:
-		print('To downgrade:', [name for name, size in transaction_dict['to_downgrade']])
-	if transaction_dict['to_remove']:
-		print('To remove:', [name for name in transaction_dict['to_remove']])
-	if transaction_dict['to_update']:
-		print('To update:', [name for name, size in transaction_dict['to_update']])
+	#~ if transaction_dict['to_build']:
+		#~ print('To build:', [name for name in transaction_dict['to_build']])
+	#~ if transaction_dict['to_install']:
+		#~ print('To install:', [name for name, size in transaction_dict['to_install']])
+	#~ if transaction_dict['to_reinstall']:
+		#~ print('To reinstall:', [name for name, size in transaction_dict['to_reinstall']])
+	#~ if transaction_dict['to_downgrade']:
+		#~ print('To downgrade:', [name for name, size in transaction_dict['to_downgrade']])
+	#~ if transaction_dict['to_remove']:
+		#~ print('To remove:', [name for name in transaction_dict['to_remove']])
+	#~ if transaction_dict['to_update']:
+		#~ print('To update:', [name for name, size in transaction_dict['to_update']])
 	return transaction_dict
 
 def set_transaction_sum(show_updates = True):
@@ -664,18 +714,21 @@ def sysupgrade(show_updates = True):
 	global to_update
 	global to_add
 	global to_remove
-	do_syncfirst, updates = get_updates()
+	syncfirst, updates = available_updates
 	if updates:
 		to_update.clear()
 		to_add.clear()
 		to_remove.clear()
-		for pkg in updates:
-			if pkg.db.name == 'AUR':
+		for name, version, db, tarpath, size in updates:
+			if db == 'AUR':
+				# call AURPkg constructor directly to avoid a request to AUR
+				infos = {'name': name, 'version': version, 'Description': '', 'URLPath': tarpath}
+				pkg = aur.AURPkg(infos)
 				to_build.append(pkg)
 			else:
-				to_update.add(pkg.name)
+				to_update.add(name)
 		error = ''
-		if do_syncfirst:
+		if syncfirst:
 			error += init_transaction()
 			if not error:
 				for name in to_update:
@@ -702,16 +755,19 @@ def sysupgrade(show_updates = True):
 		if not error:
 			set_transaction_sum(show_updates = show_updates)
 			if show_updates:
+				ProgressWindow.hide()
 				ConfDialog.show_all()
 				while Gtk.events_pending():
 					Gtk.main_iteration()
 			else:
 				if len(transaction_sum) != 0:
+					ProgressWindow.hide()
 					ConfDialog.show_all()
 					while Gtk.events_pending():
 						Gtk.main_iteration()
 				else:
 					finalize()
 		if error:
+			ProgressWindow.hide()
 			Release()
 		return error
diff --git a/start-pamac-daemon b/start-pamac-daemon
deleted file mode 100755
index efe0c72e..00000000
--- a/start-pamac-daemon
+++ /dev/null
@@ -1,3 +0,0 @@
-#! /bin/sh
-
-/usr/bin/pamac-daemon &
-- 
GitLab