Graphical package manager for pacman based on pamac 5.x.x
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1621 lines
55KB

  1. /*
  2. * pamac-vala
  3. *
  4. * Copyright (C) 2014-2016 Guillaume Benoit <guillaume@manjaro.org>
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a get of the GNU General Public License
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. namespace Pamac {
  20. [DBus (name = "org.manjaro.pamac")]
  21. interface Daemon : Object {
  22. public abstract void set_environment_variables (HashTable<string,string> variables) throws IOError;
  23. public abstract ErrorInfos get_current_error () throws IOError;
  24. public abstract void start_get_authorization () throws IOError;
  25. public abstract void start_write_pamac_config (HashTable<string,Variant> new_pamac_conf) throws IOError;
  26. public abstract void start_write_alpm_config (HashTable<string,Variant> new_alpm_conf) throws IOError;
  27. public abstract void start_write_mirrors_config (HashTable<string,Variant> new_mirrors_conf) throws IOError;
  28. public abstract void start_generate_mirrors_list () throws IOError;
  29. public abstract void start_set_pkgreason (string pkgname, uint reason) throws IOError;
  30. public abstract AlpmPackage get_installed_pkg (string pkgname) throws IOError;
  31. public abstract void start_refresh (bool force) throws IOError;
  32. public abstract bool get_checkspace () throws IOError;
  33. public abstract string[] get_ignorepkgs () throws IOError;
  34. public abstract bool should_hold (string pkgname) throws IOError;
  35. public abstract uint get_pkg_reason (string pkgname) throws IOError;
  36. public abstract uint get_pkg_origin (string pkgname) throws IOError;
  37. public abstract async AlpmPackage[] get_installed_pkgs () throws IOError;
  38. public abstract async AlpmPackage[] get_foreign_pkgs () throws IOError;
  39. public abstract async AlpmPackage[] get_orphans () throws IOError;
  40. public abstract AlpmPackage find_installed_satisfier (string depstring) throws IOError;
  41. public abstract AlpmPackage get_sync_pkg (string pkgname) throws IOError;
  42. public abstract AlpmPackage find_sync_satisfier (string depstring) throws IOError;
  43. public abstract async AlpmPackage[] search_pkgs (string search_string) throws IOError;
  44. public abstract async AURPackage[] search_in_aur (string search_string) throws IOError;
  45. public abstract async string[] get_aur_build_list (string pkgname) throws IOError;
  46. public abstract string[] get_repos_names () throws IOError;
  47. public abstract async AlpmPackage[] get_repo_pkgs (string repo) throws IOError;
  48. public abstract string[] get_groups_names () throws IOError;
  49. public abstract async AlpmPackage[] get_group_pkgs (string groupname) throws IOError;
  50. public abstract AlpmPackageDetails get_pkg_details (string pkgname) throws IOError;
  51. public abstract async AURPackageDetails get_aur_details (string pkgname) throws IOError;
  52. public abstract string[] get_pkg_uninstalled_optdeps (string pkgname) throws IOError;
  53. public abstract void add_ignorepkg (string pkgname) throws IOError;
  54. public abstract void remove_ignorepkg (string pkgname) throws IOError;
  55. public abstract void start_get_updates (bool check_aur_updates) throws IOError;
  56. public abstract bool trans_init (int transflags) throws IOError;
  57. public abstract bool trans_sysupgrade (bool enable_downgrade) throws IOError;
  58. public abstract bool trans_add_pkg (string pkgname) throws IOError;
  59. public abstract bool trans_remove_pkg (string pkgname) throws IOError;
  60. public abstract bool trans_load_pkg (string pkgpath) throws IOError;
  61. public abstract void start_trans_prepare () throws IOError;
  62. public abstract void choose_provider (int provider) throws IOError;
  63. public abstract TransactionSummary get_transaction_summary () throws IOError;
  64. public abstract void start_trans_commit () throws IOError;
  65. public abstract void trans_release () throws IOError;
  66. [DBus (no_reply = true)]
  67. public abstract void trans_cancel () throws IOError;
  68. [DBus (no_reply = true)]
  69. public abstract void quit () throws IOError;
  70. public signal void emit_event (uint primary_event, uint secondary_event, string[] details);
  71. public signal void emit_providers (string depend, string[] providers);
  72. public signal void emit_progress (uint progress, string pkgname, uint percent, uint n_targets, uint current_target);
  73. public signal void emit_download (string filename, uint64 xfered, uint64 total);
  74. public signal void emit_totaldownload (uint64 total);
  75. public signal void emit_log (uint level, string msg);
  76. public signal void set_pkgreason_finished ();
  77. public signal void refresh_finished (bool success);
  78. public signal void get_updates_finished (Updates updates);
  79. public signal void trans_prepare_finished (bool success);
  80. public signal void trans_commit_finished (bool success);
  81. public signal void get_authorization_finished (bool authorized);
  82. public signal void write_pamac_config_finished (bool recurse, uint64 refresh_period, bool no_update_hide_icon,
  83. bool enable_aur, bool search_aur, bool check_aur_updates,
  84. bool no_confirm_build);
  85. public signal void write_alpm_config_finished (bool checkspace);
  86. public signal void write_mirrors_config_finished (string choosen_country, string choosen_generation_method);
  87. public signal void generate_mirrors_list_data (string line);
  88. public signal void generate_mirrors_list_finished ();
  89. }
  90. public enum Mode {
  91. MANAGER,
  92. UPDATER
  93. }
  94. public class Transaction: Object {
  95. enum Type {
  96. STANDARD = (1 << 0),
  97. UPDATE = (1 << 1),
  98. BUILD = (1 << 2)
  99. }
  100. Daemon daemon;
  101. Pamac.Config pamac_config;
  102. public bool check_aur_updates { get { return pamac_config.check_aur_updates; } }
  103. public bool enable_aur { get { return pamac_config.enable_aur; } }
  104. public unowned GLib.HashTable<string,string> environment_variables { get {return pamac_config.environment_variables; } }
  105. public bool no_confirm_build { get { return pamac_config.no_confirm_build; } }
  106. public bool no_update_hide_icon { get { return pamac_config.no_update_hide_icon; } }
  107. public bool recurse { get { return pamac_config.no_confirm_build; } }
  108. public uint64 refresh_period { get { return pamac_config.refresh_period; } }
  109. public bool search_aur { get { return pamac_config.search_aur; } }
  110. //Alpm.TransFlag
  111. int flags;
  112. public GenericSet<string?> to_install;
  113. public GenericSet<string?> to_remove;
  114. public GenericSet<string?> to_load;
  115. public GenericSet<string?> to_build;
  116. GenericSet<string?> previous_to_install;
  117. GenericSet<string?> previous_to_remove;
  118. public GenericSet<string?> transaction_summary;
  119. public GenericSet<string?> temporary_ignorepkgs;
  120. public Mode mode { get; set; }
  121. uint64 total_download;
  122. uint64 already_downloaded;
  123. string previous_textbar;
  124. float previous_percent;
  125. string previous_filename;
  126. uint pulse_timeout_id;
  127. bool sysupgrade_after_trans;
  128. bool enable_downgrade;
  129. uint64 previous_xfered;
  130. uint64 download_rate;
  131. uint64 rates_nb;
  132. Timer timer;
  133. bool success;
  134. //dialogs
  135. TransactionSumDialog transaction_sum_dialog;
  136. TransactionInfoDialog transaction_info_dialog;
  137. ProgressDialog progress_dialog;
  138. //parent window
  139. public Gtk.ApplicationWindow? application_window { get; private set; }
  140. public signal void start_transaction ();
  141. public signal void emit_action (string action);
  142. public signal void alpm_handle_refreshed ();
  143. public signal void finished (bool success);
  144. public signal void set_pkgreason_finished ();
  145. public signal void get_updates_finished (Updates updates);
  146. public signal void write_pamac_config_finished (bool recurse, uint64 refresh_period, bool no_update_hide_icon,
  147. bool enable_aur, bool search_aur, bool check_aur_updates,
  148. bool no_confirm_build);
  149. public signal void write_alpm_config_finished (bool checkspace);
  150. public signal void write_mirrors_config_finished (string choosen_country, string choosen_generation_method);
  151. public Transaction (Gtk.ApplicationWindow? application_window) {
  152. pamac_config = new Pamac.Config ("/etc/pamac.conf");
  153. flags = (1 << 4); //Alpm.TransFlag.CASCADE
  154. if (pamac_config.recurse) {
  155. flags |= (1 << 5); //Alpm.TransFlag.RECURSE
  156. }
  157. to_install = new GenericSet<string?> (str_hash, str_equal);
  158. to_remove = new GenericSet<string?> (str_hash, str_equal);
  159. to_load = new GenericSet<string?> (str_hash, str_equal);
  160. to_build = new GenericSet<string?> (str_hash, str_equal);
  161. previous_to_install = new GenericSet<string?> (str_hash, str_equal);
  162. previous_to_remove = new GenericSet<string?> (str_hash, str_equal);
  163. transaction_summary = new GenericSet<string?> (str_hash, str_equal);
  164. temporary_ignorepkgs = new GenericSet<string?> (str_hash, str_equal);
  165. connecting_dbus_signals ();
  166. //creating dialogs
  167. this.application_window = application_window;
  168. transaction_sum_dialog = new TransactionSumDialog (application_window);
  169. transaction_info_dialog = new TransactionInfoDialog (application_window);
  170. progress_dialog = new ProgressDialog (application_window);
  171. progress_dialog.close_button.clicked.connect (hide_progress);
  172. progress_dialog.delete_event.connect (progress_dialog.hide_on_delete);
  173. progress_dialog.cancel_button.clicked.connect (on_progress_dialog_cancel_button_clicked);
  174. // connect to child_exited signal which will only be emit after a call to watch_child
  175. progress_dialog.term.child_exited.connect (on_term_child_exited);
  176. // progress data
  177. previous_textbar = "";
  178. previous_filename = "";
  179. sysupgrade_after_trans = false;
  180. timer = new Timer ();
  181. success = false;
  182. }
  183. public async void run_preferences_dialog () {
  184. SourceFunc callback = run_preferences_dialog.callback;
  185. ulong handler_id = daemon.get_authorization_finished.connect ((authorized) => {
  186. if (authorized) {
  187. var preferences_dialog = new PreferencesDialog (this);
  188. preferences_dialog.run ();
  189. preferences_dialog.destroy ();
  190. while (Gtk.events_pending ()) {
  191. Gtk.main_iteration ();
  192. }
  193. }
  194. Idle.add((owned) callback);
  195. });
  196. start_get_authorization ();
  197. yield;
  198. daemon.disconnect (handler_id);
  199. }
  200. public ErrorInfos get_current_error () {
  201. try {
  202. return daemon.get_current_error ();
  203. } catch (IOError e) {
  204. stderr.printf ("IOError: %s\n", e.message);
  205. return ErrorInfos ();
  206. }
  207. }
  208. public void start_get_authorization () {
  209. try {
  210. daemon.start_get_authorization ();
  211. } catch (IOError e) {
  212. stderr.printf ("IOError: %s\n", e.message);
  213. }
  214. }
  215. public void start_write_pamac_config (HashTable<string,Variant> new_pamac_conf) {
  216. try {
  217. daemon.start_write_pamac_config (new_pamac_conf);
  218. } catch (IOError e) {
  219. stderr.printf ("IOError: %s\n", e.message);
  220. }
  221. }
  222. public void start_write_alpm_config (HashTable<string,Variant> new_alpm_conf) {
  223. try {
  224. daemon.start_write_alpm_config (new_alpm_conf);
  225. } catch (IOError e) {
  226. stderr.printf ("IOError: %s\n", e.message);
  227. }
  228. }
  229. public void start_write_mirrors_config (HashTable<string,Variant> new_mirrors_conf) {
  230. try {
  231. daemon.start_write_mirrors_config (new_mirrors_conf);
  232. } catch (IOError e) {
  233. stderr.printf ("IOError: %s\n", e.message);
  234. }
  235. }
  236. public void show_progress () {
  237. progress_dialog.show ();
  238. }
  239. public void hide_progress () {
  240. progress_dialog.hide ();
  241. }
  242. void reset_progress_dialog (string action,
  243. bool cancel_button_visible = true,
  244. bool expander_expanded = false) {
  245. progress_dialog.spawn_in_term ({"echo", action});
  246. progress_dialog.action_label.label = action;
  247. progress_dialog.progressbar.fraction = 0;
  248. progress_dialog.progressbar.text = "";
  249. progress_dialog.cancel_button.visible = cancel_button_visible;
  250. progress_dialog.expander.expanded = expander_expanded;
  251. if (expander_expanded) {
  252. progress_dialog.width_request = 700;
  253. }
  254. }
  255. public void start_generate_mirrors_list () {
  256. string action = dgettext (null, "Refreshing mirrors list") + "...";
  257. reset_progress_dialog (action, false, true);
  258. pulse_timeout_id = Timeout.add (500, (GLib.SourceFunc) progress_dialog.progressbar.pulse);
  259. progress_dialog.show ();
  260. while (Gtk.events_pending ()) {
  261. Gtk.main_iteration ();
  262. }
  263. try {
  264. daemon.start_generate_mirrors_list ();
  265. } catch (IOError e) {
  266. stderr.printf ("IOError: %s\n", e.message);
  267. Source.remove (pulse_timeout_id);
  268. }
  269. }
  270. public void start_set_pkgreason (string pkgname, uint reason) {
  271. try {
  272. daemon.start_set_pkgreason (pkgname, reason);
  273. } catch (IOError e) {
  274. stderr.printf ("IOError: %s\n", e.message);
  275. }
  276. }
  277. public void start_refresh (bool force) {
  278. string action = dgettext (null, "Synchronizing package databases") + "...";
  279. reset_progress_dialog (action);
  280. emit_action (action);
  281. if (mode != Mode.MANAGER) {
  282. progress_dialog.show ();
  283. while (Gtk.events_pending ()) {
  284. Gtk.main_iteration ();
  285. }
  286. }
  287. try {
  288. daemon.refresh_finished.connect (on_refresh_finished);
  289. daemon.start_refresh (force);
  290. } catch (IOError e) {
  291. stderr.printf ("IOError: %s\n", e.message);
  292. daemon.refresh_finished.disconnect (on_refresh_finished);
  293. success = false;
  294. finish_transaction ();
  295. }
  296. }
  297. public bool get_checkspace () {
  298. bool checkspace = false;
  299. try {
  300. checkspace = daemon.get_checkspace ();
  301. } catch (IOError e) {
  302. stderr.printf ("IOError: %s\n", e.message);
  303. }
  304. return checkspace;
  305. }
  306. public string[] get_ignorepkgs () {
  307. string[] ignorepkgs = {};
  308. try {
  309. ignorepkgs = daemon.get_ignorepkgs ();
  310. } catch (IOError e) {
  311. stderr.printf ("IOError: %s\n", e.message);
  312. }
  313. return ignorepkgs;
  314. }
  315. public AlpmPackage get_installed_pkg (string pkgname) {
  316. try {
  317. return daemon.get_installed_pkg (pkgname);
  318. } catch (IOError e) {
  319. stderr.printf ("IOError: %s\n", e.message);
  320. return AlpmPackage () {
  321. name = "",
  322. version = "",
  323. desc = "",
  324. repo = ""
  325. };
  326. }
  327. }
  328. public AlpmPackage find_installed_satisfier (string depstring) {
  329. try {
  330. return daemon.find_installed_satisfier (depstring);
  331. } catch (IOError e) {
  332. stderr.printf ("IOError: %s\n", e.message);
  333. return AlpmPackage () {
  334. name = "",
  335. version = "",
  336. desc = "",
  337. repo = ""
  338. };
  339. }
  340. }
  341. public bool should_hold (string pkgname) {
  342. bool should_hold = false;
  343. try {
  344. should_hold = daemon.should_hold (pkgname);
  345. } catch (IOError e) {
  346. stderr.printf ("IOError: %s\n", e.message);
  347. }
  348. return should_hold;
  349. }
  350. public uint get_pkg_reason (string pkgname) {
  351. uint reason = 0;
  352. try {
  353. reason = daemon.get_pkg_reason (pkgname);
  354. } catch (IOError e) {
  355. stderr.printf ("IOError: %s\n", e.message);
  356. }
  357. return reason;
  358. }
  359. public uint get_pkg_origin (string pkgname) {
  360. uint origin = 0;
  361. try {
  362. origin = daemon.get_pkg_origin (pkgname);
  363. } catch (IOError e) {
  364. stderr.printf ("IOError: %s\n", e.message);
  365. }
  366. return origin;
  367. }
  368. public async AlpmPackage[] get_installed_pkgs () {
  369. AlpmPackage[] pkgs = {};
  370. try {
  371. pkgs = yield daemon.get_installed_pkgs ();
  372. } catch (IOError e) {
  373. stderr.printf ("IOError: %s\n", e.message);
  374. }
  375. return pkgs;
  376. }
  377. public async AlpmPackage[] get_foreign_pkgs () {
  378. AlpmPackage[] pkgs = {};
  379. try {
  380. pkgs = yield daemon.get_foreign_pkgs ();
  381. } catch (IOError e) {
  382. stderr.printf ("IOError: %s\n", e.message);
  383. }
  384. return pkgs;
  385. }
  386. public async AlpmPackage[] get_orphans () {
  387. AlpmPackage[] pkgs = {};
  388. try {
  389. pkgs = yield daemon.get_orphans ();
  390. } catch (IOError e) {
  391. stderr.printf ("IOError: %s\n", e.message);
  392. }
  393. return pkgs;
  394. }
  395. public AlpmPackage get_sync_pkg (string pkgname) {
  396. try {
  397. return daemon.get_sync_pkg (pkgname);
  398. } catch (IOError e) {
  399. stderr.printf ("IOError: %s\n", e.message);
  400. return AlpmPackage () {
  401. name = "",
  402. version = "",
  403. desc = "",
  404. repo = ""
  405. };
  406. }
  407. }
  408. public AlpmPackage find_sync_satisfier (string depstring) {
  409. try {
  410. return daemon.find_sync_satisfier (depstring);
  411. } catch (IOError e) {
  412. stderr.printf ("IOError: %s\n", e.message);
  413. return AlpmPackage () {
  414. name = "",
  415. version = "",
  416. desc = "",
  417. repo = ""
  418. };
  419. }
  420. }
  421. public async AlpmPackage[] search_pkgs (string search_string) {
  422. AlpmPackage[] pkgs = {};
  423. try {
  424. pkgs = yield daemon.search_pkgs (search_string);
  425. } catch (IOError e) {
  426. stderr.printf ("IOError: %s\n", e.message);
  427. }
  428. return pkgs;
  429. }
  430. public async AURPackage[] search_in_aur (string search_string) {
  431. AURPackage[] pkgs = {};
  432. try {
  433. pkgs = yield daemon.search_in_aur (search_string);
  434. } catch (IOError e) {
  435. stderr.printf ("IOError: %s\n", e.message);
  436. }
  437. return pkgs;
  438. }
  439. public async string[] get_aur_build_list (string pkgname) {
  440. string[] names = {};
  441. try {
  442. names = yield daemon.get_aur_build_list (pkgname);
  443. } catch (IOError e) {
  444. stderr.printf ("IOError: %s\n", e.message);
  445. }
  446. return names;
  447. }
  448. public string[] get_repos_names () {
  449. string[] repos_names = {};
  450. try {
  451. repos_names = daemon.get_repos_names ();
  452. } catch (IOError e) {
  453. stderr.printf ("IOError: %s\n", e.message);
  454. }
  455. return repos_names;
  456. }
  457. public async AlpmPackage[] get_repo_pkgs (string repo) {
  458. AlpmPackage[] pkgs = {};
  459. try {
  460. pkgs = yield daemon.get_repo_pkgs (repo);
  461. } catch (IOError e) {
  462. stderr.printf ("IOError: %s\n", e.message);
  463. }
  464. return pkgs;
  465. }
  466. public string[] get_groups_names () {
  467. string[] groups_names = {};
  468. try {
  469. groups_names = daemon.get_groups_names ();
  470. } catch (IOError e) {
  471. stderr.printf ("IOError: %s\n", e.message);
  472. }
  473. return groups_names;
  474. }
  475. public async AlpmPackage[] get_group_pkgs (string group_name) {
  476. AlpmPackage[] pkgs = {};
  477. try {
  478. pkgs = yield daemon.get_group_pkgs (group_name);
  479. } catch (IOError e) {
  480. stderr.printf ("IOError: %s\n", e.message);
  481. }
  482. return pkgs;
  483. }
  484. public string[] get_pkg_uninstalled_optdeps (string pkgname) {
  485. string[] optdeps = {};
  486. try {
  487. optdeps = daemon.get_pkg_uninstalled_optdeps (pkgname);
  488. } catch (IOError e) {
  489. stderr.printf ("IOError: %s\n", e.message);
  490. }
  491. return optdeps;
  492. }
  493. public AlpmPackageDetails get_pkg_details (string pkgname) {
  494. try {
  495. return daemon.get_pkg_details (pkgname);
  496. } catch (IOError e) {
  497. stderr.printf ("IOError: %s\n", e.message);
  498. return AlpmPackageDetails () {
  499. name = "",
  500. version = "",
  501. desc = "",
  502. repo = "",
  503. url = "",
  504. packager = "",
  505. builddate = "",
  506. installdate = "",
  507. reason = "",
  508. has_signature = ""
  509. };
  510. }
  511. }
  512. public async AURPackageDetails get_aur_details (string pkgname) {
  513. var pkg = AURPackageDetails () {
  514. name = "",
  515. version = "",
  516. desc = "",
  517. packagebase = "",
  518. url = "",
  519. maintainer = ""
  520. };
  521. try {
  522. pkg = yield daemon.get_aur_details (pkgname);
  523. } catch (IOError e) {
  524. stderr.printf ("IOError: %s\n", e.message);
  525. }
  526. return pkg;
  527. }
  528. public void start_get_updates () {
  529. daemon.get_updates_finished.connect (on_get_updates_finished);
  530. try {
  531. daemon.start_get_updates (pamac_config.enable_aur && pamac_config.check_aur_updates);
  532. } catch (IOError e) {
  533. stderr.printf ("IOError: %s\n", e.message);
  534. success = false;
  535. finish_transaction ();
  536. }
  537. }
  538. void start_get_updates_for_sysupgrade () {
  539. daemon.get_updates_finished.connect (on_get_updates_for_sysupgrade_finished);
  540. try {
  541. daemon.start_get_updates (pamac_config.enable_aur && pamac_config.check_aur_updates);
  542. } catch (IOError e) {
  543. stderr.printf ("IOError: %s\n", e.message);
  544. success = false;
  545. finish_transaction ();
  546. }
  547. }
  548. public void add_ignorepkg (string pkgname) {
  549. try {
  550. daemon.add_ignorepkg (pkgname);
  551. //temporary_ignorepkgs.add (pkgname);
  552. } catch (IOError e) {
  553. stderr.printf ("IOError: %s\n", e.message);
  554. }
  555. }
  556. public void remove_ignorepkg (string pkgname) {
  557. try {
  558. daemon.remove_ignorepkg (pkgname);
  559. } catch (IOError e) {
  560. stderr.printf ("IOError: %s\n", e.message);
  561. }
  562. }
  563. public bool init (int flags) {
  564. foreach (unowned string pkgname in temporary_ignorepkgs) {
  565. add_ignorepkg (pkgname);
  566. }
  567. try {
  568. return daemon.trans_init (flags);
  569. } catch (IOError e) {
  570. stderr.printf ("IOError: %s\n", e.message);
  571. return false;
  572. }
  573. }
  574. void sysupgrade_simple (bool enable_downgrade) {
  575. progress_dialog.progressbar.fraction = 0;
  576. progress_dialog.cancel_button.visible = true;
  577. success = init (0);
  578. if (success) {
  579. try {
  580. success = daemon.trans_sysupgrade (enable_downgrade);
  581. } catch (IOError e) {
  582. stderr.printf ("IOError: %s\n", e.message);
  583. success = false;
  584. }
  585. if (success) {
  586. if (mode != Mode.MANAGER) {
  587. progress_dialog.show ();
  588. while (Gtk.events_pending ()) {
  589. Gtk.main_iteration ();
  590. }
  591. }
  592. try {
  593. daemon.start_trans_prepare ();
  594. } catch (IOError e) {
  595. stderr.printf ("IOError: %s\n", e.message);
  596. release ();
  597. success = false;
  598. finish_transaction ();
  599. }
  600. } else {
  601. release ();
  602. handle_error (get_current_error ());
  603. }
  604. } else {
  605. handle_error (get_current_error ());
  606. }
  607. }
  608. public void sysupgrade (bool enable_downgrade) {
  609. this.enable_downgrade = enable_downgrade;
  610. string action = dgettext (null, "Starting full system upgrade") + "...";
  611. reset_progress_dialog (action);
  612. emit_action (action);
  613. start_get_updates_for_sysupgrade ();
  614. }
  615. void on_get_updates_finished (Updates updates) {
  616. daemon.get_updates_finished.disconnect (on_get_updates_finished);
  617. get_updates_finished (updates);
  618. }
  619. void on_get_updates_for_sysupgrade_finished (Updates updates) {
  620. daemon.get_updates_finished.disconnect (on_get_updates_for_sysupgrade_finished);
  621. // get syncfirst updates
  622. if (updates.is_syncfirst) {
  623. clear_lists ();
  624. if (mode == Mode.MANAGER) {
  625. sysupgrade_after_trans = true;
  626. }
  627. foreach (unowned UpdateInfos infos in updates.repos_updates) {
  628. to_install.add (infos.name);
  629. }
  630. // run as a standard transaction
  631. run ();
  632. } else {
  633. if (updates.aur_updates.length != 0) {
  634. clear_lists ();
  635. foreach (unowned UpdateInfos infos in updates.aur_updates) {
  636. if (!(infos.name in temporary_ignorepkgs)) {
  637. to_build.add (infos.name);
  638. }
  639. }
  640. }
  641. if (updates.repos_updates.length != 0) {
  642. sysupgrade_simple (enable_downgrade);
  643. } else {
  644. on_trans_prepare_finished (true);
  645. }
  646. }
  647. }
  648. public void clear_lists () {
  649. to_install.remove_all ();
  650. to_remove.remove_all ();
  651. to_build.remove_all ();
  652. }
  653. void clear_previous_lists () {
  654. previous_to_install.remove_all ();
  655. previous_to_remove.remove_all ();
  656. }
  657. public void run () {
  658. string action = dgettext (null, "Preparing") + "...";
  659. reset_progress_dialog (action);
  660. emit_action (action);
  661. if (mode != Mode.MANAGER) {
  662. progress_dialog.show ();
  663. while (Gtk.events_pending ()) {
  664. Gtk.main_iteration ();
  665. }
  666. }
  667. // run
  668. if (to_install.length == 0
  669. && to_remove.length == 0
  670. && to_load.length == 0
  671. && to_build.length != 0) {
  672. // there only AUR packages to build so no need to prepare transaction
  673. on_trans_prepare_finished (true);
  674. } else {
  675. success = false;
  676. try {
  677. success = daemon.trans_init (flags);
  678. } catch (IOError e) {
  679. stderr.printf ("IOError: %s\n", e.message);
  680. }
  681. if (success) {
  682. success = false;
  683. foreach (unowned string name in to_install) {
  684. try {
  685. success = daemon.trans_add_pkg (name);
  686. } catch (IOError e) {
  687. stderr.printf ("IOError: %s\n", e.message);
  688. }
  689. if (!success) {
  690. break;
  691. }
  692. }
  693. foreach (unowned string name in to_remove) {
  694. try {
  695. success = daemon.trans_remove_pkg (name);
  696. } catch (IOError e) {
  697. stderr.printf ("IOError: %s\n", e.message);
  698. }
  699. if (!success) {
  700. break;
  701. }
  702. }
  703. foreach (unowned string path in to_load) {
  704. try {
  705. success = daemon.trans_load_pkg (path);
  706. } catch (IOError e) {
  707. stderr.printf ("IOError: %s\n", e.message);
  708. }
  709. if (!success) {
  710. break;
  711. }
  712. }
  713. if (success) {
  714. try {
  715. daemon.start_trans_prepare ();
  716. } catch (IOError e) {
  717. stderr.printf ("IOError: %s\n", e.message);
  718. release ();
  719. success = false;
  720. finish_transaction ();
  721. }
  722. } else {
  723. release ();
  724. handle_error (get_current_error ());
  725. }
  726. } else {
  727. handle_error (get_current_error ());
  728. }
  729. }
  730. }
  731. void choose_provider (string depend, string[] providers) {
  732. var choose_provider_dialog = new ChooseProviderDialog (application_window);
  733. choose_provider_dialog.label.set_markup ("<b>%s</b>".printf (dgettext (null, "Choose a provider for %s").printf (depend)));
  734. foreach (unowned string provider in providers) {
  735. choose_provider_dialog.comboboxtext.append_text (provider);
  736. }
  737. choose_provider_dialog.comboboxtext.active = 0;
  738. choose_provider_dialog.run ();
  739. try {
  740. daemon.choose_provider (choose_provider_dialog.comboboxtext.active);
  741. } catch (IOError e) {
  742. stderr.printf ("IOError: %s\n", e.message);
  743. }
  744. choose_provider_dialog.destroy ();
  745. while (Gtk.events_pending ()) {
  746. Gtk.main_iteration ();
  747. }
  748. }
  749. Type set_transaction_sum () {
  750. // return 0 if transaction_sum is empty, 2, if there are only aur updates, 1 otherwise
  751. Type type = 0;
  752. uint64 dsize = 0;
  753. transaction_summary.remove_all ();
  754. var summary = TransactionSummary ();
  755. transaction_sum_dialog.top_label.set_markup ("<big><b>%s</b></big>".printf (dgettext (null, "Transaction Summary")));
  756. transaction_sum_dialog.sum_list.clear ();
  757. try {
  758. summary = daemon.get_transaction_summary ();
  759. } catch (IOError e) {
  760. stderr.printf ("IOError: %s\n", e.message);
  761. }
  762. var iter = Gtk.TreeIter ();
  763. if (summary.to_remove.length > 0) {
  764. type |= Type.STANDARD;
  765. foreach (unowned UpdateInfos infos in summary.to_remove) {
  766. transaction_summary.add (infos.name);
  767. transaction_sum_dialog.sum_list.insert_with_values (out iter, -1,
  768. 1, infos.name,
  769. 2, infos.old_version);
  770. }
  771. Gtk.TreePath path = transaction_sum_dialog.sum_list.get_path (iter);
  772. int pos = (path.get_indices ()[0]) - (summary.to_remove.length - 1);
  773. transaction_sum_dialog.sum_list.get_iter (out iter, new Gtk.TreePath.from_indices (pos));
  774. transaction_sum_dialog.sum_list.set (iter, 0, "<b>%s</b>".printf (dgettext (null, "To remove") + ":"));
  775. }
  776. if (summary.to_downgrade.length > 0) {
  777. type |= Type.STANDARD;
  778. foreach (unowned UpdateInfos infos in summary.to_downgrade) {
  779. dsize += infos.download_size;
  780. transaction_summary.add (infos.name);
  781. transaction_sum_dialog.sum_list.insert_with_values (out iter, -1,
  782. 1, infos.name,
  783. 2, infos.new_version,
  784. 3, "(%s)".printf (infos.old_version));
  785. }
  786. Gtk.TreePath path = transaction_sum_dialog.sum_list.get_path (iter);
  787. int pos = (path.get_indices ()[0]) - (summary.to_downgrade.length - 1);
  788. transaction_sum_dialog.sum_list.get_iter (out iter, new Gtk.TreePath.from_indices (pos));
  789. transaction_sum_dialog.sum_list.set (iter, 0, "<b>%s</b>".printf (dgettext (null, "To downgrade") + ":"));
  790. }
  791. if (to_build.length > 0) {
  792. type |= Type.BUILD;
  793. foreach (unowned string name in to_build) {
  794. transaction_summary.add (name);
  795. transaction_sum_dialog.sum_list.insert_with_values (out iter, -1,
  796. 1, name);
  797. }
  798. Gtk.TreePath path = transaction_sum_dialog.sum_list.get_path (iter);
  799. int pos = (path.get_indices ()[0]) - ((int) to_build.length - 1);
  800. transaction_sum_dialog.sum_list.get_iter (out iter, new Gtk.TreePath.from_indices (pos));
  801. transaction_sum_dialog.sum_list.set (iter, 0, "<b>%s</b>".printf (dgettext (null, "To build") + ":"));
  802. }
  803. if (summary.to_install.length > 0) {
  804. type |= Type.STANDARD;
  805. foreach (unowned UpdateInfos infos in summary.to_install) {
  806. dsize += infos.download_size;
  807. transaction_summary.add (infos.name);
  808. transaction_sum_dialog.sum_list.insert_with_values (out iter, -1,
  809. 1, infos.name,
  810. 2, infos.new_version);
  811. }
  812. Gtk.TreePath path = transaction_sum_dialog.sum_list.get_path (iter);
  813. int pos = (path.get_indices ()[0]) - (summary.to_install.length - 1);
  814. transaction_sum_dialog.sum_list.get_iter (out iter, new Gtk.TreePath.from_indices (pos));
  815. transaction_sum_dialog.sum_list.set (iter, 0, "<b>%s</b>".printf (dgettext (null, "To install") + ":"));
  816. }
  817. if (summary.to_reinstall.length > 0) {
  818. type |= Type.STANDARD;
  819. foreach (unowned UpdateInfos infos in summary.to_reinstall) {
  820. dsize += infos.download_size;
  821. transaction_summary.add (infos.name);
  822. transaction_sum_dialog.sum_list.insert_with_values (out iter, -1,
  823. 1, infos.name,
  824. 2, infos.old_version);
  825. }
  826. Gtk.TreePath path = transaction_sum_dialog.sum_list.get_path (iter);
  827. int pos = (path.get_indices ()[0]) - (summary.to_reinstall.length - 1);
  828. transaction_sum_dialog.sum_list.get_iter (out iter, new Gtk.TreePath.from_indices (pos));
  829. transaction_sum_dialog.sum_list.set (iter, 0, "<b>%s</b>".printf (dgettext (null, "To reinstall") + ":"));
  830. }
  831. if (summary.to_upgrade.length > 0) {
  832. type |= Type.UPDATE;
  833. if (mode != Mode.UPDATER) {
  834. foreach (unowned UpdateInfos infos in summary.to_upgrade) {
  835. dsize += infos.download_size;
  836. transaction_summary.add (infos.name);
  837. transaction_sum_dialog.sum_list.insert_with_values (out iter, -1,
  838. 1, infos.name,
  839. 2, infos.new_version,
  840. 3, "(%s)".printf (infos.old_version));
  841. }
  842. Gtk.TreePath path = transaction_sum_dialog.sum_list.get_path (iter);
  843. int pos = (path.get_indices ()[0]) - (summary.to_upgrade.length - 1);
  844. transaction_sum_dialog.sum_list.get_iter (out iter, new Gtk.TreePath.from_indices (pos));
  845. transaction_sum_dialog.sum_list.set (iter, 0, "<b>%s</b>".printf (dgettext (null, "To update") + ":"));
  846. }
  847. }
  848. if (dsize == 0) {
  849. transaction_sum_dialog.bottom_label.visible = false;
  850. } else {
  851. transaction_sum_dialog.bottom_label.set_markup ("<b>%s: %s</b>".printf (dgettext (null, "Total download size"), format_size (dsize)));
  852. transaction_sum_dialog.bottom_label.visible = true;
  853. }
  854. return type;
  855. }
  856. public void start_commit () {
  857. progress_dialog.cancel_button.visible = false;
  858. try {
  859. daemon.start_trans_commit ();
  860. } catch (IOError e) {
  861. stderr.printf ("IOError: %s\n", e.message);
  862. success = false;
  863. finish_transaction ();
  864. }
  865. }
  866. public void build_aur_packages () {
  867. string action = dgettext (null, "Building packages") + "...";
  868. reset_progress_dialog (action, false, true);
  869. emit_action (action);
  870. progress_dialog.term.grab_focus ();
  871. pulse_timeout_id = Timeout.add (500, (GLib.SourceFunc) progress_dialog.progressbar.pulse);
  872. progress_dialog.close_button.visible = false;
  873. progress_dialog.show ();
  874. while (Gtk.events_pending ()) {
  875. Gtk.main_iteration ();
  876. }
  877. string[] cmds = {"yaourt", "-S"};
  878. if (pamac_config.no_confirm_build) {
  879. cmds += "--noconfirm";
  880. }
  881. foreach (unowned string name in to_build) {
  882. cmds += name;
  883. }
  884. Pid child_pid;
  885. progress_dialog.spawn_in_term (cmds, out child_pid);
  886. // watch_child is needed in order to have the child_exited signal emitted
  887. progress_dialog.term.watch_child (child_pid);
  888. //~ foreach (unowned string pkgname in to_build) {
  889. //~ stdout.printf("aur deps for %s:\n", pkgname);
  890. //~ get_aur_build_list.begin (pkgname, (obj, res) => {
  891. //~ string[] names = get_aur_build_list.end (res);
  892. //~ foreach (unowned string name in names) {
  893. //~ stdout.printf("\t%s\n", name);
  894. //~ }
  895. //~ });
  896. //~ }
  897. }
  898. public void cancel () {
  899. try {
  900. daemon.trans_cancel ();
  901. } catch (IOError e) {
  902. stderr.printf ("IOError: %s\n", e.message);
  903. }
  904. progress_dialog.hide ();
  905. progress_dialog.spawn_in_term ({"/usr/bin/echo", dgettext (null, "Transaction cancelled") + ".\n"});
  906. progress_dialog.expander.expanded = false;
  907. Gtk.TextIter start_iter;
  908. Gtk.TextIter end_iter;
  909. transaction_info_dialog.textbuffer.get_start_iter (out start_iter);
  910. transaction_info_dialog.textbuffer.get_end_iter (out end_iter);
  911. transaction_info_dialog.textbuffer.delete (ref start_iter, ref end_iter);
  912. }
  913. public void release () {
  914. try {
  915. daemon.trans_release ();
  916. } catch (IOError e) {
  917. stderr.printf ("IOError: %s\n", e.message);
  918. }
  919. foreach (unowned string pkgname in temporary_ignorepkgs) {
  920. remove_ignorepkg (pkgname);
  921. }
  922. }
  923. public void stop_daemon () {
  924. try {
  925. daemon.quit ();
  926. } catch (IOError e) {
  927. stderr.printf ("IOError: %s\n", e.message);
  928. }
  929. }
  930. void on_emit_event (uint primary_event, uint secondary_event, string[] details) {
  931. string? action = null;
  932. string? detailed_action = null;
  933. switch (primary_event) {
  934. case 1: //Alpm.Event.Type.CHECKDEPS_START
  935. action = dgettext (null, "Checking dependencies") + "...";
  936. break;
  937. case 3: //Alpm.Event.Type.FILECONFLICTS_START
  938. action = dgettext (null, "Checking file conflicts") + "...";
  939. break;
  940. case 5: //Alpm.Event.Type.RESOLVEDEPS_START
  941. action = dgettext (null, "Resolving dependencies") + "...";
  942. break;
  943. case 7: //Alpm.Event.Type.INTERCONFLICTS_START
  944. action = dgettext (null, "Checking inter-conflicts") + "...";
  945. break;
  946. case 9: //Alpm.Event.Type.TRANSACTION_START
  947. progress_dialog.cancel_button.visible = false;
  948. start_transaction ();
  949. break;
  950. case 11: //Alpm.Event.Type.PACKAGE_OPERATION_START
  951. switch (secondary_event) {
  952. // special cases handle differently
  953. case 1: //Alpm.Package.Operation.INSTALL
  954. previous_filename = details[0];
  955. string msg = dgettext (null, "Installing %s").printf (details[0]) + "...";
  956. progress_dialog.action_label.label = msg;
  957. emit_action (msg);
  958. progress_dialog.spawn_in_term ({"echo", dgettext (null, "Installing %s").printf ("%s (%s)".printf (details[0], details[1]))+ "..."});
  959. break;
  960. case 2: //Alpm.Package.Operation.UPGRADE
  961. previous_filename = details[0];
  962. string msg = dgettext (null, "Upgrading %s").printf (details[0]) + "...";
  963. progress_dialog.action_label.label = msg;
  964. emit_action (msg);
  965. progress_dialog.spawn_in_term ({"echo", dgettext (null, "Upgrading %s").printf ("%s (%s -> %s)".printf (details[0], details[1], details[2]))+ "..."});
  966. break;
  967. case 3: //Alpm.Package.Operation.REINSTALL
  968. previous_filename = details[0];
  969. string msg = dgettext (null, "Reinstalling %s").printf (details[0]) + "...";
  970. progress_dialog.action_label.label = msg;
  971. emit_action (msg);
  972. progress_dialog.spawn_in_term ({"echo", dgettext (null, "Reinstalling %s").printf ("%s (%s)".printf (details[0], details[1]))+ "..."});
  973. break;
  974. case 4: //Alpm.Package.Operation.DOWNGRADE
  975. previous_filename = details[0];
  976. string msg = dgettext (null, "Downgrading %s").printf (details[0]) + "...";
  977. progress_dialog.action_label.label = msg;
  978. emit_action (msg);
  979. progress_dialog.spawn_in_term ({"echo", dgettext (null, "Downgrading %s").printf ("%s (%s -> %s)".printf (details[0], details[1], details[2]))+ "..."});
  980. break;
  981. case 5: //Alpm.Package.Operation.REMOVE
  982. previous_filename = details[0];
  983. string msg = dgettext (null, "Removing %s").printf (details[0]) + "...";
  984. progress_dialog.action_label.label = msg;
  985. emit_action (msg);
  986. progress_dialog.spawn_in_term ({"echo", dgettext (null, "Removing %s").printf ("%s (%s)".printf (details[0], details[1]))+ "..."});
  987. break;
  988. }
  989. break;
  990. case 13: //Alpm.Event.Type.INTEGRITY_START
  991. action = dgettext (null, "Checking integrity") + "...";
  992. break;
  993. case 15: //Alpm.Event.Type.LOAD_START
  994. action = dgettext (null, "Loading packages files") + "...";
  995. break;
  996. case 17: //Alpm.Event.Type.DELTA_INTEGRITY_START
  997. action = dgettext (null, "Checking delta integrity") + "...";
  998. break;
  999. case 19: //Alpm.Event.Type.DELTA_PATCHES_START
  1000. action = dgettext (null, "Applying deltas") + "...";
  1001. break;
  1002. case 21: //Alpm.Event.Type.DELTA_PATCH_START
  1003. detailed_action = dgettext (null, "Generating %s with %s").printf (details[0], details[1]) + "...";
  1004. break;
  1005. case 22: //Alpm.Event.Type.DELTA_PATCH_DONE
  1006. detailed_action = dgettext (null, "Generation succeeded") + "...";
  1007. break;
  1008. case 23: //Alpm.Event.Type.DELTA_PATCH_FAILED
  1009. detailed_action = dgettext (null, "Generation failed") + "...";
  1010. break;
  1011. case 24: //Alpm.Event.Type.SCRIPTLET_INFO
  1012. progress_dialog.expander.expanded = true;
  1013. action = dgettext (null, "Configuring %s").printf (previous_filename) + "...";
  1014. detailed_action = details[0].replace ("\n", "");
  1015. break;
  1016. case 25: //Alpm.Event.Type.RETRIEVE_START
  1017. progress_dialog.cancel_button.visible = true;
  1018. action = dgettext (null, "Downloading") + "...";
  1019. break;
  1020. case 28: //Alpm.Event.Type.PKGDOWNLOAD_START
  1021. string name_version_release = details[0].slice (0, details[0].last_index_of_char ('-'));
  1022. string name_version = name_version_release.slice (0, name_version_release.last_index_of_char ('-'));
  1023. string name = name_version.slice (0, name_version.last_index_of_char ('-'));
  1024. action = dgettext (null, "Downloading %s").printf (name) + "...";
  1025. break;
  1026. case 31: //Alpm.Event.Type.DISKSPACE_START
  1027. action = dgettext (null, "Checking available disk space") + "...";
  1028. break;
  1029. case 33: //Alpm.Event.Type.OPTDEP_REMOVAL
  1030. detailed_action = dgettext (null, "%s optionally requires %s").printf (details[0], details[1]);
  1031. Gtk.TextIter end_iter;
  1032. string msg = detailed_action + "\n";
  1033. transaction_info_dialog.textbuffer.get_end_iter (out end_iter);
  1034. transaction_info_dialog.textbuffer.insert (ref end_iter, msg, msg.length);
  1035. break;
  1036. case 34: //Alpm.Event.Type.DATABASE_MISSING
  1037. detailed_action = dgettext (null, "Database file for %s does not exist").printf (details[0]);
  1038. break;
  1039. case 35: //Alpm.Event.Type.KEYRING_START
  1040. progress_dialog.cancel_button.visible = true;
  1041. action = dgettext (null, "Checking keyring") + "...";
  1042. break;
  1043. case 37: //Alpm.Event.Type.KEY_DOWNLOAD_START
  1044. action = dgettext (null, "Downloading required keys") + "...";
  1045. break;
  1046. case 39: //Alpm.Event.Type.PACNEW_CREATED
  1047. detailed_action = dgettext (null, "%s installed as %s.pacnew").printf (details[0]);
  1048. break;
  1049. case 40: //Alpm.Event.Type.PACSAVE_CREATED
  1050. detailed_action = dgettext (null, "%s installed as %s.pacsave").printf (details[0]);
  1051. break;
  1052. case 41: //Alpm.Event.Type.HOOK_START
  1053. switch (secondary_event) {
  1054. case 1: //Alpm.HookWhen.PRE_TRANSACTION
  1055. action = dgettext (null, "Running pre-transaction hooks") + "...";
  1056. break;
  1057. case 2: //Alpm.HookWhen.POST_TRANSACTION
  1058. action = dgettext (null, "Running post-transaction hooks") + "...";
  1059. break;
  1060. default:
  1061. break;
  1062. }
  1063. break;
  1064. case 43: // Alpm.Event.Type.HOOK_RUN_START
  1065. string textbar = "%s/%s".printf (details[2], details[3]);
  1066. if (textbar != previous_textbar) {
  1067. previous_textbar = textbar;
  1068. progress_dialog.progressbar.text = textbar;
  1069. }
  1070. float fraction = (float) int.parse (details[2]) / int.parse (details[3]);
  1071. if (fraction != previous_percent) {
  1072. previous_percent = fraction;
  1073. progress_dialog.progressbar.fraction = fraction;
  1074. }
  1075. if (details[1] != "") {
  1076. detailed_action = details[1] + ":";
  1077. } else {
  1078. detailed_action = details[0] + ":";
  1079. }
  1080. break;
  1081. default:
  1082. break;
  1083. }
  1084. if (action != null) {
  1085. progress_dialog.action_label.label = action;
  1086. progress_dialog.spawn_in_term ({"echo", action});
  1087. emit_action (action);
  1088. }
  1089. if (detailed_action != null) {
  1090. progress_dialog.spawn_in_term ({"echo", detailed_action});
  1091. }
  1092. }
  1093. void on_emit_providers (string depend, string[] providers) {
  1094. choose_provider (depend, providers);
  1095. }
  1096. void on_emit_progress (uint progress, string pkgname, uint percent, uint n_targets, uint current_target) {
  1097. float fraction;
  1098. switch (progress) {
  1099. case 0: //Alpm.Progress.ADD_START
  1100. case 1: //Alpm.Progress.UPGRADE_START
  1101. case 2: //Alpm.Progress.DOWNGRADE_START
  1102. case 3: //Alpm.Progress.REINSTALL_START
  1103. case 4: //Alpm.Progress.REMOVE_START
  1104. fraction = ((float) (current_target - 1) / n_targets) + ((float) percent / (100 * n_targets));
  1105. break;
  1106. case 5: //Alpm.Progress.CONFLICTS_START
  1107. case 6: //Alpm.Progress.DISKSPACE_START
  1108. case 7: //Alpm.Progress.INTEGRITY_START
  1109. case 8: //Alpm.Progress.LOAD_START
  1110. case 9: //Alpm.Progress.KEYRING_START
  1111. default:
  1112. fraction = (float) percent / 100;
  1113. break;
  1114. }
  1115. string textbar = "%lu/%lu".printf (current_target, n_targets);
  1116. if (textbar != previous_textbar) {
  1117. previous_textbar = textbar;
  1118. progress_dialog.progressbar.text = textbar;
  1119. }
  1120. if (fraction != previous_percent) {
  1121. previous_percent = fraction;
  1122. progress_dialog.progressbar.fraction = fraction;
  1123. }
  1124. }
  1125. void on_emit_download (string filename, uint64 xfered, uint64 total) {
  1126. var text = new StringBuilder ();
  1127. float fraction;
  1128. if (total_download > 0) {
  1129. if (xfered == 0) {
  1130. previous_xfered = 0;
  1131. fraction = previous_percent;
  1132. text.append (previous_textbar);
  1133. timer.start ();
  1134. } else {
  1135. if (timer.elapsed () > 0) {
  1136. download_rate = ((download_rate * rates_nb) + (uint64) ((xfered - previous_xfered) / timer.elapsed ())) / (rates_nb + 1);
  1137. rates_nb++;
  1138. }
  1139. previous_xfered = xfered;
  1140. uint64 downloaded_total = xfered + already_downloaded;
  1141. fraction = (float) downloaded_total / total_download;
  1142. if (fraction <= 1) {
  1143. text.append ("%s/%s ".printf (format_size (xfered + already_downloaded), format_size (total_download)));
  1144. uint64 remaining_seconds = 0;
  1145. if (download_rate > 0) {
  1146. remaining_seconds = (total_download - downloaded_total) / download_rate;
  1147. }
  1148. // display remaining time after 5s and only if more than 10s are remaining
  1149. if (remaining_seconds > 9 && rates_nb > 9) {
  1150. if (remaining_seconds <= 50) {
  1151. text.append (dgettext (null, "About %u seconds remaining").printf ((uint) Math.ceilf ((float) remaining_seconds / 10) * 10));
  1152. } else {
  1153. uint remaining_minutes = (uint) Math.ceilf ((float) remaining_seconds / 60);
  1154. text.append (dngettext (null, "About %lu minute remaining",
  1155. "About %lu minutes remaining", remaining_minutes).printf (remaining_minutes));
  1156. }
  1157. }
  1158. } else {
  1159. text.append ("%s".printf (format_size (xfered + already_downloaded)));
  1160. }
  1161. if (xfered == total) {
  1162. previous_filename = "";
  1163. already_downloaded += total;
  1164. } else {
  1165. timer.start ();
  1166. }
  1167. }
  1168. } else {
  1169. if (xfered == 0) {
  1170. previous_xfered = 0;
  1171. download_rate = 0;
  1172. rates_nb = 0;
  1173. fraction = 0;
  1174. timer.start ();
  1175. // start download pkg is handled by Alpm.Event.Type.PKGDOWNLOAD_START
  1176. if (filename.has_suffix (".db")) {
  1177. string action = dgettext (null, "Refreshing %s").printf (filename.replace (".db", "")) + "...";
  1178. progress_dialog.action_label.label = action;
  1179. progress_dialog.spawn_in_term ({"echo", action});
  1180. emit_action (action);
  1181. }
  1182. } else if (xfered == total) {
  1183. timer.stop ();
  1184. fraction = 1;
  1185. previous_filename = "";
  1186. } else {
  1187. if (timer.elapsed () > 0) {
  1188. download_rate = ((download_rate * rates_nb) + (uint64) ((xfered - previous_xfered) / timer.elapsed ())) / (rates_nb + 1);
  1189. rates_nb++;
  1190. }
  1191. previous_xfered = xfered;
  1192. fraction = (float) xfered / total;
  1193. if (fraction <= 1) {
  1194. text.append ("%s/%s ".printf (format_size (xfered), format_size (total)));
  1195. uint64 remaining_seconds = 0;
  1196. if (download_rate > 0) {
  1197. remaining_seconds = (total - xfered) / download_rate;
  1198. }
  1199. // display remaining time after 5s and only if more than 10s are remaining
  1200. if (remaining_seconds > 9 && rates_nb > 9) {
  1201. if (remaining_seconds <= 50) {
  1202. text.append (dgettext (null, "About %u seconds remaining").printf ((uint) Math.ceilf ((float) remaining_seconds / 10) * 10));
  1203. } else {
  1204. uint remaining_minutes = (uint) Math.ceilf ((float) remaining_seconds / 60);
  1205. text.append (dngettext (null, "About %lu minute remaining",
  1206. "About %lu minutes remaining", remaining_minutes).printf (remaining_minutes));
  1207. }
  1208. }
  1209. } else {
  1210. text.append ("%s".printf (format_size (xfered)));
  1211. }
  1212. // reinitialize timer
  1213. timer.start ();
  1214. }
  1215. }
  1216. if (fraction != previous_percent) {
  1217. previous_percent = fraction;
  1218. progress_dialog.progressbar.fraction = fraction;
  1219. }
  1220. if (text.str != previous_textbar) {
  1221. previous_textbar = text.str;
  1222. progress_dialog.progressbar.text = text.str;
  1223. }
  1224. }
  1225. void on_emit_totaldownload (uint64 total) {
  1226. download_rate = 0;
  1227. rates_nb = 0;
  1228. previous_percent = 0;
  1229. previous_textbar = "";
  1230. total_download = total;
  1231. // this is emitted at the end of the total download
  1232. // with the value 0 so stop our timer
  1233. if (total == 0) {
  1234. timer.stop ();
  1235. }
  1236. }
  1237. void on_emit_log (uint level, string msg) {
  1238. // msg ends with \n
  1239. string? line = null;
  1240. Gtk.TextIter end_iter;
  1241. if (level == 1) { //Alpm.LogLevel.ERROR
  1242. if (previous_filename != "") {
  1243. line = dgettext (null, "Error") + ": " + previous_filename + ": " + msg;
  1244. } else {
  1245. line = dgettext (null, "Error") + ": " + msg;
  1246. }
  1247. } else if (level == (1 << 1)) { //Alpm.LogLevel.WARNING
  1248. // do not show warning when manjaro-system remove db.lck
  1249. if (previous_filename != "manjaro-system") {
  1250. if (previous_filename != "") {
  1251. line = dgettext (null, "Warning") + ": " + previous_filename + ": " + msg;
  1252. } else {
  1253. line = dgettext (null, "Warning") + ": " + msg;
  1254. }
  1255. transaction_info_dialog.textbuffer.get_end_iter (out end_iter);
  1256. transaction_info_dialog.textbuffer.insert (ref end_iter, msg, msg.length);
  1257. }
  1258. }
  1259. if (line != null) {
  1260. display_error (line, {});
  1261. }
  1262. }
  1263. void show_warnings () {
  1264. if (transaction_info_dialog.textbuffer.text != "") {
  1265. transaction_info_dialog.title = dgettext (null, "Warning");
  1266. transaction_info_dialog.label.visible = false;
  1267. transaction_info_dialog.expander.visible = true;
  1268. transaction_info_dialog.expander.expanded = true;
  1269. transaction_info_dialog.run ();
  1270. transaction_info_dialog.hide ();
  1271. while (Gtk.events_pending ()) {
  1272. Gtk.main_iteration ();
  1273. }
  1274. Gtk.TextIter start_iter;
  1275. Gtk.TextIter end_iter;
  1276. transaction_info_dialog.textbuffer.get_start_iter (out start_iter);
  1277. transaction_info_dialog.textbuffer.get_end_iter (out end_iter);
  1278. transaction_info_dialog.textbuffer.delete (ref start_iter, ref end_iter);
  1279. }
  1280. }
  1281. void display_error (string message, string[] details) {
  1282. progress_dialog.spawn_in_term ({"echo", "-n", message});
  1283. Gtk.TextIter start_iter;
  1284. Gtk.TextIter end_iter;
  1285. transaction_info_dialog.title = dgettext (null, "Error");
  1286. transaction_info_dialog.label.visible = true;
  1287. transaction_info_dialog.label.label = message;
  1288. if (details.length != 0) {
  1289. transaction_info_dialog.textbuffer.get_start_iter (out start_iter);
  1290. transaction_info_dialog.textbuffer.get_end_iter (out end_iter);
  1291. transaction_info_dialog.textbuffer.delete (ref start_iter, ref end_iter);
  1292. transaction_info_dialog.expander.visible = true;
  1293. transaction_info_dialog.expander.expanded = true;
  1294. progress_dialog.spawn_in_term ({"echo", ":"});
  1295. foreach (unowned string detail in details) {
  1296. progress_dialog.spawn_in_term ({"echo", detail});
  1297. string str = detail + "\n";
  1298. transaction_info_dialog.textbuffer.get_end_iter (out end_iter);
  1299. transaction_info_dialog.textbuffer.insert (ref end_iter, str, str.length);
  1300. }
  1301. } else {
  1302. transaction_info_dialog.expander.visible = false;
  1303. }
  1304. transaction_info_dialog.run ();
  1305. transaction_info_dialog.hide ();
  1306. transaction_info_dialog.textbuffer.get_start_iter (out start_iter);
  1307. transaction_info_dialog.textbuffer.get_end_iter (out end_iter);
  1308. transaction_info_dialog.textbuffer.delete (ref start_iter, ref end_iter);
  1309. while (Gtk.events_pending ()) {
  1310. Gtk.main_iteration ();
  1311. }
  1312. }
  1313. void handle_error (ErrorInfos error) {
  1314. if (error.message != "") {
  1315. progress_dialog.action_label.label = "";
  1316. progress_dialog.progressbar.fraction = 0;
  1317. display_error (error.message, error.details);
  1318. progress_dialog.spawn_in_term ({"echo"});
  1319. progress_dialog.spawn_in_term ({"echo"});
  1320. }
  1321. finish_transaction ();
  1322. }
  1323. void finish_transaction () {
  1324. transaction_summary.remove_all ();
  1325. if (progress_dialog.expander.expanded) {
  1326. progress_dialog.show ();
  1327. progress_dialog.cancel_button.visible = false;
  1328. progress_dialog.close_button.clicked.connect (hide_progress_and_finish);
  1329. } else {
  1330. hide_progress_and_finish ();
  1331. }
  1332. }
  1333. void on_refresh_finished (bool success) {
  1334. this.success = success;
  1335. clear_lists ();
  1336. if (success) {
  1337. finished (success);
  1338. progress_dialog.hide ();
  1339. success = false;
  1340. } else {
  1341. handle_error (get_current_error ());
  1342. }
  1343. previous_filename = "";
  1344. daemon.refresh_finished.disconnect (on_refresh_finished);
  1345. }
  1346. void hide_progress_and_finish () {
  1347. finished (success);
  1348. progress_dialog.hide ();
  1349. progress_dialog.expander.expanded = false;
  1350. success = false;
  1351. progress_dialog.close_button.clicked.connect (hide_progress);
  1352. }
  1353. void on_progress_dialog_cancel_button_clicked () {
  1354. cancel ();
  1355. }
  1356. void on_trans_prepare_finished (bool success) {
  1357. this.success = success;
  1358. if (success) {
  1359. show_warnings ();
  1360. Type type = set_transaction_sum ();
  1361. if (type == Type.UPDATE && mode == Mode.UPDATER) {
  1362. // there only updates
  1363. start_commit ();
  1364. } else if (type != 0) {
  1365. if (transaction_sum_dialog.run () == Gtk.ResponseType.OK) {
  1366. transaction_sum_dialog.hide ();
  1367. while (Gtk.events_pending ()) {
  1368. Gtk.main_iteration ();
  1369. }
  1370. if (type == Type.BUILD) {
  1371. // there only AUR packages to build
  1372. release ();
  1373. on_trans_commit_finished (true);
  1374. } else {
  1375. // backup to_install and to_remove
  1376. foreach (unowned string name in to_install) {
  1377. previous_to_install.add (name);
  1378. }
  1379. foreach (unowned string name in to_remove) {
  1380. previous_to_remove.add (name);
  1381. }
  1382. to_install.remove_all ();
  1383. to_remove.remove_all ();
  1384. start_commit ();
  1385. }
  1386. } else {
  1387. transaction_sum_dialog.hide ();
  1388. unowned string action = dgettext (null, "Transaction cancelled");
  1389. progress_dialog.spawn_in_term ({"echo", action + ".\n"});
  1390. progress_dialog.action_label.label = action;
  1391. release ();
  1392. transaction_summary.remove_all ();
  1393. sysupgrade_after_trans = false;
  1394. success = false;
  1395. finish_transaction ();
  1396. }
  1397. } else {
  1398. //var err = ErrorInfos ();
  1399. //err.message = dgettext (null, "Nothing to do") + "\n";
  1400. progress_dialog.spawn_in_term ({"echo", dgettext (null, "Nothing to do") + ".\n"});
  1401. release ();
  1402. clear_lists ();
  1403. finish_transaction ();
  1404. //handle_error (err);
  1405. }
  1406. } else {
  1407. handle_error (get_current_error ());
  1408. }
  1409. }
  1410. void on_trans_commit_finished (bool success) {
  1411. this.success = success;
  1412. if (success) {
  1413. if (to_build.length != 0) {
  1414. if (previous_to_install.length != 0
  1415. || previous_to_remove.length != 0
  1416. || to_load.length != 0) {
  1417. progress_dialog.spawn_in_term ({"echo", dgettext (null, "Transaction successfully finished") + ".\n"});
  1418. }
  1419. build_aur_packages ();
  1420. } else {
  1421. clear_previous_lists ();
  1422. show_warnings ();
  1423. if (sysupgrade_after_trans) {
  1424. sysupgrade_after_trans = false;
  1425. sysupgrade (false);
  1426. } else {
  1427. unowned string action = dgettext (null, "Transaction successfully finished");
  1428. progress_dialog.spawn_in_term ({"echo", action + ".\n"});
  1429. progress_dialog.action_label.label = action;
  1430. finish_transaction ();
  1431. }
  1432. }
  1433. } else {
  1434. // if it is an authentication or a download error, database was not modified
  1435. var err = get_current_error ();
  1436. if (err.message == dgettext (null, "Authentication failed")
  1437. || err.errno == 54) { //Alpm.Errno.EXTERNAL_DOWNLOAD
  1438. // recover old pkgnames
  1439. foreach (unowned string name in previous_to_install) {
  1440. to_install.add (name);
  1441. }
  1442. foreach (unowned string name in previous_to_remove) {
  1443. to_remove.add (name);
  1444. }
  1445. }
  1446. clear_previous_lists ();
  1447. handle_error (err);
  1448. }
  1449. total_download = 0;
  1450. already_downloaded = 0;
  1451. previous_filename = "";
  1452. }
  1453. void on_term_child_exited (int status) {
  1454. Source.remove (pulse_timeout_id);
  1455. clear_previous_lists ();
  1456. to_build.remove_all ();
  1457. // let the time to the daemon to update databases
  1458. Timeout.add (1000, () => {
  1459. if (status == 0) {
  1460. success = true;
  1461. unowned string action = dgettext (null, "Transaction successfully finished");
  1462. progress_dialog.spawn_in_term ({"echo", action + ".\n"});
  1463. progress_dialog.action_label.label = action;
  1464. } else {
  1465. success = false;
  1466. progress_dialog.spawn_in_term ({"echo"});
  1467. }
  1468. transaction_summary.remove_all ();
  1469. progress_dialog.progressbar.fraction = 1;
  1470. progress_dialog.close_button.clicked.connect (hide_progress_and_finish);
  1471. progress_dialog.close_button.visible = true;
  1472. return false;
  1473. });
  1474. }
  1475. void on_set_pkgreason_finished () {
  1476. set_pkgreason_finished ();
  1477. }
  1478. void on_write_pamac_config_finished (bool recurse, uint64 refresh_period, bool no_update_hide_icon,
  1479. bool enable_aur, bool search_aur, bool check_aur_updates,
  1480. bool no_confirm_build) {
  1481. pamac_config.reload ();
  1482. if (recurse) {
  1483. flags |= (1 << 5); //Alpm.TransFlag.RECURSE
  1484. }
  1485. write_pamac_config_finished (recurse, refresh_period, no_update_hide_icon,
  1486. enable_aur, search_aur, check_aur_updates,
  1487. no_confirm_build);
  1488. }
  1489. void on_write_alpm_config_finished (bool checkspace) {
  1490. write_alpm_config_finished (checkspace);
  1491. }
  1492. void on_write_mirrors_config_finished (string choosen_country, string choosen_generation_method) {
  1493. write_mirrors_config_finished (choosen_country, choosen_generation_method);
  1494. }
  1495. void on_generate_mirrors_list_data (string line) {
  1496. progress_dialog.spawn_in_term ({"echo", "-n", line});
  1497. }
  1498. void on_generate_mirrors_list_finished () {
  1499. Source.remove (pulse_timeout_id);
  1500. progress_dialog.spawn_in_term ({"echo"});
  1501. // force a dbs refresh
  1502. start_refresh (true);
  1503. }
  1504. void connecting_dbus_signals () {
  1505. try {
  1506. daemon = Bus.get_proxy_sync (BusType.SYSTEM, "org.manjaro.pamac", "/org/manjaro/pamac");
  1507. // Set environment variables
  1508. daemon.set_environment_variables (pamac_config.environment_variables);
  1509. // Connecting to signals
  1510. daemon.emit_event.connect (on_emit_event);
  1511. daemon.emit_providers.connect (on_emit_providers);
  1512. daemon.emit_progress.connect (on_emit_progress);
  1513. daemon.emit_download.connect (on_emit_download);
  1514. daemon.emit_totaldownload.connect (on_emit_totaldownload);
  1515. daemon.emit_log.connect (on_emit_log);
  1516. daemon.trans_prepare_finished.connect (on_trans_prepare_finished);
  1517. daemon.trans_commit_finished.connect (on_trans_commit_finished);
  1518. daemon.set_pkgreason_finished.connect (on_set_pkgreason_finished);
  1519. daemon.write_mirrors_config_finished.connect (on_write_mirrors_config_finished);
  1520. daemon.write_alpm_config_finished.connect (on_write_alpm_config_finished);
  1521. daemon.write_pamac_config_finished.connect (on_write_pamac_config_finished);
  1522. daemon.generate_mirrors_list_data.connect (on_generate_mirrors_list_data);
  1523. daemon.generate_mirrors_list_finished.connect (on_generate_mirrors_list_finished);
  1524. } catch (IOError e) {
  1525. stderr.printf ("IOError: %s\n", e.message);
  1526. }
  1527. }
  1528. }
  1529. }