diff --git a/blackbox/Functions.py b/blackbox/Functions.py index 4504cd1..933d790 100644 --- a/blackbox/Functions.py +++ b/blackbox/Functions.py @@ -1940,3 +1940,211 @@ def close_in_app_notification(self): self.notification_revealer.set_reveal_child(False) GLib.source_remove(self.timeout_id) self.timeout_id = None + +def update_package_import_textview(self, line): + try: + if len(line) > 0: + self.msg_buffer.insert( + self.msg_buffer.get_end_iter(), + " %s" % line, + len(" %s" % line), + ) + except Exception as e: + logger.error("[Exception] update_progress_textview(): %s" % e) + finally: + self.pkg_import_queue.task_done() + text_mark_end = self.msg_buffer.create_mark( + "end", self.msg_buffer.get_end_iter(), False + ) + # scroll to the end of the textview + self.textview.scroll_mark_onscreen(text_mark_end) + +def monitor_package_import(self): + while True: + if self.stop_thread is True: + break + message = self.pkg_import_queue.get() + GLib.idle_add( + update_package_import_textview, + self, + message, + priority=GLib.PRIORITY_DEFAULT, + ) + +def update_package_status_label(label, text): + label.set_markup(text) + +def import_packages(self): + try: + packages_status_list = [] + package_failed = False + package_err = {} + count = 0 + if os.path.exists(pacman_cache_dir): + query_pacman_clean_cache_str = [ + "pacman", + "-Sc", + "--noconfirm", + ] + logger.info( + "Cleaning Pacman cache directory = %s" % pacman_cache_dir + ) + event = "%s [INFO]: Cleaning pacman cache\n" % datetime.now().strftime( + "%Y-%m-%d-%H-%M-%S" + ) + self.pkg_import_queue.put(event) + GLib.idle_add( + update_package_status_label, + self.label_package_status, + "Status: Cleaning pacman cache", + ) + process_pacman_cc = subprocess.Popen( + query_pacman_clean_cache_str, + shell=False, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + universal_newlines=True, + ) + out, err = process_pacman_cc.communicate(timeout=process_timeout) + self.pkg_import_queue.put(out) + if process_pacman_cc.returncode == 0: + logger.info("Pacman cache directory cleaned") + else: + logger.error("Failed to clean Pacman cache directory") + logger.info("Running full system upgrade") + # run full system upgrade, Arch does not allow partial package updates + query_str = ["pacman", "-Syu", "--noconfirm"] + # query_str = ["pacman", "-Qqen"] + logger.info("Running %s" % " ".join(query_str)) + event = "%s [INFO]:Running full system upgrade\n" % datetime.now().strftime( + "%Y-%m-%d-%H-%M-%S" + ) + self.pkg_import_queue.put(event) + GLib.idle_add( + update_package_status_label, + self.label_package_status, + "Status: Performing full system upgrade - do not power off your system", + ) + output = [] + with subprocess.Popen( + query_str, + shell=False, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + bufsize=1, + universal_newlines=True, + ) as process: + while True: + if process.poll() is not None: + break + for line in process.stdout: + # print(line.strip()) + self.pkg_import_queue.put(line) + output.append(line) + # time.sleep(0.2) + if process.returncode == 0: + logger.info("Pacman system upgrade completed") + GLib.idle_add( + update_package_status_label, + self.label_package_status, + "Status: Full system upgrade - completed", + ) + else: + if len(output) > 0: + if "there is nothing to do" not in output: + logger.error("Pacman system upgrade failed") + GLib.idle_add( + update_package_status_label, + self.label_package_status, + "Status: Full system upgrade - failed", + ) + print("%s" % " ".join(output)) + event = "%s [ERROR]: Installation of packages aborted due to errors\n" % datetime.now().strftime( + "%Y-%m-%d-%H-%M-%S" + ) + self.pkg_import_queue.put(event) + logger.error("Installation of packages aborted due to errors") + return + # do not proceed with package installs if system upgrade fails + else: + return + # iterate through list of packages, calling pacman -S on each one + for package in self.packages_list: + process_output = [] + package = package.strip() + if len(package) > 0: + if "#" not in package: + query_str = ["pacman", "-S", package, "--needed", "--noconfirm"] + count += 1 + logger.info("Running %s" % " ".join(query_str)) + event = "%s [INFO]: Running %s\n" % ( + datetime.now().strftime("%Y-%m-%d-%H-%M-%S"), + " ".join(query_str), + ) + self.pkg_import_queue.put(event) + with subprocess.Popen( + query_str, + shell=False, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + bufsize=1, + universal_newlines=True, + ) as process: + while True: + if process.poll() is not None: + break + for line in process.stdout: + process_output.append(line.strip()) + self.pkg_import_queue.put(line) + # time.sleep(0.2) + if process.returncode == 0: + # since this is being run in another thread outside of main, use GLib to update UI component + GLib.idle_add( + update_package_status_label, + self.label_package_status, + "Status: %s -> Installed" % package, + ) + GLib.idle_add( + update_package_status_label, + self.label_package_count, + "Progress: %s/%s" + % (count, len(self.packages_list)), + ) + packages_status_list.append("%s -> Installed" % package) + else: + logger.error("%s --> Install failed" % package) + GLib.idle_add( + update_package_status_label, + self.label_package_status, + "Status: %s -> Install failed" % package, + ) + GLib.idle_add( + update_package_status_label, + self.label_package_count, + "Progress: %s/%s" + % (count, len(self.packages_list)), + ) + if len(process_output) > 0: + if "there is nothing to do" not in process_output: + logger.error("%s" % " ".join(process_output)) + # store package error in dict + package_err[package] = " ".join(process_output) + package_failed = True + packages_status_list.append("%s -> Failed" % package) + if len(packages_status_list) > 0: + self.pkg_status_queue.put(packages_status_list) + if package_failed is True: + GLib.idle_add( + update_package_status_label, + self.label_package_status, + "Some packages have failed to install see %s" % self.logfile, + ) + # end + event = "%s [INFO]: Completed, check the logfile for any errors\n" % ( + datetime.now().strftime("%Y-%m-%d-%H-%M-%S"), + ) + self.pkg_import_queue.put(event) + except Exception as e: + logger.error("Exception in import_packages(): %s" % e) + finally: + self.pkg_err_queue.put(package_err) \ No newline at end of file