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.

user_daemon.vala 32KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052
  1. /*
  2. * pamac-vala
  3. *
  4. * Copyright (C) 2017 Chris Cromer <cromer@cromnix.org>
  5. * Copyright (C) 2014-2017 Guillaume Benoit <guillaume@manjaro.org>
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 3 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a get of the GNU General Public License
  18. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  19. */
  20. // i18n
  21. const string GETTEXT_PACKAGE = "pamac";
  22. Pamac.UserDaemon user_daemon;
  23. MainLoop loop;
  24. namespace Pamac {
  25. [DBus (name = "org.pamac.user")]
  26. public class UserDaemon: Object {
  27. private AlpmConfig alpm_config;
  28. private Alpm.Handle? alpm_handle;
  29. private Alpm.Handle? files_handle;
  30. #if DISABLE_AUR
  31. #else
  32. private bool check_aur_updates;
  33. private bool aur_updates_checked;
  34. private Json.Array aur_updates_results;
  35. private HashTable<string, Json.Array> aur_search_results;
  36. private HashTable<string, Json.Object> aur_infos;
  37. #endif
  38. public signal void get_updates_finished (Updates updates);
  39. public UserDaemon () {
  40. alpm_config = new AlpmConfig ("/etc/pacman.conf");
  41. #if DISABLE_AUR
  42. #else
  43. aur_updates_results = new Json.Array ();
  44. aur_search_results = new HashTable<string, Json.Array> (str_hash, str_equal);
  45. aur_infos = new HashTable<string, Json.Object> (str_hash, str_equal);
  46. #endif
  47. try {
  48. refresh_handle ();
  49. } catch (IOError e) {
  50. stderr.printf ("IOError: %s\n", e.message);
  51. } catch (DBusError e) {
  52. stderr.printf ("DBusError: %s\n", e.message);
  53. }
  54. }
  55. public void refresh_handle () throws DBusError, IOError {
  56. alpm_config.reload ();
  57. alpm_handle = alpm_config.get_handle ();
  58. if (alpm_handle == null) {
  59. return;
  60. } else {
  61. var pamac_config = new Pamac.Config ();
  62. if (pamac_config.update_files_db) {
  63. files_handle = alpm_config.get_handle (true);
  64. } else {
  65. files_handle = alpm_config.get_handle (false);
  66. }
  67. }
  68. }
  69. public bool get_checkspace () throws DBusError, IOError {
  70. return alpm_handle.checkspace == 1 ? true : false;
  71. }
  72. public string get_lockfile () throws DBusError, IOError {
  73. return alpm_handle.lockfile;
  74. }
  75. public string[] get_ignorepkgs () throws DBusError, IOError {
  76. string[] result = {};
  77. unowned Alpm.List<unowned string> ignorepkgs = alpm_handle.ignorepkgs;
  78. while (ignorepkgs != null) {
  79. unowned string ignorepkg = ignorepkgs.data;
  80. result += ignorepkg;
  81. ignorepkgs.next ();
  82. }
  83. return result;
  84. }
  85. public bool should_hold (string pkgname) throws DBusError, IOError {
  86. if (alpm_config.get_holdpkgs ().find_custom (pkgname, strcmp) != null) {
  87. return true;
  88. }
  89. return false;
  90. }
  91. public uint get_pkg_reason (string pkgname) throws DBusError, IOError {
  92. unowned Alpm.Package? pkg = alpm_handle.localdb.get_pkg (pkgname);
  93. if (pkg != null) {
  94. return pkg.reason;
  95. }
  96. return 0;
  97. }
  98. public uint get_pkg_origin (string pkgname) throws DBusError, IOError {
  99. unowned Alpm.Package? pkg = alpm_handle.localdb.get_pkg (pkgname);
  100. if (pkg != null) {
  101. return pkg.origin;
  102. } else {
  103. pkg = get_syncpkg (pkgname);
  104. if (pkg != null) {
  105. return pkg.origin;
  106. }
  107. }
  108. return 0;
  109. }
  110. private AlpmPackage initialise_pkg_struct (Alpm.Package? alpm_pkg) {
  111. if (alpm_pkg != null) {
  112. string installed_version = "";
  113. string repo_name = "";
  114. if (alpm_pkg.origin == Alpm.Package.From.LOCALDB) {
  115. installed_version = alpm_pkg.version;
  116. unowned Alpm.Package? sync_pkg = get_syncpkg (alpm_pkg.name);
  117. if (sync_pkg != null) {
  118. repo_name = sync_pkg.db.name;
  119. }
  120. } else if (alpm_pkg.origin == Alpm.Package.From.SYNCDB) {
  121. unowned Alpm.Package? local_pkg = alpm_handle.localdb.get_pkg (alpm_pkg.name);
  122. if (local_pkg != null) {
  123. installed_version = local_pkg.version;
  124. }
  125. repo_name = alpm_pkg.db.name;
  126. }
  127. return AlpmPackage () {
  128. name = alpm_pkg.name,
  129. version = alpm_pkg.version,
  130. installed_version = (owned) installed_version,
  131. // desc can be null
  132. desc = alpm_pkg.desc ?? "",
  133. repo = (owned) repo_name,
  134. size = alpm_pkg.isize,
  135. download_size = alpm_pkg.download_size,
  136. origin = (uint) alpm_pkg.origin
  137. };
  138. } else {
  139. return AlpmPackage () {
  140. name = "",
  141. version = "",
  142. installed_version = "",
  143. desc = "",
  144. repo = ""
  145. };
  146. }
  147. }
  148. public async AlpmPackage[] get_installed_pkgs () throws DBusError, IOError {
  149. AlpmPackage[] pkgs = {};
  150. unowned Alpm.List<unowned Alpm.Package> pkgcache = alpm_handle.localdb.pkgcache;
  151. while (pkgcache != null) {
  152. unowned Alpm.Package alpm_pkg = pkgcache.data;
  153. pkgs += initialise_pkg_struct (alpm_pkg);
  154. pkgcache.next ();
  155. }
  156. return pkgs;
  157. }
  158. public async AlpmPackage[] get_explicitly_installed_pkgs () throws DBusError, IOError {
  159. AlpmPackage[] pkgs = {};
  160. unowned Alpm.List<unowned Alpm.Package> pkgcache = alpm_handle.localdb.pkgcache;
  161. while (pkgcache != null) {
  162. unowned Alpm.Package alpm_pkg = pkgcache.data;
  163. if (alpm_pkg.reason == Alpm.Package.Reason.EXPLICIT) {
  164. pkgs += initialise_pkg_struct (alpm_pkg);
  165. }
  166. pkgcache.next ();
  167. }
  168. return pkgs;
  169. }
  170. public async AlpmPackage[] get_foreign_pkgs () throws DBusError, IOError {
  171. AlpmPackage[] pkgs = {};
  172. unowned Alpm.List<unowned Alpm.Package> pkgcache = alpm_handle.localdb.pkgcache;
  173. while (pkgcache != null) {
  174. unowned Alpm.Package alpm_pkg = pkgcache.data;
  175. bool sync_found = false;
  176. unowned Alpm.List<unowned Alpm.DB> syncdbs = alpm_handle.syncdbs;
  177. while (syncdbs != null) {
  178. unowned Alpm.DB db = syncdbs.data;
  179. unowned Alpm.Package? sync_pkg = db.get_pkg (alpm_pkg.name);
  180. if (sync_pkg != null) {
  181. sync_found = true;
  182. break;
  183. }
  184. syncdbs.next ();
  185. }
  186. if (sync_found == false) {
  187. pkgs += initialise_pkg_struct (alpm_pkg);
  188. }
  189. pkgcache.next ();
  190. }
  191. return pkgs;
  192. }
  193. public async AlpmPackage[] get_orphans () throws DBusError, IOError {
  194. AlpmPackage[] pkgs = {};
  195. unowned Alpm.List<unowned Alpm.Package> pkgcache = alpm_handle.localdb.pkgcache;
  196. while (pkgcache != null) {
  197. unowned Alpm.Package alpm_pkg = pkgcache.data;
  198. if (alpm_pkg.reason == Alpm.Package.Reason.DEPEND) {
  199. Alpm.List<string> requiredby = alpm_pkg.compute_requiredby ();
  200. if (requiredby.length == 0) {
  201. Alpm.List<string> optionalfor = alpm_pkg.compute_optionalfor ();
  202. if (optionalfor.length == 0) {
  203. pkgs += initialise_pkg_struct (alpm_pkg);
  204. } else {
  205. optionalfor.free_inner (GLib.free);
  206. }
  207. } else {
  208. requiredby.free_inner (GLib.free);
  209. }
  210. }
  211. pkgcache.next ();
  212. }
  213. return pkgs;
  214. }
  215. public AlpmPackage get_installed_pkg (string pkgname) throws DBusError, IOError {
  216. return initialise_pkg_struct (alpm_handle.localdb.get_pkg (pkgname));
  217. }
  218. public AlpmPackage find_installed_satisfier (string depstring) throws DBusError, IOError {
  219. return initialise_pkg_struct (Alpm.find_satisfier (alpm_handle.localdb.pkgcache, depstring));
  220. }
  221. private unowned Alpm.Package? get_syncpkg (string name) {
  222. unowned Alpm.Package? pkg = null;
  223. unowned Alpm.List<unowned Alpm.DB> syncdbs = alpm_handle.syncdbs;
  224. while (syncdbs != null) {
  225. unowned Alpm.DB db = syncdbs.data;
  226. pkg = db.get_pkg (name);
  227. if (pkg != null) {
  228. break;
  229. }
  230. syncdbs.next ();
  231. }
  232. return pkg;
  233. }
  234. public AlpmPackage get_sync_pkg (string pkgname) throws DBusError, IOError {
  235. return initialise_pkg_struct (get_syncpkg (pkgname));
  236. }
  237. private unowned Alpm.Package? find_dbs_satisfier (string depstring) {
  238. unowned Alpm.Package? pkg = null;
  239. unowned Alpm.List<unowned Alpm.DB> syncdbs = alpm_handle.syncdbs;
  240. while (syncdbs != null) {
  241. unowned Alpm.DB db = syncdbs.data;
  242. pkg = Alpm.find_satisfier (db.pkgcache, depstring);
  243. if (pkg != null) {
  244. break;
  245. }
  246. syncdbs.next ();
  247. }
  248. return pkg;
  249. }
  250. public AlpmPackage find_sync_satisfier (string depstring) throws DBusError, IOError {
  251. return initialise_pkg_struct (find_dbs_satisfier (depstring));
  252. }
  253. private Alpm.List<unowned Alpm.Package> search_all_dbs (string search_string) {
  254. Alpm.List<unowned string> needles = null;
  255. string[] splitted = search_string.split (" ");
  256. foreach (unowned string part in splitted) {
  257. needles.add (part);
  258. }
  259. Alpm.List<unowned Alpm.Package> result = alpm_handle.localdb.search (needles);
  260. Alpm.List<unowned Alpm.Package> syncpkgs = null;
  261. unowned Alpm.List<unowned Alpm.DB> syncdbs = alpm_handle.syncdbs;
  262. while (syncdbs != null) {
  263. unowned Alpm.DB db = syncdbs.data;
  264. if (syncpkgs.length == 0) {
  265. syncpkgs = db.search (needles);
  266. } else {
  267. syncpkgs.join (db.search (needles).diff (syncpkgs, (Alpm.List.CompareFunc) alpm_pkg_compare_name));
  268. }
  269. syncdbs.next ();
  270. }
  271. result.join (syncpkgs.diff (result, (Alpm.List.CompareFunc) alpm_pkg_compare_name));
  272. // use custom sort function
  273. global_search_string = search_string;
  274. result.sort (result.length, (Alpm.List.CompareFunc) alpm_pkg_sort_search_by_relevance);
  275. return result;
  276. }
  277. public async AlpmPackage[] search_pkgs (string search_string) throws DBusError, IOError {
  278. AlpmPackage[] result = {};
  279. Alpm.List<unowned Alpm.Package> alpm_pkgs = search_all_dbs (search_string);
  280. unowned Alpm.List<unowned Alpm.Package> list = alpm_pkgs;
  281. while (list != null) {
  282. unowned Alpm.Package alpm_pkg = list.data;
  283. result += initialise_pkg_struct (alpm_pkg);
  284. list.next ();
  285. }
  286. return result;
  287. }
  288. #if DISABLE_AUR
  289. #else
  290. private AURPackage initialise_aur_struct (Json.Object json_object) {
  291. string installed_version = "";
  292. unowned Alpm.Package? pkg = alpm_handle.localdb.get_pkg (json_object.get_string_member ("Name"));
  293. if (pkg != null) {
  294. installed_version = pkg.version;
  295. }
  296. return AURPackage () {
  297. name = json_object.get_string_member ("Name"),
  298. version = json_object.get_string_member ("Version"),
  299. installed_version = (owned) installed_version,
  300. // desc can be null
  301. desc = json_object.get_null_member ("Description") ? "" : json_object.get_string_member ("Description"),
  302. popularity = json_object.get_double_member ("Popularity")
  303. };
  304. }
  305. public async AURPackage[] search_in_aur (string search_string) throws DBusError, IOError {
  306. if (!aur_search_results.contains (search_string)) {
  307. Json.Array pkgs = yield search (search_string.split (" "));
  308. aur_search_results.insert (search_string, pkgs);
  309. }
  310. AURPackage[] result = {};
  311. Json.Array aur_pkgs = aur_search_results.get (search_string);
  312. aur_pkgs.foreach_element ((array, index, node) => {
  313. Json.Object aur_pkg = node.get_object ();
  314. // remove results which exist in repos
  315. if (get_syncpkg (aur_pkg.get_string_member ("Name")) == null) {
  316. result += initialise_aur_struct (node.get_object ());
  317. }
  318. });
  319. return result;
  320. }
  321. public async AURPackageDetails get_aur_details (string pkgname) throws DBusError, IOError {
  322. string name = "";
  323. string version = "";
  324. string desc = "";
  325. double popularity = 0;
  326. string packagebase = "";
  327. string url = "";
  328. string maintainer = "";
  329. int64 firstsubmitted = 0;
  330. int64 lastmodified = 0;
  331. int64 outofdate = 0;
  332. int64 numvotes = 0;
  333. string[] licenses = {};
  334. string[] depends = {};
  335. string[] makedepends = {};
  336. string[] checkdepends = {};
  337. string[] optdepends = {};
  338. string[] provides = {};
  339. string[] replaces = {};
  340. string[] conflicts = {};
  341. var details = AURPackageDetails ();
  342. if (!aur_infos.contains (pkgname)) {
  343. Json.Array results = yield multiinfo ({pkgname});
  344. if (results.get_length () > 0) {
  345. aur_infos.insert (pkgname, results.get_object_element (0));
  346. }
  347. }
  348. unowned Json.Object? json_object = aur_infos.lookup (pkgname);
  349. if (json_object != null) {
  350. // name
  351. name = json_object.get_string_member ("Name");
  352. // version
  353. version = json_object.get_string_member ("Version");
  354. // desc can be null
  355. if (!json_object.get_null_member ("Description")) {
  356. desc = json_object.get_string_member ("Description");
  357. }
  358. popularity = json_object.get_double_member ("Popularity");
  359. // packagebase
  360. packagebase = json_object.get_string_member ("PackageBase");
  361. // url can be null
  362. unowned Json.Node? node = json_object.get_member ("URL");
  363. if (!node.is_null ()) {
  364. url = node.get_string ();
  365. }
  366. // maintainer can be null
  367. node = json_object.get_member ("Maintainer");
  368. if (!node.is_null ()) {
  369. maintainer = node.get_string ();
  370. }
  371. // firstsubmitted
  372. firstsubmitted = json_object.get_int_member ("FirstSubmitted");
  373. // lastmodified
  374. lastmodified = json_object.get_int_member ("LastModified");
  375. // outofdate can be null
  376. node = json_object.get_member ("OutOfDate");
  377. if (!node.is_null ()) {
  378. outofdate = node.get_int ();
  379. }
  380. //numvotes
  381. numvotes = json_object.get_int_member ("NumVotes");
  382. // licenses
  383. node = json_object.get_member ("License");
  384. if (!node.is_null ()) {
  385. node.get_array ().foreach_element ((array, index, _node) => {
  386. licenses += _node.get_string ();
  387. });
  388. } else {
  389. licenses += _("Unknown");
  390. }
  391. // depends
  392. node = json_object.get_member ("Depends");
  393. if (node != null) {
  394. node.get_array ().foreach_element ((array, index, _node) => {
  395. depends += _node.get_string ();
  396. });
  397. }
  398. // optdepends
  399. node = json_object.get_member ("OptDepends");
  400. if (node != null) {
  401. node.get_array ().foreach_element ((array, index, _node) => {
  402. optdepends += _node.get_string ();
  403. });
  404. }
  405. // makedepends
  406. node = json_object.get_member ("MakeDepends");
  407. if (node != null) {
  408. node.get_array ().foreach_element ((array, index, _node) => {
  409. makedepends += _node.get_string ();
  410. });
  411. }
  412. // checkdepends
  413. node = json_object.get_member ("CheckDepends");
  414. if (node != null) {
  415. node.get_array ().foreach_element ((array, index, _node) => {
  416. checkdepends += _node.get_string ();
  417. });
  418. }
  419. // provides
  420. node = json_object.get_member ("Provides");
  421. if (node != null) {
  422. node.get_array ().foreach_element ((array, index, _node) => {
  423. provides += _node.get_string ();
  424. });
  425. }
  426. // replaces
  427. node = json_object.get_member ("Replaces");
  428. if (node != null) {
  429. node.get_array ().foreach_element ((array, index, _node) => {
  430. replaces += _node.get_string ();
  431. });
  432. }
  433. // conflicts
  434. node = json_object.get_member ("Conflicts");
  435. if (node != null) {
  436. node.get_array ().foreach_element ((array, index, _node) => {
  437. conflicts += _node.get_string ();
  438. });
  439. }
  440. }
  441. details.name = (owned) name;
  442. details.version = (owned) version ;
  443. details.desc = (owned) desc;
  444. details.popularity = popularity;
  445. details.packagebase = (owned) packagebase;
  446. details.url = (owned) url;
  447. details.maintainer = (owned) maintainer ;
  448. details.firstsubmitted = firstsubmitted;
  449. details.lastmodified = lastmodified;
  450. details.outofdate = outofdate;
  451. details.numvotes = numvotes;
  452. details.licenses = (owned) licenses;
  453. details.depends = (owned) depends;
  454. details.optdepends = (owned) optdepends;
  455. details.checkdepends = (owned) checkdepends;
  456. details.makedepends = (owned) makedepends;
  457. details.provides = (owned) provides;
  458. details.replaces = (owned) replaces;
  459. details.conflicts = (owned) conflicts;
  460. return details;
  461. }
  462. #endif
  463. public string[] get_repos_names () throws DBusError, IOError {
  464. string[] repos_names = {};
  465. unowned Alpm.List<unowned Alpm.DB> syncdbs = alpm_handle.syncdbs;
  466. while (syncdbs != null) {
  467. unowned Alpm.DB db = syncdbs.data;
  468. repos_names += db.name;
  469. syncdbs.next ();
  470. }
  471. return repos_names;
  472. }
  473. public async AlpmPackage[] get_repo_pkgs (string repo) throws DBusError, IOError {
  474. AlpmPackage[] pkgs = {};
  475. unowned Alpm.List<unowned Alpm.DB> syncdbs = alpm_handle.syncdbs;
  476. while (syncdbs != null) {
  477. unowned Alpm.DB db = syncdbs.data;
  478. if (db.name == repo) {
  479. unowned Alpm.List<unowned Alpm.Package> pkgcache = db.pkgcache;
  480. while (pkgcache != null) {
  481. unowned Alpm.Package sync_pkg = pkgcache.data;
  482. unowned Alpm.Package? local_pkg = alpm_handle.localdb.get_pkg (sync_pkg.name);
  483. if (local_pkg != null) {
  484. pkgs += initialise_pkg_struct (local_pkg);
  485. } else {
  486. pkgs += initialise_pkg_struct (sync_pkg);
  487. }
  488. pkgcache.next ();
  489. }
  490. break;
  491. }
  492. syncdbs.next ();
  493. }
  494. return pkgs;
  495. }
  496. public string[] get_groups_names () throws DBusError, IOError {
  497. string[] groups_names = {};
  498. unowned Alpm.List<unowned Alpm.Group> groupcache = alpm_handle.localdb.groupcache;
  499. while (groupcache != null) {
  500. unowned Alpm.Group group = groupcache.data;
  501. if (!(group.name in groups_names)) {
  502. groups_names += group.name;
  503. }
  504. groupcache.next ();
  505. }
  506. unowned Alpm.List<unowned Alpm.DB> syncdbs = alpm_handle.syncdbs;
  507. while (syncdbs != null) {
  508. unowned Alpm.DB db = syncdbs.data;
  509. groupcache = db.groupcache;
  510. while (groupcache != null) {
  511. unowned Alpm.Group group = groupcache.data;
  512. if (!(group.name in groups_names)) {
  513. groups_names += group.name;
  514. }
  515. groupcache.next ();
  516. }
  517. syncdbs.next ();
  518. }
  519. return groups_names;
  520. }
  521. private Alpm.List<unowned Alpm.Package> group_pkgs (string group_name) {
  522. Alpm.List<unowned Alpm.Package> result = null;
  523. unowned Alpm.Group? grp = alpm_handle.localdb.get_group (group_name);
  524. if (grp != null) {
  525. unowned Alpm.List<unowned Alpm.Package> packages = grp.packages;
  526. while (packages != null) {
  527. unowned Alpm.Package pkg = packages.data;
  528. result.add (pkg);
  529. packages.next ();
  530. }
  531. }
  532. unowned Alpm.List<unowned Alpm.DB> syncdbs = alpm_handle.syncdbs;
  533. while (syncdbs != null) {
  534. unowned Alpm.DB db = syncdbs.data;
  535. grp = db.get_group (group_name);
  536. if (grp != null) {
  537. unowned Alpm.List<unowned Alpm.Package> packages = grp.packages;
  538. while (packages != null) {
  539. unowned Alpm.Package pkg = packages.data;
  540. if (result.find (pkg, (Alpm.List.CompareFunc) alpm_pkg_compare_name) == null) {
  541. result.add (pkg);
  542. }
  543. packages.next ();
  544. }
  545. }
  546. syncdbs.next ();
  547. }
  548. return result;
  549. }
  550. public async AlpmPackage[] get_group_pkgs (string groupname) throws DBusError, IOError {
  551. AlpmPackage[] pkgs = {};
  552. Alpm.List<unowned Alpm.Package> alpm_pkgs = group_pkgs (groupname);
  553. unowned Alpm.List<unowned Alpm.Package> list = alpm_pkgs;
  554. while (list != null) {
  555. unowned Alpm.Package alpm_pkg = list.data;
  556. pkgs += initialise_pkg_struct (alpm_pkg);
  557. list.next ();
  558. }
  559. return pkgs;
  560. }
  561. public string[] get_pkg_uninstalled_optdeps (string pkgname) throws DBusError, IOError {
  562. string[] optdeps = {};
  563. unowned Alpm.Package? alpm_pkg = alpm_handle.localdb.get_pkg (pkgname);
  564. if (alpm_pkg == null) {
  565. alpm_pkg = get_syncpkg (pkgname);
  566. }
  567. if (alpm_pkg != null) {
  568. unowned Alpm.List<unowned Alpm.Depend> optdepends = alpm_pkg.optdepends;
  569. while (optdepends != null) {
  570. unowned Alpm.Depend optdep = optdepends.data;
  571. if (Alpm.find_satisfier (alpm_handle.localdb.pkgcache, optdep.name) == null) {
  572. optdeps += optdep.compute_string ();
  573. }
  574. optdepends.next ();
  575. }
  576. }
  577. return optdeps;
  578. }
  579. public AlpmPackageDetails get_pkg_details (string pkgname) throws DBusError, IOError {
  580. string name = "";
  581. string version = "";
  582. string desc = "";
  583. string url = "";
  584. string repo = "";
  585. string has_signature = "";
  586. string reason = "";
  587. string packager = "";
  588. string builddate = "";
  589. string installdate = "";
  590. string downloadsize = "";
  591. string installsize = "";
  592. string[] groups = {};
  593. string[] backups = {};
  594. string[] licenses = {};
  595. string[] depends = {};
  596. string[] optdepends = {};
  597. string[] requiredby = {};
  598. string[] optionalfor = {};
  599. string[] provides = {};
  600. string[] replaces = {};
  601. string[] conflicts = {};
  602. var details = AlpmPackageDetails ();
  603. unowned Alpm.Package? alpm_pkg = alpm_handle.localdb.get_pkg (pkgname);
  604. if (alpm_pkg == null) {
  605. alpm_pkg = get_syncpkg (pkgname);
  606. }
  607. unowned Alpm.Package? alpm_pkg_sync = get_syncpkg (alpm_pkg.name);
  608. if (alpm_pkg_sync == null) {
  609. alpm_pkg_sync = get_syncpkg (pkgname);
  610. }
  611. if (alpm_pkg != null) {
  612. // name
  613. name = alpm_pkg.name;
  614. // version
  615. version = alpm_pkg.version;
  616. // desc can be null
  617. if (alpm_pkg.desc != null) {
  618. desc = alpm_pkg.desc;
  619. }
  620. details.origin = (uint) alpm_pkg.origin;
  621. // url can be null
  622. if (alpm_pkg.url != null) {
  623. url = alpm_pkg.url;
  624. }
  625. // packager can be null
  626. packager = alpm_pkg.packager ?? "";
  627. // groups
  628. unowned Alpm.List list = alpm_pkg.groups;
  629. while (list != null) {
  630. groups += ((Alpm.List<unowned string>) list).data;
  631. list.next ();
  632. }
  633. // download size
  634. if (alpm_pkg_sync != null) {
  635. downloadsize = alpm_pkg_sync.download_size.to_string ();
  636. } else {
  637. downloadsize = alpm_pkg.download_size.to_string ();
  638. }
  639. // installed size
  640. installsize = alpm_pkg.isize.to_string ();
  641. // licenses
  642. list = alpm_pkg.licenses;
  643. while (list != null) {
  644. licenses += ((Alpm.List<unowned string>) list).data;
  645. list.next ();
  646. }
  647. // build_date
  648. GLib.Time time = GLib.Time.local ((time_t) alpm_pkg.builddate);
  649. builddate = time.format ("%a %d %b %Y %X %Z");
  650. // local pkg
  651. if (alpm_pkg.origin == Alpm.Package.From.LOCALDB) {
  652. // repo
  653. unowned Alpm.Package? sync_pkg = get_syncpkg (alpm_pkg.name);
  654. if (sync_pkg != null) {
  655. repo = sync_pkg.db.name;
  656. }
  657. // reason
  658. if (alpm_pkg.reason == Alpm.Package.Reason.EXPLICIT) {
  659. reason = _("Explicitly installed");
  660. } else if (alpm_pkg.reason == Alpm.Package.Reason.DEPEND) {
  661. reason = _("Installed as a dependency for another package");
  662. } else {
  663. reason = _("Unknown");
  664. }
  665. // install_date
  666. time = GLib.Time.local ((time_t) alpm_pkg.installdate);
  667. installdate = time.format ("%a %d %b %Y %X %Z");
  668. // backups
  669. list = alpm_pkg.backups;
  670. while (list != null) {
  671. backups += "/" + ((Alpm.List<unowned Alpm.Backup>) list).data.name;
  672. list.next ();
  673. }
  674. // requiredby
  675. Alpm.List<string> pkg_requiredby = alpm_pkg.compute_requiredby ();
  676. list = pkg_requiredby;
  677. while (list != null) {
  678. requiredby += ((Alpm.List<unowned string>) list).data;
  679. list.next ();
  680. }
  681. pkg_requiredby.free_inner (GLib.free);
  682. // optionalfor
  683. Alpm.List<string> pkg_optionalfor = alpm_pkg.compute_optionalfor ();
  684. list = pkg_optionalfor;
  685. while (list != null) {
  686. optionalfor += ((Alpm.List<unowned string>) list).data;
  687. list.next ();
  688. }
  689. pkg_optionalfor.free_inner (GLib.free);
  690. // sync pkg
  691. } else if (alpm_pkg.origin == Alpm.Package.From.SYNCDB) {
  692. // repos
  693. repo = alpm_pkg.db.name;
  694. // signature
  695. has_signature = alpm_pkg.base64_sig != null ? _("Yes") : _("No");
  696. }
  697. // depends
  698. list = alpm_pkg.depends;
  699. while (list != null) {
  700. depends += ((Alpm.List<unowned Alpm.Depend>) list).data.compute_string ();
  701. list.next ();
  702. }
  703. // optdepends
  704. list = alpm_pkg.optdepends;
  705. while (list != null) {
  706. optdepends += ((Alpm.List<unowned Alpm.Depend>) list).data.compute_string ();
  707. list.next ();
  708. }
  709. // provides
  710. list = alpm_pkg.provides;
  711. while (list != null) {
  712. provides += ((Alpm.List<unowned Alpm.Depend>) list).data.compute_string ();
  713. list.next ();
  714. }
  715. // replaces
  716. list = alpm_pkg.replaces;
  717. while (list != null) {
  718. replaces += ((Alpm.List<unowned Alpm.Depend>) list).data.compute_string ();
  719. list.next ();
  720. }
  721. // conflicts
  722. list = alpm_pkg.conflicts;
  723. while (list != null) {
  724. conflicts += ((Alpm.List<unowned Alpm.Depend>) list).data.compute_string ();
  725. list.next ();
  726. }
  727. }
  728. details.name = (owned) name;
  729. details.version = (owned) version;
  730. details.desc = (owned) desc;
  731. details.repo = (owned) repo;
  732. details.url = (owned) url;
  733. details.packager = (owned) packager;
  734. details.builddate = (owned) builddate;
  735. details.installdate = (owned) installdate;
  736. details.reason = (owned) reason;
  737. details.downloadsize = (owned) downloadsize;
  738. details.installsize = (owned) installsize;
  739. details.has_signature = (owned) has_signature;
  740. details.licenses = (owned) licenses;
  741. details.depends = (owned) depends;
  742. details.optdepends = (owned) optdepends;
  743. details.requiredby = (owned) requiredby;
  744. details.optionalfor = (owned) optionalfor;
  745. details.provides = (owned) provides;
  746. details.replaces = (owned) replaces;
  747. details.conflicts = (owned) conflicts;
  748. details.groups = (owned) groups;
  749. details.backups = (owned) backups;
  750. return details;
  751. }
  752. public string[] get_pkg_files (string pkgname) throws DBusError, IOError {
  753. string[] files = {};
  754. unowned Alpm.Package? alpm_pkg = alpm_handle.localdb.get_pkg (pkgname);
  755. if (alpm_pkg != null) {
  756. unowned Alpm.FileList filelist = alpm_pkg.files;
  757. Alpm.File* file_ptr = filelist.files;
  758. for (size_t i = 0; i < filelist.count; i++, file_ptr++) {
  759. if (!file_ptr->name.has_suffix ("/")) {
  760. files += "/" + file_ptr->name;
  761. }
  762. }
  763. } else {
  764. unowned Alpm.List<unowned Alpm.DB> syncdbs = files_handle.syncdbs;
  765. while (syncdbs != null) {
  766. unowned Alpm.DB db = syncdbs.data;
  767. unowned Alpm.Package? files_pkg = db.get_pkg (pkgname);
  768. if (files_pkg != null) {
  769. unowned Alpm.FileList filelist = files_pkg.files;
  770. Alpm.File* file_ptr = filelist.files;
  771. for (size_t i = 0; i < filelist.count; i++, file_ptr++) {
  772. if (!file_ptr->name.has_suffix ("/")) {
  773. files += "/" + file_ptr->name;
  774. }
  775. }
  776. break;
  777. }
  778. syncdbs.next ();
  779. }
  780. }
  781. return files;
  782. }
  783. private int get_updates () {
  784. AlpmPackage[] updates_infos = {};
  785. #if DISABLE_AUR
  786. #else
  787. unowned Alpm.Package? pkg = null;
  788. #endif
  789. unowned Alpm.Package? candidate = null;
  790. // use a tmp handle
  791. var tmp_handle = alpm_config.get_handle (false, true);
  792. // refresh tmp dbs
  793. unowned Alpm.List<unowned Alpm.DB> syncdbs = tmp_handle.syncdbs;
  794. while (syncdbs != null) {
  795. unowned Alpm.DB db = syncdbs.data;
  796. db.update (0);
  797. syncdbs.next ();
  798. }
  799. // refresh file dbs
  800. var pamac_config = new Pamac.Config ();
  801. if (pamac_config.update_files_db) {
  802. var tmp_files_handle = alpm_config.get_handle (true, true);
  803. syncdbs = tmp_files_handle.syncdbs;
  804. while (syncdbs != null) {
  805. unowned Alpm.DB db = syncdbs.data;
  806. db.update (0);
  807. syncdbs.next ();
  808. }
  809. } else {
  810. var tmp_files_handle = alpm_config.get_handle (false, true);
  811. syncdbs = tmp_files_handle.syncdbs;
  812. while (syncdbs != null) {
  813. unowned Alpm.DB db = syncdbs.data;
  814. db.update (0);
  815. syncdbs.next ();
  816. }
  817. }
  818. #if DISABLE_AUR
  819. #else
  820. string[] local_pkgs = {};
  821. #endif
  822. unowned Alpm.List<unowned Alpm.Package> pkgcache = tmp_handle.localdb.pkgcache;
  823. while (pkgcache != null) {
  824. unowned Alpm.Package installed_pkg = pkgcache.data;
  825. // check if installed_pkg is in IgnorePkg or IgnoreGroup
  826. if (tmp_handle.should_ignore (installed_pkg) == 0) {
  827. candidate = installed_pkg.sync_newversion (tmp_handle.syncdbs);
  828. if (candidate != null) {
  829. var infos = initialise_pkg_struct (candidate);
  830. infos.installed_version = installed_pkg.version;
  831. updates_infos += (owned) infos;
  832. #if DISABLE_AUR
  833. #else
  834. } else {
  835. if (check_aur_updates && (!aur_updates_checked)) {
  836. // check if installed_pkg is a local pkg
  837. syncdbs = tmp_handle.syncdbs;
  838. while (syncdbs != null) {
  839. unowned Alpm.DB db = syncdbs.data;
  840. pkg = Alpm.find_satisfier (db.pkgcache, installed_pkg.name);
  841. if (pkg != null) {
  842. break;
  843. }
  844. syncdbs.next ();
  845. }
  846. if (pkg == null) {
  847. local_pkgs += installed_pkg.name;
  848. }
  849. }
  850. #endif
  851. }
  852. }
  853. pkgcache.next ();
  854. }
  855. #if DISABLE_AUR
  856. #else
  857. if (check_aur_updates) {
  858. // get aur updates
  859. if (!aur_updates_checked) {
  860. multiinfo.begin (local_pkgs, (obj, res) => {
  861. aur_updates_results = multiinfo.end (res);
  862. aur_updates_checked = true;
  863. var updates = Updates () {
  864. repos_updates = (owned) updates_infos,
  865. aur_updates = get_aur_updates_infos ()
  866. };
  867. get_updates_finished (updates);
  868. });
  869. } else {
  870. var updates = Updates () {
  871. repos_updates = (owned) updates_infos,
  872. aur_updates = get_aur_updates_infos ()
  873. };
  874. get_updates_finished (updates);
  875. }
  876. } else {
  877. #endif
  878. var updates = Updates () {
  879. #if DISABLE_AUR
  880. repos_updates = (owned) updates_infos
  881. #else
  882. repos_updates = (owned) updates_infos,
  883. aur_updates = {}
  884. #endif
  885. };
  886. get_updates_finished (updates);
  887. #if DISABLE_AUR
  888. #else
  889. }
  890. #endif
  891. return 0;
  892. }
  893. #if DISABLE_AUR
  894. #else
  895. private AURPackage[] get_aur_updates_infos () {
  896. AURPackage[] aur_updates_infos = {};
  897. aur_updates_results.foreach_element ((array, index, node) => {
  898. unowned Json.Object pkg_info = node.get_object ();
  899. unowned string name = pkg_info.get_string_member ("Name");
  900. unowned string new_version = pkg_info.get_string_member ("Version");
  901. unowned string old_version = alpm_handle.localdb.get_pkg (name).version;
  902. if (Alpm.pkg_vercmp (new_version, old_version) == 1) {
  903. var infos = initialise_aur_struct (pkg_info);
  904. infos.installed_version = old_version;
  905. aur_updates_infos += (owned) infos;
  906. }
  907. });
  908. return aur_updates_infos;
  909. }
  910. #endif
  911. #if DISABLE_AUR
  912. public void start_get_updates () throws DBusError, IOError {
  913. #else
  914. public void start_get_updates (bool check_aur_updates_) throws DBusError, IOError {
  915. check_aur_updates = check_aur_updates_;
  916. #endif
  917. new Thread<int> ("get updates thread", get_updates);
  918. }
  919. [DBus (no_reply = true)]
  920. public void quit () throws DBusError, IOError {
  921. loop.quit ();
  922. }
  923. // End of Daemon Object
  924. }
  925. }
  926. private int alpm_pkg_compare_name (Alpm.Package pkg_a, Alpm.Package pkg_b) {
  927. return strcmp (pkg_a.name, pkg_b.name);
  928. }
  929. private string global_search_string;
  930. private int alpm_pkg_sort_search_by_relevance (Alpm.Package pkg_a, Alpm.Package pkg_b) {
  931. if (global_search_string != null) {
  932. // display exact match first
  933. if (pkg_a.name == global_search_string) {
  934. return 0;
  935. }
  936. if (pkg_b.name == global_search_string) {
  937. return 1;
  938. }
  939. if (pkg_a.name.has_prefix (global_search_string + "-")) {
  940. if (pkg_b.name.has_prefix (global_search_string + "-")) {
  941. return strcmp (pkg_a.name, pkg_b.name);
  942. }
  943. return 0;
  944. }
  945. if (pkg_b.name.has_prefix (global_search_string + "-")) {
  946. if (pkg_a.name.has_prefix (global_search_string + "-")) {
  947. return strcmp (pkg_a.name, pkg_b.name);
  948. }
  949. return 1;
  950. }
  951. if (pkg_a.name.has_prefix (global_search_string)) {
  952. if (pkg_b.name.has_prefix (global_search_string)) {
  953. return strcmp (pkg_a.name, pkg_b.name);
  954. }
  955. return 0;
  956. }
  957. if (pkg_b.name.has_prefix (global_search_string)) {
  958. if (pkg_a.name.has_prefix (global_search_string)) {
  959. return strcmp (pkg_a.name, pkg_b.name);
  960. }
  961. return 1;
  962. }
  963. if (pkg_a.name.contains (global_search_string)) {
  964. if (pkg_b.name.contains (global_search_string)) {
  965. return strcmp (pkg_a.name, pkg_b.name);
  966. }
  967. return 0;
  968. }
  969. if (pkg_b.name.contains (global_search_string)) {
  970. if (pkg_a.name.contains (global_search_string)) {
  971. return strcmp (pkg_a.name, pkg_b.name);
  972. }
  973. return 1;
  974. }
  975. }
  976. return strcmp (pkg_a.name, pkg_b.name);
  977. }
  978. void on_bus_acquired (DBusConnection conn) {
  979. user_daemon = new Pamac.UserDaemon ();
  980. try {
  981. conn.register_object ("/org/pamac/user", user_daemon);
  982. }
  983. catch (IOError e) {
  984. stderr.printf ("Could not register service\n");
  985. loop.quit ();
  986. }
  987. }
  988. void main () {
  989. // i18n
  990. Intl.bindtextdomain(Constants.GETTEXT_PACKAGE, Path.build_filename(Constants.DATADIR,"locale"));
  991. Intl.setlocale (LocaleCategory.ALL, "");
  992. Intl.textdomain(Constants.GETTEXT_PACKAGE);
  993. Intl.bind_textdomain_codeset(Constants.GETTEXT_PACKAGE, "utf-8" );
  994. Bus.own_name (BusType.SESSION,
  995. "org.pamac.user",
  996. BusNameOwnerFlags.NONE,
  997. on_bus_acquired,
  998. null,
  999. () => {
  1000. stderr.printf ("Could not acquire name\n");
  1001. loop.quit ();
  1002. });
  1003. loop = new MainLoop ();
  1004. loop.run ();
  1005. }