diff --git a/README.md b/README.md index 627c590c91275a22d3b3bb219c7b2f4a00eaa039..f79a77a84b981c1b420e6c84c032279d2cd39f6a 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,13 @@ -Pamac is a GUI for libalpm (pacman) with AUR and Appstream support +Pamac is a Package Manager based on libalpm with AUR and Appstream support #### Features - - Library to access package infos and run transactions - - Python bindings - - CLI - - GTK3 frontend with Dbus daemon - - Tray icon with Updates notifications + - libpamac: Library to access package infos and run transactions + - Python bindings for libpamac + - pamac: a CLI + - pamac_manager/pamac-updater: a Gtk3 GUI + - pamac-tray: a Gtk3 tray icon with updates notifications + - ppamac-tray-appindicator: a AppIndicator tray icon with updates notifications #### Installing from source diff --git a/data/config/pamac.conf b/data/config/pamac.conf index 7351dd4c4f97e79a080248975ffa6f63320af935..78b652b52d98f759ce3bf0360b752e39eac7f3e3 100644 --- a/data/config/pamac.conf +++ b/data/config/pamac.conf @@ -11,13 +11,13 @@ RefreshPeriod = 6 #NoUpdateHideIcon ## Allow Pamac to search and install packages from AUR: -#EnableAUR +EnableAUR ## When AUR support is enabled check for updates from AUR: -#CheckAURUpdates +CheckAURUpdates ## AUR build directory: -BuildDirectory = /tmp +BuildDirectory = /var/tmp ## Number of versions of each package to keep in the cache: KeepNumPackages = 3 diff --git a/resources/manager_window.ui b/resources/manager_window.ui index 644eff721815f979c2bf6ddacfa24e9848333500..7ebf5b32ecdf496f92b0e1199c76e7867c79dcd1 100644 --- a/resources/manager_window.ui +++ b/resources/manager_window.ui @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> -<!-- Generated with glade 3.22.0 --> +<!-- Generated with glade 3.22.1 --> <interface> <requires lib="gtk+" version="3.20"/> <object class="GtkPopoverMenu" id="popovermenu"> @@ -97,6 +97,127 @@ <property name="gravity">center</property> <property name="show_menubar">False</property> <signal name="delete-event" handler="on_ManagerWindow_delete_event" swapped="no"/> + <child type="titlebar"> + <object class="GtkHeaderBar" id="headerbar"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="show_close_button">True</property> + <child> + <object class="GtkBox" id="header_left_buttonbox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="spacing">32</property> + <child> + <object class="GtkButton" id="button_back"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="halign">start</property> + <signal name="clicked" handler="on_button_back_clicked" swapped="no"/> + <child> + <object class="GtkImage" id="back_image"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="icon_name">go-previous-symbolic</property> + <property name="icon_size">1</property> + </object> + </child> + <style> + <class name="image-button"/> + </style> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkLabel" id="header_filter_label"> + <property name="visible">True</property> + <property name="can_focus">False</property> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + <child> + <object class="GtkButton" id="select_all_button"> + <property name="label" translatable="yes">Select All</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <property name="margin_left">18</property> + <signal name="clicked" handler="on_select_all_button_clicked" swapped="no"/> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">3</property> + </packing> + </child> + </object> + </child> + <child> + <object class="GtkBox" id="header_right_buttonbox"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="spacing">3</property> + <child> + <object class="GtkToggleButton" id="search_button"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <signal name="toggled" handler="on_search_button_toggled" swapped="no"/> + <child> + <object class="GtkImage" id="search_image"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="icon_name">edit-find-symbolic</property> + </object> + </child> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">0</property> + </packing> + </child> + <child> + <object class="GtkMenuButton" id="menu_button"> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <property name="popover">popovermenu</property> + <signal name="toggled" handler="on_menu_button_toggled" swapped="no"/> + <child> + <object class="GtkImage" id="menu_icon"> + <property name="visible">True</property> + <property name="can_focus">False</property> + <property name="icon_name">open-menu-symbolic</property> + <property name="icon_size">1</property> + </object> + </child> + <style> + <class name="image-button"/> + </style> + </object> + <packing> + <property name="expand">False</property> + <property name="fill">True</property> + <property name="position">1</property> + </packing> + </child> + </object> + <packing> + <property name="pack_type">end</property> + <property name="position">1</property> + </packing> + </child> + </object> + </child> <child> <object class="GtkBox" id="main_box"> <property name="visible">True</property> @@ -651,24 +772,10 @@ <property name="orientation">vertical</property> <property name="spacing">12</property> <property name="homogeneous">True</property> - <child> - <object class="GtkSpinner" id="checking_spinner"> - <property name="height_request">40</property> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="valign">end</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">0</property> - </packing> - </child> <child> <object class="GtkLabel" id="checking_label"> <property name="visible">True</property> <property name="can_focus">False</property> - <property name="valign">start</property> </object> <packing> <property name="expand">False</property> @@ -849,6 +956,34 @@ <property name="position">2</property> </packing> </child> + <child> + <object class="GtkToggleButton" id="build_togglebutton"> + <property name="label" translatable="yes">Build</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">False</property> + <signal name="toggled" handler="on_build_togglebutton_toggled" swapped="no"/> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">3</property> + </packing> + </child> + <child> + <object class="GtkButton" id="reset_files_button"> + <property name="label" translatable="yes">Reset build files</property> + <property name="visible">True</property> + <property name="can_focus">True</property> + <property name="receives_default">True</property> + <signal name="clicked" handler="on_reset_files_button_clicked" swapped="no"/> + </object> + <packing> + <property name="expand">True</property> + <property name="fill">True</property> + <property name="position">4</property> + </packing> + </child> </object> <packing> <property name="expand">False</property> @@ -1203,126 +1338,5 @@ </child> </object> </child> - <child type="titlebar"> - <object class="GtkHeaderBar" id="headerbar"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="show_close_button">True</property> - <child> - <object class="GtkBox" id="header_left_buttonbox"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="spacing">32</property> - <child> - <object class="GtkButton" id="button_back"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> - <property name="halign">start</property> - <signal name="clicked" handler="on_button_back_clicked" swapped="no"/> - <child> - <object class="GtkImage" id="back_image"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="icon_name">go-previous-symbolic</property> - <property name="icon_size">1</property> - </object> - </child> - <style> - <class name="image-button"/> - </style> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkLabel" id="header_filter_label"> - <property name="visible">True</property> - <property name="can_focus">False</property> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">1</property> - </packing> - </child> - <child> - <object class="GtkButton" id="select_all_button"> - <property name="label" translatable="yes">Select All</property> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">True</property> - <property name="margin_left">18</property> - <signal name="clicked" handler="on_select_all_button_clicked" swapped="no"/> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">3</property> - </packing> - </child> - </object> - </child> - <child> - <object class="GtkBox" id="header_right_buttonbox"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="spacing">3</property> - <child> - <object class="GtkToggleButton" id="search_button"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> - <signal name="toggled" handler="on_search_button_toggled" swapped="no"/> - <child> - <object class="GtkImage" id="search_image"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="icon_name">edit-find-symbolic</property> - </object> - </child> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">0</property> - </packing> - </child> - <child> - <object class="GtkMenuButton" id="menu_button"> - <property name="visible">True</property> - <property name="can_focus">True</property> - <property name="receives_default">False</property> - <property name="popover">popovermenu</property> - <signal name="toggled" handler="on_menu_button_toggled" swapped="no"/> - <child> - <object class="GtkImage" id="menu_icon"> - <property name="visible">True</property> - <property name="can_focus">False</property> - <property name="icon_name">open-menu-symbolic</property> - <property name="icon_size">1</property> - </object> - </child> - <style> - <class name="image-button"/> - </style> - </object> - <packing> - <property name="expand">False</property> - <property name="fill">True</property> - <property name="position">1</property> - </packing> - </child> - </object> - <packing> - <property name="pack_type">end</property> - <property name="position">1</property> - </packing> - </child> - </object> - </child> </template> </interface> diff --git a/resources/transaction_sum_dialog.ui b/resources/transaction_sum_dialog.ui index 9a94f0ad54b7874da4cae7d0bf58670348c71ccb..d8e3cb535f7db16d2f887f8e8d5b7756fdecf73b 100644 --- a/resources/transaction_sum_dialog.ui +++ b/resources/transaction_sum_dialog.ui @@ -1,5 +1,5 @@ <?xml version="1.0" encoding="UTF-8"?> -<!-- Generated with glade 3.20.0 --> +<!-- Generated with glade 3.22.1 --> <interface> <requires lib="gtk+" version="3.20"/> <template class="PamacTransactionSumDialog" parent="GtkDialog"> @@ -11,6 +11,9 @@ <property name="icon_name">system-software-install</property> <property name="type_hint">dialog</property> <property name="deletable">False</property> + <child> + <placeholder/> + </child> <child internal-child="vbox"> <object class="GtkBox" id="dialog-vbox6"> <property name="can_focus">False</property> @@ -25,6 +28,9 @@ <property name="label" translatable="yes">_Cancel</property> <property name="visible">True</property> <property name="can_focus">True</property> + <property name="has_focus">True</property> + <property name="can_default">True</property> + <property name="has_default">True</property> <property name="receives_default">False</property> <property name="use_underline">True</property> </object> @@ -39,9 +45,6 @@ <property name="label" translatable="yes">Commit</property> <property name="visible">True</property> <property name="can_focus">True</property> - <property name="has_focus">True</property> - <property name="can_default">True</property> - <property name="has_default">True</property> <property name="receives_default">False</property> </object> <packing> diff --git a/src/alpm_utils.vala b/src/alpm_utils.vala index 20a725b2da6e591a3ca88d2dd4f850a91424f05b..fbcc55b9494b559862d61c7c4bdbf11ad663657a 100644 --- a/src/alpm_utils.vala +++ b/src/alpm_utils.vala @@ -76,6 +76,7 @@ private int alpm_pkg_sort_search_by_relevance (Alpm.Package pkg_a, Alpm.Package namespace Pamac { internal class AlpmUtils: Object { + Config config; internal AlpmConfig alpm_config; internal Alpm.Handle? alpm_handle; internal Alpm.Handle? files_handle; @@ -87,6 +88,7 @@ namespace Pamac { internal bool enable_downgrade; internal bool check_aur_updates; internal int flags; + string[] to_syncfirst; internal string[] to_install; internal string[] to_remove; internal string[] to_load; @@ -119,12 +121,12 @@ namespace Pamac { public signal void emit_log (uint level, string msg); public signal void refresh_finished (bool success); public signal void emit_get_updates_progress (uint percent); - public signal void get_updates_finished (UpdatesStruct updates); public signal void downloading_updates_finished (); public signal void trans_prepare_finished (bool success); public signal void trans_commit_finished (bool success); - public AlpmUtils () { + public AlpmUtils (Config config) { + this.config = config; alpm_config = new AlpmConfig ("/etc/pacman.conf"); aur_pkgbases_to_build = new GLib.List<string> (); aur_desc_list = new GenericSet<string?> (str_hash, str_equal); @@ -401,12 +403,7 @@ namespace Pamac { } } }); - // keep a ref pkg is needed - var pkgs = new List<Package> (); - foreach (unowned Package pkg in result) { - pkgs.append (pkg); - } - return pkgs; + return (owned) result; } internal List<Package> get_explicitly_installed_pkgs () { @@ -587,7 +584,8 @@ namespace Pamac { name = "", version = "", installed_version = "", - desc = "" + desc = "", + packagebase = "" }; } string installed_version = ""; @@ -601,13 +599,14 @@ namespace Pamac { installed_version = (owned) installed_version, // desc can be null desc = json_object.get_null_member ("Description") ? "" : json_object.get_string_member ("Description"), - popularity = json_object.get_double_member ("Popularity") + popularity = json_object.get_double_member ("Popularity"), + packagebase = json_object.get_string_member ("PackageBase") }; } - internal List<AURPackage> search_in_aur (string search_string) { + internal async List<AURPackage> search_in_aur (string search_string) { if (!aur_search_results.contains (search_string)) { - Json.Array pkgs = aur_search (search_string.split (" ")); + Json.Array pkgs = yield aur_search (search_string.split (" ")); aur_search_results.insert (search_string, pkgs); } var result = new List<AURPackage> (); @@ -619,17 +618,12 @@ namespace Pamac { result.append (new AURPackage.from_struct (initialise_aur_struct (aur_pkg))); } }); - // keep a ref pkg is needed - var pkgs = new List<AURPackage> (); - foreach (unowned AURPackage pkg in result) { - pkgs.append (pkg); - } - return pkgs; + return (owned) result; } - internal AURPackage get_aur_pkg (string pkgname) { + internal async AURPackage get_aur_pkg (string pkgname) { if (!aur_infos.contains (pkgname)) { - Json.Array results = aur_multiinfo ({pkgname}); + Json.Array results = yield aur_multiinfo ({pkgname}); if (results.get_length () > 0) { aur_infos.insert (pkgname, results.get_object_element (0)); } @@ -638,7 +632,7 @@ namespace Pamac { return new AURPackage.from_struct (initialise_aur_struct (json_object)); } - internal AURPackageDetails get_aur_pkg_details (string pkgname) { + internal async AURPackageDetails get_aur_pkg_details (string pkgname) { string name = ""; string version = ""; string desc = ""; @@ -660,7 +654,7 @@ namespace Pamac { string[] conflicts = {}; var details = AURPackageDetailsStruct (); if (!aur_infos.contains (pkgname)) { - Json.Array results = aur_multiinfo ({pkgname}); + Json.Array results = yield aur_multiinfo ({pkgname}); if (results.get_length () > 0) { aur_infos.insert (pkgname, results.get_object_element (0)); } @@ -783,6 +777,29 @@ namespace Pamac { return new AURPackageDetails.from_struct (details); } + internal string get_srcinfo_version (string pkgdir_name) { + StringBuilder version = new StringBuilder (); + // assume file exists + var srcinfo = File.new_for_path (pkgdir_name + "/.SRCINFO"); + try { + var dis = new DataInputStream (srcinfo.read ()); + string line; + while ((line = dis.read_line ()) != null) { + if ("pkgver = " in line) { + version.append (line.split ("pkgver = ", 2)[1]); + } else if ("pkgrel = " in line) { + version.append ("-"); + version.append (line.split ("pkgrel = ", 2)[1]); + // we have all we want + break; + } + } + } catch (GLib.Error e) { + stderr.printf ("%s\n", e.message); + } + return version.str; + } + internal List<string> get_repos_names () { var repos_names = new List<string> (); unowned Alpm.List<unowned Alpm.DB> syncdbs = alpm_handle.syncdbs; @@ -924,12 +941,7 @@ namespace Pamac { } }); }); - // keep a ref pkg is needed - var pkgs = new List<Package> (); - foreach (unowned Package pkg in result) { - pkgs.append (pkg); - } - return pkgs; + return (owned) result; } internal List<string> get_pkg_uninstalled_optdeps (string pkgname) { @@ -1163,7 +1175,10 @@ namespace Pamac { Alpm.File* file_ptr = filelist.files; for (size_t i = 0; i < filelist.count; i++, file_ptr++) { if (!file_ptr->name.has_suffix ("/")) { - files.append (alpm_handle.root + file_ptr->name); + var filename = new StringBuilder (); + filename.append (alpm_handle.root); + filename.append (file_ptr->name); + files.append (filename.str); } } } else { @@ -1176,7 +1191,10 @@ namespace Pamac { Alpm.File* file_ptr = filelist.files; for (size_t i = 0; i < filelist.count; i++, file_ptr++) { if (!file_ptr->name.has_suffix ("/")) { - files.append (alpm_handle.root + file_ptr->name); + var filename = new StringBuilder (); + filename.append (alpm_handle.root); + filename.append (file_ptr->name); + files.append (filename.str); } } break; @@ -1201,9 +1219,11 @@ namespace Pamac { // exclude directory name if (!file_ptr->name.has_suffix ("/")) { // adding / to compare - string real_file_name = alpm_handle.root + file_ptr->name; - if (file in real_file_name) { - found_files += real_file_name; + var real_file_name = new StringBuilder (); + real_file_name.append (alpm_handle.root); + real_file_name.append (file_ptr->name); + if (file in real_file_name.str) { + found_files += real_file_name.str; } } } @@ -1226,9 +1246,11 @@ namespace Pamac { // exclude directory name if (!file_ptr->name.has_suffix ("/")) { // adding / to compare - string real_file_name = alpm_handle.root + file_ptr->name; - if (file in real_file_name) { - found_files += real_file_name; + var real_file_name = new StringBuilder (); + real_file_name.append (alpm_handle.root); + real_file_name.append (file_ptr->name); + if (file in real_file_name.str) { + found_files += real_file_name.str; } } } @@ -1401,7 +1423,7 @@ namespace Pamac { } } - internal void compute_aur_build_list () { + internal async void compute_aur_build_list () { try { Process.spawn_command_line_sync ("mkdir -p %s".printf (aurdb_path)); } catch (SpawnError e) { @@ -1409,146 +1431,207 @@ namespace Pamac { } aur_desc_list.remove_all (); already_checked_aur_dep.remove_all (); - check_aur_dep_list (to_build); + yield check_aur_dep_list (to_build); + } + + internal async string clone_build_files (string pkgname, bool overwrite_files) { + int status = 1; + string builddir_name = Path.build_path ("/", config.aur_build_dir, "pamac-build"); + string[] cmds; + var builddir = File.new_for_path (builddir_name); + if (!builddir.query_exists ()) { + try { + builddir.make_directory_with_parents (); + Process.spawn_command_line_sync ("chmod --quiet -R ugo+w %s".printf (builddir_name)); + } catch (Error e) { + stderr.printf ("Error: %s\n", e.message); + } + } + string pkgdir_name = builddir_name + "/" + pkgname; + var pkgdir = File.new_for_path (pkgdir_name); + var launcher = new SubprocessLauncher (SubprocessFlags.NONE); + if (overwrite_files) { + try { + Process.spawn_command_line_sync ("rm -rf %s".printf (pkgdir_name)); + } catch (Error e) { + stderr.printf ("Error: %s\n", e.message); + } + } + if (pkgdir.query_exists ()) { + var aur_pkg = yield get_aur_pkg (pkgname); + if (aur_pkg.version == alpm_utils.get_srcinfo_version (pkgdir_name)) { + // up to date + return pkgdir_name; + } else { + launcher.set_cwd (pkgdir_name); + cmds = {"git", "pull", "-q"}; + try { + Subprocess process = launcher.spawnv (cmds); + yield process.wait_async (); + if (process.get_if_exited ()) { + status = process.get_exit_status (); + } + if (status == 0) { + return pkgdir_name; + } else { + launcher.set_cwd (builddir_name); + cmds = {"git", "clone", "-q", "--depth=1", "https://aur.archlinux.org/%s.git".printf (pkgname)}; + } + } catch (Error e) { + stderr.printf ("Error: %s\n", e.message); + } + } + } else { + launcher.set_cwd (builddir_name); + cmds = {"git", "clone", "-q", "--depth=1", "https://aur.archlinux.org/%s.git".printf (pkgname)}; + } + try { + Subprocess process = launcher.spawnv (cmds); + yield process.wait_async (); + if (process.get_if_exited ()) { + status = process.get_exit_status (); + } + } catch (Error e) { + stderr.printf ("Error: %s\n", e.message); + } + if (status == 0) { + return pkgdir_name; + } + return ""; } - void check_aur_dep_list (string[] pkgnames) { - string[] dep_types = {"Depends", "MakeDepends", "CheckDepends"}; + async void check_aur_dep_list (string[] pkgnames) { string[] dep_to_check = {}; - Json.Array results = aur_multiinfo (pkgnames); - results.foreach_element ((array, index, node) => { - unowned Json.Object? pkg_info = node.get_object (); - // create fake db desc file - if (pkg_info != null) { - string name = pkg_info.get_string_member ("Name"); - string version = pkg_info.get_string_member ("Version"); + foreach (unowned string name in pkgnames) { + string version = ""; + string pkgbase = ""; + string desc = ""; + string[] depends = {}; + string[] conflicts = {}; + string[] provides = {}; + string[] replaces = {}; + // clone build files + string pkgdir_name = yield clone_build_files (name, false); + if (pkgdir_name == "") { + // error + continue; + } + // read .SRCINFO + var srcinfo = File.new_for_path (pkgdir_name + "/.SRCINFO"); + try { + var dis = new DataInputStream (srcinfo.read ()); + string line; + while ((line = dis.read_line ()) != null) { + if ("pkgbase = " in line) { + pkgbase = line.split ("pkgbase = ", 2)[1]; + } else if ("pkgdesc = " in line) { + desc = line.split ("pkgdesc = ", 2)[1]; + } else if ("pkgver = " in line) { + version = line.split ("pkgver = ", 2)[1]; + } else if ("pkgrel = " in line) { + version += "-"; + version += line.split ("pkgrel = ", 2)[1]; + // compute depends, makedepends and checkdepends in depends + } else if ("checkdepends = " in line) { + depends += line.split ("checkdepends = ", 2)[1]; + } else if ("makedepends = " in line) { + depends += line.split ("makedepends = ", 2)[1]; + } else if ("depends = " in line) { + depends += line.split ("depends = ", 2)[1]; + } else if ("provides = " in line) { + provides += line.split ("provides = ", 2)[1]; + } else if ("conflicts = " in line) { + conflicts += line.split ("conflicts = ", 2)[1]; + } else if ("replaces = " in line) { + replaces += line.split ("replaces = ", 2)[1]; + } + } + // check deps + foreach (unowned string dep_string in depends) { + string dep_name = Alpm.Depend.from_string (dep_string).name; + unowned Alpm.Package? pkg = null; + // search for the name first to avoid provides trouble + pkg = alpm_handle.localdb.get_pkg (dep_name); + if (pkg == null) { + pkg = get_syncpkg (dep_name); + } + if (pkg == null) { + if (!(dep_name in already_checked_aur_dep)) { + dep_to_check += (owned) dep_name; + } + } + } + // write desc file string pkgdir = "%s-%s".printf (name, version); string pkgdir_path = "%s/%s".printf (aurdb_path, pkgdir); aur_desc_list.add (pkgdir); already_checked_aur_dep.add (name); - try { - var file = GLib.File.new_for_path (pkgdir_path); - bool write_desc_file = false; - if (!file.query_exists ()) { - file.make_directory (); - write_desc_file = true; + var file = GLib.File.new_for_path (pkgdir_path); + // always recreate desc in case of .SRCINFO modifications + if (file.query_exists ()) { + Process.spawn_command_line_sync ("rm -rf %s".printf (pkgdir_path)); + } + file.make_directory (); + file = GLib.File.new_for_path ("%s/desc".printf (pkgdir_path)); + // creating a DataOutputStream to the file + var dos = new DataOutputStream (file.create (FileCreateFlags.REPLACE_DESTINATION)); + // fake filename + dos.put_string ("%FILENAME%\n" + "%s-%s-any.pkg.tar.xz\n\n".printf (name, version)); + // name + dos.put_string ("%NAME%\n%s\n\n".printf (name)); + // version + dos.put_string ("%VERSION%\n%s\n\n".printf (version)); + // base + dos.put_string ("%BASE%\n%s\n\n".printf (pkgbase)); + // desc + dos.put_string ("%DESC%\n%s\n\n".printf (desc)); + // version + dos.put_string ("%VERSION%\n%s\n\n".printf (version)); + // fake arch + dos.put_string ("%ARCH%\nany\n\n"); + // depends + if (depends.length > 0) { + dos.put_string ("%DEPENDS%\n"); + foreach (unowned string depend in depends) { + dos.put_string ("%s\n".printf (depend)); } - // compute depends, makedepends and checkdepends in DEPENDS - var depends = new StringBuilder (); - foreach (unowned string dep_type in dep_types) { - unowned Json.Node? dep_node = pkg_info.get_member (dep_type); - if (dep_node != null) { - dep_node.get_array ().foreach_element ((array, index, node) => { - if (write_desc_file) { - depends.append (node.get_string ()); - depends.append ("\n"); - } - // check deps - unowned string dep_string = node.get_string (); - string dep_name = Alpm.Depend.from_string (dep_string).name; - unowned Alpm.Package? pkg = null; - // search for the name first to avoid provides trouble - pkg = alpm_handle.localdb.get_pkg (dep_name); - if (pkg == null) { - pkg = get_syncpkg (dep_name); - } - if (pkg == null) { - if (!(dep_name in already_checked_aur_dep)) { - dep_to_check += (owned) dep_name; - } - } - }); - } + dos.put_string ("\n"); + } + // conflicts + if (conflicts.length > 0) { + dos.put_string ("%CONFLICTS%\n"); + foreach (unowned string conflict in conflicts) { + dos.put_string ("%s\n".printf (conflict)); } - if (write_desc_file) { - file = GLib.File.new_for_path ("%s/desc".printf (pkgdir_path)); - // creating a DataOutputStream to the file - var dos = new DataOutputStream (file.create (FileCreateFlags.REPLACE_DESTINATION)); - // fake filename - dos.put_string ("%FILENAME%\n" + "%s-%s-any.pkg.tar.xz\n\n".printf (name, version)); - // name - dos.put_string ("%NAME%\n%s\n\n".printf (name)); - // version - dos.put_string ("%VERSION%\n%s\n\n".printf (version)); - //base - dos.put_string ("%BASE%\n%s\n\n".printf (pkg_info.get_string_member ("PackageBase"))); - // desc can be null - if (!pkg_info.get_null_member ("Description")) { - dos.put_string ("%DESC%\n%s\n\n".printf (pkg_info.get_string_member ("Description"))); - } - // version - dos.put_string ("%VERSION%\n%s\n\n".printf (pkg_info.get_string_member ("Version"))); - // fake arch - dos.put_string ("%ARCH%\nany\n\n"); - // depends - if (depends.len > 0) { - dos.put_string ("%DEPENDS%\n%s\n".printf (depends.str)); - } - // conflicts - unowned Json.Node? info_node = pkg_info.get_member ("Conflicts"); - if (info_node != null) { - try { - dos.put_string ("%CONFLICTS%\n"); - info_node.get_array ().foreach_element ((array, index, _node) => { - try { - dos.put_string ("%s\n".printf (_node.get_string ())); - } catch (GLib.Error e) { - GLib.stderr.printf("%s\n", e.message); - } - }); - dos.put_string ("\n"); - } catch (GLib.Error e) { - GLib.stderr.printf("%s\n", e.message); - } - } - // provides - info_node = pkg_info.get_member ("Provides"); - if (info_node != null) { - try { - dos.put_string ("%PROVIDES%\n"); - info_node.get_array ().foreach_element ((array, index, _node) => { - try { - dos.put_string ("%s\n".printf (_node.get_string ())); - } catch (GLib.Error e) { - GLib.stderr.printf("%s\n", e.message); - } - }); - dos.put_string ("\n"); - } catch (GLib.Error e) { - GLib.stderr.printf("%s\n", e.message); - } - } - // replaces - info_node = pkg_info.get_member ("Replaces"); - if (info_node != null) { - try { - dos.put_string ("%REPLACES%\n"); - info_node.get_array ().foreach_element ((array, index, _node) => { - try { - dos.put_string ("%s\n".printf (_node.get_string ())); - } catch (GLib.Error e) { - GLib.stderr.printf("%s\n", e.message); - } - }); - dos.put_string ("\n"); - } catch (GLib.Error e) { - GLib.stderr.printf("%s\n", e.message); - } - } + dos.put_string ("\n"); + } + // provides + if (provides.length > 0) { + dos.put_string ("%PROVIDES%\n"); + foreach (unowned string provide in provides) { + dos.put_string ("%s\n".printf (provide)); } - } catch (GLib.Error e) { - GLib.stderr.printf("%s\n", e.message); + dos.put_string ("\n"); + } + // replaces + if (replaces.length > 0) { + dos.put_string ("%REPLACES%\n"); + foreach (unowned string replace in replaces) { + dos.put_string ("%s\n".printf (replace)); + } + dos.put_string ("\n"); } + } catch (GLib.Error e) { + GLib.stderr.printf("%s\n", e.message); } - }); + } if (dep_to_check.length > 0) { - check_aur_dep_list (dep_to_check); + yield check_aur_dep_list (dep_to_check); } } - internal Updates get_updates (bool refresh_files_dbs) { + internal async Updates get_updates (bool refresh_files_dbs) { var repos_updates = new List<Package> (); - var aur_updates = new List<AURPackage> (); unowned Alpm.Package? pkg = null; unowned Alpm.Package? candidate = null; // use a tmp handle @@ -1606,58 +1689,35 @@ namespace Pamac { emit_get_updates_progress (95); if (check_aur_updates) { // count this step as 5% of the total - var aur_updates_structs = get_aur_updates (aur_multiinfo (local_pkgs)); - foreach (unowned AURPackageStruct aur_struct in aur_updates_structs) { - aur_updates.append (new AURPackage.from_struct (aur_struct)); - } + emit_get_updates_progress (100); + return new Updates.from_lists ((owned) repos_updates, get_aur_updates_real (yield aur_multiinfo (local_pkgs))); + } else { + emit_get_updates_progress (100); + return new Updates.from_lists ((owned) repos_updates, new List<AURPackage> ()); } - emit_get_updates_progress (100); - return new Updates.from_lists ((owned) repos_updates, (owned) aur_updates); } - internal void get_updates_for_sysupgrade () { - // only get syncfirst repos updates and aur updates - PackageStruct[] syncfirst_updates = {}; - AURPackageStruct[] aur_updates = {}; - unowned Alpm.Package? pkg = null; - unowned Alpm.Package? candidate = null; - foreach (unowned string name in alpm_config.get_syncfirsts ()) { - pkg = Alpm.find_satisfier (alpm_handle.localdb.pkgcache, name); - if (pkg != null) { - candidate = pkg.sync_newversion (alpm_handle.syncdbs); - if (candidate != null) { - var infos = initialise_pkg_struct (candidate); - syncfirst_updates += (owned) infos; - } - } - } - if (check_aur_updates) { - // get local pkgs - string[] local_pkgs = {}; - unowned Alpm.List<unowned Alpm.Package> pkgcache = alpm_handle.localdb.pkgcache; - while (pkgcache != null) { - unowned Alpm.Package installed_pkg = pkgcache.data; - // check if installed_pkg is in IgnorePkg or IgnoreGroup - if (alpm_handle.should_ignore (installed_pkg) == 0) { - // check if installed_pkg is a local pkg - pkg = get_syncpkg (installed_pkg.name); - if (pkg == null) { - local_pkgs += installed_pkg.name; - } + internal async List<AURPackage> get_aur_updates () { + // get local pkgs + string[] local_pkgs = {}; + unowned Alpm.List<unowned Alpm.Package> pkgcache = alpm_handle.localdb.pkgcache; + while (pkgcache != null) { + unowned Alpm.Package installed_pkg = pkgcache.data; + // check if installed_pkg is in IgnorePkg or IgnoreGroup + if (alpm_handle.should_ignore (installed_pkg) == 0) { + // check if installed_pkg is a local pkg + unowned Alpm.Package? pkg = get_syncpkg (installed_pkg.name); + if (pkg == null) { + local_pkgs += installed_pkg.name; } - pkgcache.next (); } - aur_updates = get_aur_updates (aur_multiinfo (local_pkgs)); + pkgcache.next (); } - var updates = UpdatesStruct () { - syncfirst_repos_updates = (owned) syncfirst_updates, - aur_updates = (owned) aur_updates - }; - get_updates_finished (updates); + return get_aur_updates_real (yield aur_multiinfo (local_pkgs)); } - AURPackageStruct[] get_aur_updates (Json.Array aur_updates_json) { - AURPackageStruct[] aur_updates = {}; + List<AURPackage> get_aur_updates_real (Json.Array aur_updates_json) { + var aur_updates = new List<AURPackage> (); aur_updates_json.foreach_element ((array, index, node) => { unowned Json.Object pkg_info = node.get_object (); unowned string name = pkg_info.get_string_member ("Name"); @@ -1666,10 +1726,10 @@ namespace Pamac { if (Alpm.pkg_vercmp (new_version, old_version) == 1) { var infos = initialise_aur_struct (pkg_info); infos.installed_version = old_version; - aur_updates += (owned) infos; + aur_updates.append (new AURPackage.from_struct ((owned) infos)); } }); - return aur_updates; + return (owned) aur_updates; } internal int download_updates () { @@ -1714,7 +1774,6 @@ namespace Pamac { bool trans_sysupgrade () { current_error = ErrorInfos (); add_ignorepkgs (); - add_overwrite_files (); if (alpm_handle.trans_sysupgrade ((enable_downgrade) ? 1 : 0) == -1) { Alpm.Errno errno = alpm_handle.errno (); current_error.message = _("Failed to prepare transaction"); @@ -1723,6 +1782,17 @@ namespace Pamac { } return false; } + // check syncfirsts + to_syncfirst = {}; + foreach (unowned string name in alpm_config.get_syncfirsts ()) { + unowned Alpm.Package? pkg = Alpm.find_satisfier (alpm_handle.localdb.pkgcache, name); + if (pkg != null) { + unowned Alpm.Package? candidate = pkg.sync_newversion (alpm_handle.syncdbs); + if (candidate != null) { + to_syncfirst += candidate.name; + } + } + } return true; } @@ -1982,9 +2052,28 @@ namespace Pamac { void launch_trans_prepare_real () { bool success = trans_init (flags); - if (success && sysupgrade) { - // add upgrades to transaction - success = trans_sysupgrade (); + // check if you add upgrades to transaction + if (success) { + if (!sysupgrade && to_install.length > 0) { + foreach (unowned string name in to_install) { + unowned Alpm.Package? local_pkg = alpm_handle.localdb.get_pkg (name); + if (local_pkg == null) { + sysupgrade = true; + break; + } else { + unowned Alpm.Package? sync_pkg = get_syncpkg (name); + if (sync_pkg != null) { + if (local_pkg.version != sync_pkg.version) { + sysupgrade = true; + break; + } + } + } + } + } + if (sysupgrade) { + success = trans_sysupgrade (); + } } if (success) { foreach (unowned string name in to_install) { @@ -2139,13 +2228,13 @@ namespace Pamac { if (aur_pkgbases_to_build.find_custom (trans_pkg.pkgbase, strcmp) == null) { aur_pkgbases_to_build.append (trans_pkg.pkgbase); } - var pkg = AURPackageStruct () { + to_build_pkgs += AURPackageStruct () { name = trans_pkg.name, version = trans_pkg.version, installed_version = "", - desc = "" + desc = "", + packagebase = "" }; - to_build_pkgs += (owned) pkg; if (!(trans_pkg.name in to_build)) { to_install_as_dep.insert (trans_pkg.name, trans_pkg.name); } @@ -2165,8 +2254,7 @@ namespace Pamac { unowned Alpm.Package trans_pkg = pkgs_to_remove.data; // it is a pkg to remove if (!(trans_pkg.name in to_remove)) { - var pkg = initialise_pkg_struct (trans_pkg); - aur_conflicts_to_remove += (owned) pkg; + aur_conflicts_to_remove += initialise_pkg_struct (trans_pkg); } pkgs_to_remove.next (); } @@ -2231,8 +2319,7 @@ namespace Pamac { unowned Alpm.List<unowned Alpm.Package> pkgs_to_remove = alpm_handle.trans_to_remove (); while (pkgs_to_remove != null) { unowned Alpm.Package trans_pkg = pkgs_to_remove.data; - var infos = initialise_pkg_struct (trans_pkg); - to_remove += (owned) infos; + to_remove += initialise_pkg_struct (trans_pkg); pkgs_to_remove.next (); } PackageStruct[] conflicts_to_remove = {}; @@ -2258,9 +2345,83 @@ namespace Pamac { } internal void trans_commit () { + add_overwrite_files (); + bool success = false; + if (to_syncfirst.length > 0) { + trans_release (); + success = trans_init (flags); + if (success) { + foreach (unowned string name in to_syncfirst) { + success = trans_add_pkg (name); + if (!success) { + break; + } + } + if (success) { + success = trans_prepare_real (); + } + if (success) { + success = trans_commit_real (); + } + trans_release (); + if (success) { + success = trans_init (flags); + if (success && sysupgrade) { + success = trans_sysupgrade (); + } + if (success) { + foreach (unowned string name in to_install) { + success = trans_add_pkg (name); + if (!success) { + break; + } + } + } + if (success) { + foreach (unowned string name in to_remove) { + success = trans_remove_pkg (name); + if (!success) { + break; + } + } + } + if (success) { + foreach (unowned string path in to_load) { + success = trans_load_pkg (path); + if (!success) { + break; + } + } + } + if (success) { + success = trans_prepare_real (); + } else { + trans_release (); + } + } + } + if (!success) { + trans_commit_finished (success); + return; + } + } + success = trans_commit_real (); + if (success) { + to_install_as_dep.foreach_remove ((pkgname, val) => { + unowned Alpm.Package? pkg = alpm_handle.localdb.get_pkg (pkgname); + if (pkg != null) { + pkg.reason = Alpm.Package.Reason.DEPEND; + return true; // remove current pkgname + } + return false; + }); + } + trans_commit_finished (success); + } + + bool trans_commit_real () { current_error = ErrorInfos (); bool success = true; - add_overwrite_files (); Alpm.List err_data; if (alpm_handle.trans_commit (out err_data) == -1) { Alpm.Errno errno = alpm_handle.errno (); @@ -2268,7 +2429,7 @@ namespace Pamac { if (errno == Alpm.Errno.EXTERNAL_DOWNLOAD && cancellable.is_cancelled ()) { trans_release (); trans_commit_finished (false); - return; + return false; } current_error.message = _("Failed to commit transaction"); switch (errno) { @@ -2322,15 +2483,7 @@ namespace Pamac { success = false; } trans_release (); - to_install_as_dep.foreach_remove ((pkgname, val) => { - unowned Alpm.Package? pkg = alpm_handle.localdb.get_pkg (pkgname); - if (pkg != null) { - pkg.reason = Alpm.Package.Reason.DEPEND; - return true; // remove current pkgname - } - return false; - }); - trans_commit_finished (success); + return success; } internal void trans_release () { diff --git a/src/aur.vala b/src/aur.vala index 65ad5935461108425fd8a1ac527064996e721258..bb3830bc00380f3a63f605795946fd16333ef172 100644 --- a/src/aur.vala +++ b/src/aur.vala @@ -25,37 +25,41 @@ namespace Pamac { const string rpc_multiinfo = "&type=info"; const string rpc_multiinfo_arg = "&arg[]="; - Json.Array rpc_query (string uri) { + async Json.Array rpc_query (string uri) { + SourceFunc callback = rpc_query.callback; var results = new Json.Array (); var session = new Soup.Session (); // set a 15 seconds timeout because it is also the dbus daemon timeout session.timeout = 15; var message = new Soup.Message ("GET", uri); var parser = new Json.Parser (); - session.send_message (message); - try { - parser.load_from_data ((string) message.response_body.flatten ().data, -1); - } catch (Error e) { - critical (e.message); - } - unowned Json.Node? root = parser.get_root (); - if (root != null) { - if (root.get_object ().get_string_member ("type") == "error") { - stderr.printf ("Failed to query %s from AUR\n", uri); - } else { - results = root.get_object ().get_array_member ("results"); + session.queue_message (message, (sess, mess) => { + try { + parser.load_from_data ((string) mess.response_body.flatten ().data, -1); + unowned Json.Node? root = parser.get_root (); + if (root != null) { + if (root.get_object ().get_string_member ("type") == "error") { + stderr.printf ("Failed to query %s from AUR\n", uri); + } else { + results = root.get_object ().get_array_member ("results"); + } + } + } catch (Error e) { + critical (e.message); } - } + Idle.add ((owned) callback); + }); + yield; return results; } - internal Json.Array aur_search (string[] needles) { + internal async Json.Array aur_search (string[] needles) { if (needles.length == 0) { return new Json.Array (); } else { Json.Array[] found_array = {}; foreach (unowned string needle in needles) { - found_array += rpc_query (rpc_url + rpc_search + Uri.escape_string (needle)); + found_array += yield rpc_query (rpc_url + rpc_search + Uri.escape_string (needle)); } var result = new Json.Array (); foreach (unowned Json.Array found in found_array) { @@ -81,17 +85,44 @@ namespace Pamac { } } - internal Json.Array aur_multiinfo (string[] pkgnames) { + internal async Json.Array aur_multiinfo (string[] pkgnames) { if (pkgnames.length == 0) { return new Json.Array (); } - var builder = new StringBuilder (); - builder.append (rpc_url); - builder.append (rpc_multiinfo); - foreach (unowned string pkgname in pkgnames) { - builder.append (rpc_multiinfo_arg); - builder.append (Uri.escape_string (pkgname)); + // query pkgnames hundred by hundred to avoid too long uri error + // example: ros-lunar-desktop + if (pkgnames.length <= 100) { + var builder = new StringBuilder (); + builder.append (rpc_url); + builder.append (rpc_multiinfo); + foreach (unowned string pkgname in pkgnames) { + builder.append (rpc_multiinfo_arg); + builder.append (Uri.escape_string (pkgname)); + } + return yield rpc_query (builder.str); + } else { + var result = new Json.Array (); + int index_max = pkgnames.length - 1; + int index = 0; + while (index < index_max) { + var builder = new StringBuilder (); + builder.append (rpc_url); + builder.append (rpc_multiinfo); + for (int i = 0; i < 100; i++) { + unowned string pkgname = pkgnames[index]; + builder.append (rpc_multiinfo_arg); + builder.append (Uri.escape_string (pkgname)); + index++; + if (index == index_max) { + break; + } + } + var array = yield rpc_query (builder.str); + array.foreach_element ((array, index, node) => { + result.add_element (node); + }); + } + return result; } - return rpc_query (builder.str); } } diff --git a/src/cli.vala b/src/cli.vala index 74fadd0b717a235c07a3f6a5c47c0c0e49047498..1cb3b5ac6db25ecca769dc9bc15114264690a503 100644 --- a/src/cli.vala +++ b/src/cli.vala @@ -99,7 +99,10 @@ namespace Pamac { } else if (args[2] == "--aur" || args[2] == "-a") { init_database (); database.config.enable_aur = true; - search_in_aur (concatenate_strings (args[3:args.length])); + search_in_aur.begin (concatenate_strings (args[3:args.length]), () => { + loop.quit (); + }); + loop.run (); } else if (args[2] == "--files" || args[2] == "-f") { init_database (); search_files (args[3:args.length]); @@ -117,7 +120,10 @@ namespace Pamac { } else if (args[2] == "--aur" || args[2] == "-a") { init_database (); database.config.enable_aur = true; - display_aur_infos (args[3:args.length]); + display_aur_infos.begin (args[3:args.length], () => { + loop.quit (); + }); + loop.run (); } else { init_database (); display_pkg_infos (args[2:args.length]); @@ -245,7 +251,10 @@ namespace Pamac { } else if (args[1] == "checkupdates") { if (args.length == 2) { init_database (); - checkupdates (); + checkupdates.begin (() => { + loop.quit (); + }); + loop.run (); } else if (args.length == 3) { if (args[2] == "--help" || args[2] == "-h") { display_checkupdates_help (); @@ -253,7 +262,10 @@ namespace Pamac { init_database (); database.config.enable_aur = true; database.config.check_aur_updates = true; - checkupdates (); + checkupdates.begin ((obj, res) => { + loop.quit (); + }); + loop.run (); } else { display_checkupdates_help (); } @@ -742,8 +754,8 @@ namespace Pamac { } } - void search_in_aur (string search_string) { - var pkgs = database.search_in_aur (search_string); + async void search_in_aur (string search_string) { + var pkgs = yield database.search_in_aur (search_string); if (pkgs.length () == 0) { exit_status = 1; return; @@ -997,7 +1009,7 @@ namespace Pamac { } } - void display_aur_infos (string[] pkgnames) { + async void display_aur_infos (string[] pkgnames) { string[] properties = {}; properties += dgettext (null, "Name"); properties += dgettext (null, "Package Base"); @@ -1025,7 +1037,7 @@ namespace Pamac { } } foreach (string pkgname in pkgnames) { - var details = database.get_aur_pkg_details (pkgname); + var details = yield database.get_aur_pkg_details (pkgname); if (details.name == "") { print_error (dgettext (null, "target not found: %s").printf (pkgname) + "\n"); return; @@ -1306,8 +1318,8 @@ namespace Pamac { } } - void checkupdates () { - var updates = database.get_updates (); + async void checkupdates () { + var updates = yield database.get_updates (); uint updates_nb = updates.repos_updates.length () + updates.aur_updates.length (); if (updates_nb == 0) { stdout.printf ("%s.\n", dgettext (null, "Your system is up-to-date")); @@ -1362,7 +1374,6 @@ namespace Pamac { dgettext (null, "AUR")); } } - loop.quit (); } void install_pkgs (string[] targets) { diff --git a/src/common.vala b/src/common.vala index 64dc73e198d0b68bdd4bd030040bb0fbf9d6721e..8d659ed7976748eb4a1d7cbb15a61617a5e53070 100644 --- a/src/common.vala +++ b/src/common.vala @@ -65,6 +65,7 @@ namespace Pamac { public string installed_version; public string desc; public double popularity; + public string packagebase; } struct AURPackageDetailsStruct { @@ -99,9 +100,4 @@ namespace Pamac { public PackageStruct[] aur_conflicts_to_remove; public string[] aur_pkgbases_to_build; } - - struct UpdatesStruct { - public PackageStruct[] syncfirst_repos_updates; - public AURPackageStruct[] aur_updates; - } } diff --git a/src/common_daemon.vala b/src/common_daemon.vala index 35d367f1237725523f7478d7b1a0f1e2dae979d7..d146e71ca6e53198e6411ed6488919107477e92b 100644 --- a/src/common_daemon.vala +++ b/src/common_daemon.vala @@ -65,6 +65,7 @@ namespace Pamac { public string installed_version; public string desc; public double popularity; + public string packagebase; } public struct AURPackageDetailsStruct { @@ -100,11 +101,6 @@ namespace Pamac { public string[] aur_pkgbases_to_build; } - public struct UpdatesStruct { - public PackageStruct[] syncfirst_repos_updates; - public AURPackageStruct[] aur_updates; - } - public struct ErrorInfos { public string message; public string[] details; diff --git a/src/database.vala b/src/database.vala index 0218047729c9ca75b428edd4386623fea52c4982..ed0769eff7398457041d2934a88641eda9311885 100644 --- a/src/database.vala +++ b/src/database.vala @@ -31,7 +31,7 @@ namespace Pamac { construct { // alpm_utils global variable declared in alpm_utils.vala - alpm_utils = new AlpmUtils (); + alpm_utils = new AlpmUtils (config); refresh_files_dbs_on_get_updates = false; } @@ -168,18 +168,14 @@ namespace Pamac { return alpm_utils.search_pkgs (search_string); } - public List<AURPackage> search_in_aur (string search_string) { + public async List<AURPackage> search_in_aur (string search_string) { var pkgs = new List<AURPackage> (); if (config.enable_aur) { - pkgs = alpm_utils.search_in_aur (search_string); + pkgs = yield alpm_utils.search_in_aur (search_string); } return pkgs; } - public async List<AURPackage> search_in_aur_async (string search_string) { - return search_in_aur (search_string); - } - public HashTable<string, Variant> search_files (string[] files) { return alpm_utils.search_files (files); } @@ -232,40 +228,36 @@ namespace Pamac { return alpm_utils.get_pkg_files (pkgname); } - public AURPackage get_aur_pkg (string pkgname) { + public async string clone_build_files (string pkgname, bool overwrite_files) { + return yield alpm_utils.clone_build_files (pkgname, overwrite_files); + } + + public async AURPackage get_aur_pkg (string pkgname) { if (config.enable_aur) { - return alpm_utils.get_aur_pkg (pkgname); + return yield alpm_utils.get_aur_pkg (pkgname); } else { return new AURPackage (); } } - public async AURPackage get_aur_pkg_async (string pkgname) { - return get_aur_pkg (pkgname); - } - - public AURPackageDetails get_aur_pkg_details (string pkgname) { + public async AURPackageDetails get_aur_pkg_details (string pkgname) { if (config.enable_aur) { - return alpm_utils.get_aur_pkg_details (pkgname); + return yield alpm_utils.get_aur_pkg_details (pkgname); } else { return new AURPackageDetails (); } } - public async AURPackageDetails get_aur_pkg_details_async (string pkgname) { - return get_aur_pkg_details (pkgname); + public async List<AURPackage> get_aur_updates () { + return yield alpm_utils.get_aur_updates (); } - public Updates get_updates () { + public async Updates get_updates () { alpm_utils.emit_get_updates_progress.connect (on_emit_get_updates_progress); alpm_utils.check_aur_updates = config.check_aur_updates; // be sure we have the good updates alpm_utils.refresh_handle (); - return alpm_utils.get_updates (refresh_files_dbs_on_get_updates); - } - - public async Updates get_updates_async () { - return get_updates (); + return yield alpm_utils.get_updates (refresh_files_dbs_on_get_updates); } void on_emit_get_updates_progress (uint percent) { diff --git a/src/manager_window.vala b/src/manager_window.vala index 6117586a7c24b89261a7e3adb2bf9492a0959add..97ead189064ee6bd2e6c994d6ff1c5d5ec3c8ffb 100644 --- a/src/manager_window.vala +++ b/src/manager_window.vala @@ -109,8 +109,6 @@ namespace Pamac { [GtkChild] Gtk.Label checking_label; [GtkChild] - Gtk.Spinner checking_spinner; - [GtkChild] Gtk.Stack properties_stack; [GtkChild] Gtk.ListBox properties_listbox; @@ -139,6 +137,10 @@ namespace Pamac { [GtkChild] Gtk.ToggleButton install_togglebutton; [GtkChild] + Gtk.ToggleButton build_togglebutton; + [GtkChild] + Gtk.Button reset_files_button; + [GtkChild] Gtk.TextView files_textview; [GtkChild] Gtk.Box transaction_infobox; @@ -202,6 +204,7 @@ namespace Pamac { Gtk.Label pending_label; Gtk.ListBoxRow pending_row; Gtk.ListBoxRow files_row; + Gtk.ListBoxRow build_files_row; bool scroll_to_top; public ManagerWindow (Gtk.Application application) { @@ -374,8 +377,10 @@ namespace Pamac { intern_lock = false; Timeout.add (200, check_extern_lock); - transaction = new TransactionGtk (database, this as Gtk.ApplicationWindow); + transaction = new TransactionGtk (database, this); transaction.no_confirm_upgrade = true; + transaction.start_preparing.connect (on_start_preparing); + transaction.stop_preparing.connect (on_stop_preparing); transaction.start_downloading.connect (on_start_downloading); transaction.stop_downloading.connect (on_stop_downloading); transaction.start_building.connect (on_start_building); @@ -392,6 +397,8 @@ namespace Pamac { // integrate progress box and term widget main_stack.add_named (transaction.term_window, "term"); transaction_infobox.pack_start (transaction.progress_box); + // integrate build files notebook + properties_stack.add_named (transaction.build_files_notebook, "build_files"); display_package_queue = new Queue<string> (); to_install = new GenericSet<string?> (str_hash, str_equal); @@ -707,6 +714,11 @@ namespace Pamac { files_row.visible = true; files_row.add (label); properties_listbox.add (files_row); + label = create_list_label (dgettext (null, "Build files")); + build_files_row = new Gtk.ListBoxRow (); + build_files_row.visible = false; + build_files_row.add (label); + properties_listbox.add (build_files_row); properties_listbox.select_row (properties_listbox.get_row_at_index (0)); } @@ -824,10 +836,6 @@ namespace Pamac { return label as Gtk.Widget; } - void destroy_widget (Gtk.Widget widget) { - widget.destroy (); - } - async Gdk.Pixbuf get_screenshot_pixbuf (string url) { var uri = File.new_for_uri (url); var cached_screenshot = File.new_for_path ("/tmp/pamac-app-screenshots/%s".printf (uri.get_basename ())); @@ -868,7 +876,7 @@ namespace Pamac { return pixbuf; } - void set_package_details (string pkgname, string app_name) { + async void set_package_details (string pkgname, string app_name) { PackageDetails details = database.get_pkg_details (pkgname, app_name); // download screenshot app_screenshot.pixbuf = null; @@ -927,6 +935,8 @@ namespace Pamac { licenses_label.set_text (licenses.str); if (details.installed_version != "") { install_togglebutton.visible = false; + build_togglebutton.visible = false; + reset_files_button.visible = false; remove_togglebutton.visible = true; remove_togglebutton.active = to_remove.contains (details.name); reinstall_togglebutton.visible = false; @@ -937,29 +947,32 @@ namespace Pamac { reinstall_togglebutton.active = to_install.contains (details.name); } } else { - database.get_aur_pkg_details_async.begin (details.name, (obj, res) => { - AURPackageDetails aur_details = database.get_aur_pkg_details_async.end (res); - if (aur_details.name != "") { - // always show reinstall button for VCS package - if (aur_details.name.has_suffix ("-git") || - aur_details.name.has_suffix ("-svn") || - aur_details.name.has_suffix ("-bzr") || - aur_details.name.has_suffix ("-hg") || - aur_details.version == details.version) { - reinstall_togglebutton.visible = true; - reinstall_togglebutton.active = to_build.contains (details.name); - } + AURPackage aur_pkg = yield database.get_aur_pkg (details.name); + if (aur_pkg.name != "") { + // always show reinstall button for VCS package + if (aur_pkg.name.has_suffix ("-git") || + aur_pkg.name.has_suffix ("-svn") || + aur_pkg.name.has_suffix ("-bzr") || + aur_pkg.name.has_suffix ("-hg") || + aur_pkg.version == details.version) { + build_togglebutton.visible = true; + build_togglebutton.active = to_build.contains (details.name); } - }); + build_files_row.visible = true; + string aur_url = "http://aur.archlinux.org/packages/" + details.name; + link_label.set_markup ("<a href=\"%s\">%s</a>\n\n<a href=\"%s\">%s</a>".printf (escaped_url, escaped_url, aur_url, aur_url)); + } } } else { remove_togglebutton.visible = false; reinstall_togglebutton.visible = false; + build_togglebutton.visible = false; + reset_files_button.visible = false; install_togglebutton.visible = true; install_togglebutton.active = to_install.contains (details.name); } // details - details_grid.foreach (destroy_widget); + details_grid.foreach (transaction.destroy_widget); Gtk.Widget? previous_widget = null; if (details.repo != "") { previous_widget = populate_details_grid (dgettext (null, "Repository"), details.repo, previous_widget); @@ -1015,7 +1028,7 @@ namespace Pamac { } details_grid.show_all (); // deps - deps_grid.foreach (destroy_widget); + deps_grid.foreach (transaction.destroy_widget); previous_widget = null; if (details.depends.length () > 0) { previous_widget = populate_dep_grid (dgettext (null, "Depends On"), details.depends, previous_widget); @@ -1061,7 +1074,7 @@ namespace Pamac { } } - void set_aur_details (string pkgname) { + async void set_aur_details (string pkgname) { app_image.pixbuf = null; app_screenshot.pixbuf = null; name_label.set_text (""); @@ -1072,95 +1085,100 @@ namespace Pamac { remove_togglebutton.visible = false; reinstall_togglebutton.visible = false; install_togglebutton.visible = false; + build_togglebutton.visible = false; + reset_files_button.visible = false; properties_listbox.visible = false; - details_grid.foreach (destroy_widget); - deps_grid.foreach (destroy_widget); + details_grid.foreach (transaction.destroy_widget); + deps_grid.foreach (transaction.destroy_widget); this.get_window ().set_cursor (new Gdk.Cursor.for_display (Gdk.Display.get_default (), Gdk.CursorType.WATCH)); while (Gtk.events_pending ()) { Gtk.main_iteration (); } - database.get_aur_pkg_details_async.begin (pkgname, (obj, res) => { - AURPackageDetails details = database.get_aur_pkg_details_async.end (res); - // infos - name_label.set_markup ("<big><b>%s %s</b></big>".printf (details.name, details.version)); - app_image.pixbuf = package_icon; - desc_label.set_text (details.desc); - string aur_url = "http://aur.archlinux.org/packages/" + details.name; - string escaped_url = Markup.escape_text (details.url); - link_label.set_markup ("<a href=\"%s\">%s</a>\n\n<a href=\"%s\">%s</a>".printf (escaped_url, escaped_url, aur_url, aur_url)); - StringBuilder licenses = new StringBuilder (); - licenses.append (dgettext (null, "Licenses")); - licenses.append (":"); - foreach (unowned string license in details.licenses) { - licenses.append (" "); - licenses.append (license); - } - licenses_label.set_text (licenses.str); - install_togglebutton.visible = true; - install_togglebutton.active = to_build.contains (details.name); - Package pkg = database.get_installed_pkg (details.name); - if (pkg.name != "") { - remove_togglebutton.visible = true; - remove_togglebutton.active = to_remove.contains (pkg.name); - } - // details - properties_listbox.visible = true; - details_grid.foreach (destroy_widget); - Gtk.Widget? previous_widget = null; - if (details.packagebase != details.name) { - previous_widget = populate_details_grid (dgettext (null, "Package Base"), details.packagebase, previous_widget); - } - if (details.maintainer != "") { - previous_widget = populate_details_grid (dgettext (null, "Maintainer"), details.maintainer, previous_widget); - } - previous_widget = populate_details_grid (dgettext (null, "First Submitted"), details.firstsubmitted, previous_widget); - previous_widget = populate_details_grid (dgettext (null, "Last Modified"), details.lastmodified, previous_widget); - previous_widget = populate_details_grid (dgettext (null, "Votes"), details.numvotes.to_string (), previous_widget); - if (details.outofdate != "") { - previous_widget = populate_details_grid (dgettext (null, "Out of Date"), details.outofdate, previous_widget); - } - details_grid.show_all (); - // deps - previous_widget = null; - if (details.depends.length () > 0) { - previous_widget = populate_dep_grid (dgettext (null, "Depends On"), details.depends, previous_widget); - } - if (details.makedepends.length () > 0) { - previous_widget = populate_dep_grid (dgettext (null, "Make Dependencies"), details.makedepends, previous_widget); - } - if (details.checkdepends.length () > 0) { - previous_widget = populate_dep_grid (dgettext (null, "Check Dependencies"), details.checkdepends, previous_widget); - } - if (details.optdepends.length () > 0) { - previous_widget = populate_dep_grid (dgettext (null, "Optional Dependencies"), details.optdepends, previous_widget); - } - if (details.provides.length () > 0) { - var label = new Gtk.Label ("<b>%s</b>".printf (dgettext (null, "Provides") + ":")); - label.use_markup = true; - label.halign = Gtk.Align.START; - label.valign = Gtk.Align.START; - label.margin_top = 6; - deps_grid.attach_next_to (label, previous_widget, Gtk.PositionType.BOTTOM); - var box = new Gtk.Box (Gtk.Orientation.VERTICAL, 12); - box.margin = 3; - foreach (unowned string name in details.provides) { - var label2 = new Gtk.Label (name); - label2.halign = Gtk.Align.START; - label2.margin_start = 12; - box.pack_start (label2); - } - deps_grid.attach_next_to (box, label, Gtk.PositionType.RIGHT); - previous_widget = label as Gtk.Widget; - } - if (details.replaces.length () > 0) { - previous_widget = populate_dep_grid (dgettext (null, "Replaces"), details.replaces, previous_widget); - } - if (details.conflicts.length () > 0) { - previous_widget = populate_dep_grid (dgettext (null, "Conflicts With"), details.conflicts, previous_widget); + AURPackageDetails details = yield database.get_aur_pkg_details (pkgname); + // infos + name_label.set_markup ("<big><b>%s %s</b></big>".printf (details.name, details.version)); + app_image.pixbuf = package_icon; + desc_label.set_text (details.desc); + string aur_url = "http://aur.archlinux.org/packages/" + details.name; + string escaped_url = Markup.escape_text (details.url); + link_label.set_markup ("<a href=\"%s\">%s</a>\n\n<a href=\"%s\">%s</a>".printf (escaped_url, escaped_url, aur_url, aur_url)); + StringBuilder licenses = new StringBuilder (); + licenses.append (dgettext (null, "Licenses")); + licenses.append (":"); + foreach (unowned string license in details.licenses) { + licenses.append (" "); + licenses.append (license); + } + licenses_label.set_text (licenses.str); + build_togglebutton.visible = true; + build_togglebutton.active = to_build.contains (details.name); + Package pkg = database.get_installed_pkg (details.name); + if (pkg.name != "") { + remove_togglebutton.visible = true; + remove_togglebutton.active = to_remove.contains (pkg.name); + } + // details + properties_listbox.visible = true; + details_grid.foreach (transaction.destroy_widget); + Gtk.Widget? previous_widget = null; + if (details.packagebase != details.name) { + previous_widget = populate_details_grid (dgettext (null, "Package Base"), details.packagebase, previous_widget); + } + if (details.maintainer != "") { + previous_widget = populate_details_grid (dgettext (null, "Maintainer"), details.maintainer, previous_widget); + } + previous_widget = populate_details_grid (dgettext (null, "First Submitted"), details.firstsubmitted, previous_widget); + previous_widget = populate_details_grid (dgettext (null, "Last Modified"), details.lastmodified, previous_widget); + previous_widget = populate_details_grid (dgettext (null, "Votes"), details.numvotes.to_string (), previous_widget); + if (details.outofdate != "") { + previous_widget = populate_details_grid (dgettext (null, "Out of Date"), details.outofdate, previous_widget); + } + details_grid.show_all (); + // deps + previous_widget = null; + if (details.depends.length () > 0) { + previous_widget = populate_dep_grid (dgettext (null, "Depends On"), details.depends, previous_widget); + } + if (details.makedepends.length () > 0) { + previous_widget = populate_dep_grid (dgettext (null, "Make Dependencies"), details.makedepends, previous_widget); + } + if (details.checkdepends.length () > 0) { + previous_widget = populate_dep_grid (dgettext (null, "Check Dependencies"), details.checkdepends, previous_widget); + } + if (details.optdepends.length () > 0) { + previous_widget = populate_dep_grid (dgettext (null, "Optional Dependencies"), details.optdepends, previous_widget); + } + if (details.provides.length () > 0) { + var label = new Gtk.Label ("<b>%s</b>".printf (dgettext (null, "Provides") + ":")); + label.use_markup = true; + label.halign = Gtk.Align.START; + label.valign = Gtk.Align.START; + label.margin_top = 6; + deps_grid.attach_next_to (label, previous_widget, Gtk.PositionType.BOTTOM); + var box = new Gtk.Box (Gtk.Orientation.VERTICAL, 12); + box.margin = 3; + foreach (unowned string name in details.provides) { + var label2 = new Gtk.Label (name); + label2.halign = Gtk.Align.START; + label2.margin_start = 12; + box.pack_start (label2); } - deps_grid.show_all (); - this.get_window ().set_cursor (null); - }); + deps_grid.attach_next_to (box, label, Gtk.PositionType.RIGHT); + previous_widget = label as Gtk.Widget; + } + if (details.replaces.length () > 0) { + previous_widget = populate_dep_grid (dgettext (null, "Replaces"), details.replaces, previous_widget); + } + if (details.conflicts.length () > 0) { + previous_widget = populate_dep_grid (dgettext (null, "Conflicts With"), details.conflicts, previous_widget); + } + deps_grid.show_all (); + this.get_window ().set_cursor (null); + // build files + // will be populated on properties_stack switch + if (properties_stack.visible_child_name == "build_files") { + on_properties_stack_visible_child_changed (); + } } [GtkCallback] @@ -1168,14 +1186,21 @@ namespace Pamac { int index = row.get_index (); switch (index) { case 0: // details + reset_files_button.visible = false; properties_stack.visible_child_name = "details"; break; case 1: // deps + reset_files_button.visible = false; properties_stack.visible_child_name = "deps"; break; case 2: // files + reset_files_button.visible = false; properties_stack.visible_child_name = "files"; break; + case 3: // build files + reset_files_button.visible = true; + properties_stack.visible_child_name = "build_files"; + break; default: break; } @@ -1185,22 +1210,43 @@ namespace Pamac { void on_install_togglebutton_toggled () { if (install_togglebutton.active) { install_togglebutton.get_style_context ().add_class (Gtk.STYLE_CLASS_SUGGESTED_ACTION); - Package find_pkg = database.get_sync_pkg (current_package_displayed); - if (find_pkg.name != "") { - to_install.add (current_package_displayed); - } else { - to_build.add (current_package_displayed); - } + to_install.add (current_package_displayed); } else { install_togglebutton.get_style_context ().remove_class (Gtk.STYLE_CLASS_SUGGESTED_ACTION); - if (to_install.remove (current_package_displayed)) { - } else { - to_build.remove (current_package_displayed); + to_install.remove (current_package_displayed); + } + set_pendings_operations (); + } + + [GtkCallback] + void on_build_togglebutton_toggled () { + if (build_togglebutton.active) { + build_togglebutton.get_style_context ().add_class (Gtk.STYLE_CLASS_SUGGESTED_ACTION); + to_build.add (current_package_displayed); + if (properties_stack.visible_child_name == "build_files") { + transaction.save_build_files.begin (current_package_displayed); } + } else { + build_togglebutton.get_style_context ().remove_class (Gtk.STYLE_CLASS_SUGGESTED_ACTION); + to_build.remove (current_package_displayed); } set_pendings_operations (); } + [GtkCallback] + void on_reset_files_button_clicked () { + transaction.build_files_notebook.foreach (transaction.destroy_widget); + this.get_window ().set_cursor (new Gdk.Cursor.for_display (Gdk.Display.get_default (), Gdk.CursorType.WATCH)); + while (Gtk.events_pending ()) { + Gtk.main_iteration (); + } + database.get_aur_pkg.begin (current_package_displayed, (obj, res) => { + AURPackage pkg = database.get_aur_pkg.end (res); + transaction.populate_build_files.begin (pkg.packagebase, true); + this.get_window ().set_cursor (null); + }); + } + [GtkCallback] void on_remove_togglebutton_toggled () { if (remove_togglebutton.active) { @@ -1240,16 +1286,7 @@ namespace Pamac { void populate_packages_list (List<Package> pkgs) { // populate liststore - packages_treeview.freeze_notify (); - packages_treeview.freeze_child_notify (); packages_list.clear (); - // scroll to top - if (scroll_to_top) { - packages_scrolledwindow.vadjustment.value = 0; - } else { - // don't scroll to top just once - scroll_to_top = true; - } if (pkgs.length () == 0) { origin_stack.visible_child_name = "no_item"; packages_treeview.thaw_child_notify (); @@ -1263,78 +1300,78 @@ namespace Pamac { } } foreach (unowned Package pkg in pkgs) { - uint origin = 0; - string version; - uint64 size; - string size_str; - string summary; - Gdk.Pixbuf pixbuf = null; - if (pkg.app_name == "") { - summary = "<b>%s</b>\n%s".printf (pkg.name, Markup.escape_text (pkg.desc)); - } else { - summary = "<b>%s (%s)</b>\n%s".printf (Markup.escape_text (pkg.app_name), pkg.name, Markup.escape_text (pkg.desc)); - } - if (filters_stack.visible_child_name == "updates") { - version = "<b>%s</b>\n(%s)".printf (pkg.version, pkg.installed_version); - size = pkg.download_size; - size_str = pkg.download_size == 0 ? "" : GLib.format_size (pkg.download_size); - } else { - version = pkg.version; - size = pkg.size; - size_str = GLib.format_size (pkg.size); - } - if (pkg.icon != "") { + create_packagelist_row (pkg); + } + // scroll to top + if (scroll_to_top) { + packages_scrolledwindow.vadjustment.value = 0; + } else { + // don't scroll to top just once + scroll_to_top = true; + } + this.get_window ().set_cursor (null); + } + + void create_packagelist_row (Package pkg) { + uint origin = 0; + string version; + uint64 size; + string size_str; + string summary; + Gdk.Pixbuf pixbuf = null; + if (pkg.app_name == "") { + summary = "<b>%s</b>\n%s".printf (pkg.name, Markup.escape_text (pkg.desc)); + } else { + summary = "<b>%s (%s)</b>\n%s".printf (Markup.escape_text (pkg.app_name), pkg.name, Markup.escape_text (pkg.desc)); + } + if (filters_stack.visible_child_name == "updates") { + version = "<b>%s</b>\n(%s)".printf (pkg.version, pkg.installed_version); + size = pkg.download_size; + size_str = pkg.download_size == 0 ? "" : GLib.format_size (pkg.download_size); + } else { + version = pkg.version; + size = pkg.size; + size_str = GLib.format_size (pkg.size); + } + if (pkg.icon != "") { + try { + pixbuf = new Gdk.Pixbuf.from_file_at_scale (pkg.icon, 32, 32, true); + } catch (GLib.Error e) { + // some icons are not in the right repo + string icon = pkg.icon; + if ("extra" in pkg.icon) { + icon = pkg.icon.replace ("extra", "community"); + } else if ("community" in pkg.icon) { + icon = pkg.icon.replace ("community", "extra"); + } try { - pixbuf = new Gdk.Pixbuf.from_file_at_scale (pkg.icon, 32, 32, true); + pixbuf = new Gdk.Pixbuf.from_file_at_scale (icon, 32, 32, true); } catch (GLib.Error e) { - // some icons are not in the right repo - string icon = pkg.icon; - if ("extra" in pkg.icon) { - icon = pkg.icon.replace ("extra", "community"); - } else if ("community" in pkg.icon) { - icon = pkg.icon.replace ("community", "extra"); - } - try { - pixbuf = new Gdk.Pixbuf.from_file_at_scale (icon, 32, 32, true); - } catch (GLib.Error e) { - pixbuf = package_icon.scale_simple (32, 32, Gdk.InterpType.BILINEAR); - stderr.printf ("%s: %s\n", pkg.icon, e.message); - } + pixbuf = package_icon.scale_simple (32, 32, Gdk.InterpType.BILINEAR); + stderr.printf ("%s: %s\n", pkg.icon, e.message); } - } else { - pixbuf = package_icon.scale_simple (32, 32, Gdk.InterpType.BILINEAR); - } - if (pkg.installed_version == "") { - origin = 1; } - packages_list.insert_with_values (null, -1, - 0, origin, - 1, pkg.name, - 2, summary, - 3, version, - 4, pkg.repo, - 5, size, - 6, size_str, - 7, pkg.app_name, - 8, pixbuf); - } - packages_treeview.thaw_child_notify (); - packages_treeview.thaw_notify (); - this.get_window ().set_cursor (null); + } else { + pixbuf = package_icon.scale_simple (32, 32, Gdk.InterpType.BILINEAR); + } + if (pkg.installed_version == "") { + origin = 1; + } + packages_list.insert_with_values (null, -1, + 0, origin, + 1, pkg.name, + 2, summary, + 3, version, + 4, pkg.repo, + 5, size, + 6, size_str, + 7, pkg.app_name, + 8, pixbuf); } void populate_aur_list (List<AURPackage> pkgs) { // populate liststore - aur_treeview.freeze_notify (); - aur_treeview.freeze_child_notify (); aur_list.clear (); - // scroll to top - if (scroll_to_top) { - aur_scrolledwindow.vadjustment.value = 0; - } else { - // don't scroll to top just once - scroll_to_top = true; - } if (pkgs.length () == 0) { origin_stack.visible_child_name = "no_item"; aur_treeview.thaw_child_notify (); @@ -1348,28 +1385,37 @@ namespace Pamac { } } foreach (unowned AURPackage aur_pkg in pkgs) { - string version; - if (filters_stack.visible_child_name == "updates") { - version = "<b>%s</b>\n(%s)".printf (aur_pkg.version, aur_pkg.installed_version); - } else if (aur_pkg.installed_version == "") { - version = aur_pkg.version; - } else { - version = aur_pkg.installed_version; - } - aur_list.insert_with_values (null, -1, - 0, aur_pkg.installed_version == "" ? 1 : 0, // installed - 1, aur_pkg.name, - 2, "<b>%s</b>\n%s".printf (aur_pkg.name, Markup.escape_text (aur_pkg.desc)), - 3, version, - 4, aur_pkg.popularity, - 5, "%.2f".printf (aur_pkg.popularity), - 6, package_icon.scale_simple (32, 32, Gdk.InterpType.BILINEAR)); + create_aurlist_row (aur_pkg); + } + // scroll to top + if (scroll_to_top) { + aur_scrolledwindow.vadjustment.value = 0; + } else { + // don't scroll to top just once + scroll_to_top = true; } - aur_treeview.thaw_child_notify (); - aur_treeview.thaw_notify (); this.get_window ().set_cursor (null); } + void create_aurlist_row (AURPackage aur_pkg) { + string version; + if (filters_stack.visible_child_name == "updates") { + version = "<b>%s</b>\n(%s)".printf (aur_pkg.version, aur_pkg.installed_version); + } else if (aur_pkg.installed_version == "") { + version = aur_pkg.version; + } else { + version = aur_pkg.installed_version; + } + aur_list.insert_with_values (null, -1, + 0, aur_pkg.installed_version == "" ? 1 : 0, // installed + 1, aur_pkg.name, + 2, "<b>%s</b>\n%s".printf (aur_pkg.name, Markup.escape_text (aur_pkg.desc)), + 3, version, + 4, aur_pkg.popularity, + 5, "%.2f".printf (aur_pkg.popularity), + 6, package_icon.scale_simple (32, 32, Gdk.InterpType.BILINEAR)); + } + void save_packages_sort_order () { if (restore_sort_order == false) { packages_list.get_sort_column_id (out sort_column_id, out sort_order); @@ -1491,7 +1537,6 @@ namespace Pamac { packages_list.set_sort_column_id (2, Gtk.SortType.ASCENDING); hide_sidebar (); origin_stack.visible_child_name = "checking"; - checking_spinner.active = true; packages_list.clear (); aur_list.clear (); select_all_button.visible = false; @@ -1499,7 +1544,7 @@ namespace Pamac { this.get_window ().set_cursor (new Gdk.Cursor.for_display (Gdk.Display.get_default (), Gdk.CursorType.WATCH)); // let time to hide_sidebar Timeout.add (200, () => { - database.get_updates_async.begin (on_get_updates_finished); + database.get_updates.begin (on_get_updates_finished); return false; }); break; @@ -1528,8 +1573,13 @@ namespace Pamac { void display_package_properties (string pkgname, string app_name = "") { current_package_displayed = pkgname; + // select details if build files was selected + if (properties_listbox.get_selected_row ().get_index () == 3) { + properties_listbox.get_row_at_index (0).activate (); + } files_row.visible = true; - set_package_details (current_package_displayed, app_name); + build_files_row.visible = false; + set_package_details.begin (current_package_displayed, app_name); } void display_aur_properties (string pkgname) { @@ -1539,7 +1589,8 @@ namespace Pamac { properties_listbox.get_row_at_index (0).activate (); } files_row.visible = false; - set_aur_details (current_package_displayed); + build_files_row.visible = true; + set_aur_details.begin (current_package_displayed); } [GtkCallback] @@ -1587,9 +1638,9 @@ namespace Pamac { while (Gtk.events_pending ()) { Gtk.main_iteration (); } - database.get_aur_pkg_details_async.begin (depstring, (obj, res) => { + database.get_aur_pkg.begin (depstring, (obj, res) => { this.get_window ().set_cursor (null); - if (database.get_aur_pkg_details_async.end (res).name != "") { + if (database.get_aur_pkg.end (res).name != "") { display_aur_properties (depstring); } else { var pkg = database.find_installed_satisfier (depstring); @@ -1628,6 +1679,18 @@ namespace Pamac { this.get_window ().set_cursor (null); }); break; + case "build_files": + transaction.build_files_notebook.foreach (transaction.destroy_widget); + this.get_window ().set_cursor (new Gdk.Cursor.for_display (Gdk.Display.get_default (), Gdk.CursorType.WATCH)); + while (Gtk.events_pending ()) { + Gtk.main_iteration (); + } + database.get_aur_pkg.begin (current_package_displayed, (obj, res) => { + AURPackage pkg = database.get_aur_pkg.end (res); + transaction.populate_build_files.begin (pkg.packagebase, false); + this.get_window ().set_cursor (null); + }); + break; default: break; } @@ -1720,8 +1783,8 @@ namespace Pamac { pkg = database.get_sync_pkg (pkgname); } if (pkg.name == "") { - database.get_aur_pkg_details_async.begin (pkgname, (obj, res) => { - if (database.get_aur_pkg_details_async.end (res).name != "") { + database.get_aur_pkg.begin (pkgname, (obj, res) => { + if (database.get_aur_pkg.end (res).name != "") { display_aur_properties (pkgname); } else { pkg = database.find_installed_satisfier (pkgname); @@ -1924,7 +1987,7 @@ namespace Pamac { async void populate_pendings_aur_pkgs () { var aur_pkgs = new List<AURPackage> (); foreach (unowned string pkgname in to_build) { - var aur_pkg = yield database.get_aur_pkg_async (pkgname); + var aur_pkg = yield database.get_aur_pkg (pkgname); if (aur_pkg.name != "") { aur_pkgs.append (aur_pkg); } @@ -1958,9 +2021,9 @@ namespace Pamac { } var pkgs = database.search_pkgs_async.end (res); if (pkgs.length () == 0 && database.config.enable_aur) { - database.search_in_aur_async.begin (search_string, (obj, res) => { + database.search_in_aur.begin (search_string, (obj, res) => { unowned Gtk.ListBoxRow aur_row = search_listbox.get_row_at_index (1); - if (database.search_in_aur_async.end (res).length () > 0) { + if (database.search_in_aur.end (res).length () > 0) { row.activatable = false; row.selectable = false; row.has_focus = false; @@ -1992,8 +2055,8 @@ namespace Pamac { while (Gtk.events_pending ()) { Gtk.main_iteration (); } - database.search_in_aur_async.begin (search_string, (obj, res) => { - populate_aur_list (database.search_in_aur_async.end (res)); + database.search_in_aur.begin (search_string, (obj, res) => { + populate_aur_list (database.search_in_aur.end (res)); }); database.search_pkgs_async.begin (search_string, (obj, res) => { unowned Gtk.ListBoxRow repo_row = search_listbox.get_row_at_index (0); @@ -2566,8 +2629,7 @@ namespace Pamac { transaction.unlock (); if (filters_stack.visible_child_name == "updates") { origin_stack.visible_child_name = "checking"; - checking_spinner.active = true; - database.get_updates_async.begin (on_get_updates_finished); + database.get_updates.begin (on_get_updates_finished); } else { this.get_window ().set_cursor (null); } @@ -2723,7 +2785,7 @@ namespace Pamac { } void on_get_updates_finished (Object? source_object, AsyncResult res) { - var updates = database.get_updates_async.end (res); + var updates = database.get_updates.end (res); // copy updates in lists (keep a ref of them) repos_updates = new List<Package> (); foreach (unowned Package pkg in updates.repos_updates) { @@ -2734,7 +2796,6 @@ namespace Pamac { aur_updates.append (pkg); } origin_stack.visible_child_name = "repos"; - checking_spinner.active = false; if (filters_stack.visible_child_name == "updates") { populate_updates (); } else { @@ -2780,6 +2841,18 @@ namespace Pamac { } } + void on_start_preparing () { + this.get_window ().set_cursor (new Gdk.Cursor.for_display (Gdk.Display.get_default (), Gdk.CursorType.WATCH)); + } + + void on_stop_preparing () { + this.get_window ().set_cursor (null); + // restore build_files_notebook + if (properties_listbox.get_selected_row ().get_index () == 3) { + properties_stack.visible_child_name = "build_files"; + } + } + void on_start_downloading () { cancel_button.sensitive = true; } diff --git a/src/package.vala b/src/package.vala index 29e8b964ef20f524ba32966e77742cd852cccf84..30b2d8e5e6a6d4c643a4bd63d99e8048638db217 100644 --- a/src/package.vala +++ b/src/package.vala @@ -163,12 +163,14 @@ namespace Pamac { public string installed_version { get {return pkg_struct.installed_version;} } public string desc { get {return pkg_struct.desc;} } public double popularity { get {return pkg_struct.popularity;} } + public string packagebase { get {return pkg_struct.packagebase;} } internal AURPackage () { pkg_struct = AURPackageStruct () { name = "", version = "", installed_version = "", - desc = "" + desc = "", + packagebase = "" }; } internal AURPackage.from_struct (owned AURPackageStruct pkg_struct) { diff --git a/src/pamac_config.vala b/src/pamac_config.vala index cccc3731773d268562210473db328433bf133342..93af9ff96773e9cc1b57459d135f3b28db9bb7e6 100644 --- a/src/pamac_config.vala +++ b/src/pamac_config.vala @@ -76,7 +76,7 @@ namespace Pamac { recurse = false; no_update_hide_icon = false; enable_aur = false; - aur_build_dir = "/tmp"; + aur_build_dir = "/var/tmp"; check_aur_updates = false; download_updates = false; clean_keep_num_pkgs = 3; diff --git a/src/preferences_dialog.vala b/src/preferences_dialog.vala index b5dfd2acd0316d76f53a7ec63519201c26bb13d3..1dfd4c34dca1a96a2ab37b3d9df0f693314cf276 100644 --- a/src/preferences_dialog.vala +++ b/src/preferences_dialog.vala @@ -136,9 +136,9 @@ namespace Pamac { aur_build_dir_label.sensitive = transaction.database.config.enable_aur; aur_build_dir_file_chooser.sensitive = transaction.database.config.enable_aur; aur_build_dir_file_chooser.set_filename (transaction.database.config.aur_build_dir); - // add /tmp choice always visible + // add /var/tmp choice always visible try { - aur_build_dir_file_chooser.add_shortcut_folder ("/tmp"); + aur_build_dir_file_chooser.add_shortcut_folder ("/var/tmp"); } catch (GLib.Error e) { stderr.printf ("%s\n", e.message); } diff --git a/src/system_daemon.vala b/src/system_daemon.vala index 84efd392939c8257e50cb6bd128ab9192ecefa0c..d9bcb472720e1e1e17e44b472ddb457476bd4145 100644 --- a/src/system_daemon.vala +++ b/src/system_daemon.vala @@ -39,6 +39,7 @@ public class AlpmAction { namespace Pamac { [DBus (name = "org.manjaro.pamac.system")] public class SystemDaemon: Object { + private Config config; private bool refreshed; private HashTable<string,Variant> new_alpm_conf; private string mirrorlist_country; @@ -55,7 +56,6 @@ namespace Pamac { public signal void emit_log (uint level, string msg); public signal void set_pkgreason_finished (); public signal void refresh_finished (bool success); - public signal void get_updates_finished (UpdatesStruct updates); public signal void downloading_updates_finished (); public signal void trans_prepare_finished (bool success); public signal void trans_commit_finished (bool success); @@ -68,10 +68,11 @@ namespace Pamac { public signal void generate_mirrors_list_finished (); public SystemDaemon () { + config = new Config ("/etc/pamac.conf"); lock_id = new BusName (""); authorized = false; // alpm_utils global variable declared in alpm_utils.vala - alpm_utils = new AlpmUtils (); + alpm_utils = new AlpmUtils (config); lockfile = GLib.File.new_for_path (alpm_utils.alpm_handle.lockfile); check_old_lock (); check_extern_lock (); @@ -99,9 +100,6 @@ namespace Pamac { alpm_utils.refresh_finished.connect ((success) => { refresh_finished (success); }); - alpm_utils.get_updates_finished.connect ((updates) => { - get_updates_finished (updates); - }); alpm_utils.downloading_updates_finished.connect (() => { downloading_updates_finished (); }); @@ -279,15 +277,14 @@ namespace Pamac { public void start_write_pamac_config (HashTable<string,Variant> new_pamac_conf, GLib.BusName sender) throws Error { check_authorization.begin (sender, (obj, res) => { - var pamac_config = new Config ("/etc/pamac.conf"); bool authorized = check_authorization.end (res); if (authorized) { - pamac_config.write (new_pamac_conf); - pamac_config.reload (); + config.write (new_pamac_conf); + config.reload (); } - write_pamac_config_finished (pamac_config.recurse, pamac_config.refresh_period, pamac_config.no_update_hide_icon, - pamac_config.enable_aur, pamac_config.aur_build_dir, pamac_config.check_aur_updates, - pamac_config.download_updates); + write_pamac_config_finished (config.recurse, config.refresh_period, config.no_update_hide_icon, + config.enable_aur, config.aur_build_dir, config.check_aur_updates, + config.download_updates); }); } @@ -423,15 +420,6 @@ namespace Pamac { } } - public void start_get_updates_for_sysupgrade (bool check_aur_updates) throws Error { - alpm_utils.check_aur_updates = check_aur_updates; - try { - thread_pool.add (new AlpmAction (alpm_utils.get_updates_for_sysupgrade)); - } catch (ThreadError e) { - stderr.printf ("Thread Error %s\n", e.message); - } - } - public void start_downloading_updates () throws Error { // do not add this thread to the threadpool so it won't be queued new Thread<int> ("download updates thread", alpm_utils.download_updates); @@ -484,9 +472,7 @@ namespace Pamac { alpm_utils.to_load = to_load; alpm_utils.to_build = to_build; alpm_utils.overwrite_files = overwrite_files; - if (alpm_utils.to_install.length > 0) { - alpm_utils.sysupgrade = true; - } + alpm_utils.sysupgrade = false; if (alpm_utils.downloading_updates) { alpm_utils.cancellable.cancel (); // let time to cancel download updates @@ -501,12 +487,13 @@ namespace Pamac { private void launch_prepare_thread () { if (alpm_utils.to_build.length != 0) { - try { - thread_pool.add (new AlpmAction (alpm_utils.compute_aur_build_list)); - thread_pool.add (new AlpmAction (alpm_utils.build_prepare)); - } catch (ThreadError e) { - stderr.printf ("Thread Error %s\n", e.message); - } + alpm_utils.compute_aur_build_list.begin (() => { + try { + thread_pool.add (new AlpmAction (alpm_utils.build_prepare)); + } catch (ThreadError e) { + stderr.printf ("Thread Error %s\n", e.message); + } + }); } else { try { thread_pool.add (new AlpmAction (alpm_utils.trans_prepare)); diff --git a/src/transaction-cli.vala b/src/transaction-cli.vala index fb6422d89cf1c205b9c0104b4ddc8dd2a9457737..5162941106665b30343235ea7351343f68591ac9 100644 --- a/src/transaction-cli.vala +++ b/src/transaction-cli.vala @@ -454,5 +454,29 @@ namespace Pamac { } return false; } + + protected override async void review_build_files (string pkgname) { + string builddir_name = Path.build_path ("/", database.config.aur_build_dir, "pamac-build", pkgname); + string[] cmds = {"nano", "-S", "-w", "-i"}; + // PKGBUILD + cmds += Path.build_path ("/", builddir_name, "PKGBUILD"); + // other file + var build_dir = File.new_for_path (builddir_name); + try { + FileEnumerator enumerator = yield build_dir.enumerate_children_async ("standard::*", FileQueryInfoFlags.NONE); + FileInfo info; + while ((info = enumerator.next_file (null)) != null) { + unowned string filename = info.get_name (); + if (".install" in filename || ".patch" in filename) { + cmds += Path.build_path ("/", builddir_name, filename); + } + } + var process = new Subprocess.newv (cmds, SubprocessFlags.STDIN_INHERIT); + yield process.wait_async (); + } catch (Error e) { + print ("Error: %s\n", e.message); + } + yield regenerate_srcinfo (pkgname); + } } } diff --git a/src/transaction-gtk.vala b/src/transaction-gtk.vala index 6d17dc1e72c6bd0932911f44b917748651f30c32..3458ebdce4a425ff3cef02070a16e8685c6f2ce1 100644 --- a/src/transaction-gtk.vala +++ b/src/transaction-gtk.vala @@ -29,6 +29,7 @@ namespace Pamac { Vte.Terminal term; Vte.Pty pty; public Gtk.ScrolledWindow term_window; + public Gtk.Notebook build_files_notebook; //parent window public Gtk.ApplicationWindow? application_window { get; construct; } // ask_confirmation option @@ -69,6 +70,10 @@ namespace Pamac { term_window.visible = true; term_window.propagate_natural_height = true; term_window.add (term); + // create build files notebook + build_files_notebook = new Gtk.Notebook (); + build_files_notebook.visible = true; + build_files_notebook.expand = true; // connect to signal emit_action.connect (display_action); emit_action_progress.connect (display_action_progress); @@ -84,6 +89,8 @@ namespace Pamac { sysupgrade_finished.connect (on_finished); start_generating_mirrors_list.connect (start_progressbar_pulse); generate_mirrors_list_finished.connect (reset_progress_box); + start_preparing.connect (start_progressbar_pulse); + stop_preparing.connect (stop_progressbar_pulse); start_building.connect (start_progressbar_pulse); stop_building.connect (stop_progressbar_pulse); write_pamac_config_finished.connect (set_trans_flags); @@ -345,6 +352,138 @@ namespace Pamac { return false; } + public void destroy_widget (Gtk.Widget widget) { + widget.destroy (); + } + + protected override async void review_build_files (string pkgname) { + // remove noteboook from manager_window properties stack + unowned Gtk.Stack? stack = build_files_notebook.get_parent () as Gtk.Stack; + if (stack != null) { + stack.remove (build_files_notebook); + } + // create dialog + var flags = Gtk.DialogFlags.MODAL; + int use_header_bar; + Gtk.Settings.get_default ().get ("gtk-dialogs-use-header", out use_header_bar); + if (use_header_bar == 1) { + flags |= Gtk.DialogFlags.USE_HEADER_BAR; + } + var dialog = new Gtk.Dialog.with_buttons (dgettext (null, "Review %s build files".printf (pkgname)), + application_window, + flags); + dialog.border_width = 6; + dialog.icon_name = "system-software-install"; + unowned Gtk.Widget widget = dialog.add_button (dgettext (null, "_Close"), Gtk.ResponseType.CLOSE); + widget.can_focus = true; + widget.has_focus = true; + widget.can_default = true; + widget.has_default = true; + unowned Gtk.Box box = dialog.get_content_area (); + box.add (build_files_notebook); + dialog.default_width = 700; + dialog.default_height = 500; + // populate notebook + yield populate_build_files (pkgname, false); + // run + dialog.run (); + // re-add noteboook to manager_window properties stack + box.remove (build_files_notebook); + if (stack != null) { + stack.add_named (build_files_notebook, "build_files"); + } + dialog.destroy (); + // save modifications + yield save_build_files (pkgname); + } + + async void create_build_files_tab (File parent, string filename) { + var file = parent.get_child (filename); + if (file.query_exists ()) { + try { + StringBuilder text = new StringBuilder (); + var fis = yield file.read_async (); + var dis = new DataInputStream (fis); + string line; + while ((line = yield dis.read_line_async ()) != null) { + text.append (line); + text.append ("\n"); + } + var scrolled_window = new Gtk.ScrolledWindow (null, null); + scrolled_window.visible = true; + var textview = new Gtk.TextView (); + textview.wrap_mode = Gtk.WrapMode.NONE; + textview.top_margin = 8; + textview.bottom_margin = 8; + textview.left_margin = 8; + textview.right_margin = 8; + textview.buffer.set_text (text.str, (int) text.len); + Gtk.TextIter iter; + textview.buffer.get_start_iter (out iter); + textview.buffer.place_cursor (iter); + textview.visible = true; + scrolled_window.add (textview); + var label = new Gtk.Label (filename); + label.visible = true; + build_files_notebook.append_page (scrolled_window, label); + } catch (GLib.Error e) { + stderr.printf ("%s\n", e.message); + } + } + } + + public async void populate_build_files (string pkgname, bool overwrite) { + build_files_notebook.foreach (destroy_widget); + string clone_dir_name = yield database.clone_build_files (pkgname, overwrite); + if (clone_dir_name != "") { + var clone_dir = File.new_for_path (clone_dir_name); + // PKGBUILD + yield create_build_files_tab (clone_dir, "PKGBUILD"); + // other file + try { + FileEnumerator enumerator = yield clone_dir.enumerate_children_async ("standard::*", FileQueryInfoFlags.NONE); + FileInfo info; + while ((info = enumerator.next_file (null)) != null) { + string filename = info.get_name (); + if (".install" in filename || ".patch" in filename) { + yield create_build_files_tab (clone_dir, filename); + } + } + } catch (Error e) { + print ("Error: %s\n", e.message); + } + } + } + + public async void save_build_files (string pkgname) { + string pkgdir_name = Path.build_path ("/", database.config.aur_build_dir, "pamac-build", pkgname); + int num_pages = build_files_notebook.get_n_pages (); + int index = 0; + while (index < num_pages) { + Gtk.Widget child = build_files_notebook.get_nth_page (index); + string file_name = Path.build_path ("/", pkgdir_name, build_files_notebook.get_tab_label_text (child)); + var scrolled_window = child as Gtk.ScrolledWindow; + var textview = scrolled_window.get_child () as Gtk.TextView; + var file = File.new_for_path (file_name); + Gtk.TextIter start_iter; + Gtk.TextIter end_iter; + textview.buffer.get_start_iter (out start_iter); + textview.buffer.get_end_iter (out end_iter); + try { + // delete the file before rewrite it + yield file.delete_async (); + // creating a DataOutputStream to the file + var dos = new DataOutputStream (yield file.create_async (FileCreateFlags.REPLACE_DESTINATION)); + // writing a string to the stream + dos.put_string (textview.buffer.get_text (start_iter, end_iter, false)); + } catch (GLib.Error e) { + stderr.printf("%s\n", e.message); + } + index++; + } + yield regenerate_srcinfo (pkgname); + } + void show_warnings (bool block) { if (warning_textbuffer.len > 0) { var flags = Gtk.DialogFlags.MODAL; diff --git a/src/transaction.vala b/src/transaction.vala index 21a8d81c09ba2b2b5305a227eaaa7c3c731bb848..984149824372b8c875b13915adaec5fda3956fce 100644 --- a/src/transaction.vala +++ b/src/transaction.vala @@ -31,17 +31,20 @@ namespace Pamac { string current_status; double current_progress; string current_filename; - bool sysupgrade_after_trans; bool no_confirm_commit; bool enable_downgrade; bool sysupgrading; bool force_refresh; - string[] to_install_first; + string[] to_install; + string[] to_remove; + string[] to_load; + string[] to_build; string[] temporary_ignorepkgs; string[] overwrite_files; // building data Queue<string> to_build_queue; string[] aur_pkgs_to_install; + GenericSet<string?> build_files_reviewed; bool building; Cancellable build_cancellable; // download data @@ -62,6 +65,8 @@ namespace Pamac { public signal void emit_script_output (string message); public signal void emit_warning (string message); public signal void emit_error (string message, string[] details); + public signal void start_preparing (); + public signal void stop_preparing (); public signal void start_downloading (); public signal void stop_downloading (); public signal void start_building (); @@ -100,14 +105,13 @@ namespace Pamac { current_action = ""; current_status = ""; current_filename = ""; - sysupgrade_after_trans = false; no_confirm_commit = false; sysupgrading = false; - to_install_first = {}; temporary_ignorepkgs = {}; overwrite_files = {}; // building data to_build_queue = new Queue<string> (); + build_files_reviewed = new GenericSet<string?> (str_hash, str_equal); build_cancellable = new Cancellable (); building = false; // download data @@ -123,6 +127,35 @@ namespace Pamac { return true; } + protected virtual async void review_build_files (string pkgname) { + // nothing + } + + protected async void regenerate_srcinfo (string pkgname) { + string pkgdir_name = Path.build_path ("/", database.config.aur_build_dir, "pamac-build", pkgname); + // generate .SRCINFO + var launcher = new SubprocessLauncher (SubprocessFlags.STDOUT_PIPE); + launcher.set_cwd (pkgdir_name); + try { + Subprocess process = launcher.spawnv ({"makepkg", "--printsrcinfo"}); + yield process.wait_async (); + var dis = new DataInputStream (process.get_stdout_pipe ()); + var file = File.new_for_path (Path.build_path ("/", pkgdir_name, ".SRCINFO")); + try { + // delete the file before rewrite it + yield file.delete_async (); + // creating a DataOutputStream to the file + var dos = new DataOutputStream (yield file.create_async (FileCreateFlags.REPLACE_DESTINATION)); + // writing makepkg output to .SRCINFO + yield dos.splice_async (dis, 0); + } catch (GLib.Error e) { + stderr.printf("%s\n", e.message); + } + } catch (Error e) { + stderr.printf ("Error: %s\n", e.message); + } + } + protected virtual int choose_provider (string depend, string[] providers) { // choose first provider return 0; @@ -206,13 +239,7 @@ namespace Pamac { downloading_updates_finished (); } - void start_get_updates_for_sysupgrade () { - transaction_interface.get_updates_finished.connect (on_get_updates_for_sysupgrade_finished); - transaction_interface.start_get_updates_for_sysupgrade (database.config.check_aur_updates); - } - - void sysupgrade_real (string[] to_build) { - connecting_signals (); + void sysupgrade_real () { // this will respond with trans_prepare_finished signal transaction_interface.start_sysupgrade_prepare (enable_downgrade, temporary_ignorepkgs, to_build, overwrite_files); } @@ -223,49 +250,41 @@ namespace Pamac { this.overwrite_files = overwrite_files; sysupgrading = true; emit_action (dgettext (null, "Starting full system upgrade") + "..."); - start_get_updates_for_sysupgrade (); - } - - void on_get_updates_for_sysupgrade_finished (UpdatesStruct updates_struct) { - transaction_interface.get_updates_finished.disconnect (on_get_updates_for_sysupgrade_finished); - if (updates_struct.syncfirst_repos_updates.length != 0) { - to_install_first = {}; - foreach (unowned PackageStruct infos in updates_struct.syncfirst_repos_updates) { - to_install_first += infos.name; - } - } - string[] to_build = {}; - foreach (unowned AURPackageStruct infos in updates_struct.aur_updates) { - if (!(infos.name in temporary_ignorepkgs)) { - to_build += infos.name; - } + connecting_signals (); + if (database.config.check_aur_updates) { + database.get_aur_updates.begin ((obj, res) => { + var aur_updates = database.get_aur_updates.end (res); + to_build = {}; + foreach (unowned AURPackage aur_update in aur_updates) { + if (!(aur_update.name in temporary_ignorepkgs)) { + to_build += aur_update.name; + } + } + sysupgrade_real (); + }); + } else { + sysupgrade_real (); } - // to_install_first will be read by start_commit - sysupgrade_real (to_build); } - void start_trans_prepare (string[] to_install, string[] to_remove, string[] to_load, string[] to_build) { + void trans_prepare_real () { transaction_interface.start_trans_prepare (flags, to_install, to_remove, to_load, to_build, overwrite_files); } public void start (string[] to_install, string[] to_remove, string[] to_load, string[] to_build, string[] overwrite_files) { + this.to_install = to_install; + this.to_remove = to_remove; + this.to_load = to_load; + this.to_build = to_build; this.overwrite_files = overwrite_files; emit_action (dgettext (null, "Preparing") + "..."); + start_preparing (); connecting_signals (); - start_trans_prepare (to_install, to_remove, to_load, to_build); + trans_prepare_real (); } void start_commit () { - if (to_install_first.length > 0) { - release (); - to_build_queue.clear (); - no_confirm_commit = true; - sysupgrade_after_trans = true; - start_trans_prepare (to_install_first, {}, {}, {}); - to_install_first = {}; - } else { - transaction_interface.start_trans_commit (); - } + transaction_interface.start_trans_commit (); } public virtual async int run_cmd_line (string[] args, string working_directory, Cancellable cancellable) { @@ -303,12 +322,7 @@ namespace Pamac { important_details_outpout (false); string [] built_pkgs = {}; int status = 1; - string builddir; - if (database.config.aur_build_dir == "/tmp") { - builddir = "/tmp/pamac-build-%s".printf (Environment.get_user_name ()); - } else { - builddir = database.config.aur_build_dir; - } + string builddir = Path.build_path ("/", database.config.aur_build_dir, "pamac-build"); status = yield run_cmd_line ({"mkdir", "-p", builddir}, "/", build_cancellable); if (status == 0) { status = yield run_cmd_line ({"rm", "-rf", pkgname}, builddir, build_cancellable); @@ -368,7 +382,12 @@ namespace Pamac { if (status == 0 && built_pkgs.length > 0) { no_confirm_commit = true; emit_script_output (""); - start_trans_prepare ({}, {}, built_pkgs, {}); + to_install = {}; + to_remove = {}; + to_load = built_pkgs; + to_build = {}; + overwrite_files = {}; + trans_prepare_real (); } else { important_details_outpout (true); to_build_queue.clear (); @@ -764,14 +783,6 @@ namespace Pamac { } if (summary_struct.to_build.length > 0) { type |= Type.BUILD; - // populate build queue - foreach (unowned string name in summary_struct.aur_pkgbases_to_build) { - to_build_queue.push_tail (name); - } - aur_pkgs_to_install = {}; - foreach (unowned AURPackageStruct infos in summary_struct.to_build) { - aur_pkgs_to_install += infos.name; - } } if (no_confirm_commit) { no_confirm_commit = false; @@ -779,33 +790,77 @@ namespace Pamac { } else if (type != 0) { var summary = new TransactionSummary (summary_struct); if (ask_confirmation (summary)) { - if (type == Type.BUILD) { - // there only AUR packages to build - release (); - on_trans_commit_finished (true); + if ((type & Type.BUILD) != 0) { + // ask to review build files + string[] build_files_to_review = {}; + foreach (unowned string name in summary_struct.aur_pkgbases_to_build) { + if (!build_files_reviewed.contains (name)) { + build_files_to_review += name; + } + } + if (build_files_to_review.length > 0) { + release (); + review_build_files_and_reprepare.begin (build_files_to_review); + return; + } + // populate build queue + foreach (unowned string name in summary_struct.aur_pkgbases_to_build) { + to_build_queue.push_tail (name); + } + aur_pkgs_to_install = {}; + foreach (unowned AURPackageStruct infos in summary_struct.to_build) { + aur_pkgs_to_install += infos.name; + } + stop_preparing (); + if (type == Type.BUILD) { + // there only AUR packages to build + release (); + on_trans_commit_finished (true); + } else { + start_commit (); + } } else { + stop_preparing (); start_commit (); } } else { + stop_preparing (); emit_action (dgettext (null, "Transaction cancelled") + "."); release (); to_build_queue.clear (); - sysupgrade_after_trans = false; finish_transaction (false); } } else { //var err = ErrorInfos (); //err.message = dgettext (null, "Nothing to do") + "\n"; + stop_preparing (); emit_action (dgettext (null, "Nothing to do") + "."); release (); finish_transaction (true); //handle_error (err); } } else { + stop_preparing (); handle_error (get_current_error ()); } } + async void review_build_files_and_reprepare (string[] build_files_to_review) { + foreach (string name in build_files_to_review) { + yield review_build_files (name); + build_files_reviewed.add (name); + } + emit_script_output (""); + // prepare again + if (sysupgrading) { + emit_action (dgettext (null, "Starting full system upgrade") + "..."); + sysupgrade_real (); + } else { + emit_action (dgettext (null, "Preparing") + "..."); + trans_prepare_real (); + } + } + void launch_build_next_aur_package (bool authorized) { get_authorization_finished.disconnect (launch_build_next_aur_package); if (authorized) { @@ -819,19 +874,13 @@ namespace Pamac { void on_trans_commit_finished (bool success) { if (success) { if (to_build_queue.get_length () != 0) { + build_files_reviewed.remove_all (); emit_script_output (""); get_authorization_finished.connect (launch_build_next_aur_package); start_get_authorization (); } else { - if (sysupgrade_after_trans) { - sysupgrade_after_trans = false; - no_confirm_commit = true; - disconnecting_signals (); - start_sysupgrade (enable_downgrade, temporary_ignorepkgs, {}); - } else { - emit_action (dgettext (null, "Transaction successfully finished") + "."); - finish_transaction (true); - } + emit_action (dgettext (null, "Transaction successfully finished") + "."); + finish_transaction (true); } } else { to_build_queue.clear (); diff --git a/src/transaction_interface.vala b/src/transaction_interface.vala index a589c829f294fc913257e42226d0cdf0d68beae7..428d3a4e04b49d0b30722a7d9445f5eeeed8c08d 100644 --- a/src/transaction_interface.vala +++ b/src/transaction_interface.vala @@ -37,9 +37,7 @@ namespace Pamac { public abstract void start_trans_commit (); public abstract void trans_release (); public abstract void trans_cancel (); - public abstract void start_get_updates_for_sysupgrade (bool check_aur_updates); public abstract void quit_daemon (); - public signal void get_updates_finished (UpdatesStruct updates_struct); public signal void emit_event (uint primary_event, uint secondary_event, string[] details); public signal void emit_providers (string depend, string[] providers); public signal void emit_progress (uint progress, string pkgname, uint percent, uint n_targets, uint current_target); diff --git a/src/transaction_interface_daemon.vala b/src/transaction_interface_daemon.vala index cfbce6f5c3a534a9e34f79517ad23545367ae0e6..ee5537ca109062310ae90c3753dd27ef5724e4fe 100644 --- a/src/transaction_interface_daemon.vala +++ b/src/transaction_interface_daemon.vala @@ -39,10 +39,8 @@ namespace Pamac { public abstract void start_trans_commit () throws Error; public abstract void trans_release () throws Error; public abstract void trans_cancel () throws Error; - public abstract void start_get_updates_for_sysupgrade (bool check_aur_updates) throws Error; [DBus (no_reply = true)] public abstract void quit () throws Error; - public signal void get_updates_finished (UpdatesStruct updates_struct); public signal void emit_event (uint primary_event, uint secondary_event, string[] details); public signal void emit_providers (string depend, string[] providers); public signal void emit_progress (uint progress, string pkgname, uint percent, uint n_targets, uint current_target); @@ -216,20 +214,6 @@ namespace Pamac { downloading_updates_finished (); } - public void start_get_updates_for_sysupgrade (bool check_aur_updates) { - try { - system_daemon.start_get_updates_for_sysupgrade (check_aur_updates); - system_daemon.get_updates_finished.connect (on_get_updates_finished); - } catch (Error e) { - stderr.printf ("start_get_updates: %s\n", e.message); - } - } - - void on_get_updates_finished (UpdatesStruct updates) { - system_daemon.get_updates_finished.disconnect (on_get_updates_finished); - get_updates_finished (updates); - } - void start_sysupgrade_prepare (bool enable_downgrade, string[] temporary_ignorepkgs, string[] to_build, diff --git a/src/transaction_interface_root.vala b/src/transaction_interface_root.vala index 8e8dd298925bf3332cf0e810a893b6eb48d0c68a..6de6257af56fa583195ebd47a5119f173ee0788d 100644 --- a/src/transaction_interface_root.vala +++ b/src/transaction_interface_root.vala @@ -44,9 +44,6 @@ namespace Pamac { alpm_utils.refresh_finished.connect ((success) => { refresh_finished (success); }); - alpm_utils.get_updates_finished.connect ((updates) => { - get_updates_finished (updates); - }); alpm_utils.downloading_updates_finished.connect (() => { downloading_updates_finished (); }); @@ -173,16 +170,6 @@ namespace Pamac { } } - int get_updates_for_sysupgrade () { - alpm_utils.get_updates_for_sysupgrade (); - return 0; - } - - public void start_get_updates_for_sysupgrade (bool check_aur_updates) { - alpm_utils.check_aur_updates = check_aur_updates; - new Thread<int> ("get_updates_for_sysupgrade", get_updates_for_sysupgrade); - } - int download_updates () { alpm_utils.download_updates (); return 0; @@ -229,9 +216,7 @@ namespace Pamac { alpm_utils.to_load = to_load; alpm_utils.to_build = to_build; alpm_utils.overwrite_files = overwrite_files; - if (alpm_utils.to_install.length > 0) { - alpm_utils.sysupgrade = true; - } + alpm_utils.sysupgrade = false; if (alpm_utils.downloading_updates) { alpm_utils.cancellable.cancel (); // let time to cancel download updates @@ -249,15 +234,11 @@ namespace Pamac { return 0; } - int build_prepare () { - alpm_utils.build_prepare (); - return 0; - } - private void launch_prepare () { if (alpm_utils.to_build.length != 0) { - alpm_utils.compute_aur_build_list (); - new Thread<int> ("build_prepare", build_prepare); + alpm_utils.compute_aur_build_list.begin (() => { + alpm_utils.build_prepare (); + }); } else { new Thread<int> ("trans_prepare", trans_prepare); } diff --git a/src/tray.vala b/src/tray.vala index d15c117538f9db60a18f265341ad8375f0b43700..2587b4790467f30b611a7260950b2b8b1e42f711 100644 --- a/src/tray.vala +++ b/src/tray.vala @@ -139,25 +139,27 @@ namespace Pamac { bool check_updates () { if (database.config.refresh_period != 0) { - var updates = database.get_updates (); - updates_nb = updates.repos_updates.length () + updates.aur_updates.length (); - if (updates_nb == 0) { - set_icon (noupdate_icon_name); - set_tooltip (noupdate_info); - set_icon_visible (!database.config.no_update_hide_icon); - close_notification (); - } else { - if (!check_pamac_running () && database.config.download_updates) { - start_system_daemon (); - try { - system_daemon.start_download_updates (); - } catch (Error e) { - stderr.printf ("Error: %s\n", e.message); - } + database.get_updates.begin ((obj, res) => { + var updates = database.get_updates.end (res); + updates_nb = updates.repos_updates.length () + updates.aur_updates.length (); + if (updates_nb == 0) { + set_icon (noupdate_icon_name); + set_tooltip (noupdate_info); + set_icon_visible (!database.config.no_update_hide_icon); + close_notification (); } else { - show_or_update_notification (); + if (!check_pamac_running () && database.config.download_updates) { + start_system_daemon (); + try { + system_daemon.start_download_updates (); + } catch (Error e) { + stderr.printf ("Error: %s\n", e.message); + } + } else { + show_or_update_notification (); + } } - } + }); } return true; }