From 60a34f6681b6d014e5d4244f74d6b3630c652f5d Mon Sep 17 00:00:00 2001 From: guinux Date: Wed, 22 Oct 2014 18:44:02 +0200 Subject: [PATCH] first commit --- AUTHORS | 2 + COPYING | 674 +++++++++++ README | 1 + TODO | 1 + create_pot_file.sh | 3 + data/applications/pamac-install.desktop | 131 +++ data/applications/pamac-manager.desktop | 139 +++ data/applications/pamac-tray.desktop | 7 + data/applications/pamac-updater.desktop | 135 +++ data/config/pamac.conf | 11 + data/dbus/org.manjaro.pamac.conf | 16 + data/dbus/org.manjaro.pamac.service | 5 + .../16x16/apps/system-software-install.png | Bin 0 -> 748 bytes .../24x24/status/pamac-tray-no-update.png | Bin 0 -> 1057 bytes data/icons/24x24/status/pamac-tray-update.png | Bin 0 -> 1050 bytes .../32x32/apps/system-software-install.png | Bin 0 -> 1910 bytes data/networkmanager/99_update_pamac_tray | 10 + data/polkit/org.manjaro.pamac.policy | 25 + data/systemd/pamac.service | 7 + examples/pactree.vala | 278 +++++ files_to_translate | 24 + pamac.pot | 279 +++++ pot_head | 21 + resources/choose_provider_dialog.ui | 86 ++ resources/history_dialog.ui | 75 ++ resources/manager_window.ui | 818 ++++++++++++++ resources/package-available.png | Bin 0 -> 298 bytes resources/package-install.png | Bin 0 -> 539 bytes resources/package-installed-locked.png | Bin 0 -> 478 bytes resources/package-installed-updated.png | Bin 0 -> 348 bytes resources/package-reinstall.png | Bin 0 -> 555 bytes resources/package-remove.png | Bin 0 -> 618 bytes resources/packages_chooser_dialog.ui | 75 ++ resources/pamac.installer.gresource.xml | 9 + resources/pamac.manager.gresource.xml | 23 + resources/pamac.updater.gresource.xml | 15 + resources/preferences_dialog.ui | 203 ++++ resources/progress_window.ui | 115 ++ resources/transaction_info_dialog.ui | 100 ++ resources/transaction_sum_dialog.ui | 142 +++ resources/updater_window.ui | 191 ++++ src/Makefile | 146 +++ src/alpm_config.vala | 258 +++++ src/aur.vala | 102 ++ src/aur3.vala | 72 ++ src/choose_provider_dialog.vala | 34 + src/common.vala | 265 +++++ src/daemon.vala | 697 ++++++++++++ src/history_dialog.vala | 40 + src/installer.vala | 69 ++ src/manager.vala | 55 + src/manager_window.vala | 927 +++++++++++++++ src/package.vala | 61 + src/packages_chooser_dialog.vala | 56 + src/packages_model.vala | 309 +++++ src/pamac_config.vala | 133 +++ src/preferences_dialog.vala | 40 + src/progress_window.vala | 61 + src/transaction.vala | 899 +++++++++++++++ src/transaction_info_dialog.vala | 40 + src/transaction_sum_dialog.vala | 41 + src/tray.vala | 256 +++++ src/updater.vala | 55 + src/updater_window.vala | 178 +++ update_po_files.sh | 5 + util/alpm-util.c | 55 + util/alpm-util.h | 20 + vapi/libalpm.vapi | 1006 +++++++++++++++++ vapi/polkit-gobject-1.vapi | 220 ++++ 69 files changed, 9721 insertions(+) create mode 100644 AUTHORS create mode 100644 COPYING create mode 100644 README create mode 100644 TODO create mode 100755 create_pot_file.sh create mode 100644 data/applications/pamac-install.desktop create mode 100644 data/applications/pamac-manager.desktop create mode 100644 data/applications/pamac-tray.desktop create mode 100644 data/applications/pamac-updater.desktop create mode 100644 data/config/pamac.conf create mode 100644 data/dbus/org.manjaro.pamac.conf create mode 100644 data/dbus/org.manjaro.pamac.service create mode 100644 data/icons/16x16/apps/system-software-install.png create mode 100644 data/icons/24x24/status/pamac-tray-no-update.png create mode 100644 data/icons/24x24/status/pamac-tray-update.png create mode 100644 data/icons/32x32/apps/system-software-install.png create mode 100755 data/networkmanager/99_update_pamac_tray create mode 100644 data/polkit/org.manjaro.pamac.policy create mode 100644 data/systemd/pamac.service create mode 100644 examples/pactree.vala create mode 100644 files_to_translate create mode 100644 pamac.pot create mode 100644 pot_head create mode 100644 resources/choose_provider_dialog.ui create mode 100644 resources/history_dialog.ui create mode 100644 resources/manager_window.ui create mode 100644 resources/package-available.png create mode 100644 resources/package-install.png create mode 100644 resources/package-installed-locked.png create mode 100644 resources/package-installed-updated.png create mode 100644 resources/package-reinstall.png create mode 100644 resources/package-remove.png create mode 100644 resources/packages_chooser_dialog.ui create mode 100644 resources/pamac.installer.gresource.xml create mode 100644 resources/pamac.manager.gresource.xml create mode 100644 resources/pamac.updater.gresource.xml create mode 100644 resources/preferences_dialog.ui create mode 100644 resources/progress_window.ui create mode 100644 resources/transaction_info_dialog.ui create mode 100644 resources/transaction_sum_dialog.ui create mode 100644 resources/updater_window.ui create mode 100644 src/Makefile create mode 100644 src/alpm_config.vala create mode 100644 src/aur.vala create mode 100644 src/aur3.vala create mode 100644 src/choose_provider_dialog.vala create mode 100644 src/common.vala create mode 100644 src/daemon.vala create mode 100644 src/history_dialog.vala create mode 100644 src/installer.vala create mode 100644 src/manager.vala create mode 100644 src/manager_window.vala create mode 100644 src/package.vala create mode 100644 src/packages_chooser_dialog.vala create mode 100644 src/packages_model.vala create mode 100644 src/pamac_config.vala create mode 100644 src/preferences_dialog.vala create mode 100644 src/progress_window.vala create mode 100644 src/transaction.vala create mode 100644 src/transaction_info_dialog.vala create mode 100644 src/transaction_sum_dialog.vala create mode 100644 src/tray.vala create mode 100644 src/updater.vala create mode 100644 src/updater_window.vala create mode 100755 update_po_files.sh create mode 100644 util/alpm-util.c create mode 100644 util/alpm-util.h create mode 100644 vapi/libalpm.vapi create mode 100644 vapi/polkit-gobject-1.vapi diff --git a/AUTHORS b/AUTHORS new file mode 100644 index 0000000..e7cb480 --- /dev/null +++ b/AUTHORS @@ -0,0 +1,2 @@ +Main developers: + Guillaume Benoit diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..94a9ed0 --- /dev/null +++ b/COPYING @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/README b/README new file mode 100644 index 0000000..e07a1f1 --- /dev/null +++ b/README @@ -0,0 +1 @@ +A DBus daemon and Gtk3 frontend for libalpm written in vala diff --git a/TODO b/TODO new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/TODO @@ -0,0 +1 @@ + diff --git a/create_pot_file.sh b/create_pot_file.sh new file mode 100755 index 0000000..c009b28 --- /dev/null +++ b/create_pot_file.sh @@ -0,0 +1,3 @@ +#! /bin/sh + +xgettext --from-code=UTF-8 --files-from=./files_to_translate --keyword=translatable --keyword=_ --output=pamac.pot diff --git a/data/applications/pamac-install.desktop b/data/applications/pamac-install.desktop new file mode 100644 index 0000000..eeef2c6 --- /dev/null +++ b/data/applications/pamac-install.desktop @@ -0,0 +1,131 @@ +[Desktop Entry] +Name=Software Install +Name[af]=Sagteware installeer +Name[ar]=تثبيت البرامج +Name[as]=চফ্টৱেৰ ইনস্টল +Name[ast]=Instalador de software +Name[be]=Усталяванне апраграмавання +Name[bg]=Инсталиране на софтуер +Name[bn_IN]=সফ্টওয়্যার ইনস্টলেশন +Name[ca]=Instal·lació de programari +Name[ca@valencia]=Instal·lació de programari +Name[cs]=Instalace softwaru +Name[da]=Softwareinstallation +Name[de]=Software-Installation +Name[el]=Εγκατάσταση λογισμικού +Name[en_GB]=Software Install +Name[es]=Instalador de software +Name[et]=Tarkvara paigaldamine +Name[eu]=Paketeen instalatzailea +Name[fa]=نصب نرم‌افزار +Name[fi]=Ohjelmistojen asennus +Name[fr]=Installation de logiciels +Name[gl]=Instalador de software +Name[gu]=સોફ્ટવેર સ્થાપન +Name[he]=התקנת תכנה +Name[hi]=सॉफ्टवेयर संस्थापित करें +Name[hu]=Szoftvertelepítő +Name[id]=Pasang Perangkat Lunak +Name[it]=Installatore software +Name[ja]=ソフトウェアのインストール +Name[kn]=ತಂತ್ರಾಂಶ ಅನುಸ್ಥಾಪನೆ +Name[ko]=소프트웨어 설치 +Name[lt]=Programinės įrangos įdiegimas +Name[lv]=Programmatūras instalēšana +Name[mk]=Инсталација на софтвер +Name[ml]=സോഫ്റ്റ്‌വെയര്‍ ഇന്‍സ്റ്റോള്‍ +Name[mr]=सॉफ्टवेअर प्रतिष्ठापन +Name[nb]=Programvareinstallasjon +Name[nl]=Software-installatie +Name[pa]=ਸਾਫਟਵੇਅਰ ਇੰਸਟਾਲ ਕਰੋ +Name[pl]=Instalacja oprogramowania +Name[pt]=Instalar Software +Name[pt_BR]=Instalação de programas +Name[ru]=Установка программ +Name[sk]=Inštalácia softvéru +Name[sl]=Nameščanje programske opreme +Name[sr]=Инсталација софтвера +Name[sr@latin]=Instalacija softvera +Name[sv]=Programinstallation +Name[ta]=மென்பொருள் நிறுவல் +Name[te]=సాఫ్ట్‍వేర్ స్థాపన +Name[th]=ติดตั้งซอฟต์แวร์ +Name[tr]=Yazılım Kur +Name[ug]=يۇمشاق دېتال ئورنات +Name[uk]=Установлення програм +Name[vi]=Cài phần mềm +Name[zh_CN]=软件安装程序 +Name[zh_HK]=軟件安裝 +Name[zh_TW]=軟體安裝 +Comment=Install selected software on the system +Comment[af]=Installeer gekose sagteware op die stelsel +Comment[ar]=ثبت البرمجيات المختارة على النظام +Comment[as]=চিস্টেমত নিৰ্বাচিত চফ্টৱেৰ ইনস্টল কৰক +Comment[ast]=Instalar el software escoyíu nel sistema +Comment[be]=Усталяваць вылучанае апраграмаванне ў сістэму +Comment[bg]=Инсталиране на избрания софтуер на системата +Comment[bn]=সিস্টেমের মধ্যে নির্বাচিত সফ্টওয়্যার ইনস্টল +Comment[bn_IN]=সিস্টেমের মধ্যে নির্বাচিত সফ্টওয়্যার ইনস্টল করুন +Comment[ca]=Instal·la el programari seleccionat en el sistema +Comment[ca@valencia]=Instal·la el programari seleccionat en el sistema +Comment[cs]=Instalovat vybraný software do tohoto systému +Comment[da]=Installér valgt software på systemet +Comment[de]=Ausgewählte Software auf dem System installieren +Comment[el]=Εγκατάσταση του επιλεγμένου λογισμικού στο σύστημα +Comment[en@shaw]=𐑦𐑯𐑕𐑑𐑷𐑤 𐑕𐑩𐑤𐑧𐑒𐑑𐑩𐑛 𐑕𐑪𐑓𐑑𐑢𐑺 𐑪𐑯 𐑞 𐑕𐑦𐑕𐑑𐑩𐑥 +Comment[en_GB]=Install selected software on the system +Comment[eo]=Instali elektitan programaron sur the sistemo +Comment[es]=Instalar el software seleccionado en el sistema +Comment[et]=Valitud tarkvara paigaldamine arvutisse +Comment[eu]=Instalatu hautatutako softwarea sisteman +Comment[fa]=نصب نرم‌افزار انتخاب شده بر روی سیستم +Comment[fi]=Asenna valitut ohjelmistot järjestelmään +Comment[fr]=Installer le logiciel sélectionné sur le système +Comment[gl]=Instalar o programa seleccionado no sistema +Comment[gu]=સિસ્ટમ પર પસંદ થયેલ સોફ્ટવેરને સ્થાપિત કરો +Comment[he]=התקנת התוכנות הנבחרות על המערכת +Comment[hi]=सिस्टम पर चयनित सॉफ्टवेयर संस्थापित करें +Comment[hu]=A kijelölt szoftverek telepítése a rendszerre +Comment[id]=Pasang perangkat lunak yang dipilih pada sistem +Comment[it]=Installa il software selezionato sul sistema +Comment[ja]=選択されたソフトウェアをシステムにインストールします +Comment[kn]=ಆರಿಸಲಾದ ತಂತ್ರಾಂಶವನ್ನು ಗಣಕದಲ್ಲಿ ಅನುಸ್ಥಾಪಿಸು +Comment[ko]=선택한 소프트웨어를 시스템에 설치합니다 +Comment[lt]=Įdiegti pasirinktą programinę įrangą sistemoje +Comment[lv]=Instalēt izvēlēto programmatūru sistēmā +Comment[mk]=Инсталирај го избраниот софтвер на системот +Comment[ml]=തെരഞ്ഞെടുത്ത സോഫ്റ്റ്‌വെയറുകള്‍ സിസ്റ്റമില്‍ ഇന്‍സ്റ്റോള്‍ ചെയ്യുക +Comment[mr]=नीवडलेले सॉफ्टवेअर प्रणालीवर प्रतिष्ठापीत करा +Comment[nb]=Installer valgt programvare på systemet +Comment[nl]=Geselecteerde software op het systeem installeren +Comment[nn]=Installer vald programvare på systemet +Comment[or]=ତନ୍ତ୍ରରେ ବଚ୍ଛିତ ସଫ୍ଟୱେର ସ୍ଥାପନ କରନ୍ତୁ +Comment[pa]=ਚੁਣੇ ਸਾਫਟਵੇਅਰ ਸਿਸਟਮ ਉੱਤੇ ਇੰਸਟਾਲ ਕਰੋ +Comment[pl]=Instalacja wybranego oprogramowania w systemie +Comment[pt]=Instalar software seleccionado no sistema +Comment[pt_BR]=Instale o programa selecionado no sistema +Comment[ro]=Instalează pachetele selectate pe sistem +Comment[ru]=Установить в систему выбранные программы +Comment[sk]=Nainštalovať na systéme zvolený softvér +Comment[sl]=Namestitev izbrane programske opreme v sistem +Comment[sr]=Инсталирајте изабране програме на систем +Comment[sr@latin]=Instalirajte izabrane programe na sistem +Comment[sv]=Installera markerad programvara på systemet +Comment[ta]=தேர்ந்தெடுக்கப்பட்ட மென்பொருளை கணினியில் நிறுவவும் +Comment[te]=ఎంచుకున్న సాఫ్ట్‍‌వేర్‌ను వ్యవస్థ నందు స్థాపించు +Comment[th]=ติดตั้งซอฟต์แวร์ที่เลือกไว้ลงในระบบ +Comment[tr]=Seçili yazılımı sisteme kur +Comment[ug]=تاللانغان يۇمشاق دېتالنى سىستېمىغا ئورنات +Comment[uk]=Встановити у систему вибрані програми +Comment[vi]=Cài đặt phần mềm đã chọn vào hệ thống +Comment[zh_CN]=在系统中安装选定的软件 +Comment[zh_HK]=安裝選取的軟件到系統中 +Comment[zh_TW]=安裝選取的軟體到系統中 +Categories=System; +Exec=pamac-install %F +Terminal=false +Type=Application +Icon=system-software-install +StartupNotify=true +NoDisplay=true +MimeType=application/x-xz-compressed-tar; diff --git a/data/applications/pamac-manager.desktop b/data/applications/pamac-manager.desktop new file mode 100644 index 0000000..b510029 --- /dev/null +++ b/data/applications/pamac-manager.desktop @@ -0,0 +1,139 @@ +[Desktop Entry] +Name=Add/Remove Software +Name[af]=Voeg by/verwyder sagteware +Name[ar]=إضافة وإزالة البرمجيات +Name[as]=চালনাজ্ঞান যোগ কৰক/আঁতৰাই দিয়ক +Name[ast]=Amestar/Quitar software +Name[be]=Дадаць/выдаліць апраграмаванне +Name[bg]=Инсталиране/деинсталиране на софтуер +Name[bn]=সফ্টওয়্যার যোগ/অপসারণ +Name[bn_IN]=সফ্টওয়্যার যোগ/অপসারণ করুন +Name[ca]=Afegeix/Suprimeix programari +Name[ca@valencia]=Afig/Suprimeix programari +Name[cs]=Přidat/odebrat software +Name[da]=Tilføj/fjern software +Name[de]=Software hinzufügen/entfernen +Name[el]=Προσθαφαίρεση λογισμικού +Name[en@shaw]=𐑨𐑛/𐑮𐑦𐑥𐑵𐑝 𐑕𐑪𐑓𐑑𐑢𐑺 +Name[en_GB]=Add/Remove Software +Name[eo]=Aldoni/forigi instalitan pogramaron +Name[es]=Añadir/Quitar software +Name[et]=Tarkvara lisamine ja eemaldamine +Name[eu]=Gehitu/Kendu softwarea +Name[fa]=افزودن/حذف نرم‌افزار +Name[fi]=Lisää tai poista ohjelmistoja +Name[fr]=Ajouter/supprimer des logiciels +Name[ga]=Cuir Leis/Bain Bogearraí +Name[gl]=Engadir ou eliminar programas +Name[gu]=સોફ્ટવેરને ઉમેરો/દૂર કરો +Name[he]=הוספת/הסרת תכנה +Name[hi]=सॉफ्टवेयर जोड़ें/हटायें +Name[hu]=Szoftver telepítése/eltávolítása +Name[id]=Tambah/Hapus Piranti Lunak +Name[it]=Aggiungi/Rimuovi software +Name[ja]=ソフトウェアの追加と削除 +Name[kn]=ತಂತ್ರಾಂಶವನ್ನು ಸೇರಿಸು ಅಥವ ತೆಗೆ +Name[ko]=소프트웨어 추가/제거 +Name[lt]=Įdiegti ar šalinti programinę įrangą +Name[lv]=Pievienot/Izņemt programmatūru +Name[mk]=Инсталирај/избриши софтвер +Name[ml]=സോഫ്റ്റ്‌വെയര്‍ ചേര്‍ക്കുക/നീക്കം ചെയ്യുക +Name[mr]=सॉफ्टवेअर जोडा/काढून टाका +Name[ms]=Menambah/Memadam perisian +Name[nb]=Legg til/fjern programvare +Name[nl]=Software installeren/verwijderen +Name[nn]=Legg til/fjern programvare +Name[or]=ସଫ୍ଟୱେର ଯୋଗ/ଅପସାରଣ କରନ୍ତୁ +Name[pa]=ਸਾਫਟਵੇਅਰ ਸ਼ਾਮਲ/ਹਟਾਓ +Name[pl]=Dodanie/usuwanie oprogramowania +Name[pt]=Adicionar/Remover Software +Name[pt_BR]=Adicionar/remover programas +Name[ro]=Adăugare sau ștergere programe +Name[ru]=Установка и удаление программ +Name[sk]=Pridať/odstrániť softvér +Name[sl]=Upravljanje programske opreme +Name[sr]=Додај-уклони програме +Name[sr@latin]=Dodaj-ukloni programe +Name[sv]=Lägg till/Ta bort programvara +Name[ta]=மென்பொருளை சேர்த்தல்/நீக்குதல் +Name[te]=సాఫ్ట్‍వేర్ జతచేయి/తీసివేయి +Name[th]=เพิ่ม/ลบซอฟต์แวร์ +Name[tr]=Yazılım Ekle/Kaldır +Name[ug]=يۇمشاق دېتالنى قوش/ئۆچۈر +Name[uk]=Встановлення та вилучення програм +Name[vi]=Thêm/Gỡ phần mềm +Name[zh_CN]=添加/删除软件 +Name[zh_HK]=加入或移除軟件 +Name[zh_TW]=加入或移除軟體 +Comment=Add or remove software installed on the system +Comment[af]=Voeg by of verwyder sagteware geïnstalleer op die stelsel +Comment[ar]=أضف أو أزل البرمجيات المثبتة على النظام +Comment[as]=ব্যৱস্থাপ্ৰণালীত সংস্থাপিত চালনাজ্ঞান উন্নয়ন কৰক +Comment[ast]=Amestar o quitar software instaláu nel sistema +Comment[be]=Дадаць ці выдаліць апраграмаванне, усталяванае ў сістэме +Comment[bg]=Инсталиране и деинсталиране на софтуер към системата +Comment[bn]=সিস্টেমে সফ্টওয়্যার যোগ করুন অথবা ইনস্টল করা সফ্টওয়্যার অপসারণ +Comment[bn_IN]=সিস্টেমে সফ্টওয়্যার যোগ করুন অথবা ইনস্টল করা সফ্টওয়্যার সরিয়ে ফেলুন +Comment[ca]=Afegeix o suprimeix programari instal·lat en el sistema +Comment[ca@valencia]=Afig o suprimeix programari instal·lat en el sistema +Comment[cs]=Přidat nebo odebrat software instalovaný v systému +Comment[da]=Tilføj eller fjern software installeret på systemet +Comment[de]=Auf dem System installierte Software aktualisieren oder neue Software hinzufügen +Comment[el]=Προσθαφαίρεση λογισμικού στο σύστημα +Comment[en@shaw]=𐑨𐑛 𐑹 𐑮𐑦𐑥𐑵𐑝 𐑕𐑪𐑓𐑑𐑢𐑺 𐑦𐑯𐑕𐑑𐑷𐑤𐑛 𐑪𐑯 𐑞 𐑕𐑦𐑕𐑑𐑩𐑥 +Comment[en_GB]=Add or remove software installed on the system +Comment[eo]=Aldoni aŭ forigi instalitan pogramaron sur via sistemo +Comment[es]=Añadir o quitar software instalado en el sistema +Comment[et]=Arvutisse paigaldatud tarkvara lisamine ja eemaldamine +Comment[eu]=Gehitu edo kendu sisteman instalatutako softwarea +Comment[fa]=حذف یا افزودن نرم‌افزارهای نصب شده بر روی این سیستم +Comment[fi]=Lisää tai poista järjestelmään asennettuja ohjelmistoja +Comment[fr]=Ajouter ou supprimer des logiciels installés sur le système +Comment[gl]=Engadir e eliminar o software instalado no sistema +Comment[gu]=સિસ્ટમ પર સ્થાપિત થયેલ સોફ્ટવેરને ઉમેરો અથવા દૂર કરો +Comment[he]=הוספה או הסרה של יישומי המערכת +Comment[hi]=सिस्टम पर संस्थापित सॉफ्टवेयर जोड़ें या हटाएँ +Comment[hu]=Szoftverek rendszerre telepítése vagy eltávolítása +Comment[id]=Tambah atau hapus perangkat lunak yang terpasang pada sistem +Comment[it]=Aggiunge o rimuove software installato sul sistema +Comment[ja]=システムにインストールされたパッケージの追加と削除 +Comment[kn]=ಗಣಕಕ್ಕೆ ತಂತ್ರಾಂಶವನ್ನು ಸೇರಿಸು ಅಥವ ಅನುಸ್ಥಾಪಿತಗೊಂಡಿರುವುದನ್ನು ತೆಗೆದು ಹಾಕು +Comment[ko]=시스템에 설치하는 소프트웨어를 추가하거나 제거합니다 +Comment[lt]=Įdiegti ar šalinti sistemoje įdiegtą programinę įrangą +Comment[lv]=Pievienot vai izņemt programmatūru sistēmā +Comment[mk]=Инсталирајте или избришете софтвер на системот +Comment[ml]=സിസ്റ്റത്തില്‍ ഇന്‍സ്റ്റോള്‍ ചെയ്തിരിക്കുന്ന സോഫ്റ്റ്‌വെയര്‍ ചേര്‍ക്കുക അല്ലെങ്കില്‍ നീക്കം ചെയ്യുക +Comment[mr]=प्रणालीवर प्रतिष्ठापीत सॉफ्टवेअर समावेष करा किंवा काढूण टाका +Comment[ms]=Menambah atau memadam perisian yang dipasang pada sistem +Comment[nb]=Legg til eller fjern programvare på systemet +Comment[nl]=Software installeren op, of verwijderen van het systeem +Comment[nn]=Legg til eller fjern programvare som er installert på systemet +Comment[or]=ତନ୍ତ୍ରରେ ସ୍ଥାପିତ ସଫ୍ଟୱେରରେ ଯୋଗକରନ୍ତୁ କିମ୍ବା କାଢ଼ି ଦିଅନ୍ତୁ +Comment[pa]=ਸਿਸਟਮ ਉੱਤੇ ਸਾਫਟਵੇਅਰ ਇੰਸਟਾਲ ਕਰੋ ਜਾਂ ਇੰਸਟਾਲ ਕੀਤੇ ਹਟਾਓ +Comment[pl]=Instalowanie lub usuwanie oprogramowania zainstalowanego w systemie +Comment[pt]=Adicionar ou remover software instalado no sistema +Comment[pt_BR]=Adicione ou remova programas instalados no sistema +Comment[ro]=Adăugați sau ștergeți programe instalate pe sistem +Comment[ru]=Установка и удаление программ, установленных в системе +Comment[sk]=Pridať alebo odstrániť softvér nainštalovaný na systéme +Comment[sl]=Nameščanje in odstranjevanje programske opreme sistema +Comment[sr]=Додајте или уклоните програме инсталиране на овом систему +Comment[sr@latin]=Dodajte ili uklonite programe instalirane na ovom sistemu +Comment[sv]=Lägg till eller ta bort programvara installerad på systemet +Comment[ta]=கணினியில் நிறுவப்பட்ட மென்பொருளை சேர்க்கவும் அல்லது நீக்கவும் +Comment[te]=ఈ వ్యవస్థ నందు స్థాపించిన సాఫ్ట్‍వేర్‌ను జతచేయి లేదా తీసివేయి +Comment[th]=เพิ่มหรือลบซอฟต์แวร์ที่ติดตั้งในระบบ +Comment[tr]=Sisteminizde yüklü yazılımları ekleyin veya kaldırın +Comment[ug]=سىستېمىڭىزغا ئورنىتىلغان يۇمشاق دېتاللارنى قوشىدۇ ياكى ئۆچۈرىدۇ +Comment[uk]=Встановлення та вилучення програм у системі +Comment[vi]=Thêm hoặc gỡ phần mềm cài đặt trên hệ thống +Comment[zh_CN]=添加或删除系统中安装的软件 +Comment[zh_HK]=加入或移除系統上安裝的軟件 +Comment[zh_TW]=加入或移除系統上安裝的軟體 +Icon=system-software-install +Exec=pamac-manager +Terminal=false +Type=Application +Categories=GNOME;GTK;System; +#NotShowIn=KDE; +StartupNotify=true diff --git a/data/applications/pamac-tray.desktop b/data/applications/pamac-tray.desktop new file mode 100644 index 0000000..e98a745 --- /dev/null +++ b/data/applications/pamac-tray.desktop @@ -0,0 +1,7 @@ +[Desktop Entry] +Name=Update Notifier +Icon=update-notifier +Exec=pamac-tray +Terminal=false +Type=Application +StartupNotify=true diff --git a/data/applications/pamac-updater.desktop b/data/applications/pamac-updater.desktop new file mode 100644 index 0000000..a24cb54 --- /dev/null +++ b/data/applications/pamac-updater.desktop @@ -0,0 +1,135 @@ +[Desktop Entry] +Name=Software Update +Name[af]=Sagtewarebywerking +Name[ar]=تحديث البرمجيات +Name[as]=চালনাজ্ঞান উন্নয়ন ব্যৱস্থা +Name[ast]=Anovamientu de software +Name[be]=Абнаўленне апраграмавання +Name[bg]=Обновление на софтуера +Name[bn]=সফ্টওয়্যার হালনাগাদ +Name[bn_IN]=সফ্টওয়্যার আপডেট ব্যবস্থা +Name[ca]=Actualització de programari +Name[ca@valencia]=Actualització de programari +Name[cs]=Aktualizace softwaru +Name[da]=Softwareopdatering +Name[de]=Software-Aktualisierungen +Name[el]=Ενημέρωση λογισμικού +Name[en@shaw]=𐑕𐑪𐑓𐑑𐑢𐑺 𐑳𐑐𐑛𐑱𐑑 +Name[en_GB]=Software Update +Name[eo]=Programar-ĝistatigo +Name[es]=Actualización de software +Name[et]=Tarkvarauuendus +Name[eu]=Softwarearen eguneraketa +Name[fa]=بروزرسانی نرم‌افزار +Name[fi]=Ohjelmistopäivitykset +Name[fr]=Mise à jour des logiciels +Name[gl]=Actualización de software +Name[gu]=સોફ્ટવેર સુધારા +Name[he]=עדכון תכנה +Name[hi]=सॉफ्टवेयर अद्यतन +Name[hu]=Szoftverfrissítés +Name[id]=Pembaruan Perangkat Lunak +Name[it]=Aggiornamento software +Name[ja]=ソフトウェアの更新 +Name[kn]=ತಂತ್ರಾಂಶ ಅಪ್‌ಡೇಟ್‌ +Name[ko]=소프트웨어 업데이트 +Name[lt]=Programinės įrangos atnaujinimas +Name[lv]=Programmatūras atjaunināšana +Name[mk]=Ажурирање на софтвер +Name[ml]=സോഫ്റ്റ്‌വെയര്‍ പരിഷ്കാരം +Name[mr]=सॉफ्टवेअर अद्ययावत +Name[nb]=Programvareoppdatering +Name[nl]=Software bijwerken +Name[nn]=Programvareoppdatering +Name[or]=ସଫ୍ଟୱେର ଅଦ୍ୟତନ +Name[pa]=ਸਾਫਟਵੇਅਰ ਅੱਪਡੇਟ +Name[pl]=Aktualizacja oprogramowania +Name[pt]=Actualização de Software +Name[pt_BR]=Atualizações de programas +Name[ro]=Actualizări de programe +Name[ru]=Обновление программ +Name[sk]=Aktualizácia softvéru +Name[sl]=Posodobitev programske opreme +Name[sr]=Ажурирање програма +Name[sr@latin]=Ažuriranje programa +Name[sv]=Programuppdatering +Name[ta]=மென்பொருள் மேம்படுத்தல் +Name[te]=సాప్ట్‍వేర్ నవీకరణ +Name[th]=ปรับรุ่นซอฟต์แวร์ +Name[tr]=Yazılım Güncelleme +Name[ug]=يۇمشاق دېتال يېڭىلاش +Name[uk]=Оновлення програм +Name[vi]=Bản cập nhật phần mềm +Name[zh_CN]=软件更新 +Name[zh_HK]=軟件更新 +Name[zh_TW]=軟體更新 +Comment=Update software installed on the system +Comment[af]=Werk geïnstalleer sagteware op die stelsel by +Comment[ar]=حدّث الحزم المُثبّتة على النظام +Comment[as]=ব্যৱস্থাপ্ৰণালীত সংস্থাপিত চালনাজ্ঞান উন্নয়ন কৰক +Comment[ast]=Anovar el software instaláu nel sistema +Comment[be]=Абнаўленне апраграмавання, усталяванага ў сістэме +Comment[bg]=Обновяване на софтуера инсталиран върху системата +Comment[bn]=সিস্টেমে ইনস্টলকৃত সফ্টওয়্যার হালনাগাদ +Comment[bn_IN]=সিস্টেমে ইনস্টল থাকা সফ্টওয়্যার আপডেট করুন +Comment[ca]=Actualitza el programari instal·lat en el sistema +Comment[ca@valencia]=Actualitza el programari instal·lat en el sistema +Comment[cs]=Aktualizovat software instalovaný v tomto systému +Comment[da]=Opdatér software installeret på systemet +Comment[de]=Auf dem System installierte Software aktualisieren +Comment[el]=Ενημέρωση εγκατεστημένου λογισμικού +Comment[en@shaw]=𐑳𐑐𐑛𐑱𐑑 𐑕𐑪𐑓𐑑𐑢𐑺 𐑦𐑯𐑕𐑑𐑷𐑤𐑛 𐑪𐑯 𐑞 𐑕𐑦𐑕𐑑𐑩𐑥 +Comment[en_GB]=Update software installed on the system +Comment[es]=Actualizar el software instalado en el sistema +Comment[et]=Süsteemi paigaldatud tarkvara uuendamine +Comment[eu]=Eguneratu sisteman instalatutako softwarea +Comment[fa]=بروزرسانی نرم‌افزار نصب شده بر روی سیستم +Comment[fi]=Päivitä järjestelmään asennettuja ohjelmistoja +Comment[fr]=Met à jour les logiciels installés sur le système +Comment[gl]=Actualizar o software instalado no sistema +Comment[gu]=સિસ્ટમ પર સ્થાપિત થયેલ સોફ્ટવેરને સુધારો +Comment[he]=עדכון תוכנות המותקנות על המערכת +Comment[hi]=सिस्टम पर संस्थापित सॉफ्टवेयर अद्यतन करें +Comment[hu]=A rendszerre telepített szoftverek frissítése +Comment[id]=Mutakhirkan perangkat lunak yang terpasang pada sistem +Comment[it]=Aggiorna il software installato sul sistema +Comment[ja]=システムにインストールされたパッケージの更新 +Comment[kn]=ಗಣಕದಲ್ಲಿ ಅನುಸ್ಥಾಪಿತಗೊಂಡಿರುವ ತಂತ್ರಾಂಶವನ್ನು ಅಪ್ಡೇಟ್ ಮಾಡು +Comment[ko]=시스템에 설치한 소프트웨어를 업데이트합니다 +Comment[lt]=Atnaujinti sistemoje įdiegtą programinę įrangą +Comment[lv]=Atjaunināt sistēmā instalēto programmatūru +Comment[mk]=Ажурирај го софтверот инсталирај на системот +Comment[ml]=സിസ്റ്റമില്‍ ഇന്‍സ്റ്റോള്‍ ചെയ്തിരിക്കുന്ന സോഫ്റ്റ്‌വെയറുകള്‍ പരിഷ്കരിക്കുക +Comment[mr]=प्रणालीवर प्रतिष्ठापीत सॉफ्टवेअर अद्ययावत करा +Comment[nb]=Oppdater programvare som er installert på systemet +Comment[nl]=Werk de op uw systeem geïnstalleerde software bij +Comment[nn]=Oppdater programvare installert på systemet +Comment[or]=ତନ୍ତ୍ରରେ ସ୍ଥାପନ କରାଯାଇଥିବା ସଫ୍ଟୱେରକୁ ଅଦ୍ୟତନ କରନ୍ତୁ +Comment[pa]=ਸਿਸਟਮ ਉੱਤੇ ਇੰਸਟਾਲ ਸਾਫਟਵੇਅਰ ਅੱਪਡੇਟ ਕਰੋ +Comment[pl]=Aktualizacja oprogramowania zainstalowanego w systemie +Comment[pt]=Actualizar software instalado no sistema +Comment[pt_BR]=Atualize os programas instalados no sistema +Comment[ro]=Actualizați programele instalate pe sistem +Comment[ru]=Обновление программ, установленных в системе +Comment[sk]=Aktualizovať softvér nainštalovaný na tomto systéme +Comment[sl]=Posodobitev programske opreme nameščene na sistemu +Comment[sr]=Ажурирајте програме инсталиране на овом систему +Comment[sr@latin]=Ažurirajte programe instalirane na ovom sistemu +Comment[sv]=Uppdatera programvara installerade på systemet +Comment[ta]=கணினியில் நிறுவப்பட்ட மென்பொருளை புதுப்பிக்கவும் +Comment[te]=వ్యవస్థ నందు స్థాపించిన సాఫ్ట్‍వేర్‌ను నవీకరించు +Comment[th]=ปรับรุ่นซอฟต์แวร์ที่ติดตั้งอยู่ในระบบ +Comment[tr]=Sisteminizde yüklü yazılımı güncelleyin +Comment[ug]=يېڭىلاش يۇمشاق دېتال بۇ سىستېمىغا ئورنىتىلدى +Comment[uk]=Оновлення програм, встановлених у системі +Comment[vi]=Cập nhật phần mềm đã cài đặt trên hệ thống +Comment[zh_CN]=更新本系统中安装的软件 +Comment[zh_HK]=更新系統中已安裝的軟件 +Comment[zh_TW]=更新系統中已安裝的軟體 +Icon=system-software-update +Exec=pamac-updater +Terminal=false +Type=Application +Categories=GNOME;GTK;System; +#NotShowIn=KDE +StartupNotify=true diff --git a/data/config/pamac.conf b/data/config/pamac.conf new file mode 100644 index 0000000..d0ee221 --- /dev/null +++ b/data/config/pamac.conf @@ -0,0 +1,11 @@ +### Pamac configuration file + +## How often to check for updates, value in hours: +RefreshPeriod = 4 + +## Allow Pamac to search and install packages from AUR: +EnableAUR + +## When removing a package, also remove those dependencies +## that are not required by other packages (recurse option): +#RemoveUnrequiredDeps diff --git a/data/dbus/org.manjaro.pamac.conf b/data/dbus/org.manjaro.pamac.conf new file mode 100644 index 0000000..2d727f7 --- /dev/null +++ b/data/dbus/org.manjaro.pamac.conf @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + diff --git a/data/dbus/org.manjaro.pamac.service b/data/dbus/org.manjaro.pamac.service new file mode 100644 index 0000000..1d8b045 --- /dev/null +++ b/data/dbus/org.manjaro.pamac.service @@ -0,0 +1,5 @@ +[D-BUS Service] +Name=org.manjaro.pamac +Exec=/usr/bin/pamac-daemon +User=root +SystemdService=pamac.service diff --git a/data/icons/16x16/apps/system-software-install.png b/data/icons/16x16/apps/system-software-install.png new file mode 100644 index 0000000000000000000000000000000000000000..f88f63d8d2d28f74d5c10ee4cb80cc87d1f42575 GIT binary patch literal 748 zcmV zgHNl$V2vc6;5#IAe6slnm1O{Pz-k~f1tu?0S`}rh{@;SA`#H0g*`EbmUQ!M@^-3 zw1M&P6jRTpT+SRPhrdy~j@q?Y*YRZOBeG2M=WxQ{*_V8rz5+n0jGw>T<^IFR)Uzo@ zf)E;u(Xi4lSm_r46uoLbLgu)zLw-5?0e}bV&ml%aW04>j?*m<9kq{QI6dh$(tZ z>=@@F024b#M7W$xXj+d6LGZ03iYx#ow&lS5L3uCdeDns_%rA8``kh-}f6mLpQ)afs z1QFWCBL4xr{&k=6*@XDChhME}+PQ*htZ7b8sD3QTG-wHeZ!A${!Hr6Mwp!u#rnn15 z@CCsaxC@2bn{sElK&6BZBG`I{h+Om1Xg2ywGiF#l z@540}QG|Y>`66E-?rY-yJT8sm`0WTqdS%L7Z=amkFJ8Z&Zr${8F(qm@-_b!eLMugX e^kKhew*LbEb&W!rA`3$R0000!lvI6;x#X;^) z4C~IxyaaL-l0AZa85pY67#JE_7#My5g&JNkFq9fFFuY1&V6d9Oz#v{QXIG#NP=YPV z+ueoXKL{?^yL>WGgtNdSvKVOfbr5EB(wJSrz`*p;)5S5wqbGk=8}bBnbRILL`QL`eVoGQ*4&;|z>&h2l6m5W-qE>>9p%Hs5iZSRoLp;%QEfafnff;dH=2z%CIWP@ZIL-=Dx2k)Y-CXRr1A*l9Y;y zAJPvB*R#x@?zPnZ(8CX!o|7abBo>6Ne)!vt;b6jqg$osJ&O387KDKB-nes{N!xCAK zS56OZZ+lxcuY6VTh0iwMzJ2SvFMGU@aer{0dei0xm6i`J0=B$991l%5o@2V5f2=9r z=6Hkm&75z`GH3CpMA|90ED)cb`m+bf+jR4d?}H%W*GG7oHb%TTJ$35T-(8DhR)nqI zvF>*8S6%K_Czr*6Ik)R9?d+AmuKG@E;wy>ncMC0_QwcfUa^*_yf|8iR=(w1`DW}`p+iM%Q`v6&c!fq!wedDv^ zWNV&TVN+KHbgzw}p`nqbW#!Y{1>WA?r`r;9@^W%4tgWp@?|(0S;A-A!lvI6;x#X;^) z4C~IxyaaL-l0AZa85pY67#JE_7#My5g&JNkFq9fFFuY1&V6d9Oz#v{QXIG#NP=YPV z+ueoXKL{?^yL>WGgtNdSvKVOfbr5EB(wJSrz`*p%)5S5wBVg7w+dz%g_IvSG@0e`8oc7 zuP;b_2yKuMU^r8+JoCk?BR76t?cDg;;miCm0j5I@d@CFh-d%~--~RelHDjO$&lj0} zwzm5>1pTs)`1GBjZ0n}git~1Ucz1nTrf%-D?RgSA|J=QIJlbBse4RVvmU;Ww?f<9k zxqM6HRacAL+mAnM=We{X`FLZ>UdE`&`FpCai+8q7UB=;M(6RZ0@Fgv;^*{c+IB(N^ z=ceN`vyEo*Imh*Dudzx@b(t4+>!#-66lKwMzb>8(o-zC9;qX(leAkO9FlemH1S7;dapohY6$OS10o(s$p~&)>MduRdzl*Sl^<-yg63^3!^ISlIFTv;X~& zR&ZbW@F{~=dhuuB&H4Q`k8~|Ke_vBln!K)i50CD(rtQBuwz>b`SYPyN>(ZQWb_%D3 zPA<*4_UFT?tFx8kR4)n?M=nbdQlFV}YMS}YS;JP0qO=1=Z(XYkhm6!}8@8yDMVy%XV0O3$SFb zn?KPiZo{{=Q+7Qt4q`rFnXtMhY^RozR?jh0({EGUFUEiPAy<8LJ-?jGubnSze#Rb* zir4c{*SyoiE#7c8it$u$KI0=_soMK&@|E%I^`=GaXT;0p=AGeO7aUWP=^&#bsLIZ4 zP}Fo~QRdn2S+6$craW7uypCzkwXF*cymA6}e6~CoexPbCSGL}6p`z|Xd%vyLmWvbl z^v$e>(Lno7@8wxV8roA?yRskVJG1_3G}p9qNNw>>|NCZt=YQire4L!K5`OjYTm)tX z)e_f;l9a@fRIB8oR3OD*WMF8dYiOWrY!G5-Ze?g;Wn!UiU}$Av5dUIjK8l9i{FKbJ zO57UswhCSbYLEok5S*V@Ql40p%1~Zju9umYU7Va)kgAtols@~NjTBH3gQu&X%Q~lo FCIH9o&Nl!6 literal 0 HcmV?d00001 diff --git a/data/icons/32x32/apps/system-software-install.png b/data/icons/32x32/apps/system-software-install.png new file mode 100644 index 0000000000000000000000000000000000000000..6e02c4dfd39f4e3f0b7113009802fafb6480bf92 GIT binary patch literal 1910 zcmV-+2Z{KJP)u&8_n&OjqMh7y>s#E zWcQ`>Z|uJChnM$&+RP$=m>D9H|K<5-o;`8=#J5d@XlRJBMnfRR8jB4v1T@y|s*#m5 zU!|!^di^0WG+e##TfFx;pW=Li^9kN32lgr6C)A;--g@WK(@#A0%umd$N<>6}wUZ}K zJW)+H#WbQC(HKw-XpC65w);Q`VIh>U2{;kVDVTy8)+wDDMxHO_58nUj9{@iWkt+`H zz)8ThA1J1J`_*&-fSF<#m@+@d4(!a=dxgI;ok*EgkOW_#9%Gg7!dO1ryVX)Fi zeUJVqTS$RetPt<`_}y1%nm`PZ7y~gH8Wo939wUiYT&^TpkG6}0xP-fgDT8HC;=%if zvl1UFw3t%VDPig;CL0_-^F^lHTMGbOIoYQ6d!R<8P);Y5)5)PeAON8(Xvzr|BLcks(s}Bl z;=;MV;he*)Jro1X@L6xJF3mg2(E*%!4B9oQ7$c^Urkqlj#f$_pk3ftOvGxOvN(hmr z>E?j$KRgE{g6=48Ga$yC0Wro|oDS81k1=!rA|itKjx5h{ z-s41CqhhqzhVu5C?@-q@RasNlCC66!Y_68L&v`;xFpXm}H=xG~^?McRg_=YSiJ@)B z?HI6M0~!M2S^#YyfEcyyp4#?*5eH&qX-X{i=sRIFND;}{I$KiQbA`>F_c?f3n;C;+ zcW~$08T{`j^g}qh6NU~zjFC{+oIL$0Vho(R|2~?!X)9U`LvRB9rEG5GYJZpU`up72 zzC1*v-Gnvy+V*qUdEDicpMaAaTtBCguhbt{W z5kwqHTMqzL6WDxs%*M_o3}axcoLc_UegvvFxIBH0Mkb8cE@H`X1}#+%(a^fxHx95J3O1UHRH5}Mb$4)jbsxaqUO}~Gh`{yc8c9B6pvwyY zh%wALJK39J0?s9@jQTk55jSTng3Nxh;Wn8RQ-T`zjvnE@!K2*2{^dD#CS zIJfajUVQl%hX7pJ`hcIl_&vytx;B#QzUyd*N3!l#aH!m6tarTN>I2 z$jVa2QtDaGQ}Wc4r3s+}c(W#AoVmP;Z8)0Rkfp$nfAd{7C)arTx$iUf|DtJ(P#L51 zeb$yzu8jA#fD$m@0kEB-e(>b_@c3xZ%bib=B*iBgKFRTEPLlOn&6i2@K54H{)@#?% zaD@IlXFC*>{f0W3^1>gVo;Q#;t07*qoM6N<$f+S3z-~a#s literal 0 HcmV?d00001 diff --git a/data/networkmanager/99_update_pamac_tray b/data/networkmanager/99_update_pamac_tray new file mode 100755 index 0000000..7042895 --- /dev/null +++ b/data/networkmanager/99_update_pamac_tray @@ -0,0 +1,10 @@ +#!/bin/sh + +INTERFACE=$1 # The interface which is brought up or down +STATUS=$2 # The new state of the interface + +case "$STATUS" in + 'up') # $INTERFACE is up + /usr/bin/pamac-refresh + ;; +esac diff --git a/data/polkit/org.manjaro.pamac.policy b/data/polkit/org.manjaro.pamac.policy new file mode 100644 index 0000000..65c0a53 --- /dev/null +++ b/data/polkit/org.manjaro.pamac.policy @@ -0,0 +1,25 @@ + + + + Manjaro + http://manjaro.org/ + package-x-generic + + Authentication is required + + no + no + auth_admin_keep + + + + Authentication is required + + no + no + auth_admin_keep + + + diff --git a/data/systemd/pamac.service b/data/systemd/pamac.service new file mode 100644 index 0000000..536e633 --- /dev/null +++ b/data/systemd/pamac.service @@ -0,0 +1,7 @@ +[Unit] +Description=Pamac + +[Service] +Type=dbus +BusName=org.manjaro.pamac +ExecStart=/usr/bin/pamac-daemon diff --git a/examples/pactree.vala b/examples/pactree.vala new file mode 100644 index 0000000..4dfb58e --- /dev/null +++ b/examples/pactree.vala @@ -0,0 +1,278 @@ +/* + * pactree.vala - a simple dependency tree viewer translated in Vala + * + * Copyright (C) 2014 Guillaume Benoit + * Copyright (c) 2010-2011 Pacman Development Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +// Compile with: valac --pkg=libalpm --vapidir=../vapi --Xcc=-I../util ../util/alpm-util.c pactree.vala -o pactree + +using Alpm; + +/* output */ +string provides; +string unresolvable; +string branch_tip1; +string branch_tip2; +int indent_size; + +/* color */ +string branch1_color; +string branch2_color; +string leaf1_color; +string leaf2_color; +string color_off; + +/* globals */ +Handle handle; +unowned DB localdb; +Alpm.List walked = null; +Alpm.List provisions = null; + +/* options */ +bool color; +bool graphviz; +bool linear; +int max_depth; +bool reverse; +bool unique; +string dbpath; + +const OptionEntry[] options = { + { "dbpath", 'b', 0, OptionArg.STRING, ref dbpath, "set an alternate database location", "path" }, + { "color", 'c', 0, OptionArg.NONE, ref color, "colorize output", null }, + { "depth", 'd', 0, OptionArg.INT, ref max_depth, "limit the depth of recursion", "number" }, + { "graph", 'g', 0, OptionArg.NONE, ref graphviz, "generate output for graphviz", null }, + { "linear", 'l', 0, OptionArg.NONE, ref linear, "enable linear output", null }, + { "reverse", 'r', 0, OptionArg.NONE, ref reverse, "show reverse dependencies", null }, + { "unique", 'u', 0, OptionArg.NONE, ref unique, "show dependencies with no duplicates (implies -l)", null }, + { null } +}; + +static void init_options() { + /* initialize options */ + color = false; + graphviz = false; + linear = false; + max_depth = -1; + reverse = false; + unique = false; + dbpath = "/var/lib/pacman"; + + /* output */ + provides = " provides"; + unresolvable = " [unresolvable]"; + branch_tip1 = "|--"; + branch_tip2 = "+--"; + indent_size = 3; + + /* color */ + branch1_color = "\033[0;33m"; /* yellow */ + branch2_color = "\033[0;37m"; /* white */ + leaf1_color = "\033[1;32m"; /* bold green */ + leaf2_color = "\033[0;32m"; /* green */ + color_off = "\033[0m"; +} + +static int parse_options(ref unowned string[] args) { + var opts = new OptionContext(""); + opts.set_help_enabled(true); + opts.add_main_entries(options, null); + + try { + bool b = opts.parse(ref args); + if (!b) { + stderr.puts(opts.get_help(false, null)); + return 1; + } + } + catch (OptionError e) + { + stderr.puts("Unable to parse options : " + e.message + "\n"); + return 1; + } + /* there must be (at least) one argument left */ + if (args.length == 1) return 1; + /* unique implies linear */ + if (unique) linear = true; + + /* no color */ + if (!color) { + branch1_color = branch2_color = ""; + leaf1_color = leaf2_color = ""; + color_off = ""; + } + + /* linear */ + if (linear) { + provides = ""; + branch_tip1 = branch_tip2 = ""; + indent_size = 0; + } + return 0; +} + +static void local_init() { + Alpm.Errno error; + handle = new Handle ("/", dbpath, out error); + assert (error == 0); + localdb = handle.localdb; + assert (localdb != null); +} + +static int main (string[] args) { + init_options(); + int ret = parse_options(ref args); + if (ret != 0) return ret; + + local_init(); + string? target_name = args[1]; + + unowned Package? pkg = find_satisfier(localdb.pkgcache, target_name); + if (pkg == null) { + stderr.printf("Error: package '%s' not found\n", target_name); + return 1; + } + + /* begin writing */ + print_start(pkg.name, target_name); + if(reverse) + walk_reverse_deps(pkg, 1); + else + walk_deps(pkg, 1); + + print_end(); + return 0; +} + +static void print_text(string? pkg, string? provision, int depth) +{ + int indent_sz = (depth + 1) * indent_size; + + if ((pkg == null) && (provision == null)) return; + + if (pkg == null) { + /* we failed to resolve provision */ + stdout.printf("%s%*s%s%s%s%s%s\n", branch1_color, indent_sz, branch_tip1, + leaf1_color, provision, branch1_color, unresolvable, color_off); + } else if ((provision != null) && (provision != pkg)) { + /* pkg provides provision */ + stdout.printf("%s%*s%s%s%s%s %s%s%s\n", branch2_color, indent_sz, branch_tip2, + leaf1_color, pkg, leaf2_color, provides, leaf1_color, provision, + color_off); + } else { + /* pkg is a normal package */ + stdout.printf("%s%*s%s%s%s\n", branch1_color, indent_sz, branch_tip1, leaf1_color, + pkg, color_off); + } +} + +/** + * walk dependencies in reverse, showing packages which require the target + */ +static void walk_reverse_deps(Package pkg, int depth) { + if((max_depth >= 0) && (depth > max_depth)) return; + + walked.add(pkg.name); + unowned Alpm.List required_by = pkg.compute_requiredby (); + + foreach(string? i in required_by) { + string pkgname = i; + if (walked.find_str(pkgname) != null) { + /* if we've already seen this package, don't print in "unique" output + * and don't recurse */ + if (!unique) print(pkg.name, pkgname, null, depth); + } else { + print(pkg.name, pkgname, null, depth); + walk_reverse_deps(localdb.get_pkg(pkgname), depth + 1); + } + } +} + +/** + * walk dependencies, showing dependencies of the target + */ +static void walk_deps(Package pkg, int depth) +{ + if((max_depth >= 0) && (depth > max_depth)) return; + + walked.add(pkg.name); + + foreach (unowned Depend depend in pkg.depends) { + string depname = depend.name; + unowned Package? provider = find_satisfier (localdb.pkgcache, depname); + + if (provider != null) { + string provname = provider.name; + + if (walked.find_str (provname) != null) { + /* if we've already seen this package, don't print in "unique" output + * and don't recurse */ + if (!unique) { + print (pkg.name, provname, depname, depth); + } + } else { + print (pkg.name, provname, depname, depth); + walk_deps(provider, depth + 1); + } + } else { + /* unresolvable package */ + print(pkg.name, null, depname, depth); + } + } +} + +static void print_graph(string parentname, string? pkgname, string? depname) +{ + if(depname != null) { + stdout.printf("\"%s\" -> \"%s\" [color=chocolate4];\n", parentname, depname); + if((pkgname != null) && (depname != pkgname) && (provisions.find_str(depname) != null)) { + stdout.printf("\"%s\" -> \"%s\" [arrowhead=none, color=grey];\n", depname, pkgname); + provisions.add(depname); + } + } else if(pkgname != null) { + stdout.printf("\"%s\" -> \"%s\" [color=chocolate4];\n", parentname, pkgname); + } +} + +/* parent depends on dep which is satisfied by pkg */ +static void print(string? parentname, string? pkgname, string? depname, int depth) +{ + if(graphviz) { + print_graph(parentname, pkgname, depname); + } else { + print_text(pkgname, depname, depth); + } +} + +static void print_start(string pkgname, string provname) +{ + if(graphviz) { + stdout.printf("digraph G { START [color=red, style=filled];\n" + + "node [style=filled, color=green];\n" + + " \"START\" -> \"%s\";\n", pkgname); + } else { + print_text(pkgname, provname, 0); + } +} + +static void print_end() +{ + if(graphviz) { + /* close graph output */ + stdout.printf("}\n"); + } +} diff --git a/files_to_translate b/files_to_translate new file mode 100644 index 0000000..95e7f1f --- /dev/null +++ b/files_to_translate @@ -0,0 +1,24 @@ +./resources/choose_provider_dialog.ui +./resources/packages_chooser_dialog.ui +./resources/progress_window.ui +./resources/history_dialog.ui +./resources/transaction_info_dialog.ui +./resources/transaction_sum_dialog.ui +./resources/manager_window.ui +./resources/updater_window.ui +./resources/preferences_dialog.ui + +./src/packages_chooser_dialog.vala +./src/transaction_info_dialog.vala +./src/history_dialog.vala +./src/transaction_sum_dialog.vala +./src/installer.vala +./src/tray.vala +./src/manager.vala +./src/preferences_dialog.vala +./src/updater.vala +./src/choose_provider_dialog.vala +./src/manager_window.vala +./src/progress_window.vala +./src/updater_window.vala +./src/common.vala diff --git a/pamac.pot b/pamac.pot new file mode 100644 index 0000000..134f1ae --- /dev/null +++ b/pamac.pot @@ -0,0 +1,279 @@ +# Translation of Pamac. +# Copyright (C) 2007-2012 Free Software Foundation, Inc. +# This file is distributed under the same license as the Pamac package. +# Guillaume Benoit , 2013-2014. +# +msgid "" +msgstr "" +"Project-Id-Version: pamac 2.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2014-13-10 15:09+0100\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: data/polkit/org.manjaro.pamac.policy:10 +msgid "Authentication is required" +msgstr "" + +#: resources/choose_provider_dialog.ui:7 +msgid "Choose a Provider" +msgstr "" + +#: resources/packages_chooser_dialog.ui:7 resources/manager_window.ui:789 +msgid "Install local packages" +msgstr "" + +#: resources/progress_window.ui:16 +msgid "Progress" +msgstr "" + +#: resources/progress_window.ui:63 resources/transaction_info_dialog.ui:84 +msgid "details" +msgstr "" + +#: resources/history_dialog.ui:7 +msgid "Pamac History" +msgstr "" + +#: resources/manager_window.ui:14 src/tray.vala:76 +msgid "Package Manager" +msgstr "" + +#: resources/manager_window.ui:23 +msgid "Refresh" +msgstr "" + +#: resources/manager_window.ui:47 +msgid "Apply changes" +msgstr "" + +#: resources/manager_window.ui:71 +msgid "Cancel" +msgstr "" + +#: resources/manager_window.ui:170 +msgid "Search in AUR" +msgstr "" + +#: resources/manager_window.ui:234 +msgid "Search" +msgstr "" + +#: resources/manager_window.ui:279 src/manager_window.vala:336 +msgid "Groups" +msgstr "" + +#: resources/manager_window.ui:325 resources/manager_window.ui:418 +msgid "State" +msgstr "" + +#: resources/manager_window.ui:371 +msgid "Repos" +msgstr "" + +#: resources/manager_window.ui:433 +msgid "Name" +msgstr "" + +#: resources/manager_window.ui:448 +msgid "Version" +msgstr "" + +#: resources/manager_window.ui:463 +msgid "Repo" +msgstr "" + +#: resources/manager_window.ui:478 +msgid "Size" +msgstr "" + +#: resources/manager_window.ui:582 +msgid "Infos" +msgstr "" + +#: resources/manager_window.ui:642 +msgid "Deps" +msgstr "" + +#: resources/manager_window.ui:707 +msgid "Details" +msgstr "" + +#: resources/manager_window.ui:740 +msgid "Files" +msgstr "" + +#: resources/manager_window.ui:779 +msgid "View History" +msgstr "" + +#: resources/updater_window.ui:14 src/tray.vala:73 src/tray.vala:166 +#: src/tray.vala:238 +msgid "Update Manager" +msgstr "" + +#: resources/preferences_dialog.ui:6 +msgid "Pamac Preferences" +msgstr "" + +#: resources/preferences_dialog.ui:74 +msgid "Enable AUR support" +msgstr "" + +#: resources/preferences_dialog.ui:87 +msgid "Allow Pamac to search and install packages from AUR" +msgstr "" + +#: resources/preferences_dialog.ui:105 +msgid "Remove unrequired dependencies" +msgstr "" + +#: resources/preferences_dialog.ui:118 +msgid "" +"When removing a package, also remove those dependencies that are not " +"required by other packages" +msgstr "" + +#: resources/preferences_dialog.ui:152 src/preferences_dialog.vala:37 +msgid "How often to check for updates, value in hours" +msgstr "" + +#: resources/preferences_dialog.ui:177 +msgid "Options" +msgstr "" + +#: src/packages_chooser_dialog.vala:32 +msgid "Packages" +msgstr "" + +#: src/tray.vala:24 src/updater_window.vala:167 +msgid "{number} available updates" +msgstr "" + +#: src/tray.vala:25 src/updater_window.vala:164 +msgid "1 available update" +msgstr "" + +#: src/tray.vala:27 src/updater_window.vala:56 src/updater_window.vala:161 +msgid "Your system is up-to-date" +msgstr "" + +#: src/tray.vala:79 +msgid "Quit" +msgstr "" + +#: src/tray.vala:167 +msgid "Show available updates" +msgstr "" + +#: src/manager_window.vala:179 src/manager_window.vala:777 +msgid "local" +msgstr "" + +#: src/manager_window.vala:183 src/manager_window.vala:250 +#: src/manager_window.vala:262 src/manager_window.vala:737 +msgid "Installed" +msgstr "" + +#: src/manager_window.vala:185 src/manager_window.vala:751 +msgid "Orphans" +msgstr "" + +#: src/manager_window.vala:186 src/manager_window.vala:720 +msgid "To install" +msgstr "" + +#: src/manager_window.vala:187 src/manager_window.vala:731 +msgid "To remove" +msgstr "" + +#: src/manager_window.vala:210 +msgid "Licenses" +msgstr "" + +#: src/manager_window.vala:232 +msgid "Depends On" +msgstr "" + +#: src/manager_window.vala:252 +msgid "Optional Deps" +msgstr "" + +#: src/manager_window.vala:272 +msgid "Required By" +msgstr "" + +#: src/manager_window.vala:286 +msgid "Provides" +msgstr "" + +#: src/manager_window.vala:299 +msgid "Replaces" +msgstr "" + +#: src/manager_window.vala:312 +msgid "Conflicts With" +msgstr "" + +#: src/manager_window.vala:328 +msgid "Repository" +msgstr "" + +#: src/manager_window.vala:346 +msgid "Packager" +msgstr "" + +#: src/manager_window.vala:352 +msgid "Install Date" +msgstr "" + +#: src/manager_window.vala:356 +msgid "Explicitly installed" +msgstr "" + +#: src/manager_window.vala:358 +msgid "Installed as a dependency for another package" +msgstr "" + +#: src/manager_window.vala:360 +msgid "Unknown" +msgstr "" + +#: src/manager_window.vala:362 +msgid "Install Reason" +msgstr "" + +#: src/manager_window.vala:367 +msgid "Signatures" +msgstr "" + +#: src/manager_window.vala:375 +msgid "Backup files" +msgstr "" + +#: src/manager_window.vala:497 +msgid "No package found" +msgstr "" + +#: src/manager_window.vala:739 +msgid "Uninstalled" +msgstr "" + +#: src/updater_window.vala:173 +msgid "Total download size:" +msgstr "" + +#: src/common.vala:62 +#, c-format +msgid "%.0f KiB" +msgstr "" + +#: src/common.vala:65 +#, c-format +msgid "%.2f MiB" +msgstr "" diff --git a/pot_head b/pot_head new file mode 100644 index 0000000..8580c26 --- /dev/null +++ b/pot_head @@ -0,0 +1,21 @@ +# Translation of Pamac. +# Copyright (C) 2007-2012 Free Software Foundation, Inc. +# This file is distributed under the same license as the Pamac package. +# Guillaume Benoit , 2013-2014. +# +msgid "" +msgstr "" +"Project-Id-Version: pamac 2.0\n" +"Report-Msgid-Bugs-To: \n" +"POT-Creation-Date: 2013-03-30 15:09+0100\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: FULL NAME \n" +"Language-Team: LANGUAGE \n" +"Language: \n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" + +#: data/polkit/org.manjaro.pamac.policy:10 +msgid "Authentication is required" +msgstr "" diff --git a/resources/choose_provider_dialog.ui b/resources/choose_provider_dialog.ui new file mode 100644 index 0000000..ed444bb --- /dev/null +++ b/resources/choose_provider_dialog.ui @@ -0,0 +1,86 @@ + + + + + diff --git a/resources/history_dialog.ui b/resources/history_dialog.ui new file mode 100644 index 0000000..dcf2eb9 --- /dev/null +++ b/resources/history_dialog.ui @@ -0,0 +1,75 @@ + + + + + diff --git a/resources/manager_window.ui b/resources/manager_window.ui new file mode 100644 index 0000000..e31655f --- /dev/null +++ b/resources/manager_window.ui @@ -0,0 +1,818 @@ + + + + + + True + False + gtk-file + 1 + + + True + False + 16 + emblem-package + + + True + False + + + View History + True + False + file_icon + False + + + + + + Install local packages + True + False + local_icon + False + + + + + + gtk-preferences + True + False + True + True + + + + + + gtk-about + True + False + True + True + + + + + diff --git a/resources/package-available.png b/resources/package-available.png new file mode 100644 index 0000000000000000000000000000000000000000..0fcb7b44a588270ed6ef9ee6bc459cab365092f9 GIT binary patch literal 298 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`EX7WqAsj$Z!;#Vf2?p zUk71ECym(^Ktah8*NBqf{Irtt#G+J&^73-M%)IR4hpG8!%J<}*1wnC-uCw4 zyY7xV7Zu9yyFTfh^V!cR%GIdoT(!~Wm9MQPE`VRa&W~^k_=ss(&XRyy0H;E3v@r;Piw3oa@pHDtm@S3j3^P6}m<$3-z zgm9>oT4#m`A&iw$ugJ1&Y>bgv!x$r3mW^ZY{aO@77-ME>0HqY(`?c5@gZF+WGl2IV zV+^simJq^J!^iLY0BqgcZ_li?#LhWHcDUziBF4c--Fuz&Upr@ZsA508j4k zwfoOMkC?w10dVJ5zty*Z$rIjxeNBFL++5m5l%E~bO(KkjXX`0T$s_8z{tK|yw#3C= zpZHhP$)_Jj0FAj4oi`KUow7B61RUyWQQ2?p zUk71ECym(^Ktah8*NBqf{Irtt#G+J&^73-M%)IR4Pi&L)CLh+30j;qadv#(1(iGHE2vEzm4A~8qT3w}LZ zn_XG9uHfdHdG3s5@p7@LQ;J*PH8wVWp4(r4u7Z8~?bmIGH$DH&dSnHE_Iekijrv<2 zoqBaDs;(+a@0`s&_PI`vpRG}HYTn~#vrv6~GN+o*W)9v@PMWRz_>y>;8I&7>xSXbc_|EhO zo{W@EuSvq<4TlALJr&q5Hl1Mcd1vnRQje$MupuvNJ$u=9Gi6r(gFht>dTjaj*>lMO zPZu_&E!*x^hMqQ-{J4JM{8y#CPT98)ea?Nk?qk@tg|S`AAB6w?J+dVH7mNC2?p zUk71ECym(^Ktah8*NBqf{Irtt#G+J&^73-M%)IR4N>*o|G!200xJ84eESu3h9wAl!mJ3JS<)A@#J+e4={Z#+80oV-~%)gGMxbNAx0 zjN0{n_50=+pS^qd?AGXcW}3YL1@i^Dt+MhxZ={7EE-bgP&_DV3YpwY#`@82gtgSMy zTh!QyG4A~)a`U2~@nhd@u89l=IS0=u2)54@XJ$}%q>$RYGL-QYTaf9DP^K(}zlT{w z|FdPOcQl8{M%{M!zqm2;FTYQH!!EY{4o_Kv*`Ibi%{x3@Jv~IkZjVLLkx8>eCO`jK mCuOPU)o^85==%FU`xxFkPZydlViykdB!j1`pUXO@geCxepMtyq literal 0 HcmV?d00001 diff --git a/resources/package-reinstall.png b/resources/package-reinstall.png new file mode 100644 index 0000000000000000000000000000000000000000..46930b802364841666cced3b57e481e454d2968c GIT binary patch literal 555 zcmV+`0@VG9P)F(Nd*xDn6Ft9!dH?MDr&ASMdXan1BK)=ypx{=CEj^{R=1(-; zNDN?@qP0dvk;NGMs9-q02H<6*R9CV(hxi%;fgE4o2 z!N>>Tpj*lA-rP_s7Xc_0D_OsYLCK1R!O&;wN$OG3+SC)aO9gZ&9JTjpHVQ1Fixd#q zC17cxRHy(R0OuD00L865VPNQYUr?($%oo41X;Xk$WI4g})-Kz{GGBg-vnCx1uU~bj z*BrbRacaTh+)iM`;Q14F>Mn=vJ;Fc;1L3f}$4=eF^Cwx~?UBf$jI6J5W+pTnEqdL3 z0Gf?FGkO`5b}&v5RG}?JG$5c2NL+jFH!9x( zZv9HVawu(s5>bgiqQOycAe6APUb}|`M`@uFbA0>e?VC5_9De@rF}2Pfj=RNkDoek* z6WJ#v#@Szgzf<#O!e{m0^}1U}-wyUwlBBgMeL>ngdX~UcAs|W8nv%Z8_B#1P<7ov_To2%8wGlCrS6LlDklyC(n`o!}a6up(Fy zOw^?4dz6>AF*+qw5GpV_rM$dN(f2S>bHpEvFmeE3TTS9?7bDqNi1B5Fci$SrL?Q@0XN-K@I3X^1Y%B#iX5>L&=-~U=EuC(kxhV&cj8_{q0M6@&%uGNl zy2Xg)-Roj5;2Ifa;QIlA3q~?3)lEWQ5&DWsbrT~QfeXGLj4}{|GGcQFZ(c6p`6U2K zo{K&oTxV(FElG8Ku#s>Q6CDp7*oP4Y^V+i`$}g$_+@Fn3`zhQ=g37FIw63$Y`RNCd zI*--gc)OpG*|ebwq`O~ElRc9 + + + + diff --git a/resources/pamac.installer.gresource.xml b/resources/pamac.installer.gresource.xml new file mode 100644 index 0000000..05c08ed --- /dev/null +++ b/resources/pamac.installer.gresource.xml @@ -0,0 +1,9 @@ + + + + progress_window.ui + choose_provider_dialog.ui + transaction_sum_dialog.ui + transaction_info_dialog.ui + + diff --git a/resources/pamac.manager.gresource.xml b/resources/pamac.manager.gresource.xml new file mode 100644 index 0000000..409ad49 --- /dev/null +++ b/resources/pamac.manager.gresource.xml @@ -0,0 +1,23 @@ + + + + manager_window.ui + history_dialog.ui + packages_chooser_dialog.ui + package-available.png + package-install.png + package-installed-locked.png + package-installed-updated.png + package-reinstall.png + package-remove.png + + + preferences_dialog.ui + + + progress_window.ui + choose_provider_dialog.ui + transaction_sum_dialog.ui + transaction_info_dialog.ui + + diff --git a/resources/pamac.updater.gresource.xml b/resources/pamac.updater.gresource.xml new file mode 100644 index 0000000..fdec047 --- /dev/null +++ b/resources/pamac.updater.gresource.xml @@ -0,0 +1,15 @@ + + + + updater_window.ui + + + preferences_dialog.ui + + + progress_window.ui + choose_provider_dialog.ui + transaction_sum_dialog.ui + transaction_info_dialog.ui + + diff --git a/resources/preferences_dialog.ui b/resources/preferences_dialog.ui new file mode 100644 index 0000000..a7d44da --- /dev/null +++ b/resources/preferences_dialog.ui @@ -0,0 +1,203 @@ + + + + + + 1 + 10000 + 1 + 10 + + diff --git a/resources/progress_window.ui b/resources/progress_window.ui new file mode 100644 index 0000000..25f56e1 --- /dev/null +++ b/resources/progress_window.ui @@ -0,0 +1,115 @@ + + + + + diff --git a/resources/transaction_info_dialog.ui b/resources/transaction_info_dialog.ui new file mode 100644 index 0000000..3bb6ac7 --- /dev/null +++ b/resources/transaction_info_dialog.ui @@ -0,0 +1,100 @@ + + + + + diff --git a/resources/transaction_sum_dialog.ui b/resources/transaction_sum_dialog.ui new file mode 100644 index 0000000..507b0e5 --- /dev/null +++ b/resources/transaction_sum_dialog.ui @@ -0,0 +1,142 @@ + + + + + diff --git a/resources/updater_window.ui b/resources/updater_window.ui new file mode 100644 index 0000000..480db0d --- /dev/null +++ b/resources/updater_window.ui @@ -0,0 +1,191 @@ + + + + + diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 0000000..f1f8c1b --- /dev/null +++ b/src/Makefile @@ -0,0 +1,146 @@ +COMMON_VALA_FLAGS = --pkg=libalpm \ + --pkg=gio-2.0 \ + --pkg=posix \ + --pkg=json-glib-1.0 \ + --pkg=libsoup-2.4 \ + --vapidir=../vapi \ + --Xcc=-I../util \ + -X -D_FILE_OFFSET_BITS=64 \ + --target-glib=2.38 + +COMMON_SOURCES = ../util/alpm-util.c \ + alpm_config.vala \ + pamac_config.vala \ + aur.vala \ + common.vala + +MANAGER_GRESOURCE_FILE = ../resources/pamac.manager.gresource.xml + +MANAGER_RESOURCES_FILES = ../resources/manager_window.ui \ + ../resources/packages_chooser_dialog.ui \ + ../resources/history_dialog.ui \ + ../resources/preferences_dialog.ui \ + ../resources/progress_window.ui \ + ../resources/choose_provider_dialog.ui \ + ../resources/transaction_sum_dialog.ui \ + ../resources/transaction_info_dialog.ui \ + ../resources/package-available.png \ + ../resources/package-install.png \ + ../resources/package-installed-locked.png \ + ../resources/package-installed-updated.png \ + ../resources/package-reinstall.png \ + ../resources/package-remove.png + +UPDATER_GRESOURCE_FILE = ../resources/pamac.updater.gresource.xml + +UPDATER_RESOURCES_FILES = ../resources/updater_window.ui \ + ../resources/preferences_dialog.ui \ + ../resources/progress_window.ui \ + ../resources/choose_provider_dialog.ui \ + ../resources/transaction_sum_dialog.ui \ + ../resources/transaction_info_dialog.ui + +INSTALLER_GRESOURCE_FILE = ../resources/pamac.installer.gresource.xml + +INSTALLER_RESOURCES_FILES = ../resources/progress_window.ui \ + ../resources/choose_provider_dialog.ui \ + ../resources/transaction_sum_dialog.ui \ + ../resources/transaction_info_dialog.ui + +DIALOGS_FILES = choose_provider_dialog.vala \ + transaction_sum_dialog.vala \ + transaction_info_dialog.vala \ + progress_window.vala + +pamac-daemon: $(COMMON_SOURCES) daemon.vala + valac -o pamac-daemon \ + $(COMMON_VALA_FLAGS) \ + --pkg=polkit-gobject-1 \ + -X -DGETTEXT_PACKAGE="pacman" \ + --thread \ + $(COMMON_SOURCES) \ + daemon.vala + +pamac-tray: $(COMMON_SOURCES) tray.vala + valac -o pamac-tray \ + $(COMMON_VALA_FLAGS) \ + --pkg=gtk+-3.0 \ + --pkg=libnotify \ + -X -DGETTEXT_PACKAGE="pamac" \ + $(COMMON_SOURCES) \ + tray.vala + +manager_resources.c: $(MANAGER_GRESOURCE_FILE) $(MANAGER_RESOURCES_FILES) + glib-compile-resources $(MANAGER_GRESOURCE_FILE) --sourcedir=../resources --target=manager_resources.c --generate-source + +updater_resources.c: $(UPDATER_GRESOURCE_FILE) $(UPDATER_RESOURCES_FILES) + glib-compile-resources $(UPDATER_GRESOURCE_FILE) --sourcedir=../resources --target=updater_resources.c --generate-source + +installer_resources.c: $(INSTALLER_GRESOURCE_FILE) $(INSTALLER_RESOURCES_FILES) + glib-compile-resources $(INSTALLER_GRESOURCE_FILE) --sourcedir=../resources --target=installer_resources.c --generate-source + +pamac-manager: $(COMMON_SOURCES) $(DIALOGS_FILES) preferences_dialog.vala history_dialog.vala packages_chooser_dialog.vala manager_resources.c package.vala transaction.vala packages_model.vala manager_window.vala manager.vala + valac -o pamac-manager \ + $(COMMON_VALA_FLAGS) \ + --pkg=gtk+-3.0 \ + --pkg=gmodule-2.0 \ + --pkg=gdk-3.0 \ + --pkg=vte-2.91 \ + --gresources=$(MANAGER_GRESOURCE_FILE) \ + -X -DGETTEXT_PACKAGE="pamac" \ + $(COMMON_SOURCES) \ + $(DIALOGS_FILES) \ + preferences_dialog.vala \ + history_dialog.vala \ + packages_chooser_dialog.vala \ + manager_resources.c \ + package.vala \ + transaction.vala \ + packages_model.vala \ + manager_window.vala \ + manager.vala + +pamac-updater: $(COMMON_SOURCES) $(DIALOGS_FILES) preferences_dialog.vala updater_resources.c transaction.vala updater_window.vala updater.vala + valac -o pamac-updater \ + $(COMMON_VALA_FLAGS) \ + --pkg=gtk+-3.0 \ + --pkg=gmodule-2.0 \ + --pkg=vte-2.91 \ + --gresources=$(UPDATER_GRESOURCE_FILE) \ + -X -DGETTEXT_PACKAGE="pamac" \ + $(COMMON_SOURCES) \ + $(DIALOGS_FILES) \ + preferences_dialog.vala \ + updater_resources.c \ + transaction.vala \ + updater_window.vala \ + updater.vala + +pamac-install: $(COMMON_SOURCES) $(DIALOGS_FILES) installer_resources.c transaction.vala installer.vala + valac -o pamac-install \ + $(COMMON_VALA_FLAGS) \ + --pkg=gtk+-3.0 \ + --pkg=gmodule-2.0 \ + --pkg=vte-2.91 \ + --gresources=$(INSTALLER_GRESOURCE_FILE) \ + -X -DGETTEXT_PACKAGE="pamac" \ + $(COMMON_SOURCES) \ + $(DIALOGS_FILES) \ + installer_resources.c \ + transaction.vala \ + installer.vala + +all: pamac-daemon pamac-tray pamac-updater pamac-manager pamac-install + +clean: + rm -f *.c pamac-daemon pamac-tray pamac-updater pamac-manager pamac-install + +install: + install -Dm744 pamac-daemon /usr/bin/pamac-daemon + install -Dm755 pamac-tray /usr/bin/pamac-tray + install -Dm755 pamac-manager /usr/bin/pamac-manager + install -Dm755 pamac-updater /usr/bin/pamac-updater + install -Dm755 pamac-install /usr/bin/pamac-install + +uninstall: + rm -f /usr/bin/pamac-daemon /usr/bin/pamac-updater /usr/bin/pamac-tray /usr/bin/pamac-manager /usr/bin/pamac-install diff --git a/src/alpm_config.vala b/src/alpm_config.vala new file mode 100644 index 0000000..05d0f7f --- /dev/null +++ b/src/alpm_config.vala @@ -0,0 +1,258 @@ +/* + * pamac-vala + * + * Copyright (C) 2014 Guillaume Benoit + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a get of the GNU General Public License + * along with this program. If not, see . + */ + +namespace Alpm { + class Repo { + public string name; + public SigLevel siglevel; + public string[] urls; + + public Repo (string name) { + this.name = name; + urls = {}; + } + } + + public class Config { + public Handle handle; + private string[] priv_holdpkg; + private string[] priv_syncfirst; + public string[] holdpkg; + public string[] syncfirst; + SigLevel siglevel; + SigLevel localfilesiglevel; + SigLevel remotefilesiglevel; + Repo[] repo_order; + + public Config (string path) { + // rootdir and dbpath are hardcoded so we parse config file only once + const string rootdir = "/"; + const string dbpath = "/var/lib/pacman"; + Alpm.Errno error; + handle = new Handle (rootdir, dbpath, out error); + const string gpgdir = "/etc/pacman.d/gnupg/"; + const string logfile = "/var/log/pacman.log"; + const string cachedir = "/var/cache/pacman/pkg/"; + priv_holdpkg = {}; + priv_syncfirst = {}; + siglevel = SigLevel.PACKAGE | SigLevel.PACKAGE_OPTIONAL | SigLevel.DATABASE | SigLevel.DATABASE_OPTIONAL; + localfilesiglevel = SigLevel.USE_DEFAULT; + remotefilesiglevel = SigLevel.USE_DEFAULT; + repo_order = {}; + // parse conf file + parse_file (path); + // check essential settings + if (handle.gpgdir == null) handle.gpgdir = gpgdir; + if (handle.logfile == null) handle.logfile = logfile; + if (handle.arch == null) handle.arch = Posix.utsname().machine; + if (handle.cachedirs == null) handle.add_cachedir(cachedir); + // register dbs + foreach (Repo repo in repo_order) { + unowned DB db = handle.register_syncdb (repo.name, repo.siglevel); + foreach (string url in repo.urls) { + db.add_server (url.replace ("$repo", repo.name).replace ("$arch", handle.arch)); + } + } + } + + public void parse_file (string path, string? section = null) { + string current_section = section; + var file = GLib.File.new_for_path (path); + if (file.query_exists () == false) + GLib.stderr.printf ("File '%s' doesn't exist.\n", file.get_path ()); + else { + try { + // Open file for reading and wrap returned FileInputStream into a + // DataInputStream, so we can read line by line + var dis = new DataInputStream (file.read ()); + string line; + // Read lines until end of file (null) is reached + while ((line = dis.read_line (null)) != null) { + line = line.strip (); + if (line.length == 0) continue; + if (line[0] == '#') continue; + if (line[0] == '[' && line[line.length-1] == ']') { + current_section = line[1:-1]; + if (current_section != "options") { + Repo repo = new Repo (current_section); + repo.siglevel = siglevel; + repo_order += repo; + } + continue; + } + string[] splitted = line.split ("="); + string _key = splitted[0].strip (); + string _value = null; + if (splitted[1] != null) + _value = splitted[1].strip (); + if (_key == "Include") + parse_file (_value, current_section); + if (current_section == "options") { + if (_key == "GPGDir") + handle.gpgdir = _value; + else if (_key == "LogFile") + handle.logfile = _value; + else if (_key == "Architecture") { + if (_value == "auto") + handle.arch = Posix.utsname ().machine; + else + handle.arch = _value; + } else if (_key == "UseDelta") + handle.deltaratio = double.parse (_value); + else if (_key == "UseSysLog") + handle.usesyslog = 1; + else if (_key == "CheckSpace") + handle.checkspace = 1; + else if (_key == "SigLevel") + siglevel = define_siglevel (siglevel, _value); + else if (_key == "LocalSigLevel") + handle.localfilesiglevel = merge_siglevel (siglevel, define_siglevel (localfilesiglevel, _value)); + else if (_key == "RemoteSigLevel") + handle.remotefilesiglevel = merge_siglevel (siglevel, define_siglevel (remotefilesiglevel, _value)); + else if (_key == "HoldPkg") { + foreach (string name in _value.split (" ")) { + priv_holdpkg += name; + } + } else if (_key == "SyncFirst") { + foreach (string name in _value.split (" ")) { + priv_syncfirst += name; + } + } else if (_key == "CacheDir") { + foreach (string dir in _value.split (" ")) { + handle.add_cachedir (dir); + } + } else if (_key == "IgnoreGroup") { + foreach (string name in _value.split (" ")) { + handle.add_ignoregroup (name); + } + } else if (_key == "IgnorePkg") { + foreach (string name in _value.split (" ")) { + handle.add_ignorepkg (name); + } + } else if (_key == "Noextract") { + foreach (string name in _value.split (" ")) { + handle.add_noextract (name); + } + } else if (_key == "NoUpgrade") { + foreach (string name in _value.split (" ")) { + handle.add_noupgrade (name); + } + } + } else { + foreach (Repo _repo in repo_order) { + if (_repo.name == current_section) { + if (_key == "Server") + _repo.urls += _value; + else if (_key == "SigLevel") + _repo.siglevel = define_siglevel(siglevel, _value); + } + } + } + } + } catch (GLib.Error e) { + GLib.stderr.printf("%s\n", e.message); + } + holdpkg = priv_holdpkg; + syncfirst = priv_syncfirst; + } + } + + public SigLevel define_siglevel (SigLevel default_level, string conf_string) { + foreach (string directive in conf_string.split(" ")) { + bool affect_package = false; + bool affect_database = false; + if ("Package" in directive) affect_package = true; + else if ("Database" in directive) affect_database = true; + else { + affect_package = true; + affect_database = true; + } + if ("Never" in directive) { + if (affect_package) { + default_level &= ~SigLevel.PACKAGE; + default_level |= SigLevel.PACKAGE_SET; + } + if (affect_database) default_level &= ~SigLevel.DATABASE; + } + else if ("Optional" in directive) { + if (affect_package) { + default_level |= SigLevel.PACKAGE; + default_level |= SigLevel.PACKAGE_OPTIONAL; + default_level |= SigLevel.PACKAGE_SET; + } + if (affect_database) { + default_level |= SigLevel.DATABASE; + default_level |= SigLevel.DATABASE_OPTIONAL; + } + } + else if ("Required" in directive) { + if (affect_package) { + default_level |= SigLevel.PACKAGE; + default_level &= ~SigLevel.PACKAGE_OPTIONAL; + default_level |= SigLevel.PACKAGE_SET; + } + if (affect_database) { + default_level |= SigLevel.DATABASE; + default_level &= ~SigLevel.DATABASE_OPTIONAL; + } + } + else if ("TrustedOnly" in directive) { + if (affect_package) { + default_level &= ~SigLevel.PACKAGE_MARGINAL_OK; + default_level &= ~SigLevel.PACKAGE_UNKNOWN_OK; + default_level |= SigLevel.PACKAGE_TRUST_SET; + } + if (affect_database) { + default_level &= ~SigLevel.DATABASE_MARGINAL_OK; + default_level &= ~SigLevel.DATABASE_UNKNOWN_OK; + } + } + else if ("TrustAll" in directive) { + if (affect_package) { + default_level |= SigLevel.PACKAGE_MARGINAL_OK; + default_level |= SigLevel.PACKAGE_UNKNOWN_OK; + default_level |= SigLevel.PACKAGE_TRUST_SET; + } + if (affect_database) { + default_level |= SigLevel.DATABASE_MARGINAL_OK; + default_level |= SigLevel.DATABASE_UNKNOWN_OK; + } + } + else GLib.stderr.printf("unrecognized siglevel: %s\n", conf_string); + } + default_level &= ~SigLevel.USE_DEFAULT; + return default_level; + } + + public SigLevel merge_siglevel (SigLevel base_level, SigLevel over_level) { + if ((over_level & SigLevel.USE_DEFAULT) != 0) over_level = base_level; + else { + if ((over_level & SigLevel.PACKAGE_SET) == 0) { + over_level |= base_level & SigLevel.PACKAGE; + over_level |= base_level & SigLevel.PACKAGE_OPTIONAL; + } + if ((over_level & SigLevel.PACKAGE_TRUST_SET) == 0) { + over_level |= base_level & SigLevel.PACKAGE_MARGINAL_OK; + over_level |= base_level & SigLevel.PACKAGE_UNKNOWN_OK; + } + } + return over_level; + } + } +} diff --git a/src/aur.vala b/src/aur.vala new file mode 100644 index 0000000..5fa661c --- /dev/null +++ b/src/aur.vala @@ -0,0 +1,102 @@ +/* + * pamac-vala + * + * Copyright (C) 2014 Guillaume Benoit + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a get of the GNU General Public License + * along with this program. If not, see . + */ + +//~ const string srcpkgdir = "/tmp/pamac"; + +namespace AUR { + // AUR urls + const string aur_url = "http://aur.archlinux.org"; + const string rpc_url = aur_url + "/rpc.php"; + const string rpc_search = "?type=search&arg="; + const string rpc_info = "?type=info&arg="; + const string rpc_multiinfo = "?type=multiinfo"; + const string rpc_multiinfo_arg = "&arg[]="; + const string aur_url_id = "/packages.php?setlang=en&ID="; + + public Json.Array search (string needle) { + string uri = rpc_url + rpc_search + needle; + var session = new Soup.Session (); + var message = new Soup.Message ("GET", uri); + session.send_message (message); + Json.Array results = new Json.Array (); + + try { + var parser = new Json.Parser (); + parser.load_from_data ((string) message.response_body.flatten ().data, -1); + + unowned Json.Object root_object = parser.get_root ().get_object (); + results = root_object.get_array_member ("results"); +//~ foreach (unowned Json.Node node in results.get_elements ()) { +//~ Json.Object pkg_info = node.get_object (); +//~ results.append (new Pamac.Package (null, pkg_info)); +//~ } + } catch (Error e) { + print (e.message); + } + return results; + } + + public Json.Object? info (string pkgname) { + unowned Json.Object? pkg_info = null; + string uri = rpc_url + rpc_info + pkgname; + stdout.printf("get %s from AUR\n", pkgname); + var session = new Soup.Session (); + var message = new Soup.Message ("GET", uri); + session.send_message (message); + + try { + var parser = new Json.Parser (); + parser.load_from_data ((string) message.response_body.flatten ().data, -1); + pkg_info = parser.get_root ().get_object ().get_object_member ("results"); + } catch (Error e) { + stderr.printf ("Failed to get infos about %s from AUR\n", pkgname); + print (e.message); + } + return pkg_info; + } + + public Json.Array multiinfo (string[] pkgnames) { + Json.Array results = new Json.Array (); + var builder = new StringBuilder (); + builder.append (rpc_url); + builder.append (rpc_multiinfo); + foreach (string pkgname in pkgnames) { + builder.append (rpc_multiinfo_arg); + builder.append (pkgname); + } + var session = new Soup.Session (); + var message = new Soup.Message ("GET", builder.str); + session.send_message (message); + + try { + var parser = new Json.Parser (); + parser.load_from_data ((string) message.response_body.flatten ().data, -1); + + unowned Json.Object root_object = parser.get_root ().get_object (); + results = root_object.get_array_member ("results"); +//~ foreach (var node in results.get_elements ()) { +//~ var pkg_info = node.get_object (); +//~ results.append (new Pamac.Package (null, pkg_info)); +//~ } + } catch (Error e) { + print (e.message); + } + return results; + } +} diff --git a/src/aur3.vala b/src/aur3.vala new file mode 100644 index 0000000..df90424 --- /dev/null +++ b/src/aur3.vala @@ -0,0 +1,72 @@ +/* + * pamac-vala + * + * Copyright (C) 2014 Guillaume Benoit + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a get of the GNU General Public License + * along with this program. If not, see . + */ + +//~ const string srcpkgdir = "/tmp/pamac"; + +namespace AUR { + // AUR urls + const string aur_url = "http://aur3.org/"; + + + public string[] search (string needle) { + string[] results = {}; + try { + // Resolve hostname to IP address + var resolver = Resolver.get_default (); + var addresses = resolver.lookup_by_name (host, null); + var address = addresses.nth_data (0); + // Connect + var client = new SocketClient (); + var conn = client.connect (new InetSocketAddress (address, 1819)); + // Send HTTP GET request + var message = @"nd $query"; + conn.output_stream.write (message.data); + // Receive response + var response = new DataInputStream (conn.input_stream); + string line; + while ((line = response.read_line (null)) != null) { + results += line; + } + } catch (Error e) { + stderr.printf ("%s\n", e.message); + } + return results; + } + + public void info (string pkgname) { + string uri = rpc_url + rpc_info + pkgname; + var session = new Soup.Session (); + var message = new Soup.Message ("GET", uri); + session.send_message (message); + + try { + var parser = new Json.Parser (); + parser.load_from_data ((string) message.response_body.flatten ().data, -1); + + var root_object = parser.get_root ().get_object (); + var pkg_info = root_object.get_object_member ("results"); + AUR.Pkg aur_pkg = new AUR.Pkg (pkg_info); + stdout.printf ("got %s (%s)\n", aur_pkg.name, aur_pkg.license); + } catch (Error e) { + stderr.printf ("Failed to get infos about %s from AUR\n", pkgname); + print (e.message); + } + } + +} diff --git a/src/choose_provider_dialog.vala b/src/choose_provider_dialog.vala new file mode 100644 index 0000000..6b43e32 --- /dev/null +++ b/src/choose_provider_dialog.vala @@ -0,0 +1,34 @@ +/* + * pamac-vala + * + * Copyright (C) 2014 Guillaume Benoit + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a get of the GNU General Public License + * along with this program. If not, see . + */ + +namespace Pamac { + + [GtkTemplate (ui = "/org/manjaro/pamac/transaction/choose_provider_dialog.ui")] + public class ChooseProviderDialog : Gtk.Dialog { + + [GtkChild] + public Gtk.Label label; + [GtkChild] + public Gtk.ComboBoxText comboboxtext; + + public ChooseProviderDialog (Gtk.ApplicationWindow? window) { + Object (transient_for: window, use_header_bar: 0); + } + } +} diff --git a/src/common.vala b/src/common.vala new file mode 100644 index 0000000..5200bde --- /dev/null +++ b/src/common.vala @@ -0,0 +1,265 @@ +/* + * pamac-vala + * + * Copyright (C) 2014 Guillaume Benoit + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a get of the GNU General Public License + * along with this program. If not, see . + */ + +namespace Pamac { + public struct UpdatesInfos { + public string name; + public string version; + public string db_name; + public string tarpath; + public uint64 download_size; + } + + public struct Updates { + public bool syncfirst; + public UpdatesInfos[] infos; + } + + public enum Mode { + MANAGER, + UPDATER, + NO_CONFIRM + } + + public struct TransactionData { + public Alpm.TransFlag flags; + // those hashtables will be used as set + public HashTable to_add; + public HashTable to_remove; + public HashTable to_load; + public HashTable to_build; + } + + public struct ErrorInfos { + public string str; + public string[] details; + public ErrorInfos () { + str = ""; + details = {}; + } + } +} + +public string format_size (uint64 size) { + float KiB_size = size / 1024; + if (KiB_size < 1000) { + string size_string = dgettext ("pamac", "%.0f KiB").printf (KiB_size); + return size_string; + } else { + string size_string = dgettext ("pamac", "%.2f MiB").printf (KiB_size / 1024); + return size_string; + } +} + +public int pkgcmp (Alpm.Package pkg1, Alpm.Package pkg2) { + return strcmp (pkg1.name, pkg2.name); +} + +public unowned Alpm.List search_all_dbs (Alpm.Handle handle, Alpm.List needles) { + unowned Alpm.List syncpkgs = null; + unowned Alpm.List tmp = null; + unowned Alpm.List diff = null; + unowned Alpm.List result = null; + + result = handle.localdb.search (needles); + + foreach (unowned Alpm.DB db in handle.syncdbs) { + if (syncpkgs.length == 0) + syncpkgs = db.search (needles); + else { + tmp = db.search (needles); + diff = tmp.diff (syncpkgs, (Alpm.List.CompareFunc) pkgcmp); + syncpkgs.join (diff); + } + } + + diff = syncpkgs.diff (result, (Alpm.List.CompareFunc) pkgcmp); + + result.join (diff); + //result.sort ((Alpm.List.CompareFunc) pkgcmp); + + return result; +} + +public unowned Alpm.List group_pkgs_all_dbs (Alpm.Handle handle, string grp_name) { + unowned Alpm.List result = null; + + unowned Alpm.Group? grp = handle.localdb.get_group (grp_name); + if (grp != null) { + foreach (unowned Alpm.Package pkg in grp.packages) + result.add (pkg); + } + + // FIX IT: provided methods don't work for syncdbs so it's done manually + foreach (unowned Alpm.DB db in handle.syncdbs) { + foreach (unowned Alpm.Package pkg in db.pkgcache) { + foreach (string name in pkg.groups) { + if (name == grp_name) { + if (Alpm.pkg_find (result, pkg.name) == null) + result.add (pkg); + } + } + } + } + + //result.sort ((Alpm.List.CompareFunc) pkgcmp); + + return result; +} + +public unowned Alpm.List get_all_pkgs (Alpm.Handle handle) { + unowned Alpm.List syncpkgs = null; + unowned Alpm.List tmp = null; + unowned Alpm.List diff = null; + unowned Alpm.List result = null; + + result = handle.localdb.pkgcache; + + foreach (unowned Alpm.DB db in handle.syncdbs) { + if (syncpkgs.length == 0) + syncpkgs = db.pkgcache; + else { + tmp = db.pkgcache; + diff = tmp.diff (syncpkgs, (Alpm.List.CompareFunc) pkgcmp); + syncpkgs.join (diff); + } + } + + diff = syncpkgs.diff (result, (Alpm.List.CompareFunc) pkgcmp); + + result.join (diff); + //result.sort ((Alpm.List.CompareFunc) pkgcmp); + + return result; +} + +public unowned Alpm.Package? get_syncpkg (Alpm.Handle handle, string name) { + unowned Alpm.Package? pkg = null; + foreach (unowned Alpm.DB db in handle.syncdbs) { + pkg = db.get_pkg (name); + if (pkg != null) + break; + } + return pkg; +} + +public Pamac.UpdatesInfos[] get_syncfirst_updates (Alpm.Config alpm_config) { + Pamac.UpdatesInfos infos = Pamac.UpdatesInfos (); + Pamac.UpdatesInfos[] syncfirst_infos = {}; + unowned Alpm.Package? pkg = null; + unowned Alpm.Package? candidate = null; + foreach (string name in alpm_config.syncfirst) { + pkg = Alpm.find_satisfier (alpm_config.handle.localdb.pkgcache, name); + if (pkg != null) { + candidate = Alpm.sync_newversion (pkg, alpm_config.handle.syncdbs); + if (candidate != null) { + infos.name = candidate.name; + infos.version = candidate.version; + infos.db_name = candidate.db.name; + infos.tarpath = ""; + infos.download_size = candidate.download_size; + syncfirst_infos += infos; + } + } + } + return syncfirst_infos; +} + +public string[] get_ignore_pkgs (Alpm.Config alpm_config) { + string[] ignore_pkgs = {}; + unowned Alpm.Group? group = null; + foreach (string name in alpm_config.handle.ignorepkgs) + ignore_pkgs += name; + foreach (string grp_name in alpm_config.handle.ignoregroups) { + group = alpm_config.handle.localdb.get_group (grp_name); + if (group != null) { + foreach (unowned Alpm.Package found_pkg in group.packages) + ignore_pkgs += found_pkg.name; + } + } + return ignore_pkgs; +} + +public Pamac.UpdatesInfos[] get_repos_updates (Alpm.Config alpm_config, string[] ignore_pkgs) { + unowned Alpm.Package? candidate = null; + Pamac.UpdatesInfos infos = Pamac.UpdatesInfos (); + Pamac.UpdatesInfos[] updates = {}; + foreach (unowned Alpm.Package local_pkg in alpm_config.handle.localdb.pkgcache) { + // continue only if the local pkg is not in IgnorePkg or IgnoreGroup + if ((local_pkg.name in ignore_pkgs) == false) { + candidate = Alpm.sync_newversion (local_pkg, alpm_config.handle.syncdbs); + if (candidate != null) { + infos.name = candidate.name; + infos.version = candidate.version; + infos.db_name = candidate.db.name; + infos.tarpath = ""; + infos.download_size = candidate.download_size; + updates += infos; + } + } + } + return updates; +} + +public Pamac.UpdatesInfos[] get_aur_updates (Alpm.Config alpm_config, string[] ignore_pkgs) { + unowned Alpm.Package? sync_pkg = null; + unowned Alpm.Package? candidate = null; + string[] local_pkgs = {}; + Pamac.UpdatesInfos infos = Pamac.UpdatesInfos (); + Pamac.UpdatesInfos[] aur_updates = {}; + // get local pkgs + foreach (unowned Alpm.Package local_pkg in alpm_config.handle.localdb.pkgcache) { + // continue only if the local pkg is not in IgnorePkg or IgnoreGroup + if ((local_pkg.name in ignore_pkgs) == false) { + // check updates from AUR only for local packages + foreach (unowned Alpm.DB db in alpm_config.handle.syncdbs) { + sync_pkg = Alpm.find_satisfier (db.pkgcache, local_pkg.name); + if (sync_pkg != null) + break; + } + if (sync_pkg == null) { + // check update from AUR only if no package from dbs will replace it + candidate = Alpm.sync_newversion (local_pkg, alpm_config.handle.syncdbs); + if (candidate == null) { + local_pkgs += local_pkg.name; + } + } + } + } + // get aur updates + Json.Array aur_pkgs = AUR.multiinfo (local_pkgs); + int cmp; + string version; + string name; + foreach (Json.Node node in aur_pkgs.get_elements ()) { + unowned Json.Object pkg_info = node.get_object (); + version = pkg_info.get_string_member ("Version"); + name = pkg_info.get_string_member ("Name"); + cmp = Alpm.pkg_vercmp (version, alpm_config.handle.localdb.get_pkg (name).version); + if (cmp == 1) { + infos.name = name; + infos.version = version; + infos.db_name = "AUR"; + infos.tarpath = pkg_info.get_string_member ("URLPath"); + infos.download_size = 0; + aur_updates += infos; + } + } + return aur_updates; +} diff --git a/src/daemon.vala b/src/daemon.vala new file mode 100644 index 0000000..ae83ab0 --- /dev/null +++ b/src/daemon.vala @@ -0,0 +1,697 @@ +/* + * pamac-vala + * + * Copyright (C) 2014 Guillaume Benoit + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a get of the GNU General Public License + * along with this program. If not, see . + */ + +using Alpm; +using Pamac; +using Polkit; + +// i18n +const string GETTEXT_PACKAGE = "pacman"; + +PamacServer server; +MainLoop loop; + +[DBus (name = "org.manjaro.pamac")] +public class PamacServer : Object { + Alpm.Config alpm_config; + Pamac.Config pamac_config; + unowned Alpm.DB localdb; + unowned Alpm.List syncdbs; + public uint64 previous_percent; + unowned Alpm.List local_packages; + int force_refresh; + bool emit_refreshed_signal; + public Cond provider_cond; + public Mutex provider_mutex; + public int? choosen_provider; + + public signal void emit_event (uint event, string msg); + public signal void emit_providers (string depend, string[] providers); + public signal void emit_progress (uint progress, string action, string pkgname, int percent, uint n_targets, uint current_target); + public signal void emit_download (string filename, uint64 xfered, uint64 total); + public signal void emit_totaldownload (uint64 total); + public signal void emit_log (uint level, string msg); + public signal void emit_updates (Updates updates); + public signal void emit_refreshed (ErrorInfos error); + public signal void emit_trans_prepared (ErrorInfos error); + public signal void emit_trans_committed (ErrorInfos error); + + public PamacServer () { + previous_percent = 0; + local_packages = null; + get_handle (); + force_refresh = 0; + emit_refreshed_signal = true; + } + + private void get_handle () { + alpm_config = new Alpm.Config ("/etc/pacman.conf"); + pamac_config = new Pamac.Config ("/etc/pamac.conf"); + alpm_config.handle.eventcb = (EventCallBack) cb_event; + alpm_config.handle.progresscb = (ProgressCallBack) cb_progress; + alpm_config.handle.questioncb = (QuestionCallBack) cb_question; + alpm_config.handle.dlcb = (DownloadCallBack) cb_download; + alpm_config.handle.totaldlcb = (TotalDownloadCallBack) cb_totaldownload; + alpm_config.handle.logcb = (LogCallBack) cb_log; + localdb = alpm_config.handle.localdb; + syncdbs = alpm_config.handle.syncdbs; + } + + public void write_config (HashTable new_conf, GLib.BusName sender) { + try { + Polkit.Authority authority = Polkit.Authority.get_sync (null); + Polkit.Subject subject = Polkit.SystemBusName.new (sender); + Polkit.AuthorizationResult result = authority.check_authorization_sync + (subject, + "org.manjaro.pamac.commit", + null, + Polkit.CheckAuthorizationFlags.ALLOW_USER_INTERACTION, + null); + if (result.get_is_authorized ()) { + pamac_config.write (new_conf); + } + } catch (GLib.Error e) { + stderr.printf ("%s\n", e.message); + } + } + + private void refresh_real () { + ErrorInfos err = ErrorInfos (); + string[] details = {}; + uint success = 0; + int ret = alpm_config.handle.trans_init (0); + if (ret == 0) { + foreach (unowned DB db in syncdbs) { + ret = db.update (force_refresh); + if (ret >= 0) { + success++; + } + } + // We should always succeed if at least one DB was upgraded - we may possibly + // fail later with unresolved deps, but that should be rare, and would be expected + if (success == 0) { + err.str = _("failed to synchronize any databases\n"); + details += Alpm.strerror (alpm_config.handle.errno ()) + "\n"; + err.details = details; + } + trans_release (); + get_handle (); + if (emit_refreshed_signal) + emit_refreshed (err); + else + emit_refreshed_signal = true; + } + } + + public async void refresh (int force, bool emit_signal) { + force_refresh = force; + emit_refreshed_signal = emit_signal; + try { + new Thread.try ("refresh thread", (ThreadFunc) refresh_real); + } catch (GLib.Error e) { + stderr.printf ("%s\n", e.message); + } + } + + public UpdatesInfos[] get_updates () { + UpdatesInfos[] updates = {}; + updates = get_syncfirst_updates (alpm_config); + if (updates.length != 0) { + return updates; + } else { + string[] ignore_pkgs = get_ignore_pkgs (alpm_config); + updates = get_repos_updates (alpm_config, ignore_pkgs); + if (pamac_config.enable_aur) { + UpdatesInfos[] aur_updates = get_aur_updates (alpm_config, ignore_pkgs); + foreach (UpdatesInfos infos in aur_updates) + updates += infos; + } + return updates; + } + } + + public ErrorInfos trans_init (TransFlag transflags) { + ErrorInfos err = ErrorInfos (); + int ret = alpm_config.handle.trans_init (transflags); + if (ret == -1) { + //err = _("failed to init transaction (%s)\n").printf (Alpm.strerror (errno)); + err.str = Alpm.strerror (alpm_config.handle.errno ()) + "\n"; + } + return err; + } + + public ErrorInfos trans_sysupgrade (int enable_downgrade) { + ErrorInfos err = ErrorInfos (); + int ret = alpm_config.handle.trans_sysupgrade (enable_downgrade); + if (ret == -1) {; + err.str = Alpm.strerror (alpm_config.handle.errno ()) + "\n"; + } + return err; + } + + public ErrorInfos trans_add_pkg (string pkgname) { + ErrorInfos err = ErrorInfos (); + unowned Package? pkg = null; + //pkg = alpm_config.handle.find_dbs_satisfier (syncdbs, pkgname); + foreach (var db in syncdbs) { + pkg = find_satisfier (db.pkgcache, pkgname); + if (pkg != null) + break; + } + if (pkg == null) { + err.str = _("target not found: %s\n").printf (pkgname); + return err; + } + int ret = alpm_config.handle.trans_add_pkg (pkg); + if (ret == -1) { + Alpm.Errno errno = alpm_config.handle.errno (); + if (errno == Errno.TRANS_DUP_TARGET || errno == Errno.PKG_IGNORED) + // just skip duplicate or ignored targets + return err; + else { + err.str = "'%s': %s\n".printf (pkg.name, Alpm.strerror (errno)); + return err; + } + } + return err; + } + + public ErrorInfos trans_load_pkg (string pkgpath) { + ErrorInfos err = ErrorInfos (); + unowned Package? pkg = alpm_config.handle.load_file (pkgpath, 1, alpm_config.handle.localfilesiglevel); + if (pkg == null) { + err.str = "'%s': %s\n".printf (pkgpath, Alpm.strerror (alpm_config.handle.errno ())); + return err; + } else { + int ret = alpm_config.handle.trans_add_pkg (pkg); + if (ret == -1) { + Alpm.Errno errno = alpm_config.handle.errno (); + if (errno == Errno.TRANS_DUP_TARGET || errno == Errno.PKG_IGNORED) { + // just skip duplicate or ignored targets + return err; + } else { + err.str = "'%s': %s\n".printf (pkg.name, Alpm.strerror (errno)); + return err; + } + } + } + return err; + } + + public ErrorInfos trans_remove_pkg (string pkgname) { + ErrorInfos err = ErrorInfos (); + unowned Package? pkg = localdb.get_pkg (pkgname); + if (pkg == null) { + err.str = _("target not found: %s\n").printf (pkgname); + return err; + } + int ret = alpm_config.handle.trans_remove_pkg (pkg); + if (ret == -1) { + err.str = "'%s': %s\n".printf (pkg.name, Alpm.strerror (alpm_config.handle.errno ())); + } + return err; + } + + public void trans_prepare_real () { + ErrorInfos err = ErrorInfos (); + string[] details = {}; + Alpm.List err_data = null; + int ret = alpm_config.handle.trans_prepare (out err_data); + if (ret == -1) { + Alpm.Errno errno = alpm_config.handle.errno (); + //err = _("failed to prepare transaction (%s)\n").printf (); + err.str = Alpm.strerror (errno) + "\n"; + switch (errno) { + case Errno.PKG_INVALID_ARCH: + foreach (void *i in err_data) { + char *pkgname = i; + details += _("package %s does not have a valid architecture\n").printf (pkgname); + } + break; + case Errno.UNSATISFIED_DEPS: + foreach (void *i in err_data) { + DepMissing *miss = i; + string depstring = miss->depend.compute_string (); + details += _("%s: requires %s\n").printf (miss->target, depstring); + } + break; + case Errno.CONFLICTING_DEPS: + foreach (void *i in err_data) { + Conflict *conflict = i; + // only print reason if it contains new information + if (conflict->reason.mod == DepMod.ANY) + details += _("%s and %s are in conflict\n").printf (conflict->package1, conflict->package2); + else { + string reason = conflict->reason.compute_string (); + details += _("%s and %s are in conflict (%s)\n").printf (conflict->package1, conflict->package2, reason); + } + } + break; + default: + break; + } + err.details = details; + trans_release (); + } + emit_trans_prepared (err); + } + + public async void trans_prepare () { + try { + new Thread.try ("prepare thread", (ThreadFunc) trans_prepare_real); + } catch (GLib.Error e) { + stderr.printf ("%s\n", e.message); + } + } + + public void choose_provider (int provider) { + provider_mutex.lock (); + choosen_provider = provider; + provider_cond.signal (); + provider_mutex.unlock (); + } + + public UpdatesInfos[] trans_to_add () { + UpdatesInfos info = UpdatesInfos (); + UpdatesInfos[] infos = {}; + foreach (unowned Package pkg in alpm_config.handle.trans_to_add ()) { + info.name = pkg.name; + info.version = pkg.version; + // if pkg was load from a file, pkg.db is null + if (pkg.db != null) + info.db_name = pkg.db.name; + else + info.db_name = ""; + info.tarpath = ""; + info.download_size = pkg.download_size; + infos += info; + } + return infos; + } + + public UpdatesInfos[] trans_to_remove () { + UpdatesInfos info = UpdatesInfos (); + UpdatesInfos[] infos = {}; + foreach (unowned Package pkg in alpm_config.handle.trans_to_remove ()) { + info.name = pkg.name; + info.version = pkg.version; + info.db_name = pkg.db.name; + info.tarpath = ""; + info.download_size = pkg.download_size; + infos += info; + } + return infos; + } + + private void trans_commit_real () { + ErrorInfos err = ErrorInfos (); + string[] details = {}; + Alpm.List err_data = null; + int ret = alpm_config.handle.trans_commit (out err_data); + if (ret == -1) { + Alpm.Errno errno = alpm_config.handle.errno (); + //err = _("failed to commit transaction (%s)\n").printf (Alpm.strerror (errno)); + err.str = Alpm.strerror (errno) + "\n"; + switch (errno) { + case Alpm.Errno.FILE_CONFLICTS: + TransFlag flags = alpm_config.handle.trans_get_flags (); + if ((flags & TransFlag.FORCE) != 0) { + details += _("unable to %s directory-file conflicts\n").printf ("--force"); + } + foreach (void *i in err_data) { + FileConflict *conflict = i; + switch (conflict->type) { + case FileConflictType.TARGET: + details += _("%s exists in both '%s' and '%s'\n").printf (conflict->file, conflict->target, conflict->ctarget); + break; + case FileConflictType.FILESYSTEM: + details += _("%s: %s exists in filesystem\n").printf (conflict->target, conflict->file); + break; + } + } + break; + case Alpm.Errno.PKG_INVALID: + case Alpm.Errno.PKG_INVALID_CHECKSUM: + case Alpm.Errno.PKG_INVALID_SIG: + case Alpm.Errno.DLT_INVALID: + foreach (void *i in err_data) { + char *filename = i; + details += _("%s is invalid or corrupted\n").printf (filename); + } + break; + default: + break; + } + err.details = details; + } + trans_release (); + get_handle (); + emit_trans_committed (err); + } + + public async void trans_commit (GLib.BusName sender) { + try { + Polkit.Authority authority = Polkit.Authority.get_sync (null); + Polkit.Subject subject = Polkit.SystemBusName.new (sender); + Polkit.AuthorizationResult result = authority.check_authorization_sync + (subject, + "org.manjaro.pamac.commit", + null, + Polkit.CheckAuthorizationFlags.ALLOW_USER_INTERACTION, + null); + if (result.get_is_authorized ()) { + new Thread.try ("commit thread", (ThreadFunc) trans_commit_real); + } else { + ErrorInfos err = ErrorInfos (); + err.str = "Not Authorized\n"; + emit_trans_committed (err); + trans_release (); + } + } catch (GLib.Error e) { + stderr.printf ("%s\n", e.message); + } + } + + public int trans_release () { + return alpm_config.handle.trans_release (); + } + + public void trans_cancel () { + alpm_config.handle.trans_interrupt (); + alpm_config.handle.trans_release (); + get_handle (); + } + + public void quit () { + GLib.File lockfile = GLib.File.new_for_path ("/var/lib/pacman/db.lck"); + if (lockfile.query_exists () == false) + loop.quit (); + } +// End of Server Object +} + +private void write_log_file (string event) { + var now = new DateTime.now_local (); + string log = "%s %s".printf (now.format ("[%Y-%m-%d %H:%M]"), event); + var file = GLib.File.new_for_path ("/var/log/pamac.log"); + try { + // creating a DataOutputStream to the file + var dos = new DataOutputStream (file.append_to (FileCreateFlags.NONE)); + // writing a short string to the stream + dos.put_string (log); + } catch (GLib.Error e) { + GLib.stderr.printf("%s\n", e.message); + } +} + +private void cb_event (Event event, void *data1, void *data2) { + string event_str = null; + switch (event) { + case Event.CHECKDEPS_START: + event_str = _("checking dependencies...\n"); + break; + case Event.FILECONFLICTS_START: + event_str = _("checking for file conflicts...\n"); + break; + case Event.RESOLVEDEPS_START: + event_str = _("resolving dependencies...\n"); + break; + case Event.INTERCONFLICTS_START: + event_str = _("looking for inter-conflicts...\n"); + break; + case Event.ADD_START: + unowned Package pkg = (Package) data1; + event_str = _("installing %s...\n").printf ("%s (%s)".printf (pkg.name, pkg.version)); + break; + case Event.ADD_DONE: + unowned Package pkg = (Package) data1; + string log = "installed %s (%s)\n".printf (pkg.name, pkg.version); + write_log_file (log); + break; + case Event.REMOVE_START: + unowned Package pkg = (Package) data1; + event_str = _("removing %s...\n").printf ("%s (%s)".printf (pkg.name, pkg.version)); + break; + case Event.REMOVE_DONE: + unowned Package pkg = (Package) data1; + string log = "removed %s (%s)\n".printf (pkg.name, pkg.version); + write_log_file (log); + break; + case Event.UPGRADE_START: + unowned Package new_pkg = (Package) data1; + unowned Package old_pkg = (Package) data2; + event_str = _("upgrading %s...\n").printf ("%s (%s -> %s)".printf (old_pkg.name, old_pkg.version, new_pkg.version)); + break; + case Event.UPGRADE_DONE: + unowned Package new_pkg = (Package) data1; + unowned Package old_pkg = (Package) data2; + string log = _("upgraded %s (%s -> %s)\n").printf (old_pkg.name, old_pkg.version, new_pkg.version); + write_log_file (log); + break; + case Event.DOWNGRADE_START: + unowned Package new_pkg = (Package) data1; + unowned Package old_pkg = (Package) data2; + event_str = _("downgrading %s...\n").printf ("%s (%s -> %s)".printf (old_pkg.name, old_pkg.version, new_pkg.version)); + break; + case Event.DOWNGRADE_DONE: + unowned Package new_pkg = (Package) data1; + unowned Package old_pkg = (Package) data2; + string log = _("downgraded %s (%s -> %s)\n").printf (old_pkg.name, old_pkg.version, new_pkg.version); + write_log_file (log); + break; + case Event.REINSTALL_START: + unowned Package pkg = (Package) data1; + event_str = _("reinstalling %s...\n").printf ("%s (%s)".printf (pkg.name, pkg.version)); + break; + case Event.REINSTALL_DONE: + unowned Package pkg = (Package) data1; + string log = "reinstalled %s (%s)\n".printf (pkg.name, pkg.version); + write_log_file (log); + break; + case Event.INTEGRITY_START: + event_str = _("checking package integrity...\n"); + break; + case Event.KEYRING_START: + event_str = _("checking keyring...\n"); + break; + case Event.KEY_DOWNLOAD_START: + event_str = _("downloading required keys...\n"); + break; + case Event.LOAD_START: + event_str = _("loading package files...\n"); + break; + case Event.DELTA_INTEGRITY_START: + event_str = _("checking delta integrity...\n"); + break; + case Event.DELTA_PATCHES_START: + event_str = _("applying deltas...\n"); + break; + case Event.DELTA_PATCH_START: + unowned string string1 = (string) data1; + unowned string string2 = (string) data2; + event_str = _("generating %s with %s... ").printf (string1, string2); + break; + case Event.DELTA_PATCH_DONE: + event_str = _("success!\n"); + break; + case Event.DELTA_PATCH_FAILED: + event_str = _("failed.\n"); + break; + case Event.SCRIPTLET_INFO: + unowned string info = (string) data1; + event_str = info; + write_log_file (event_str); + break; + case Event.RETRIEVE_START: + event_str = _("Retrieving packages ...\n"); + break; + case Event.DISKSPACE_START: + event_str = _("checking available disk space...\n"); + break; + case Event.OPTDEP_REQUIRED: + unowned Package pkg = (Package) data1; + Depend *depend = data2; + event_str = _("%s optionally requires %s\n").printf (pkg.name, depend->compute_string ()); + break; + case Event.DATABASE_MISSING: + event_str = _("database file for '%s' does not exist\n").printf ((char *) data1); + break; + /* all the simple done events, with fallthrough for each */ + + case Event.FILECONFLICTS_DONE: + case Event.CHECKDEPS_DONE: + case Event.RESOLVEDEPS_DONE: + case Event.INTERCONFLICTS_DONE: + case Event.INTEGRITY_DONE: + case Event.KEYRING_DONE: + case Event.KEY_DOWNLOAD_DONE: + case Event.LOAD_DONE: + case Event.DELTA_INTEGRITY_DONE: + case Event.DELTA_PATCHES_DONE: + case Event.DISKSPACE_DONE: + /* nothing */ + break; + default: + event_str = "unknown event"; + break; + } + if (event_str != null) + server.emit_event ((uint) event, event_str); +} + +private void cb_question (Question question, void *data1, void *data2, void *data3, out int response) { + switch (question) { + case Question.INSTALL_IGNOREPKG: + // Do not install package in IgnorePkg/IgnoreGroup + response = 0; + break; + case Question.REPLACE_PKG: + // Auto-remove conflicts in case of replaces + response = 1; + break; + case Question.CONFLICT_PKG: + // Auto-remove conflicts + response = 1; + break; + case Question.REMOVE_PKGS: + // Do not upgrade packages which have unresolvable dependencies + response = 1; + break; + case Question.SELECT_PROVIDER: + unowned Alpm.List providers = (Alpm.List) data1; + Depend *depend = data2; + string depend_str = depend->compute_string (); + string[] providers_str = {}; + foreach (unowned Package pkg in providers) { + providers_str += pkg.name; + } + server.provider_cond = Cond (); + server.provider_mutex = Mutex (); + server.choosen_provider = null; + server.emit_providers (depend_str, providers_str); + server.provider_mutex.lock (); + while (server.choosen_provider == null) { + server.provider_cond.wait (server.provider_mutex); + } + response = server.choosen_provider; + server.provider_mutex.unlock (); + break; + case Question.CORRUPTED_PKG: + // Auto-remove corrupted pkgs in cache + response = 1; + break; + case Question.IMPORT_KEY: + PGPKey *key = data1; + // Do not get revoked key + if (key->revoked == 1) response = 0; + // Auto get not revoked key + else response = 1; + break; + default: + response = 0; + break; + } +} + +private void cb_progress (Progress progress, string pkgname, int percent, uint n_targets, uint current_target) { + string action = ""; + switch (progress) { + case Progress.ADD_START: + action = _("installing"); + break; + case Progress.UPGRADE_START: + action = _("upgrading"); + break; + case Progress.DOWNGRADE_START: + action = _("downgrading"); + break; + case Progress.REINSTALL_START: + action = _("reinstalling"); + break; + case Progress.REMOVE_START: + action = _("removing"); + break; + case Progress.CONFLICTS_START: + action = _("checking for file conflicts"); + break; + case Progress.DISKSPACE_START: + action = _("checking available disk space"); + break; + case Progress.INTEGRITY_START: + action = _("checking package integrity"); + break; + case Progress.KEYRING_START: + action = _("checking keys in keyring"); + break; + case Progress.LOAD_START: + action = _("loading package files"); + break; + default: + break; + } + if ((uint64) percent != server.previous_percent) { + server.previous_percent = (uint64) percent; + server.emit_progress ((uint) progress, action, pkgname, percent, n_targets, current_target); + } +} + +private void cb_download (string filename, uint64 xfered, uint64 total) { + if (xfered != server.previous_percent) { + server.previous_percent = xfered; + server.emit_download (filename, xfered, total); + } +} + +private void cb_totaldownload (uint64 total) { + server.emit_totaldownload (total); +} + +private void cb_log (LogLevel level, string fmt, va_list args) { + LogLevel logmask = LogLevel.ERROR | LogLevel.WARNING; + if ((level & logmask) == 0) + return; + string? log = null; + log = fmt.vprintf (args); + if (log != null) + server.emit_log ((uint) level, log); +} + +void on_bus_acquired (DBusConnection conn) { + server = new PamacServer (); + try { + conn.register_object ("/org/manjaro/pamac", server); + } + catch (IOError e) { + stderr.printf ("Could not register service\n"); + } +} + +void main () { + // i18n + Intl.setlocale(LocaleCategory.ALL, ""); + Intl.textdomain(GETTEXT_PACKAGE); + + Bus.own_name(BusType.SYSTEM, "org.manjaro.pamac", BusNameOwnerFlags.NONE, + on_bus_acquired, + () => {}, + () => stderr.printf("Could not acquire name\n")); + + loop = new MainLoop (); + loop.run (); +} diff --git a/src/history_dialog.vala b/src/history_dialog.vala new file mode 100644 index 0000000..e9a55d5 --- /dev/null +++ b/src/history_dialog.vala @@ -0,0 +1,40 @@ +/* + * pamac-vala + * + * Copyright (C) 2014 Guillaume Benoit + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a get of the GNU General Public License + * along with this program. If not, see . + */ + +namespace Pamac { + + [GtkTemplate (ui = "/org/manjaro/pamac/manager/history_dialog.ui")] + public class HistoryDialog : Gtk.Dialog { + + [GtkChild] + public Gtk.TextView textview; + + public HistoryDialog (ManagerWindow window) { + Object (transient_for: window, use_header_bar: 0); + } + + [GtkCallback] + public void on_textview_size_allocate () { + // auto-scrolling method + var scrollable = textview as Gtk.Scrollable; + var adj = scrollable.get_vadjustment (); + adj.set_value (adj.get_upper () - adj.get_page_size ()); + } + } +} diff --git a/src/installer.vala b/src/installer.vala new file mode 100644 index 0000000..8f6b8a1 --- /dev/null +++ b/src/installer.vala @@ -0,0 +1,69 @@ +/* + * pamac-vala + * + * Copyright (C) 2014 Guillaume Benoit + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a get of the GNU General Public License + * along with this program. If not, see . + */ + +namespace Pamac { + + public class Installer: Gtk.Application { + Transaction transaction; + Pamac.Config pamac_config; + + public Installer () { + application_id = "org.manjaro.pamac.install"; + flags |= ApplicationFlags.HANDLES_OPEN; + } + + public override void startup () { + // i18n + Intl.textdomain ("pamac"); + Intl.setlocale (LocaleCategory.ALL, ""); + + base.startup (); + + pamac_config = new Pamac.Config ("/etc/pamac.conf"); + transaction = new Pamac.Transaction (null, pamac_config); + transaction.finished.connect (on_emit_trans_finished); + + this.hold (); + } + + public override void activate () { + print ("\nError: Path(s) of tarball(s) to install is needed\n"); + transaction.stop_daemon (); + this.release (); + } + + public override void open (File[] files, string hint) { + foreach (File file in files) { + string? path = file.get_path (); + transaction.data.to_load.insert (path, path); + } + transaction.run (); + } + + public void on_emit_trans_finished (bool error) { + transaction.stop_daemon (); + this.release (); + } + + public static int main (string[] args) { + var installer = new Installer(); + return installer.run (args); + } + } +} diff --git a/src/manager.vala b/src/manager.vala new file mode 100644 index 0000000..d8fe6ea --- /dev/null +++ b/src/manager.vala @@ -0,0 +1,55 @@ +/* + * pamac-vala + * + * Copyright (C) 2014 Guillaume Benoit + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a get of the GNU General Public License + * along with this program. If not, see . + */ + +namespace Pamac { + + public class Manager : Gtk.Application { + + ManagerWindow manager_window; + + public Manager () { + application_id = "org.manjaro.pamac.manager"; + flags = ApplicationFlags.FLAGS_NONE; + } + + public override void startup () { + // i18n + Intl.textdomain ("pamac"); + Intl.setlocale (LocaleCategory.ALL, ""); + + base.startup (); + + manager_window = new ManagerWindow (this); + } + + public override void activate () { + manager_window.present (); + } + + public override void shutdown () { + base.shutdown (); + manager_window.transaction.stop_daemon (); + } + } + + public static int main (string[] args) { + var manager = new Manager (); + return manager.run (args); + } +} diff --git a/src/manager_window.vala b/src/manager_window.vala new file mode 100644 index 0000000..9dee1f5 --- /dev/null +++ b/src/manager_window.vala @@ -0,0 +1,927 @@ +/* + * pamac-vala + * + * Copyright (C) 2014 Guillaume Benoit + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a get of the GNU General Public License + * along with this program. If not, see . + */ + +using Gtk; +using Alpm; + +const string VERSION = "2.0"; + +namespace Pamac { + + public struct SortInfo { + public int column_number; + public Gtk.SortType sort_type; + } + + [GtkTemplate (ui = "/org/manjaro/pamac/manager/manager_window.ui")] + public class ManagerWindow : Gtk.ApplicationWindow { + // icons + public Gdk.Pixbuf? installed_icon; + public Gdk.Pixbuf? uninstalled_icon; + public Gdk.Pixbuf? to_install_icon; + public Gdk.Pixbuf? to_reinstall_icon; + public Gdk.Pixbuf? to_remove_icon; + public Gdk.Pixbuf? locked_icon; + + // manager objects + [GtkChild] + public TreeView packages_treeview; + [GtkChild] + public TreeViewColumn state_column; + [GtkChild] + public TreeViewColumn name_column; + [GtkChild] + public TreeViewColumn version_column; + [GtkChild] + public TreeViewColumn repo_column; + [GtkChild] + public TreeViewColumn size_column; + [GtkChild] + public Notebook filters_notebook; + [GtkChild] + public SearchEntry search_entry; + [GtkChild] + public TreeView search_treeview; + [GtkChild] + public TreeView groups_treeview; + [GtkChild] + public TreeView states_treeview; + [GtkChild] + public TreeView repos_treeview; + [GtkChild] + public TreeView deps_treeview; + [GtkChild] + public TreeView details_treeview; + [GtkChild] + public ScrolledWindow deps_scrolledwindow; + [GtkChild] + public ScrolledWindow details_scrolledwindow; + [GtkChild] + public ScrolledWindow files_scrolledwindow; + [GtkChild] + public Label name_label; + [GtkChild] + public Label desc_label; + [GtkChild] + public Label link_label; + [GtkChild] + public Label licenses_label; + [GtkChild] + public TextView files_textview; + [GtkChild] + public Switch search_aur_button; + [GtkChild] + public Button valid_button; + [GtkChild] + public Button cancel_button; + + public ListStore search_list; + public ListStore groups_list; + public ListStore states_list; + public ListStore repos_list; + public ListStore deps_list; + public ListStore details_list; + + PackagesModel packages_list; + HashTable aur_results; + + public Pamac.Config pamac_config; + public Transaction transaction; + + public SortInfo sortinfo; + + //dialogs + HistoryDialog history_dialog; + PackagesChooserDialog packages_chooser_dialog; + PreferencesDialog preferences_dialog; + + public ManagerWindow (Gtk.Application application) { + Object (application: application); + + aur_results = new HashTable (str_hash, str_equal); + + search_list = new Gtk.ListStore (1, typeof (string)); + search_treeview.set_model (search_list); + groups_list = new Gtk.ListStore (1, typeof (string)); + groups_treeview.set_model (groups_list); + states_list = new Gtk.ListStore (1, typeof (string)); + states_treeview.set_model (states_list); + repos_list = new Gtk.ListStore (1, typeof (string)); + repos_treeview.set_model (repos_list); + deps_list = new Gtk.ListStore (2, typeof (string), typeof (string)); + deps_treeview.set_model (deps_list); + details_list = new Gtk.ListStore (2, typeof (string), typeof (string)); + details_treeview.set_model (details_list);; + + try { + installed_icon = new Gdk.Pixbuf.from_resource ("/org/manjaro/pamac/manager/package-installed-updated.png"); + uninstalled_icon = new Gdk.Pixbuf.from_resource ("/org/manjaro/pamac/manager/package-available.png"); + to_install_icon = new Gdk.Pixbuf.from_resource ("/org/manjaro/pamac/manager/package-install.png"); + to_reinstall_icon = new Gdk.Pixbuf.from_resource ("/org/manjaro/pamac/manager/package-reinstall.png"); + to_remove_icon = new Gdk.Pixbuf.from_resource ("/org/manjaro/pamac/manager/package-remove.png"); + locked_icon = new Gdk.Pixbuf.from_resource ("/org/manjaro/pamac/manager/package-installed-locked.png"); + } catch (GLib.Error e) { + stderr.printf (e.message); + } + + pamac_config = new Pamac.Config ("/etc/pamac.conf"); + + transaction = new Pamac.Transaction (this as ApplicationWindow, pamac_config); + transaction.finished.connect (on_emit_trans_finished); + + history_dialog = new HistoryDialog (this); + packages_chooser_dialog = new PackagesChooserDialog (this, transaction); + preferences_dialog = new PreferencesDialog (this as ApplicationWindow); + + set_buttons_sensitive (false); + search_aur_button.set_active (pamac_config.enable_aur); + + // sort by name by default + sortinfo = {0, SortType.ASCENDING}; + update_lists (); + } + + public void enable_aur (bool enable) { + search_aur_button.set_active (enable); + } + + public void set_buttons_sensitive (bool sensitive) { + valid_button.set_sensitive (sensitive); + cancel_button.set_sensitive (sensitive); + } + + public void update_lists () { + Alpm.List grps = null; + TreeIter iter; + foreach (unowned DB db in transaction.alpm_config.handle.syncdbs) { + repos_list.insert_with_values (out iter, -1, 0, db.name); + foreach (unowned Group grp in db.groupcache) { + if (grps.find_str (grp.name) == null) + grps.add(grp.name); + } + } + repos_list.insert_with_values (out iter, -1, 0, dgettext (null, "local")); + foreach (string name in grps) + groups_list.insert_with_values (out iter, -1, 0, name); + groups_list.set_sort_column_id (0, SortType.ASCENDING); + states_list.insert_with_values (out iter, -1, 0, dgettext (null, "Installed")); + //states_list.insert_with_values (out iter, -1, 0, dgettext (null, "Uninstalled")); + states_list.insert_with_values (out iter, -1, 0, dgettext (null, "Orphans")); + states_list.insert_with_values (out iter, -1, 0, dgettext (null, "To install")); + states_list.insert_with_values (out iter, -1, 0, dgettext (null, "To remove")); + } + + public void set_infos_list (Pamac.Package pkg) { + name_label.set_markup ("%s %s".printf (pkg.name, pkg.version)); + // fix &,-,>,< in desc + string desc; + if (pkg.alpm_pkg != null) + desc = pkg.alpm_pkg.desc; + else + desc = pkg.aur_json.get_string_member ("Description"); + desc = desc.replace ("&", "&"); + desc = desc.replace ("<->", "/"); + desc_label.set_markup (desc); + // fix & in url + string url; + if (pkg.alpm_pkg != null) + url = pkg.alpm_pkg.url; + else + url = pkg.aur_json.get_string_member ("URL"); + url = url.replace ("&", "&"); + link_label.set_markup ("%s".printf (url, url)); + StringBuilder licenses = new StringBuilder (); + licenses.append (dgettext (null, "Licenses")); + licenses.append (":"); + if (pkg.alpm_pkg != null) { + foreach (unowned string license in pkg.alpm_pkg.licenses) { + licenses.append (" "); + licenses.append (license); + } + } else { + licenses.append (" "); + licenses.append (pkg.aur_json.get_string_member ("License")); + } + licenses_label.set_markup (licenses.str); + } + + public void set_deps_list (Alpm.Package pkg) { + deps_list.clear (); + TreeIter iter; + unowned Alpm.List list = pkg.depends; + size_t len = list.length; + size_t i; + if (len != 0) { + deps_list.insert_with_values (out iter, -1, + 0, dgettext (null, "Depends On") + ":", + 1, list.nth (0).get_data ().compute_string ()); + i = 1; + while (i < len) { + deps_list.insert_with_values (out iter, -1, + 1, list.nth (i).get_data ().compute_string ()); + i++; + } + } + list = pkg.optdepends; + len = list.length; + if (len != 0) { + unowned Depend optdep = list.nth (0).get_data (); + unowned Alpm.Package? satisfier = find_satisfier ( + transaction.alpm_config.handle.localdb.pkgcache, + optdep.name); + string optdep_str = optdep.compute_string (); + if (satisfier != null) + optdep_str = optdep_str + " [" + dgettext (null, "Installed") + "]"; + deps_list.insert_with_values (out iter, -1, + 0, dgettext (null, "Optional Deps") + ":", + 1, optdep_str); + i = 1; + while (i < len) { + optdep = list.nth (i).get_data (); + satisfier = find_satisfier ( + transaction.alpm_config.handle.localdb.pkgcache, + optdep.name); + optdep_str = optdep.compute_string (); + if (satisfier != null) + optdep_str = optdep_str + " [" + dgettext (null, "Installed") + "]"; + deps_list.insert_with_values (out iter, -1, 1, optdep_str); + i++; + } + } + if (pkg.origin == PkgFrom.LOCALDB) { + unowned Alpm.List str_list = pkg.compute_requiredby (); + len = str_list.length; + if (len != 0) { + deps_list.insert_with_values (out iter, -1, + 0, dgettext (null, "Required By") + ":", + 1, str_list.nth (0).get_data ()); + i = 1; + while (i < len) { + deps_list.insert_with_values (out iter, -1, + 1, str_list.nth (i).get_data ()); + i++; + } + } + } + list = pkg.provides; + len = list.length; + if (len != 0) { + deps_list.insert_with_values (out iter, -1, + 0, dgettext (null, "Provides") + ":", + 1, list.nth (0).get_data ().compute_string ()); + i = 1; + while (i < len) { + deps_list.insert_with_values (out iter, -1, + 1, list.nth (i).get_data ().compute_string ()); + i++; + } + } + list = pkg.replaces; + len = list.length; + if (len != 0) { + deps_list.insert_with_values (out iter, -1, + 0, dgettext (null, "Replaces") + ":", + 1, list.nth (0).get_data ().compute_string ()); + i = 1; + while (i < len) { + deps_list.insert_with_values (out iter, -1, + 1, list.nth (i).get_data ().compute_string ()); + i++; + } + } + list = pkg.conflicts; + len = list.length; + if (len != 0) { + deps_list.insert_with_values (out iter, -1, + 0, dgettext (null, "Conflicts With") + ":", + 1, list.nth (0).get_data ().compute_string ()); + i = 1; + while (i < len) { + deps_list.insert_with_values (out iter, -1, + 1, list.nth (i).get_data ().compute_string ()); + i++; + } + } + } + + public void set_details_list (Alpm.Package pkg) { + details_list.clear (); + TreeIter iter; + if (pkg.origin == PkgFrom.SYNCDB) { + details_list.insert_with_values (out iter, -1, + 0, dgettext (null, "Repository") + ":", + 1, pkg.db.name); + } + unowned Alpm.List list = pkg.groups; + size_t len = list.length; + size_t i; + if (len != 0) { + details_list.insert_with_values (out iter, -1, + 0, dgettext (null, "Groups") + ":", + 1, list.nth (0).get_data ()); + i = 1; + while (i < len) { + details_list.insert_with_values (out iter, -1, + 1, list.nth (i).get_data ()); + i++; + } + } + details_list.insert_with_values (out iter, -1, + 0, dgettext (null, "Packager") + ":", + 1, pkg.packager); + if (pkg.origin == PkgFrom.LOCALDB) { + GLib.Time time = GLib.Time.local ((time_t) pkg.installdate); + string strtime = time.format ("%a %d %b %Y %X %Z"); + details_list.insert_with_values (out iter, -1, + 0, dgettext (null, "Install Date") + ":", + 1, strtime); + string reason; + if (pkg.reason == PkgReason.EXPLICIT) + reason = dgettext (null, "Explicitly installed"); + else if (pkg.reason == PkgReason.EXPLICIT) + reason = dgettext (null, "Installed as a dependency for another package"); + else + reason = dgettext (null, "Unknown"); + details_list.insert_with_values (out iter, -1, + 0, dgettext (null, "Install Reason") + ":", + 1, reason); + } + if (pkg.origin == PkgFrom.SYNCDB) { + details_list.insert_with_values (out iter, -1, + 0, dgettext (null, "Signatures") + ":", + 1, pkg.base64_sig != null ? "Yes" : "No"); + } + if (pkg.origin == PkgFrom.LOCALDB) { + unowned Alpm.List backup_list = pkg.backup; + len = backup_list.length; + if (len != 0) { + details_list.insert_with_values (out iter, -1, + 0, dgettext (null, "Backup files") + ":", + 1, "/" + backup_list.nth (0).get_data ().name); + i = 1; + while (i < len) { + details_list.insert_with_values (out iter, -1, + 1, "/" + backup_list.nth (i).get_data ().name); + i++; + } + } + } + } + + public void set_files_list (Alpm.Package pkg) { + StringBuilder text = new StringBuilder (); + foreach (unowned Alpm.File file in pkg.files) { + if (text.len != 0) + text.append ("\n"); + text.append ("/"); + text.append (file.name); + } + files_textview.buffer.set_text (text.str, (int) text.len); + } + + public async unowned Alpm.List search_pkgs (string search_string, out Json.Array aur_pkgs) { + unowned Alpm.List pkgs = null; + unowned Alpm.List needles = null; + string[] splitted = search_string.split (" "); + foreach (unowned string part in splitted) + needles.add (part); + pkgs = search_all_dbs (transaction.alpm_config.handle, needles); + if (search_aur_button.get_active()) { + if (aur_results.contains (search_string)) { + aur_pkgs = aur_results.get (search_string); + } else { + aur_pkgs = AUR.search (search_string); + aur_results.insert (search_string, aur_pkgs); + } + } else { + aur_pkgs = new Json.Array (); + } + return pkgs; + } + + public void populate_packages_list (Alpm.List? pkgs, Json.Array? aur_pkgs = null) { + packages_treeview.freeze_child_notify (); + packages_treeview.set_model (null); + + // populate liststore + packages_list = new PackagesModel (pkgs, aur_pkgs, this); + + // sort liststore + int column = sortinfo.column_number; + if (column == 0) + packages_list.sort_by_name (sortinfo.sort_type); + else if (column == 1) + packages_list.sort_by_state (sortinfo.sort_type); + else if (column == 2) + packages_list.sort_by_version (sortinfo.sort_type); + else if (column == 3) + packages_list.sort_by_repo (sortinfo.sort_type); + else if (column == 4) + packages_list.sort_by_size (sortinfo.sort_type); + + packages_treeview.set_model (packages_list); + packages_treeview.thaw_child_notify (); + + this.get_window ().set_cursor (null); + } + + public void refresh_packages_list () { + int current_page = filters_notebook.get_current_page (); + if (current_page == 0) { + TreeModel model; + TreeIter? iter; + TreeSelection selection = search_treeview.get_selection (); + if (selection.get_selected (out model, out iter)) { + on_search_treeview_selection_changed (); + } + } else if (current_page == 1) { + on_groups_treeview_selection_changed (); + } else if (current_page == 2) { + on_states_treeview_selection_changed (); + } else if (current_page == 3) { + on_repos_treeview_selection_changed (); + } + } + + [GtkCallback] + public void on_packages_treeview_selection_changed () { + TreeModel model; + TreeIter? iter; + TreeSelection selection = packages_treeview.get_selection (); + if (selection.get_selected (out model, out iter)) { + Pamac.Package pkg = (Pamac.Package) iter.user_data; + if (pkg.alpm_pkg != null) { + set_infos_list (pkg); + set_deps_list (pkg.alpm_pkg); + set_details_list (pkg.alpm_pkg); + deps_scrolledwindow.visible = true; + details_scrolledwindow.visible = true; + if (pkg.alpm_pkg.origin == PkgFrom.LOCALDB) { + set_files_list (pkg.alpm_pkg); + files_scrolledwindow.visible = true; + } else { + files_scrolledwindow.visible = false; + } + } else if (pkg.aur_json != null) { + set_infos_list (pkg); + deps_scrolledwindow.visible = false; + details_scrolledwindow.visible = false; + files_scrolledwindow.visible = false; + } + } + } + + [GtkCallback] + public void on_packages_treeview_row_activated (TreeView treeview, TreePath path, TreeViewColumn column) { + TreeIter iter; + if (packages_list.get_iter (out iter, path)) { + GLib.Value val; + packages_list.get_value (iter, 0, out val); + string name = val.get_string (); + if (name != dgettext (null, "No package found")) { + if (transaction.data.to_add.contains (name)) { + transaction.data.to_add.steal (name); + } else if (transaction.data.to_remove.contains (name)) { + transaction.data.to_remove.steal (name); + } else if (transaction.data.to_build.contains (name)) { + transaction.data.to_build.steal (name); + } else { + packages_list.get_value (iter, 3, out val); + string db_name = val.get_string (); + if (db_name == "local") { + if (!(name in transaction.alpm_config.holdpkg)) { + transaction.data.to_remove.insert (name, name); + } + } else if (db_name == "AUR") { + transaction.data.to_build.insert (name, name); + } else { + transaction.data.to_add.insert (name, name); + } + } + } + } + if (transaction.data.to_add.size () + transaction.data.to_remove.size () + transaction.data.to_build.size () == 0) { + set_buttons_sensitive (false); + } else { + set_buttons_sensitive (true); + } + // force a display refresh + packages_treeview.queue_draw (); + } + + [GtkCallback] + public bool on_list_treeview_button_press_event (Gdk.EventButton event) { + // to do + return false; + } + + [GtkCallback] + public void on_name_column_clicked () { + SortType new_order; + if (name_column.sort_indicator == false) + new_order = SortType.ASCENDING; + else { + if (sortinfo.sort_type == SortType.ASCENDING) + new_order = SortType.DESCENDING; + else + new_order = SortType.ASCENDING; + } + packages_list.sort_by_name (new_order); + // force a display refresh + packages_treeview.queue_draw (); + } + + [GtkCallback] + public void on_state_column_clicked () { + SortType new_order; + if (state_column.sort_indicator == false) + new_order = SortType.ASCENDING; + else { + if (sortinfo.sort_type == SortType.ASCENDING) + new_order = SortType.DESCENDING; + else + new_order = SortType.ASCENDING; + } + packages_list.sort_by_state (new_order); + // force a display refresh + packages_treeview.queue_draw (); + } + + [GtkCallback] + public void on_version_column_clicked () { + SortType new_order; + if (version_column.sort_indicator == false) + new_order = SortType.ASCENDING; + else { + if (sortinfo.sort_type == SortType.ASCENDING) + new_order = SortType.DESCENDING; + else + new_order = SortType.ASCENDING; + } + packages_list.sort_by_version (new_order); + // force a display refresh + packages_treeview.queue_draw (); + } + + [GtkCallback] + public void on_repo_column_clicked () { + SortType new_order; + if (repo_column.sort_indicator == false) + new_order = SortType.ASCENDING; + else { + if (sortinfo.sort_type == SortType.ASCENDING) + new_order = SortType.DESCENDING; + else + new_order = SortType.ASCENDING; + } + packages_list.sort_by_repo (new_order); + // force a display refresh + packages_treeview.queue_draw (); + } + + [GtkCallback] + public void on_size_column_clicked () { + SortType new_order; + if (size_column.sort_indicator == false) + new_order = SortType.ASCENDING; + else { + if (sortinfo.sort_type == SortType.ASCENDING) + new_order = SortType.DESCENDING; + else + new_order = SortType.ASCENDING; + } + packages_list.sort_by_size (new_order); + // force a display refresh + packages_treeview.queue_draw (); + } + + [GtkCallback] + public void on_search_entry_activate () { + string search_string = search_entry.get_text (); + if (search_string != "") { + this.get_window ().set_cursor (new Gdk.Cursor (Gdk.CursorType.WATCH)); + while (Gtk.events_pending ()) + Gtk.main_iteration (); + search_pkgs.begin (search_string, (obj, res) => { + Json.Array aur_pkgs; + unowned Alpm.List pkgs = search_pkgs.end (res, out aur_pkgs); + if (pkgs.length != 0) { + // add search string in search_list if needed + bool found = false; + TreeIter? iter; + TreeModel model; + TreeSelection selection = search_treeview.get_selection (); + // check if search string is already selected in search list + if (selection.get_selected (out model, out iter)) { + GLib.Value val; + model.get_value (iter, 0, out val); + string selected_string = val.get_string (); + if (selected_string == search_string) { + found = true; + // we need to populate packages_list + populate_packages_list (pkgs, aur_pkgs); + } else { + search_list.foreach ((_model, _path, _iter) => { + GLib.Value line; + model.get_value (_iter, 0, out line); + if ((string) line == search_string) { + found = true; + // populate will be done because we select the iter in search_list + selection.select_iter (_iter); + } + return found; + }); + } + } + if (!found) { + search_list.insert_with_values (out iter, -1, 0, search_string); + // populate will be done because we select the iter in search_list + selection.select_iter (iter); + } + } else + // populate with empty lists + populate_packages_list (pkgs, aur_pkgs); + }); + } + } + + [GtkCallback] + public void on_search_entry_icon_press (EntryIconPosition p0, Gdk.Event? p1) { + on_search_entry_activate (); + } + + [GtkCallback] + public void on_search_treeview_selection_changed () { + TreeModel model; + TreeIter? iter; + TreeSelection selection = search_treeview.get_selection (); + if (selection.get_selected (out model, out iter)) { + this.get_window ().set_cursor (new Gdk.Cursor (Gdk.CursorType.WATCH)); + while (Gtk.events_pending ()) + Gtk.main_iteration (); + GLib.Value val; + model.get_value (iter, 0, out val); + string search_string = val.get_string (); + search_pkgs.begin (search_string, (obj, res) => { + Json.Array aur_pkgs; + unowned Alpm.List pkgs = search_pkgs.end (res, out aur_pkgs); + populate_packages_list (pkgs, aur_pkgs); + }); + } + } + + [GtkCallback] + public void on_groups_treeview_selection_changed () { + TreeModel model; + TreeIter? iter; + TreeSelection selection = groups_treeview.get_selection (); + if (selection.get_selected (out model, out iter)) { + this.get_window ().set_cursor (new Gdk.Cursor (Gdk.CursorType.WATCH)); + while (Gtk.events_pending ()) + Gtk.main_iteration (); + GLib.Value val; + model.get_value (iter, 0, out val); + string grp_name = val.get_string (); + unowned Alpm.List pkgs = group_pkgs_all_dbs (transaction.alpm_config.handle, grp_name); + populate_packages_list (pkgs); + } + } + + [GtkCallback] + public void on_states_treeview_selection_changed () { + TreeModel model; + TreeIter? iter; + TreeSelection selection = states_treeview.get_selection (); + if (selection.get_selected (out model, out iter)) { + this.get_window ().set_cursor (new Gdk.Cursor (Gdk.CursorType.WATCH)); + while (Gtk.events_pending ()) + Gtk.main_iteration (); + GLib.Value val; + model.get_value (iter, 0, out val); + string state = val.get_string (); + unowned Alpm.List pkgs = null; + unowned Alpm.Package? find_pkg = null; + if (state == dgettext (null, "To install")) { + foreach (string name in transaction.data.to_add.get_keys ()) { + find_pkg = transaction.alpm_config.handle.localdb.get_pkg (name); + if (find_pkg != null) + pkgs.add (find_pkg); + else { + find_pkg = get_syncpkg (transaction.alpm_config.handle, name); + if (find_pkg != null) + pkgs.add (find_pkg); + } + } + } else if (state == dgettext (null, "To remove")) { + foreach (string name in transaction.data.to_remove.get_keys ()) { + find_pkg = transaction.alpm_config.handle.localdb.get_pkg (name); + if (find_pkg != null) + pkgs.add (find_pkg); + } + } else if (state == dgettext (null, "Installed")) { + pkgs = transaction.alpm_config.handle.localdb.pkgcache; + } else if (state == dgettext (null, "Uninstalled")) { + unowned Alpm.List tmp = null; + unowned Alpm.List diff = null; + foreach (unowned DB db in transaction.alpm_config.handle.syncdbs) { + if (pkgs.length == 0) + pkgs = db.pkgcache; + else { + tmp = db.pkgcache; + diff = tmp.diff (pkgs, (Alpm.List.CompareFunc) pkgcmp); + pkgs.join (diff); + } + } + } else if (state == dgettext (null, "Orphans")) { + foreach (unowned Alpm.Package pkg in transaction.alpm_config.handle.localdb.pkgcache) { + if (pkg.reason == PkgReason.DEPEND) { + if (pkg.compute_requiredby().length == 0) + pkgs.add (pkg); + } + } + } + populate_packages_list (pkgs); + } + } + + [GtkCallback] + public void on_repos_treeview_selection_changed () { + TreeModel model; + TreeIter? iter; + TreeSelection selection = repos_treeview.get_selection (); + if (selection.get_selected (out model, out iter)) { + this.get_window ().set_cursor (new Gdk.Cursor (Gdk.CursorType.WATCH)); + while (Gtk.events_pending ()) + Gtk.main_iteration (); + GLib.Value val; + model.get_value (iter, 0, out val); + string repo = val.get_string (); + unowned Alpm.List pkgs = null; + unowned Alpm.Package? find_pkg = null; + if (repo == dgettext (null, "local")) { + foreach (unowned Alpm.Package pkg in transaction.alpm_config.handle.localdb.pkgcache) { + find_pkg = get_syncpkg (transaction.alpm_config.handle, pkg.name); + if (find_pkg == null) + pkgs.add (pkg); + } + } else { + foreach (unowned DB db in transaction.alpm_config.handle.syncdbs) { + if (db.name == repo) { + foreach (unowned Alpm.Package pkg in db.pkgcache) { + find_pkg = transaction.alpm_config.handle.localdb.get_pkg (pkg.name); + if (find_pkg != null) + pkgs.add (find_pkg); + else + pkgs.add (pkg); + } + } + } + } + populate_packages_list (pkgs); + } + } + + [GtkCallback] + public void on_filters_notebook_switch_page (Widget page, uint page_num) { + refresh_packages_list (); + } + + [GtkCallback] + public void on_history_item_activate () { + var file = GLib.File.new_for_path ("/var/log/pamac.log"); + if (!file.query_exists ()) + GLib.stderr.printf ("File '%s' doesn't exist.\n", file.get_path ()); + else { + StringBuilder text = new StringBuilder (); + try { + // Open file for reading and wrap returned FileInputStream into a + // DataInputStream, so we can read line by line + var dis = new DataInputStream (file.read ()); + string line; + // Read lines until end of file (null) is reached + while ((line = dis.read_line (null)) != null) { + text.append (line); + text.append ("\n"); + } + } catch (GLib.Error e) { + GLib.stderr.printf("%s\n", e.message); + } + history_dialog.textview.buffer.set_text (text.str, (int) text.len); + history_dialog.run (); + history_dialog.hide (); + } + } + + [GtkCallback] + public void on_local_item_activate () { + int response = packages_chooser_dialog.run (); + if (response== ResponseType.ACCEPT) { + SList packages_paths = packages_chooser_dialog.get_filenames (); + if (packages_paths.length () != 0) { + foreach (string path in packages_paths) { + transaction.data.to_load.insert (path, path); + } + this.get_window ().set_cursor (new Gdk.Cursor (Gdk.CursorType.WATCH)); + packages_chooser_dialog.hide (); + while (Gtk.events_pending ()) + Gtk.main_iteration (); + transaction.run (); + } + } else + packages_chooser_dialog.hide (); + } + + [GtkCallback] + public void on_preferences_item_activate () { + bool enable_aur = pamac_config.enable_aur; + bool recurse = pamac_config.recurse; + uint64 refresh_period = pamac_config.refresh_period; + preferences_dialog.enable_aur_button.set_active (enable_aur); + preferences_dialog.remove_unrequired_deps_button.set_active (recurse); + preferences_dialog.refresh_period_spin_button.set_value (refresh_period); + int response = preferences_dialog.run (); + while (Gtk.events_pending ()) + Gtk.main_iteration (); + if (response == ResponseType.OK) { + HashTable new_conf = new HashTable (str_hash, str_equal); + enable_aur = preferences_dialog.enable_aur_button.get_active (); + recurse = preferences_dialog.remove_unrequired_deps_button.get_active (); + refresh_period = (uint64) preferences_dialog.refresh_period_spin_button.get_value (); + if (enable_aur != pamac_config.enable_aur) { + search_aur_button.set_active (enable_aur); + new_conf.insert ("EnableAUR", enable_aur.to_string ()); + } + if (recurse != pamac_config.recurse) + new_conf.insert ("RemoveUnrequiredDeps", recurse.to_string ()); + if (refresh_period != pamac_config.refresh_period) + new_conf.insert ("RefreshPeriod", refresh_period.to_string ()); + if (new_conf.size () != 0) { + transaction.write_config (new_conf); + pamac_config.reload (); + } + } + preferences_dialog.hide (); + } + + [GtkCallback] + public void on_about_item_activate () { + Gtk.show_about_dialog ( + this, + "program_name", "Pamac", + "logo_icon_name", "system-software-install", + "comments", "A GTK3 frontend of libalpm", + "copyright", "Copyright © 2014 Guillaume Benoit", + "version", VERSION, + "license_type", License.GPL_3_0, + "website", "http://manjaro.org"); + } + + [GtkCallback] + public void on_valid_button_clicked () { + this.get_window ().set_cursor (new Gdk.Cursor (Gdk.CursorType.WATCH)); + while (Gtk.events_pending ()) + Gtk.main_iteration (); + if (pamac_config.recurse) + transaction.data.flags |= Alpm.TransFlag.RECURSE; + transaction.run (); + } + + [GtkCallback] + public void on_cancel_button_clicked () { + transaction.clear_lists (); + set_buttons_sensitive (false); + // force a display refresh + packages_treeview.queue_draw (); + } + + [GtkCallback] + public void on_refresh_button_clicked () { + transaction.refresh (0); + } + + public void on_emit_trans_finished (bool error) { + if (error == false) { + set_buttons_sensitive (false); + refresh_packages_list (); + } + transaction.data.to_load.steal_all (); + this.get_window ().set_cursor (null); + } + } +} diff --git a/src/package.vala b/src/package.vala new file mode 100644 index 0000000..ac7a280 --- /dev/null +++ b/src/package.vala @@ -0,0 +1,61 @@ +/* + * pamac-vala + * + * Copyright (C) 2014 Guillaume Benoit + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a get of the GNU General Public License + * along with this program. If not, see . + */ + +namespace Pamac { + public class Package: Object { + public unowned Alpm.Package? alpm_pkg; + public unowned Json.Object? aur_json; + public string name; + public string version; + public string repo; + public uint64 size; + public string size_string; + + public Package (Alpm.Package? alpm_pkg, Json.Object? aur_json) { + if (alpm_pkg != null) { + this.alpm_pkg = alpm_pkg; + this.aur_json = null; + name = alpm_pkg.name; + version = alpm_pkg.version; + if (alpm_pkg.db != null) + repo = alpm_pkg.db.name; + else + repo = ""; + size = alpm_pkg.isize; + size_string = format_size (alpm_pkg.isize); + } else if (aur_json != null ) { + this.alpm_pkg = null; + this.aur_json = aur_json; + name = aur_json.get_string_member ("Name"); + version = aur_json.get_string_member ("Version"); + repo = "AUR"; + size = 0; + size_string = ""; + } else { + this.alpm_pkg = null; + this.aur_json = null; + name = dgettext (null, "No package found"); + version = ""; + repo = ""; + size = 0; + size_string = ""; + } + } + } +} diff --git a/src/packages_chooser_dialog.vala b/src/packages_chooser_dialog.vala new file mode 100644 index 0000000..1cbef4b --- /dev/null +++ b/src/packages_chooser_dialog.vala @@ -0,0 +1,56 @@ +/* + * pamac-vala + * + * Copyright (C) 2014 Guillaume Benoit + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a get of the GNU General Public License + * along with this program. If not, see . + */ + +namespace Pamac { + + [GtkTemplate (ui = "/org/manjaro/pamac/manager/packages_chooser_dialog.ui")] + public class PackagesChooserDialog : Gtk.FileChooserDialog { + + ManagerWindow window; + Transaction transaction; + + public PackagesChooserDialog (ManagerWindow window, Transaction transaction) { + Object (transient_for: window, use_header_bar: 0); + + Gtk.FileFilter package_filter = new Gtk.FileFilter (); + package_filter.set_filter_name (dgettext (null, "Packages")); + package_filter.add_pattern ("*.pkg.tar.gz"); + package_filter.add_pattern ("*.pkg.tar.xz"); + this.add_filter (package_filter); + + this.window = window; + this.transaction = transaction; + } + + [GtkCallback] + public void on_file_activated () { + SList packages_paths = this.get_filenames (); + if (packages_paths.length () != 0) { + foreach (string path in packages_paths) { + transaction.data.to_load.insert (path, path); + } + window.get_window ().set_cursor (new Gdk.Cursor (Gdk.CursorType.WATCH)); + this.hide (); + while (Gtk.events_pending ()) + Gtk.main_iteration (); + transaction.run (); + } + } + } +} diff --git a/src/packages_model.vala b/src/packages_model.vala new file mode 100644 index 0000000..ab3b2cd --- /dev/null +++ b/src/packages_model.vala @@ -0,0 +1,309 @@ +/* + * pamac-vala + * + * Copyright (C) 2014 Guillaume Benoit + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a get of the GNU General Public License + * along with this program. If not, see . + */ + +namespace Pamac { + + public class PackagesModel : Object, Gtk.TreeModel { + private GLib.List all_pkgs; + public ManagerWindow manager_window; + + public PackagesModel (Alpm.List? alpm_pkgs, Json.Array? aur_pkgs, ManagerWindow manager_window) { + this.manager_window = manager_window; + all_pkgs = new GLib.List (); + foreach (unowned Alpm.Package alpm_pkg in alpm_pkgs) { + all_pkgs.append (new Pamac.Package (alpm_pkg, null)); + } + if (aur_pkgs != null) { + unowned Json.Object pkg_info; + string name; + bool found; + foreach (Json.Node node in aur_pkgs.get_elements ()) { + pkg_info = node.get_object (); + name = pkg_info.get_string_member ("Name"); + // add only the packages which are not already in the list + found = false; + foreach (Pamac.Package pkg in all_pkgs) { + if (pkg.name == name) { + found = true; + break; + } + } + if (found == false) + all_pkgs.append (new Pamac.Package (null, pkg_info)); + } + } + if (all_pkgs.length () == 0) { + // create a fake "No package found" package + all_pkgs.append (new Pamac.Package (null, null)); + } + } + + // TreeModel interface + public Type get_column_type (int index) { + switch (index) { + case 0: // name + case 2: // version + case 3: // repo + case 4: // installed size + return typeof (string); + case 1: // icon + return typeof (Gdk.Pixbuf); + default: + return Type.INVALID; + } + } + + public Gtk.TreeModelFlags get_flags () { + return Gtk.TreeModelFlags.LIST_ONLY | Gtk.TreeModelFlags.ITERS_PERSIST; + } + + public void get_value (Gtk.TreeIter iter, int column, out Value val) { + Pamac.Package pkg = (Pamac.Package) iter.user_data; + return_if_fail (pkg != null); + switch (column) { + case 0: + val = Value (typeof (string)); + val.set_string (pkg.name); + break; + case 1: + val = Value (typeof (Object)); + if (pkg.alpm_pkg != null) { + if (pkg.name in manager_window.transaction.alpm_config.holdpkg) + val.set_object (manager_window.locked_icon); + else if (pkg.repo == "local") { + if (manager_window.transaction.data.to_add.contains (pkg.name)) + val.set_object (manager_window.to_reinstall_icon); + else if (manager_window.transaction.data.to_remove.contains (pkg.name)) + val.set_object (manager_window.to_remove_icon); + else + val.set_object (manager_window.installed_icon); + } else if (manager_window.transaction.data.to_add.contains (pkg.name)) + val.set_object (manager_window.to_install_icon); + else + val.set_object (manager_window.uninstalled_icon); + } else if (pkg.aur_json != null) { + if (manager_window.transaction.data.to_build.contains (pkg.name)) + val.set_object (manager_window.to_install_icon); + else + val.set_object (manager_window.uninstalled_icon); + } else { + Object? object = null; + val.set_object (object); + } + break; + case 2: + val = Value (typeof (string)); + val.set_string (pkg.version); + break; + case 3: + val = Value (typeof (string)); + val.set_string (pkg.repo); + break; + case 4: + val = Value (typeof (string)); + val.set_string (pkg.size_string); + break; + default: + val = Value (Type.INVALID); + break; + } + } + + public bool get_iter (out Gtk.TreeIter iter, Gtk.TreePath path) {; + if (path.get_depth () != 1 || all_pkgs.length () == 0) { + return invalid_iter (out iter); + } + iter = Gtk.TreeIter (); + int pos = path.get_indices ()[0]; + iter.stamp = pos; + Pamac.Package pkg = all_pkgs.nth_data((uint) pos); + iter.user_data = pkg; + return true; + } + + public int get_n_columns () { + // name, icon, version, repo, isize + return 5; + } + + public Gtk.TreePath? get_path (Gtk.TreeIter iter) { + return new Gtk.TreePath.from_indices (iter.stamp); + } + + public int iter_n_children (Gtk.TreeIter? iter) { + return 0; + } + + public bool iter_next (ref Gtk.TreeIter iter) { + int pos = (iter.stamp) + 1; + if (pos >= all_pkgs.length ()) { + return false; + } + iter.stamp = pos; + Pamac.Package pkg = all_pkgs.nth_data((uint) pos); + iter.user_data = pkg; + return true; + } + + public bool iter_previous (ref Gtk.TreeIter iter) { + int pos = iter.stamp; + if (pos >= 0) { + return false; + } + iter.stamp = (--pos); + Pamac.Package pkg = all_pkgs.nth_data((uint) pos); + iter.user_data = pkg; + return true; + } + + public bool iter_nth_child (out Gtk.TreeIter iter, Gtk.TreeIter? parent, int n) { + return invalid_iter (out iter); + } + + public bool iter_children (out Gtk.TreeIter iter, Gtk.TreeIter? parent) { + return invalid_iter (out iter); + } + + public bool iter_has_child (Gtk.TreeIter iter) { + return false; + } + + public bool iter_parent (out Gtk.TreeIter iter, Gtk.TreeIter child) { + return invalid_iter (out iter); + } + + private bool invalid_iter (out Gtk.TreeIter iter) { + iter = Gtk.TreeIter (); + iter.stamp = -1; + return false; + } + + // custom sort functions + public void sort_by_name (Gtk.SortType order) { + CompareFunc namecmp = (pkg_a, pkg_b) => { + return strcmp (pkg_a.name, pkg_b.name); + }; + all_pkgs.sort (namecmp); + if (order == Gtk.SortType.DESCENDING) + all_pkgs.reverse (); + manager_window.name_column.sort_order = order; + manager_window.state_column.sort_indicator = false; + manager_window.name_column.sort_indicator = true; + manager_window.version_column.sort_indicator = false; + manager_window.repo_column.sort_indicator = false; + manager_window.size_column.sort_indicator = false; + manager_window.sortinfo.column_number = 0; + manager_window.sortinfo.sort_type = order; + } + + public void sort_by_state (Gtk.SortType order) { + CompareFunc statecmp = (pkg_a, pkg_b) => { + int state_a; + int state_b; + if (pkg_a.alpm_pkg != null) { + if (pkg_a.repo == "local") + state_a = 0; + else + state_a = 1; + } else + state_a = 1; + if (pkg_b.alpm_pkg != null) { + if (pkg_b.repo == "local") + state_b = 0; + else + state_b = 1; + } else + state_b = 1; + return (int) (state_a > state_b) - (int) (state_a < state_b); + }; + all_pkgs.sort (statecmp); + if (order == Gtk.SortType.DESCENDING) + all_pkgs.reverse (); + manager_window.state_column.sort_order = order; + manager_window.state_column.sort_indicator = true; + manager_window.name_column.sort_indicator = false; + manager_window.version_column.sort_indicator = false; + manager_window.repo_column.sort_indicator = false; + manager_window.size_column.sort_indicator = false; + manager_window.sortinfo.column_number = 1; + manager_window.sortinfo.sort_type = order; + } + + public void sort_by_version (Gtk.SortType order) { + CompareFunc versioncmp = (pkg_a, pkg_b) => { + return Alpm.pkg_vercmp (pkg_a.version, pkg_b.version); + }; + all_pkgs.sort (versioncmp); + if (order == Gtk.SortType.DESCENDING) + all_pkgs.reverse (); + manager_window.version_column.sort_order = order; + manager_window.state_column.sort_indicator = false; + manager_window.name_column.sort_indicator = false; + manager_window.version_column.sort_indicator = true; + manager_window.repo_column.sort_indicator = false; + manager_window.size_column.sort_indicator = false; + manager_window.sortinfo.column_number = 2; + manager_window.sortinfo.sort_type = order; + } + + public void sort_by_repo (Gtk.SortType order) { + CompareFunc repocmp = (pkg_a, pkg_b) => { + return strcmp (pkg_a.repo, pkg_b.repo); + }; + all_pkgs.sort (repocmp); + if (order == Gtk.SortType.DESCENDING) + all_pkgs.reverse (); + manager_window.repo_column.sort_order = order; + manager_window.state_column.sort_indicator = false; + manager_window.name_column.sort_indicator = false; + manager_window.version_column.sort_indicator = false; + manager_window.repo_column.sort_indicator = true; + manager_window.size_column.sort_indicator = false; + manager_window.sortinfo.column_number = 3; + manager_window.sortinfo.sort_type = order; + } + + public void sort_by_size (Gtk.SortType order) { + CompareFunc sizecmp = (pkg_a, pkg_b) => { + uint64 size_a; + uint64 size_b; + if (pkg_a.alpm_pkg != null) + size_a = pkg_a.size; + else + size_a = 0; + if (pkg_b.alpm_pkg != null) + size_b = pkg_b.size; + else + size_b = 0; + return (int) (size_a > size_b) - (int) (size_a < size_b); + }; + all_pkgs.sort (sizecmp); + if (order == Gtk.SortType.DESCENDING) + all_pkgs.reverse (); + manager_window.size_column.sort_order = order; + manager_window.state_column.sort_indicator = false; + manager_window.name_column.sort_indicator = false; + manager_window.version_column.sort_indicator = false; + manager_window.repo_column.sort_indicator = false; + manager_window.size_column.sort_indicator = true; + manager_window.sortinfo.column_number = 4; + manager_window.sortinfo.sort_type = order; + } + } +} diff --git a/src/pamac_config.vala b/src/pamac_config.vala new file mode 100644 index 0000000..c061d6d --- /dev/null +++ b/src/pamac_config.vala @@ -0,0 +1,133 @@ +/* + * pamac-vala + * + * Copyright (C) 2014 Guillaume Benoit + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a get of the GNU General Public License + * along with this program. If not, see . + */ + +namespace Pamac { + public class Config: Object { + public uint64 refresh_period; + public bool enable_aur; + public bool recurse; + public string conf_path; + + public Config (string path) { + this.conf_path = path; + // set default options + this.refresh_period = 4; + this.enable_aur = false; + this.recurse = false; + // parse conf file + this.parse_include_file (conf_path); + } + + public void parse_include_file (string path) { + var file = GLib.File.new_for_path (path); + if (file.query_exists () == false) + GLib.stderr.printf ("File '%s' doesn't exist.\n", file.get_path ()); + else { + try { + // Open file for reading and wrap returned FileInputStream into a + // DataInputStream, so we can read line by line + var dis = new DataInputStream (file.read ()); + string line; + // Read lines until end of file (null) is reached + while ((line = dis.read_line (null)) != null) { + line = line.strip (); + if (line.length == 0) continue; + if (line[0] == '#') continue; + string[] splitted = line.split ("="); + string _key = splitted[0].strip (); + string _value = null; + if (splitted[1] != null) + _value = splitted[1].strip (); + if (_key == "RefreshPeriod") + this.refresh_period = uint64.parse (_value); + else if (_key == "EnableAUR") + this.enable_aur = true; + else if (_key == "RemoveUnrequiredDeps") + this.recurse = true; + } + } catch (GLib.Error e) { + GLib.stderr.printf("%s\n", e.message); + } + } + } + + public void write (HashTable new_conf) { + var file = GLib.File.new_for_path (this.conf_path); + if (file.query_exists () == false) + GLib.stderr.printf ("File '%s' doesn't exist.\n", file.get_path ()); + else { + try { + // Open file for reading and wrap returned FileInputStream into a + // DataInputStream, so we can read line by line + var dis = new DataInputStream (file.read ()); + string line; + string[] data = {}; + // Read lines until end of file (null) is reached + while ((line = dis.read_line (null)) != null) { + if (line.contains ("RefreshPeriod")) { + if (new_conf.contains ("RefreshPeriod")) { + string _value = new_conf.get ("RefreshPeriod"); + data += "RefreshPeriod = %s\n".printf (_value); + this.refresh_period = uint64.parse (_value); + } else + data += line + "\n"; + } else if (line.contains ("EnableAUR")) { + if (new_conf.contains ("EnableAUR")) { + bool _value = bool.parse (new_conf.get ("EnableAUR")); + if (_value == true) + data += "EnableAUR\n"; + else + data += "#EnableAUR\n"; + this.enable_aur = _value; + } else + data += line + "\n"; + } else if (line.contains ("RemoveUnrequiredDeps")) { + if (new_conf.contains ("RemoveUnrequiredDeps")) { + bool _value = bool.parse (new_conf.get ("RemoveUnrequiredDeps")); + if (_value == true) + data += "RemoveUnrequiredDeps\n"; + else + data += "#RemoveUnrequiredDeps\n"; + this.enable_aur = _value; + } else + data += line + "\n"; + } else + data += line + "\n"; + } + // delete the file before rewrite it + file.delete (); + // creating a DataOutputStream to the file + var dos = new DataOutputStream (file.create (FileCreateFlags.REPLACE_DESTINATION)); + foreach (string new_line in data) { + // writing a short string to the stream + dos.put_string (new_line); + } + } catch (GLib.Error e) { + GLib.stderr.printf("%s\n", e.message); + } + } + } + + public void reload () { + this.enable_aur = false; + this.recurse = false; + this.parse_include_file (this.conf_path); + } + } +} diff --git a/src/preferences_dialog.vala b/src/preferences_dialog.vala new file mode 100644 index 0000000..0dc4e12 --- /dev/null +++ b/src/preferences_dialog.vala @@ -0,0 +1,40 @@ +/* + * pamac-vala + * + * Copyright (C) 2014 Guillaume Benoit + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a get of the GNU General Public License + * along with this program. If not, see . + */ + +namespace Pamac { + + [GtkTemplate (ui = "/org/manjaro/pamac/preferences/preferences_dialog.ui")] + public class PreferencesDialog : Gtk.Dialog { + + [GtkChild] + public Gtk.Switch enable_aur_button; + [GtkChild] + public Gtk.Switch remove_unrequired_deps_button; + [GtkChild] + public Gtk.SpinButton refresh_period_spin_button; + [GtkChild] + public Gtk.Label refresh_period_label; + + public PreferencesDialog (Gtk.ApplicationWindow window) { + Object (transient_for: window, use_header_bar: 0); + + refresh_period_label.set_markup (dgettext (null, "How often to check for updates, value in hours") +":"); + } + } +} diff --git a/src/progress_window.vala b/src/progress_window.vala new file mode 100644 index 0000000..6068737 --- /dev/null +++ b/src/progress_window.vala @@ -0,0 +1,61 @@ +/* + * pamac-vala + * + * Copyright (C) 2014 Guillaume Benoit + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a get of the GNU General Public License + * along with this program. If not, see . + */ + +namespace Pamac { + + [GtkTemplate (ui = "/org/manjaro/pamac/transaction/progress_window.ui")] + public class ProgressWindow : Gtk.Window { + + [GtkChild] + public Gtk.ProgressBar progressbar; + [GtkChild] + public Gtk.Label action_label; + [GtkChild] + public Gtk.Button cancel_button; + [GtkChild] + public Gtk.Button close_button; + [GtkChild] + public Gtk.Expander expander; + + Transaction transaction; + + public ProgressWindow (Transaction transaction, Gtk.ApplicationWindow? window) { + Object (transient_for: window); + + this.transaction = transaction; + } + + [GtkCallback] + public void on_close_button_clicked () { + this.hide (); + while (Gtk.events_pending ()) + Gtk.main_iteration (); + } + + [GtkCallback] + public void on_cancel_button_clicked () { + transaction.cancel (); + transaction.clear_lists (); + transaction.finished (false); + this.hide (); + while (Gtk.events_pending ()) + Gtk.main_iteration (); + } + } +} diff --git a/src/transaction.vala b/src/transaction.vala new file mode 100644 index 0000000..13d724e --- /dev/null +++ b/src/transaction.vala @@ -0,0 +1,899 @@ +/* + * pamac-vala + * + * Copyright (C) 2014 Guillaume Benoit + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a get of the GNU General Public License + * along with this program. If not, see . + */ + +using Gtk; +using Vte; +using Alpm; + +namespace Pamac { + [DBus (name = "org.manjaro.pamac")] + public interface Daemon : Object { + public abstract void write_config (HashTable new_conf) throws IOError; + public abstract async void refresh (int force, bool emit_signal) throws IOError; + public abstract ErrorInfos trans_init (TransFlag transflags) throws IOError; + public abstract ErrorInfos trans_sysupgrade (int enable_downgrade) throws IOError; + public abstract ErrorInfos trans_add_pkg (string pkgname) throws IOError; + public abstract ErrorInfos trans_remove_pkg (string pkgname) throws IOError; + public abstract ErrorInfos trans_load_pkg (string pkgpath) throws IOError; + public abstract async void trans_prepare () throws IOError; + public abstract void choose_provider (int provider) throws IOError; + public abstract UpdatesInfos[] trans_to_add () throws IOError; + public abstract UpdatesInfos[] trans_to_remove () throws IOError; + public abstract async void trans_commit () throws IOError; + public abstract void trans_release () throws IOError; + public abstract void trans_cancel () throws IOError; + [DBus (no_reply = true)] + public abstract void quit () throws IOError; + public signal void emit_event (uint event, string msg); + public signal void emit_providers (string depend, string[] providers); + public signal void emit_progress (uint progress, string action, string pkgname, int percent, uint n_targets, uint current_target); + public signal void emit_download (string filename, uint64 xfered, uint64 total); + public signal void emit_totaldownload (uint64 total); + public signal void emit_log (uint level, string msg); + public signal void emit_refreshed (ErrorInfos error); + public signal void emit_trans_prepared (ErrorInfos error); + public signal void emit_trans_committed (ErrorInfos error); + } + + public class Transaction: Object { + public Daemon daemon; + + public Alpm.Config alpm_config; + public Pamac.Config pamac_config; + + public TransactionData data; + public Mode mode; + + uint64 total_download; + uint64 already_downloaded; + string previous_label; + string previous_textbar; + double previous_percent; + string previous_filename; + uint build_timeout_id; + bool sysupgrade_after_trans; + bool sysupgrade_after_build; + + Terminal term; + + //dialogs + ChooseProviderDialog choose_provider_dialog; + TransactionSumDialog transaction_sum_dialog; + TransactionInfoDialog transaction_info_dialog; + ProgressWindow progress_window; + //parent window + ApplicationWindow? window; + + public signal void finished (bool error); + + public Transaction (ApplicationWindow? window, Pamac.Config pamac_config) { + alpm_config = new Alpm.Config ("/etc/pacman.conf"); + this.pamac_config = pamac_config; + mode = Mode.MANAGER; + data = TransactionData (); + data.flags = Alpm.TransFlag.CASCADE; + data.to_add = new HashTable (str_hash, str_equal); + data.to_remove = new HashTable (str_hash, str_equal); + data.to_load = new HashTable (str_hash, str_equal); + data.to_build = new HashTable (str_hash, str_equal); + connecting_dbus_signals (); + //creating dialogs + this.window = window; + choose_provider_dialog = new ChooseProviderDialog (window); + transaction_sum_dialog = new TransactionSumDialog (window); + transaction_info_dialog = new TransactionInfoDialog (window); + progress_window = new ProgressWindow (this, window); + //creating terminal + term = new Terminal (); + term.scroll_on_output = false; + term.expand = true; + term.height_request = 200; + term.set_visible (true); + // add term in a grid with a scrollbar + var grid = new Grid (); + grid.expand = true; + grid.set_visible (true); + var sb = new Scrollbar (Orientation.VERTICAL, term.vadjustment); + sb.set_visible (true); + grid.attach (term, 0, 0, 1, 1); + grid.attach (sb, 1, 0, 1, 1); + progress_window.expander.add (grid); + // progress data + total_download = 0; + already_downloaded = 0; + previous_label = ""; + previous_textbar = ""; + previous_percent = 0.0; + previous_filename = ""; + sysupgrade_after_trans = false; + sysupgrade_after_build = false; + } + + public void write_config (HashTable new_conf) { + try { + daemon.write_config (new_conf); + } catch (IOError e) { + stderr.printf ("IOError: %s\n", e.message); + } + } + + public void refresh_alpm_config () { + alpm_config = new Alpm.Config ("/etc/pacman.conf"); + } + + public void refresh (int force) { + string action = dgettext ("pacman", "Synchronizing package databases...\n").replace ("\n", ""); + try { + term.reset (true, true); + term.spawn_sync (PtyFlags.DEFAULT, "~/", {"/usr/bin/echo", action}, {}, SpawnFlags.DO_NOT_REAP_CHILD, null, null); + } catch (Error e) { + stderr.printf ("Error: %s\n", e.message); + } + progress_window.action_label.set_text (action); + progress_window.progressbar.set_fraction (0); + progress_window.progressbar.set_text (""); + progress_window.cancel_button.visible = true; + progress_window.close_button.visible = false; + progress_window.show (); + daemon.refresh.begin (force, true, (obj, res) => { + try { + daemon.refresh.end (res); + } catch (IOError e) { + stderr.printf ("IOError: %s\n", e.message); + } + }); + } + + public void sysupgrade_simple (int enable_downgrade) { + print("simple sysupgrade\n"); + progress_window.progressbar.set_fraction (0); + progress_window.cancel_button.visible = true; + ErrorInfos err = ErrorInfos (); + try { + err = daemon.trans_init (0); + } catch (IOError e) { + stderr.printf ("IOError: %s\n", e.message); + } + if (err.str != "") { + finished (true); + handle_error (err); + } else { + try { + err = daemon.trans_sysupgrade (enable_downgrade); + } catch (IOError e) { + stderr.printf ("IOError: %s\n", e.message); + } + if (err.str == "") { + progress_window.show (); + while (Gtk.events_pending ()) + Gtk.main_iteration (); + daemon.trans_prepare.begin ((obj, res) => { + try { + daemon.trans_prepare.end (res); + } catch (IOError e) { + stderr.printf ("IOError: %s\n", e.message); + } + }); + } else { + release (); + finished (true); + handle_error (err); + } + } + } + + public void sysupgrade (int enable_downgrade) { + string action = dgettext ("pacman", "Starting full system upgrade...\n").replace ("\n", ""); + try { + term.spawn_sync (PtyFlags.DEFAULT, "~/", {"/usr/bin/echo", action}, {}, SpawnFlags.DO_NOT_REAP_CHILD, null, null); + } catch (Error e) { + stderr.printf ("Error: %s\n", e.message); + } + progress_window.action_label.set_text (action); + progress_window.progressbar.set_fraction (0); + progress_window.progressbar.set_text (""); + progress_window.cancel_button.visible = true; + progress_window.close_button.visible = false; + while (Gtk.events_pending ()) + Gtk.main_iteration (); + // sysupgrade + print("get syncfirst\n"); + // get syncfirst updates + UpdatesInfos[] syncfirst_updates = get_syncfirst_updates (alpm_config); + if (syncfirst_updates.length != 0) { + clear_lists (); + if (mode == Mode.MANAGER) + sysupgrade_after_trans = true; + foreach (UpdatesInfos infos in syncfirst_updates) + data.to_add.insert (infos.name, infos.name); + // run as a standard transaction + run (); + } else { + if (pamac_config.enable_aur) { + print("get aur updates\n"); + string[] ignore_pkgs = get_ignore_pkgs (alpm_config); + UpdatesInfos[] aur_updates = get_aur_updates (alpm_config, ignore_pkgs); + if (aur_updates.length != 0) { + clear_lists (); + sysupgrade_after_build = true; + foreach (UpdatesInfos infos in aur_updates) + data.to_build.insert (infos.name, infos.name); + } + } + sysupgrade_simple (enable_downgrade); + } + } + + public void clear_lists () { + data.to_add.steal_all (); + data.to_remove.steal_all (); + data.to_build.steal_all (); + } + + public void run () { + string action = dgettext (null,"Preparing") + "..."; + try { + term.reset (true, true); + term.spawn_sync (PtyFlags.DEFAULT, "~/", {"/usr/bin/echo", action}, {}, SpawnFlags.DO_NOT_REAP_CHILD, null, null); + } catch (Error e) { + stderr.printf ("Error: %s\n", e.message); + } + progress_window.action_label.set_text (action); + progress_window.progressbar.set_fraction (0); + progress_window.progressbar.set_text (""); + progress_window.cancel_button.visible = true; + progress_window.close_button.visible = false; + progress_window.show (); + while (Gtk.events_pending ()) + Gtk.main_iteration (); + // run + ErrorInfos err = ErrorInfos (); + if (data.to_add.size () == 0 + && data.to_remove.size () == 0 + && data.to_load.size () == 0 + && data.to_build.size () != 0) { + // there only AUR packages to build so no need to prepare transaction + on_emit_trans_prepared (err); + } else { + try { + err = daemon.trans_init (data.flags); + } catch (IOError e) { + stderr.printf ("IOError: %s\n", e.message); + } + if (err.str != "") { + finished (true); + handle_error (err); + } else { + foreach (string name in data.to_add.get_keys ()) { + try { + err = daemon.trans_add_pkg (name); + } catch (IOError e) { + stderr.printf ("IOError: %s\n", e.message); + } + if (err.str != "") + break; + } + foreach (string name in data.to_remove.get_keys ()) { + try { + err = daemon.trans_remove_pkg (name); + } catch (IOError e) { + stderr.printf ("IOError: %s\n", e.message); + } + if (err.str != "") + break; + } + foreach (string path in data.to_load.get_keys ()) { + try { + err = daemon.trans_load_pkg (path); + } catch (IOError e) { + stderr.printf ("IOError: %s\n", e.message); + } + if (err.str != "") + break; + } + if (err.str == "") { + daemon.trans_prepare.begin ((obj, res) => { + try { + daemon.trans_prepare.end (res); + } catch (IOError e) { + stderr.printf ("IOError: %s\n", e.message); + } + }); + } else { + release (); + finished (true); + handle_error (err); + } + } + } + } + + public void choose_provider (string depend, string[] providers) { + int len = providers.length; + choose_provider_dialog.label.set_markup ("%s".printf (dgettext (null, "Choose a provider for %s:").printf (depend, len))); + choose_provider_dialog.comboboxtext.remove_all (); + foreach (string provider in providers) + choose_provider_dialog.comboboxtext.append_text (provider); + choose_provider_dialog.comboboxtext.active = 0; + choose_provider_dialog.run (); + choose_provider_dialog.hide (); + while (Gtk.events_pending ()) + Gtk.main_iteration (); + try { + daemon.choose_provider (choose_provider_dialog.comboboxtext.active); + } catch (IOError e) { + stderr.printf ("IOError: %s\n", e.message); + } + } + + public int set_transaction_sum () { + // return 1 if transaction_sum is empty, 0 otherwise + int ret = 1; + uint64 dsize = 0; + UpdatesInfos[] prepared_to_add = {}; + UpdatesInfos[] prepared_to_remove = {}; + string[] to_downgrade = {}; + string[] to_install = {}; + string[] to_reinstall = {}; + string[] to_update = {}; + string[] to_build = {}; + TreeIter iter; + transaction_sum_dialog.top_label.set_markup ("%s".printf (dgettext (null, "Transaction Summary"))); + transaction_sum_dialog.sum_list.clear (); + try { + prepared_to_add = daemon.trans_to_add (); + prepared_to_remove = daemon.trans_to_remove (); + } catch (IOError e) { + stderr.printf ("IOError: %s\n", e.message); + } + foreach (UpdatesInfos pkg_info in prepared_to_add) { + dsize += pkg_info.download_size; + unowned Alpm.Package? local_pkg = alpm_config.handle.localdb.get_pkg (pkg_info.name); + if (local_pkg == null) { + to_install += "%s %s".printf (pkg_info.name, pkg_info.version); + } else { + int cmp = pkg_vercmp (pkg_info.version, local_pkg.version); + if (cmp == 1) + to_update += "%s %s".printf (pkg_info.name, pkg_info.version); + else if (cmp == 0) + to_reinstall += "%s %s".printf (pkg_info.name, pkg_info.version); + else + to_downgrade += "%s %s".printf (pkg_info.name, pkg_info.version); + } + } + foreach (string name in data.to_build.get_keys ()) + to_build += name; + int len = prepared_to_remove.length; + int i; + if (len != 0) { + ret = 0; + transaction_sum_dialog.sum_list.insert_with_values (out iter, -1, + 0, dgettext (null, "To remove") + ":", + 1, "%s %s".printf (prepared_to_remove[0].name, prepared_to_remove[0].version)); + i = 1; + while (i < len) { + transaction_sum_dialog.sum_list.insert_with_values (out iter, -1, + 1, "%s %s".printf (prepared_to_remove[i].name, prepared_to_remove[i].version)); + i++; + } + } + len = to_downgrade.length; + if (len != 0) { + ret = 0; + transaction_sum_dialog.sum_list.insert_with_values (out iter, -1, + 0, dgettext (null, "To downgrade") + ":", + 1, to_downgrade[0]); + i = 1; + while (i < len) { + transaction_sum_dialog.sum_list.insert_with_values (out iter, -1, + 1, to_downgrade[i]); + i++; + } + } + len = to_build.length; + if (len != 0) { + ret = 0; + transaction_sum_dialog.sum_list.insert_with_values (out iter, -1, + 0, dgettext (null, "To build") + ":", + 1, to_build[0]); + i = 1; + while (i < len) { + transaction_sum_dialog.sum_list.insert_with_values (out iter, -1, + 1, to_build[i]); + i++; + } + } + len = to_install.length; + if (len != 0) { + ret = 0; + transaction_sum_dialog.sum_list.insert_with_values (out iter, -1, + 0, dgettext (null, "To install") + ":", + 1, to_install[0]); + i = 1; + while (i < len) { + transaction_sum_dialog.sum_list.insert_with_values (out iter, -1, + 1, to_install[i]); + i++; + } + } + len = to_reinstall.length; + if (len != 0) { + ret = 0; + transaction_sum_dialog.sum_list.insert_with_values (out iter, -1, + 0, dgettext (null, "To reinstall") + ":", + 1, to_reinstall[0]); + i = 1; + while (i < len) { + transaction_sum_dialog.sum_list.insert_with_values (out iter, -1, + 1, to_reinstall[i]); + i++; + } + } + if (mode == Mode.MANAGER) { + len = to_update.length; + if (len != 0) { + ret = 0; + transaction_sum_dialog.sum_list.insert_with_values (out iter, -1, + 0, dgettext (null, "To update") + ":", + 1, to_update[0]); + i = 1; + while (i < len) { + transaction_sum_dialog.sum_list.insert_with_values (out iter, -1, + 1, to_update[i]); + i++; + } + } + } + if (dsize == 0) + transaction_sum_dialog.bottom_label.set_visible (false); + else { + transaction_sum_dialog.bottom_label.set_markup ("%s %s".printf (dgettext (null, "Total download size:"), format_size (dsize))); + transaction_sum_dialog.bottom_label.set_visible (true); + } + return ret; + } + + public void commit () { + progress_window.cancel_button.visible = false; + daemon.trans_commit.begin ((obj, res) => { + try { + daemon.trans_commit.end (res); + } catch (IOError e) { + stderr.printf ("IOError: %s\n", e.message); + } + }); + } + + public void build_aur_packages () { + string[] cmds = {"/usr/bin/yaourt", "-S"}; + foreach (string name in data.to_build.get_keys ()) + cmds += name; + string action = dgettext (null,"Building packages") + "..."; + try { + term.reset (true, true); + term.spawn_sync (PtyFlags.DEFAULT, "~/", {"/usr/bin/echo", action}, {}, SpawnFlags.DO_NOT_REAP_CHILD, null, null); + } catch (Error e) { + stderr.printf ("Error: %s\n", e.message); + } + progress_window.action_label.set_text (action); + progress_window.progressbar.set_fraction (0); + progress_window.progressbar.set_text (""); + progress_window.cancel_button.visible = false; + progress_window.close_button.visible = false; + progress_window.expander.set_expanded (true); + progress_window.width_request = 700; + term.child_exited.connect (on_term_child_exited); + term.grab_focus (); + build_timeout_id = Timeout.add (500, (GLib.SourceFunc) progress_window.progressbar.pulse); + try { + Pid child_pid; + term.spawn_sync (PtyFlags.DEFAULT, "~/", cmds, {}, SpawnFlags.DO_NOT_REAP_CHILD, null, out child_pid); + //term.watch_child (child_pid); + } catch (Error e) { + stderr.printf ("Error: %s\n", e.message); + } + } + + public void cancel () { + try { + daemon.trans_cancel (); + } catch (IOError e) { + stderr.printf ("IOError: %s\n", e.message); + } + } + + public void release () { + try { + daemon.trans_release (); + } catch (IOError e) { + stderr.printf ("IOError: %s\n", e.message); + } + } + + public void stop_daemon () { + try { + daemon.quit (); + } catch (IOError e) { + stderr.printf ("IOError: %s\n", e.message); + } + } + + void on_emit_event (uint event, string msg) { + switch (event) { + case Event.CHECKDEPS_START: + break; + case Event.FILECONFLICTS_START: + break; + case Event.RESOLVEDEPS_START: + break; + case Event.INTERCONFLICTS_START: + break; + case Event.ADD_START: + progress_window.cancel_button.visible = false; + break; + case Event.ADD_DONE: + break; + case Event.REMOVE_START: + progress_window.cancel_button.visible = false; + break; + case Event.REMOVE_DONE: + break; + case Event.UPGRADE_START: + break; + case Event.UPGRADE_DONE: + break; + case Event.DOWNGRADE_START: + break; + case Event.DOWNGRADE_DONE: + break; + case Event.REINSTALL_START: + break; + case Event.REINSTALL_DONE: + break; + case Event.INTEGRITY_START: + break; + case Event.KEYRING_START: + break; + //~ case Event.KEY_DOWNLOAD_START: + //~ break; + case Event.LOAD_START: + break; + //~ case Event.DELTA_INTEGRITY_START: + //~ break; + //~ case Event.DELTA_PATCHES_START: + //~ break; + //~ case Event.DELTA_PATCH_START: + //~ break; + //~ case Event.DELTA_PATCH_DONE: + //~ break; + //~ case Event.DELTA_PATCH_FAILED: + //~ break; + case Event.SCRIPTLET_INFO: + progress_window.expander.set_expanded (true); + break; + case Event.RETRIEVE_START: + progress_window.action_label.set_text (msg.replace ("\n", "")); + break; + case Event.DISKSPACE_START: + break; + //~ case Event.OPTDEP_REQUIRED: + //~ break; + //~ case Event.DATABASE_MISSING: + //~ break; + case Event.FILECONFLICTS_DONE: + case Event.CHECKDEPS_DONE: + case Event.RESOLVEDEPS_DONE: + case Event.INTERCONFLICTS_DONE: + case Event.INTEGRITY_DONE: + case Event.KEYRING_DONE: + case Event.KEY_DOWNLOAD_DONE: + case Event.LOAD_DONE: + case Event.DELTA_INTEGRITY_DONE: + case Event.DELTA_PATCHES_DONE: + case Event.DISKSPACE_DONE: + break; + default: + break; + } + try { + term.spawn_sync (PtyFlags.DEFAULT, "~/", {"/usr/bin/echo", "-n", msg}, {}, SpawnFlags.DO_NOT_REAP_CHILD, null, null); + } catch (Error e) { + stderr.printf ("Error: %s\n", e.message); + } + } + + void on_emit_providers (string depend, string[] providers) { + choose_provider (depend, providers); + } + + void on_emit_progress (uint progress, string action, string pkgname, int percent, uint n_targets, uint current_target) { + double fraction; + switch (progress) { + case Progress.ADD_START: + case Progress.UPGRADE_START: + case Progress.DOWNGRADE_START: + case Progress.REINSTALL_START: + case Progress.REMOVE_START: + fraction = ((float) (current_target-1)/n_targets)+((float) percent/(100*n_targets)); + break; + case Progress.CONFLICTS_START: + case Progress.DISKSPACE_START: + case Progress.INTEGRITY_START: + case Progress.KEYRING_START: + case Progress.LOAD_START: + default: + fraction = (float) percent/100; + break; + } + string label; + if (pkgname != "") + label = "%s %s...".printf (action, pkgname); + else + label = "%s...".printf (action); + if (label != previous_label) { + previous_label = label; + progress_window.action_label.set_text (label); + } + string textbar = "%lu/%lu".printf (current_target, n_targets); + if (textbar != previous_textbar) { + previous_textbar = textbar; + progress_window.progressbar.set_text (textbar); + } + if (fraction != previous_percent) { + previous_percent = fraction; + progress_window.progressbar.set_fraction (fraction); + } + while (Gtk.events_pending ()) + Gtk.main_iteration (); + } + + void on_emit_download (string filename, uint64 xfered, uint64 total) { + string label; + string textbar; + double fraction; + if (filename != previous_filename) { + previous_filename = filename; + if (filename.has_suffix (".db")) { + label = dgettext (null, "Refreshing {repo}").replace ("{repo}", filename.replace (".db", "")) + "..."; + } else { + label = dgettext (null, "Downloading {pkgname}").replace ("{pkgname}", filename.replace (".pkg.tar.xz", "")) + "..."; + } + if (label != previous_label) { + previous_label = label; + progress_window.action_label.set_text (label); + try { + term.spawn_sync (PtyFlags.DEFAULT, "~/", {"/usr/bin/echo", label}, {}, SpawnFlags.DO_NOT_REAP_CHILD, null, null); + } catch (Error e) { + stderr.printf ("Error: %s\n", e.message); + } + } + } + if (total_download > 0) { + fraction = (float) (xfered + already_downloaded) / total_download; + textbar = "%s/%s".printf (format_size (xfered + already_downloaded), format_size (total_download)); + } else { + fraction = (float) xfered / total; + textbar = "%s/%s".printf (format_size (xfered), format_size (total)); + } + if (fraction != previous_percent) { + previous_percent = fraction; + progress_window.progressbar.set_fraction (fraction); + } + + if (textbar != previous_textbar) { + previous_textbar = textbar; + progress_window.progressbar.set_text (textbar); + } + if (xfered == total) + already_downloaded += total; + } + + void on_emit_totaldownload (uint64 total) { + total_download = total; + } + + void on_emit_log (uint level, string msg) { + // msg ends with \n + string? line = null; + TextIter end_iter; + if ((Alpm.LogLevel) level == Alpm.LogLevel.WARNING) { + line = dgettext (null, "Warning") + ": " + msg; + transaction_info_dialog.textbuffer.get_end_iter (out end_iter); + transaction_info_dialog.textbuffer.insert (ref end_iter, msg, msg.length); + } else if ((Alpm.LogLevel) level == Alpm.LogLevel.ERROR) { + line = dgettext (null, "Error") + ": " + msg; + } + if (line != null) { + progress_window.expander.set_expanded (true); + try { + term.spawn_sync (PtyFlags.DEFAULT, "~/", {"/usr/bin/echo", "-n", line}, {}, SpawnFlags.DO_NOT_REAP_CHILD, null, null); + } catch (Error e) { + stderr.printf ("Error: %s\n", e.message); + } + } + } + + public void handle_warning () { + if (transaction_info_dialog.textbuffer.text != "") { + transaction_info_dialog.set_title (dgettext (null, "Warning")); + transaction_info_dialog.label.set_visible (false); + transaction_info_dialog.expander.set_visible (true); + transaction_info_dialog.expander.set_expanded (true); + transaction_info_dialog.run (); + transaction_info_dialog.hide (); + TextIter start_iter; + TextIter end_iter; + transaction_info_dialog.textbuffer.get_start_iter (out start_iter); + transaction_info_dialog.textbuffer.get_end_iter (out end_iter); + transaction_info_dialog.textbuffer.delete (ref start_iter, ref end_iter); + } + } + + public void handle_error (ErrorInfos error) { + TextIter start_iter; + TextIter end_iter; + transaction_info_dialog.set_title (dgettext (null, "Error")); + transaction_info_dialog.label.set_visible (true); + transaction_info_dialog.label.set_markup (error.str.replace ("\n", "")); + transaction_info_dialog.textbuffer.get_start_iter (out start_iter); + transaction_info_dialog.textbuffer.get_end_iter (out end_iter); + transaction_info_dialog.textbuffer.delete (ref start_iter, ref end_iter); + if (error.details.length != 0) { + foreach (string detail in error.details) { + transaction_info_dialog.textbuffer.get_end_iter (out end_iter); + transaction_info_dialog.textbuffer.insert (ref end_iter, detail, detail.length); + } + transaction_info_dialog.expander.set_visible (true); + } else + transaction_info_dialog.expander.set_visible (false); + transaction_info_dialog.run (); + transaction_info_dialog.hide (); + progress_window.hide (); + while (Gtk.events_pending ()) + Gtk.main_iteration (); + } + + public void on_emit_refreshed (ErrorInfos error) { + print("transaction refreshed\n"); + refresh_alpm_config (); + if (error.str == "") { + if (mode == Mode.UPDATER) { + progress_window.hide (); + finished (false); + } else { + sysupgrade (0); + } + } else { + handle_error (error); + finished (true); + } + } + + public void on_emit_trans_prepared (ErrorInfos error) { + print ("transaction prepared\n"); + if (error.str == "") { + handle_warning (); + int ret = set_transaction_sum (); + if (ret == 0) { + if (data.to_add.size () == 0 + && data.to_remove.size () == 0 + && data.to_load.size () == 0 + && data.to_build.size () != 0) { + // there only AUR packages to build or we update AUR packages first + release (); + if (transaction_sum_dialog.run () == ResponseType.OK) { + transaction_sum_dialog.hide (); + while (Gtk.events_pending ()) + Gtk.main_iteration (); + ErrorInfos err = ErrorInfos (); + on_emit_trans_committed (err); + } else { + progress_window.hide (); + transaction_sum_dialog.hide (); + finished (true); + } + } else if (sysupgrade_after_build) { + print("sysupgrade_after_build\n"); + sysupgrade_after_build = false; + commit (); + } else if (transaction_sum_dialog.run () == ResponseType.OK) { + transaction_sum_dialog.hide (); + while (Gtk.events_pending ()) + Gtk.main_iteration (); + commit (); + } else { + progress_window.hide (); + transaction_sum_dialog.hide (); + release (); + finished (true); + } + } else if (mode == Mode.UPDATER) { + commit (); + } else { + //ErrorInfos err = ErrorInfos (); + //err.str = dgettext (null, "Nothing to do") + "\n"; + progress_window.hide (); + release (); + clear_lists (); + finished (false); + //handle_error (err); + } + } else { + finished (true); + handle_error (error); + } + } + + public void on_emit_trans_committed (ErrorInfos error) { + print("transaction committed\n"); + term.child_exited.disconnect (on_term_child_exited); + if (error.str == "") { + if (data.to_build.size () != 0) { + build_aur_packages (); + } else { + //progress_window.action_label.set_text (dgettext (null, "Transaction successfully finished")); + //progress_window.close_button.set_visible (true); + clear_lists (); + handle_warning (); + refresh_alpm_config (); + if (sysupgrade_after_trans) { + sysupgrade_after_trans = false; + sysupgrade (0); + } else if (sysupgrade_after_build) { + sysupgrade_simple (0); + } else { + progress_window.hide (); + finished (false); + } + } + } else { + finished (true); + handle_error (error); + } + total_download = 0; + already_downloaded = 0; + } + + void on_term_child_exited (int status) { + Source.remove (build_timeout_id); + data.to_build.steal_all (); + ErrorInfos err = ErrorInfos (); + on_emit_trans_committed (err); + } + + void connecting_dbus_signals () { + try { + daemon = Bus.get_proxy_sync (BusType.SYSTEM, "org.manjaro.pamac", + "/org/manjaro/pamac"); + // Connecting to signals + daemon.emit_event.connect (on_emit_event); + daemon.emit_providers.connect (on_emit_providers); + daemon.emit_progress.connect (on_emit_progress); + daemon.emit_download.connect (on_emit_download); + daemon.emit_totaldownload.connect (on_emit_totaldownload); + daemon.emit_log.connect (on_emit_log); + daemon.emit_refreshed.connect (on_emit_refreshed); + daemon.emit_trans_prepared.connect (on_emit_trans_prepared); + daemon.emit_trans_committed.connect (on_emit_trans_committed); + } catch (IOError e) { + stderr.printf ("IOError: %s\n", e.message); + } + } + } +} diff --git a/src/transaction_info_dialog.vala b/src/transaction_info_dialog.vala new file mode 100644 index 0000000..74f3c14 --- /dev/null +++ b/src/transaction_info_dialog.vala @@ -0,0 +1,40 @@ +/* + * pamac-vala + * + * Copyright (C) 2014 Guillaume Benoit + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a get of the GNU General Public License + * along with this program. If not, see . + */ + +namespace Pamac { + + [GtkTemplate (ui = "/org/manjaro/pamac/transaction/transaction_info_dialog.ui")] + public class TransactionInfoDialog : Gtk.Dialog { + + [GtkChild] + public Gtk.Label label; + [GtkChild] + public Gtk.Expander expander; + [GtkChild] + public Gtk.TextView textview; + + public Gtk.TextBuffer textbuffer; + + public TransactionInfoDialog (Gtk.ApplicationWindow? window) { + Object (transient_for: window, use_header_bar: 0); + + textbuffer = textview.get_buffer (); + } + } +} diff --git a/src/transaction_sum_dialog.vala b/src/transaction_sum_dialog.vala new file mode 100644 index 0000000..7dd5c69 --- /dev/null +++ b/src/transaction_sum_dialog.vala @@ -0,0 +1,41 @@ +/* + * pamac-vala + * + * Copyright (C) 2014 Guillaume Benoit + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a get of the GNU General Public License + * along with this program. If not, see . + */ + +namespace Pamac { + + [GtkTemplate (ui = "/org/manjaro/pamac/transaction/transaction_sum_dialog.ui")] + public class TransactionSumDialog : Gtk.Dialog { + + [GtkChild] + public Gtk.Label top_label; + [GtkChild] + public Gtk.Label bottom_label; + [GtkChild] + public Gtk.TreeView treeview; + + public Gtk.ListStore sum_list; + + public TransactionSumDialog (Gtk.ApplicationWindow? window) { + Object (transient_for: window, use_header_bar: 0); + + sum_list = new Gtk.ListStore (2, typeof (string), typeof (string)); + treeview.set_model (sum_list); + } + } +} diff --git a/src/tray.vala b/src/tray.vala new file mode 100644 index 0000000..0dc489d --- /dev/null +++ b/src/tray.vala @@ -0,0 +1,256 @@ +/* + * pamac-vala + * + * Copyright (C) 2014 Guillaume Benoit + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a get of the GNU General Public License + * along with this program. If not, see . + */ + +// i18n +const string GETTEXT_PACKAGE = "pamac"; + +const string update_icon_name = "pamac-tray-update"; +const string update_info = _("{number} available updates"); +const string one_update_info = _("1 available update"); +const string noupdate_icon_name = "pamac-tray-no-update"; +const string noupdate_info = _("Your system is up-to-date"); + +namespace Pamac { + [DBus (name = "org.manjaro.pamac")] + public interface Daemon : Object { + public abstract async void refresh (int force, bool emit_signal) throws IOError; + public abstract UpdatesInfos[] get_updates () throws IOError; + [DBus (no_reply = true)] + public abstract void quit () throws IOError; + } + + public class TrayIcon: Gtk.Application { + Notify.Notification notification; + Daemon daemon; + Pamac.Config pamac_config; + bool locked; + uint refresh_timeout_id; + Gtk.StatusIcon status_icon; + Gtk.Menu menu; + + public TrayIcon () { + application_id = "org.manjaro.pamac.tray"; + flags = ApplicationFlags.FLAGS_NONE; + } + + void start_daemon () { + try { + daemon = Bus.get_proxy_sync (BusType.SYSTEM, "org.manjaro.pamac", + "/org/manjaro/pamac"); + } catch (IOError e) { + stderr.printf ("IOError: %s\n", e.message); + } + } + + void stop_daemon () { + try { + daemon.quit (); + } catch (IOError e) { + stderr.printf ("IOError: %s\n", e.message); + } + } + + // Create menu for right button + void create_menu () { + menu = new Gtk.Menu (); + Gtk.MenuItem item; + item = new Gtk.MenuItem.with_label (_("Update Manager")); + item.activate.connect (execute_updater); + menu.append (item); + item = new Gtk.MenuItem.with_label (_("Package Manager")); + item.activate.connect (execute_manager); + menu.append (item); + item = new Gtk.MenuItem.with_label (_("Quit")); + item.activate.connect (this.release); + menu.append (item); + menu.show_all (); + } + + // Show popup menu on right button + void menu_popup (uint button, uint time) { + menu.popup (null, null, null, button, time); + } + + void left_clicked () { + if (status_icon.icon_name == "pamac-tray-update") + execute_updater (); + } + + void execute_updater () { + try { + Process.spawn_async(null, new string[]{"/usr/bin/pamac-updater"}, null, SpawnFlags.SEARCH_PATH, null, null); + } catch (Error e) { + print(e.message); + } + } + + void execute_manager () { + try { + Process.spawn_async(null, new string[]{"/usr/bin/pamac-manager"}, null, SpawnFlags.SEARCH_PATH, null, null); + } catch (Error e) { + print(e.message); + } + } + + public void update_icon (string icon, string info) { + status_icon.set_from_icon_name (icon); + status_icon.set_tooltip_markup (info); + } + + bool refresh () { + start_daemon (); + daemon.refresh.begin (1, false, (obj, res) => { + try { + daemon.refresh.end (res); + } catch (IOError e) { + stderr.printf ("IOError: %s\n", e.message); + } + }); + return true; + } + + void check_updates () { + UpdatesInfos[] updates = {}; + bool pamac_run = check_pamac_running (); + try { + updates = daemon.get_updates (); + } catch (IOError e) { + stderr.printf ("IOError: %s\n", e.message); + } + uint updates_nb = updates.length; + if (updates_nb == 0) { + this.update_icon (noupdate_icon_name, noupdate_info); + } else if (updates_nb == 1) { + this.update_icon (update_icon_name, one_update_info); + if (pamac_run == false) + show_notification (one_update_info); + } else { + // workaround to use python format string + string info = update_info.replace ("{number}", updates_nb.to_string ()); + this.update_icon (update_icon_name, info); + if (pamac_run == false) + show_notification (info); + } + if (pamac_run == false) + stop_daemon (); + } + + void show_notification (string info) { +//~ notification = new Notification (_("Update Manager")); +//~ Gtk.IconTheme icon_theme = Gtk.IconTheme.get_default (); +//~ Gdk.Pixbuf icon = icon_theme.load_icon ("system-software-update", 32, 0); +//~ notification.set_icon (icon); +//~ notification.set_body (info); +//~ var action = new SimpleAction ("update", null); +//~ action.activate.connect (execute_updater); +//~ this.add_action (action); +//~ notification.add_button (_("Show available updates"), "app.update"); +//~ this.send_notification (_("Update Manager"), notification); + try { + notification = new Notify.Notification (_("Update Manager"), info, "system-software-update"); + notification.add_action ("update", _("Show available updates"), execute_updater); + notification.show (); + } catch (Error e) { + stderr.printf ("Notify Error: %s", e.message); + } + } + + bool check_pamac_running () { + Application app; + bool run = false; + app = new Application ("org.manjaro.pamac.manager", 0); + try { + app.register (); + } catch (GLib.Error e) { + stderr.printf ("%s\n", e.message); + } + run = app.get_is_remote (); + if (run) + return run; + else { + app = new Application ("org.manjaro.pamac.updater", 0); + try { + app.register (); + } catch (GLib.Error e) { + stderr.printf ("%s\n", e.message); + } + run = app.get_is_remote (); + return run; + } + } + + bool check_pacman_running () { + GLib.File lockfile = GLib.File.new_for_path ("/var/lib/pacman/db.lck"); + if (locked) { + if (lockfile.query_exists () == false) { + locked = false; + check_updates (); + } + } else { + if (lockfile.query_exists () == true) { + locked = true; + } + } + return true; + } + + void launch_refresh_timeout (string? msg = null) { + if (refresh_timeout_id != 0) { + pamac_config.reload (); + Source.remove (refresh_timeout_id); + } + refresh_timeout_id = Timeout.add_seconds ((uint) pamac_config.refresh_period*3600, refresh); + } + + public override void startup () { + // i18n + Intl.textdomain ("pamac"); + Intl.setlocale (LocaleCategory.ALL, ""); + + base.startup (); + + pamac_config = new Pamac.Config ("/etc/pamac.conf"); + locked = false; + refresh_timeout_id = 0; + + status_icon = new Gtk.StatusIcon (); + status_icon.set_visible (true); + status_icon.activate.connect (left_clicked); + create_menu (); + status_icon.popup_menu.connect (menu_popup); + + Notify.init(_("Update Manager")); + + refresh (); + launch_refresh_timeout (); + Timeout.add (500, check_pacman_running); + + this.hold (); + } + + public override void activate () { + // nothing to do + } + + public static int main (string[] args) { + var tray_icon = new TrayIcon(); + return tray_icon.run (args); + } + } +} diff --git a/src/updater.vala b/src/updater.vala new file mode 100644 index 0000000..46d9aed --- /dev/null +++ b/src/updater.vala @@ -0,0 +1,55 @@ +/* + * pamac-vala + * + * Copyright (C) 2014 Guillaume Benoit + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a get of the GNU General Public License + * along with this program. If not, see . + */ + +namespace Pamac { + + public class Updater : Gtk.Application { + + UpdaterWindow updater_window; + + public Updater () { + application_id = "org.manjaro.pamac.updater"; + flags = ApplicationFlags.FLAGS_NONE; + } + + public override void startup () { + // i18n + Intl.textdomain ("pamac"); + Intl.setlocale (LocaleCategory.ALL, ""); + + base.startup (); + + updater_window = new UpdaterWindow (this); + } + + public override void activate () { + updater_window.present (); + } + + public override void shutdown () { + base.shutdown (); + updater_window.transaction.stop_daemon (); + } + } + + public static int main (string[] args) { + var updater = new Updater (); + return updater.run (args); + } +} diff --git a/src/updater_window.vala b/src/updater_window.vala new file mode 100644 index 0000000..a703fac --- /dev/null +++ b/src/updater_window.vala @@ -0,0 +1,178 @@ +/* + * pamac-vala + * + * Copyright (C) 2014 Guillaume Benoit + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a get of the GNU General Public License + * along with this program. If not, see . + */ + +using Gtk; + +namespace Pamac { + + [GtkTemplate (ui = "/org/manjaro/pamac/updater/updater_window.ui")] + public class UpdaterWindow : Gtk.ApplicationWindow { + + [GtkChild] + public Label top_label; + [GtkChild] + public TreeView updates_treeview; + [GtkChild] + public Label bottom_label; + [GtkChild] + public Button apply_button; + + public ListStore updates_list; + public Pamac.Config pamac_config; + public Pamac.Transaction transaction; + + PreferencesDialog preferences_dialog; + + public UpdaterWindow (Gtk.Application application) { + Object (application: application); + + pamac_config = new Pamac.Config ("/etc/pamac.conf"); + + updates_list = new Gtk.ListStore (2, typeof (string), typeof (string)); + updates_treeview.set_model (updates_list); + + transaction = new Transaction (this as ApplicationWindow, pamac_config); + transaction.mode = Mode.UPDATER; + transaction.finished.connect (on_emit_trans_finished); + + preferences_dialog = new PreferencesDialog (this as ApplicationWindow); + + top_label.set_markup("%s".printf (dgettext (null, "Your system is up-to-date"))); + bottom_label.set_visible (false); + apply_button.set_sensitive (false); + + transaction.refresh (0); + } + + [GtkCallback] + public void on_preferences_button_clicked () { + bool enable_aur = pamac_config.enable_aur; + bool recurse = pamac_config.recurse; + uint64 refresh_period = pamac_config.refresh_period; + preferences_dialog.enable_aur_button.set_active (enable_aur); + preferences_dialog.remove_unrequired_deps_button.set_active (recurse); + preferences_dialog.refresh_period_spin_button.set_value (refresh_period); + int response = preferences_dialog.run (); + while (Gtk.events_pending ()) + Gtk.main_iteration (); + if (response == ResponseType.OK) { + HashTable new_conf = new HashTable (str_hash, str_equal); + enable_aur = preferences_dialog.enable_aur_button.get_active (); + recurse = preferences_dialog.remove_unrequired_deps_button.get_active (); + refresh_period = (uint64) preferences_dialog.refresh_period_spin_button.get_value (); + if (enable_aur != pamac_config.enable_aur) { + new_conf.insert ("EnableAUR", enable_aur.to_string ()); + } + if (recurse != pamac_config.recurse) + new_conf.insert ("RemoveUnrequiredDeps", recurse.to_string ()); + if (refresh_period != pamac_config.refresh_period) + new_conf.insert ("RefreshPeriod", refresh_period.to_string ()); + if (new_conf.size () != 0) { + transaction.write_config (new_conf); + pamac_config.reload (); + } + } + preferences_dialog.hide (); + } + + [GtkCallback] + public void on_apply_button_clicked () { + this.get_window ().set_cursor (new Gdk.Cursor (Gdk.CursorType.WATCH)); + while (Gtk.events_pending ()) + Gtk.main_iteration (); + transaction.sysupgrade (0); + } + + [GtkCallback] + public void on_refresh_button_clicked () { + this.get_window ().set_cursor (new Gdk.Cursor (Gdk.CursorType.WATCH)); + while (Gtk.events_pending ()) + Gtk.main_iteration (); + transaction.refresh (0); + } + + [GtkCallback] + public void on_close_button_clicked () { + this.application.quit (); + } + + public void on_emit_trans_finished (bool error) { + if (error == false) { + set_updates_list (); + } + this.get_window ().set_cursor (null); + } + + public void set_updates_list () { + TreeIter iter; + string name; + string size; + uint64 dsize = 0; + uint updates_nb = 0; + updates_list.clear (); + // get syncfirst updates + UpdatesInfos[] syncfirst_updates = get_syncfirst_updates (transaction.alpm_config); + if (syncfirst_updates.length != 0) { + updates_nb = syncfirst_updates.length; + foreach (UpdatesInfos infos in syncfirst_updates) { + name = infos.name + " " + infos.version; + size = format_size (infos.download_size); + dsize += infos.download_size; + updates_list.insert_with_values (out iter, -1, 0, name, 1, size); + } + } else { + string[] ignore_pkgs = get_ignore_pkgs (transaction.alpm_config); + UpdatesInfos[] updates = get_repos_updates (transaction.alpm_config, ignore_pkgs); + foreach (UpdatesInfos infos in updates) { + name = infos.name + " " + infos.version; + size = format_size (infos.download_size); + dsize += infos.download_size; + updates_list.insert_with_values (out iter, -1, 0, name, 1, size); + } + updates_nb += updates.length; + if (pamac_config.enable_aur) { + UpdatesInfos[] aur_updates = get_aur_updates (transaction.alpm_config, ignore_pkgs); + updates_nb += aur_updates.length; + foreach (UpdatesInfos infos in aur_updates) { + name = infos.name + " " + infos.version; + size = format_size (infos.download_size); + dsize += infos.download_size; + updates_list.insert_with_values (out iter, -1, 0, name, 1, size); + } + } + } + if (updates_nb == 0) { + top_label.set_markup("%s".printf (dgettext (null, "Your system is up-to-date"))); + apply_button.set_sensitive (false); + } else if (updates_nb == 1) { + top_label.set_markup("%s".printf (dgettext (null, "1 available update"))); + apply_button.set_sensitive (true); + } else { + top_label.set_markup("%s".printf (dgettext (null, "{number} available updates").replace ("{number}", updates_nb.to_string ()))); + apply_button.set_sensitive (true); + } + if (dsize == 0) + bottom_label.set_visible (false); + else { + bottom_label.set_markup("%s %s".printf (dgettext (null, "Total download size:"), format_size(dsize))); + bottom_label.set_visible (true); + } + } + } +} diff --git a/update_po_files.sh b/update_po_files.sh new file mode 100755 index 0000000..3647da1 --- /dev/null +++ b/update_po_files.sh @@ -0,0 +1,5 @@ +#! /bin/sh + +for i in `ls po | sed s'|.po||'` ; do + msgmerge --update --no-fuzzy-matching po/$i.po pamac.pot +done diff --git a/util/alpm-util.c b/util/alpm-util.c new file mode 100644 index 0000000..7e2fb8e --- /dev/null +++ b/util/alpm-util.c @@ -0,0 +1,55 @@ +#include "alpm-util.h" + +alpm_pkg_t* alpm_pkg_load_file (alpm_handle_t *handle, const char *filename, int full, alpm_siglevel_t level) { + alpm_pkg_t *p; + int err = alpm_pkg_load(handle, filename, full, level, &p); + if (err == -1) return NULL; + else return p; +} + +alpm_list_t* alpm_pkg_get_files_list (alpm_pkg_t* pkg) { + alpm_list_t *list = NULL; + alpm_filelist_t *pkgfiles; + size_t i; + + pkgfiles = alpm_pkg_get_files(pkg); + + for(i = 0; i < pkgfiles->count; i++) { + const alpm_file_t *file = pkgfiles->files + i; + list = alpm_list_add(list, file); + } + return list; +} + +void* alpm_list_get_data (alpm_list_t *list) { + return list->data; +} + +alpm_list_t* alpm_list_remove_data (alpm_list_t *list, const void *needle, alpm_list_fn_cmp fn) { + void *data = NULL; + list = alpm_list_remove (list, needle, fn, data); + free(data); + return list; +} + +alpm_list_t* alpm_list_sort_data (alpm_list_t *list, alpm_list_fn_cmp fn) { + list = alpm_list_msort (list, alpm_list_count (list), fn); + return list; +} + +void alpm_list_free_all(alpm_list_t *list) { + do { alpm_list_free_inner(list, free); alpm_list_free(list); list = NULL; } while(0); +} + +void alpm_list_iterator(alpm_list_t *list, alpm_list_iterator_t* iter) { + iter->pos = list; +} + +void* alpm_list_iterator_next_value (alpm_list_iterator_t *iter) { + if (iter->pos) { + void* result = alpm_list_get_data(iter->pos); + iter->pos = alpm_list_next(iter->pos); + return result; + } + else return NULL; +} diff --git a/util/alpm-util.h b/util/alpm-util.h new file mode 100644 index 0000000..9753e6a --- /dev/null +++ b/util/alpm-util.h @@ -0,0 +1,20 @@ +#ifndef ALPM_VALA_H +#define ALPM_VALA_H + +#include + +typedef struct __alpm_list_iterator_t { + alpm_list_t* pos; +} alpm_list_iterator_t; + +void* alpm_list_get_data(alpm_list_t *list); +alpm_list_t *alpm_list_remove_data(alpm_list_t *list, const void *needle, alpm_list_fn_cmp fn); +alpm_list_t *alpm_list_sort_data(alpm_list_t *list, alpm_list_fn_cmp fn); +void alpm_list_free_all(alpm_list_t *list); +void alpm_list_iterator(alpm_list_t *list, alpm_list_iterator_t* i); +void* alpm_list_iterator_next_value(alpm_list_iterator_t *iter); + +alpm_pkg_t* alpm_pkg_load_file(alpm_handle_t *handle, const char *filename, int full, alpm_siglevel_t level); +alpm_list_t* alpm_pkg_get_files_list (alpm_pkg_t* pkg); + +#endif //!ALPM_VALA_H diff --git a/vapi/libalpm.vapi b/vapi/libalpm.vapi new file mode 100644 index 0000000..89619cb --- /dev/null +++ b/vapi/libalpm.vapi @@ -0,0 +1,1006 @@ +/* + * libalpm-vala + * Vala bindings for libalpm + * + * Copyright (C) 2014 Guillaume Benoit + * Copyright (c) 2011 Rémy Oudompheng + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a get of the GNU General Public License + * along with this program. If not, see . + */ + +[CCode (cprefix = "alpm_", cheader_filename="alpm.h")] +namespace Alpm { + + [SimpleType] + [CCode (cname = "alpm_time_t", has_type_id = false)] + public struct Time : uint64 {} + + /** + * Library + */ + public string version(); + + public unowned Package? find_satisfier(Alpm.List pkgs, string depstring); + public unowned Package? pkg_find(Alpm.List haystack, string needle); + public int pkg_vercmp(string a, string b); + public unowned Alpm.List find_group_pkgs(Alpm.List dbs, string name); + public unowned Package? sync_newversion(Package pkg, Alpm.List dbs); + /** Returns the string corresponding to an error number. */ + public unowned string strerror(Errno err); + + /** Package install reasons. */ + [CCode (cname = "alpm_pkgreason_t", cprefix = "ALPM_PKG_REASON_")] + public enum PkgReason { + /** Explicitly requested by the user. */ + EXPLICIT = 0, + /** Installed as a dependency for another package. */ + DEPEND = 1 + } + + /** Location a package object was loaded from. */ + [CCode (cname = "alpm_pkgfrom_t", cprefix = "ALPM_PKG_FROM_")] + public enum PkgFrom { + FILE = 1, + LOCALDB, + SYNCDB + } + + /** Method used to validate a package. */ + [CCode (cname = "alpm_pkgvalidation_t", cprefix = "ALPM_PKG_VALIDATION_")] + public enum PkgValidation { + UNKNOWN = 0, + NONE = (1 << 0), + MD5SUM = (1 << 1), + SHA256SUM = (1 << 2), + SIGNATURE = (1 << 3) + } + + /** Types of version constraints in dependency specs. */ + [CCode (cname = "alpm_depmod_t", cprefix = "ALPM_DEP_MOD_")] + public enum DepMod { + /** No version constraint */ + ANY = 1, + /** Test version equality (package=x.y.z) */ + EQ, + /** Test for at least a version (package>=x.y.z) */ + GE, + /** Test for at most a version (package<=x.y.z) */ + LE, + /** Test for greater than some version (package>x.y.z) */ + GT, + /** Test for less than some version (package cachedirs { + [CCode (cname = "alpm_option_get_cachedirs")] get; + [CCode (cname = "alpm_option_set_cachedirs")] set; + } + [CCode (cname = "alpm_option_add_cachedir")] + public int add_cachedir(string cachedir); + [CCode (cname = "alpm_option_remove_cachedir")] + public int remove_cachedir(string cachedir); + + public unowned string logfile { + [CCode (cname = "alpm_option_get_logfile")] get; + [CCode (cname = "alpm_option_set_logfile")] set; + } + public unowned string lockfile { + [CCode (cname = "alpm_option_get_lockfile")] get; + } + public unowned string gpgdir { + [CCode (cname = "alpm_option_get_gpgdir")] get; + [CCode (cname = "alpm_option_set_gpgdir")] set; + } + public int usesyslog { + [CCode (cname = "alpm_option_get_usesyslog")] get; + /** Sets whether to use syslog (0 is FALSE, TRUE otherwise). */ + [CCode (cname = "alpm_option_set_usesyslog")] set; + } + public unowned Alpm.List noupgrades { + [CCode (cname = "alpm_option_get_noupgrades")] get; + [CCode (cname = "alpm_option_set_noupgrades")] set; + } + [CCode (cname = "alpm_option_add_noupgrade")] + public int add_noupgrade(string pkg); + [CCode (cname = "alpm_option_remove_noupgrade")] + public int remove_noupgrade(string pkg); + + public unowned Alpm.List noextracts { + [CCode (cname = "alpm_option_get_noextracts")] get; + [CCode (cname = "alpm_option_set_noextracts")] set; + } + [CCode (cname = "alpm_option_add_noextract")] + public int add_noextract(string pkg); + [CCode (cname = "alpm_option_remove_noextract")] + public int remove_noextract(string pkg); + + public unowned Alpm.List ignorepkgs { + [CCode (cname = "alpm_option_get_ignorepkgs")] get; + [CCode (cname = "alpm_option_set_ignorepkgs")] set; + } + [CCode (cname = "alpm_option_add_ignorepkg")] + public int add_ignorepkg(string pkg); + [CCode (cname = "alpm_option_remove_ignorepkg")] + public int remove_ignorepkg(string pkg); + + public unowned Alpm.List ignoregroups { + [CCode (cname = "alpm_option_get_ignoregroups")] get; + [CCode (cname = "alpm_option_set_ignoregroups")] set; + } + [CCode (cname = "alpm_option_add_ignoregroup")] + public int add_ignoregroup(string grp); + [CCode (cname = "alpm_option_remove_ignorepkg")] + public int remove_ignoregroup(string grp); + + public double deltaratio { + [CCode (cname = "alpm_option_get_deltaratio")] get; + [CCode (cname = "alpm_option_set_deltaratio")] set; + } + + public int checkspace { + [CCode (cname = "alpm_option_get_checkspace")] get; + [CCode (cname = "alpm_option_set_checkspace")] set; + } + + public SigLevel localfilesiglevel { + [CCode (cname = "alpm_option_get_local_file_siglevel")] get; + [CCode (cname = "alpm_option_set_local_file_siglevel")] set; + } + + public SigLevel remotefilesiglevel { + [CCode (cname = "alpm_option_get_remote_file_siglevel")] get; + [CCode (cname = "alpm_option_set_remote_file_siglevel")] set; + } + + [CCode (cname = "alpm_register_syncdb")] + public unowned DB? register_syncdb(string treename, SigLevel level); + [CCode (cname = "alpm_unregister_all_syncdbs")] + public int unregister_all_syncdbs(); + + + public unowned DB? localdb { + [CCode (cname = "alpm_get_localdb")] get; + } + + public unowned Alpm.List syncdbs { + [CCode (cname = "alpm_get_syncdbs")] get; + } + + [CCode (cname = "alpm_pkg_load_file")] + public unowned Package? load_file(string filename, int full, SigLevel level); + +//~ /** Test if a package should be ignored. +//~ * Checks if the package is ignored via IgnorePkg, or if the package is +//~ * in a group ignored via IgnoreGroup. +//~ * @param pkg the package to test +//~ * @return 1 if the package should be ignored, 0 otherwise +//~ */ +//~ [CCode (cname = "alpm_pkg_should_ignore")] +//~ public int should_ignore(Package pkg); + + [CCode (cname = "alpm_fetch_pkgurl")] + public string? fetch_pkgurl(string url); + + [CCode (cname = "alpm_find_dbs_satisfier")] + public unowned Package? find_dbs_satisfier(Alpm.List dbs, string depstring); + + /** Returns the current error code from the handle. */ + [CCode (cname = "alpm_errno")] + public Errno errno(); + + /** Returns the bitfield of flags for the current transaction.*/ + [CCode (cname = "alpm_trans_get_flags")] + public TransFlag trans_get_flags(); + + /** Returns a list of packages added by the transaction.*/ + [CCode (cname = "alpm_trans_get_add")] + public unowned Alpm.List trans_to_add(); + + /** Returns the list of packages removed by the transaction.*/ + [CCode (cname = "alpm_trans_get_remove")] + public unowned Alpm.List trans_to_remove(); + + public LogCallBack logcb { + [CCode (cname = "alpm_option_get_logcb")] get; + [CCode (cname = "alpm_option_set_logcb")] set; + } + + public DownloadCallBack dlcb { + [CCode (cname = "alpm_option_get_dlcb")] get; + [CCode (cname = "alpm_option_set_dlcb")] set; + } + + public FetchCallBack fetchcb { + [CCode (cname = "alpm_option_get_fetchcb")] get; + [CCode (cname = "alpm_option_set_fetchcb")] set; + } + + public TotalDownloadCallBack totaldlcb { + [CCode (cname = "alpm_option_get_totaldlcb")] get; + [CCode (cname = "alpm_option_set_totaldlcb")] set; + } + + public EventCallBack eventcb { + [CCode (cname = "alpm_option_get_eventcb")] get; + [CCode (cname = "alpm_option_set_eventcb")] set; + } + + public QuestionCallBack questioncb { + [CCode (cname = "alpm_option_get_questioncb")] get; + [CCode (cname = "alpm_option_set_questioncb")] set; + } + + public ProgressCallBack progresscb { + [CCode (cname = "alpm_option_get_progresscb")] get; + [CCode (cname = "alpm_option_set_progresscb")] set; + } + + /** Initialize the transaction. + * @param flags flags of the transaction (like nodeps, etc) + * @return 0 on success, -1 on error (Errno is set accordingly) + */ + [CCode (cname = "alpm_trans_init")] + public int trans_init(TransFlag transflags); + + /** Prepare a transaction. + * @param an alpm_list where detailed description of an error + * can be dumped (i.e. list of conflicting packages) + * @return 0 on success, -1 on error (Errno is set accordingly) + */ + [CCode (cname = "alpm_trans_prepare")] + public int trans_prepare(out Alpm.List data); + + /** Commit a transaction. + * @param an alpm_list where detailed description of an error + * can be dumped (i.e. list of conflicting files) + * @return 0 on success, -1 on error (Errno is set accordingly) + */ + [CCode (cname = "alpm_trans_commit")] + public int trans_commit(out Alpm.List data); + + /** Interrupt a transaction. + * @return 0 on success, -1 on error (Errno is set accordingly) + */ + [CCode (cname = "alpm_trans_interrupt")] + public int trans_interrupt(); + + /** Release a transaction. + * @return 0 on success, -1 on error (Errno is set accordingly) + */ + [CCode (cname = "alpm_trans_release")] + public int trans_release(); + + /** Search for packages to upgrade and add them to the transaction. + * @param enable_downgrade allow downgrading of packages if the remote version is lower + * @return 0 on success, -1 on error (Errno is set accordingly) + */ + [CCode (cname = "alpm_sync_sysupgrade")] + public int trans_sysupgrade(int enable_downgrade); + + /** Add a package to the transaction. + * If the package was loaded by load_file(), it will be freed upon + * trans_release() invocation. + * @param pkg the package to add + * @return 0 on success, -1 on error (Errno is set accordingly) + */ + [CCode (cname = "alpm_add_pkg")] + public int trans_add_pkg(Package pkg); + + /** Add a package removal action to the transaction. + * @param pkg the package to uninstall + * @return 0 on success, -1 on error (Errno is set accordingly) + */ + [CCode (cname = "alpm_remove_pkg")] + public int trans_remove_pkg(Package pkg); + } + + /** + * Databases + */ + [CCode (cname = "alpm_db_t", cprefix = "alpm_db_")]//,free_function = "alpm_db_unregister")] + [Compact] + public class DB { + public int unregister(); + + public unowned string name { + [CCode (cname = "alpm_db_get_name")] get; + } + + public SigLevel siglevel { + [CCode (cname = "alpm_db_get_siglevel")] get; + } + + public unowned string url { + [CCode (cname = "alpm_db_get_url")] get; + } + + public unowned Alpm.List servers { + [CCode (cname = "alpm_db_get_servers")] get; + [CCode (cname = "alpm_db_set_servers")] set; + } + + public unowned Alpm.List pkgcache { + [CCode (cname = "alpm_db_get_pkgcache")] get; + } + + public unowned Alpm.List groupcache { + [CCode (cname = "alpm_db_get_groupcache")] get; + } + + public int add_server(string url); + public int remove_server(string url); + + [CCode (instance_pos = 1.1)] + public int update(int force); + + public unowned Package? get_pkg(string name); + public unowned Group? get_group(string name); + public unowned Alpm.List search(Alpm.List needles); + } + + /** + * Packages + */ + [CCode (cname = "alpm_pkg_t", cprefix = "alpm_pkg_", + free_function = "alpm_pkg_free")] + [Compact] + public class Package { + public static int checkmd5sum(); + + public unowned Alpm.List compute_requiredby(); + public unowned Alpm.List compute_optionalfor(); + + /* properties */ + [CCode (array_length = false)] + public unowned string filename { + [CCode (cname = "alpm_pkg_get_filename")] get; + } + [CCode (array_length = false)] + public unowned string name { + [CCode (cname = "alpm_pkg_get_name")] get; + } + [CCode (array_length = false)] + public unowned string version { + [CCode (cname = "alpm_pkg_get_version")] get; + } + public PkgFrom origin { + [CCode (cname = "alpm_pkg_get_origin")] get; + } + [CCode (array_length = false)] + public unowned string desc { + [CCode (cname = "alpm_pkg_get_desc")] get; + } + [CCode (array_length = false)] + public unowned string url { + [CCode (cname = "alpm_pkg_get_url")] get; + } + public Time builddate { + [CCode (cname = "alpm_pkg_get_builddate")] get; + } + public Time installdate { + [CCode (cname = "alpm_pkg_get_installdate")] get; + } + [CCode (array_length = false)] + public unowned string packager { + [CCode (cname = "alpm_pkg_get_packager")] get; + } + [CCode (array_length = false)] + public unowned string md5sum { + [CCode (cname = "alpm_pkg_get_md5sum")] get; + } + [CCode (array_length = false)] + public unowned string arch { + [CCode (cname = "alpm_pkg_get_arch")] get; + } + public uint64 size { + [CCode (cname = "alpm_pkg_get_size")] get; + } + public uint64 isize { + [CCode (cname = "alpm_pkg_get_isize")] get; + } + public uint64 download_size { + [CCode (cname = "alpm_pkg_download_size")] get; + } + public PkgReason reason { + [CCode (cname = "alpm_pkg_get_reason")] get; + /** The provided package object must be from the local database or this method + * will fail. The write to the local database is performed immediately. + * @return 0 on success, -1 on error (Errno is set accordingly) + */ + [CCode (cname = "alpm_pkg_set_reason")] set; + } + public unowned Alpm.List licenses { + [CCode (cname = "alpm_pkg_get_licenses")] get; + } + public unowned Alpm.List groups { + [CCode (cname = "alpm_pkg_get_groups")] get; + } + public unowned Alpm.List depends { + [CCode (cname = "alpm_pkg_get_depends")] get; + } + public unowned Alpm.List optdepends { + [CCode (cname = "alpm_pkg_get_optdepends")] get; + } + public unowned Alpm.List conflicts { + [CCode (cname = "alpm_pkg_get_conflicts")] get; + } + public unowned Alpm.List provides { + [CCode (cname = "alpm_pkg_get_provides")] get; + } + public unowned Alpm.List replaces { + [CCode (cname = "alpm_pkg_get_replaces")] get; + } + public unowned Alpm.List files { + [CCode (cname = "alpm_pkg_get_files_list")] get; + } + public unowned Alpm.List backup { + [CCode (cname = "alpm_pkg_get_backup")] get; + } + public unowned DB? db { + [CCode (cname = "alpm_pkg_get_db")] get; + } + public unowned string base64_sig { + [CCode (cname = "alpm_pkg_get_base64_sig")] get; + } + /* TODO: changelog functions */ + } + + /** Dependency */ + [CCode (cname = "alpm_depend_t", has_type_id = false)] + public class Depend { + public string name; + public string version; + public string desc; + public ulong name_hash; + public DepMod mod; + [CCode (cname = "alpm_dep_compute_string")] + public unowned string compute_string(); + } + + /** Missing dependency */ + [CCode (cname = "alpm_depmissing_t", has_type_id = false)] + public class DepMissing { + public string target; + public unowned Depend depend; + /* this is used only in the case of a remove dependency error */ + public string causingpkg; + } + + /** Conflict */ + [CCode (cname = "alpm_conflict_t", has_type_id = false)] + public class Conflict { + public ulong package1_hash; + public ulong package2_hash; + public string package1; + public string package2; + public unowned Depend reason; + } + + /** File conflict */ + [CCode (cname = "alpm_fileconflict_t", has_type_id = false)] + public class FileConflict { + public string target; + public FileConflictType type; + public string file; + public string ctarget; + } + + /** Package group */ + [CCode (cname = "alpm_group_t", has_type_id = false)] + public class Group { + public string name; + public unowned Alpm.List packages; + } + + /** Package upgrade delta */ + [CCode (cname = "alpm_delta_t", has_type_id = false)] + public class Delta { + /** filename of the delta patch */ + public string delta; + /** md5sum of the delta file */ + public string delta_md5; + /** filename of the 'before' file */ + public string from; + /** filename of the 'after' file */ + public string to; + /** filesize of the delta file */ + public uint64 delta_size; + /** download filesize of the delta file */ + public uint64 download_size; + } + + /** File in a package */ + [CCode (cname = "alpm_file_t", has_type_id = false)] + public class File { + public string name; + public uint64 size; + public uint64 mode; + } + + /** Package filelist container */ + /*[CCode (cname = "alpm_filelist_t", has_type_id = false)] + public class FileList { + public size_t count; + public Alpm.File *files; + public char **resolved_path; + }*/ + + /** Local package or package file backup entry */ + [CCode (cname = "alpm_backup_t", has_type_id = false)] + public class Backup { + public string name; + public string hash; + } + + [CCode (cname = "alpm_pgpkey_t", has_type_id = false)] + public class PGPKey { + public void *data; + public string fingerprint; + public string uid; + public string name; + public string email; + public Time created; + public Time expires; + public uint length; + public uint revoked; + public string pubkey_algo; + } + + /** + * Signature result. Contains the key, status, and validity of a given + * signature. + */ + [CCode (cname = "alpm_sigresult_t", has_type_id = false)] + public class SigResult { + public PGPKey key; + public SigStatus status; + public SigValidity validity; + } + + /** + * Signature list. Contains the number of signatures found and a pointer to an + * array of results. The array is of size count. + */ + [CCode (cname = "alpm_siglist_t", has_type_id = false)] + public class SigList { + public size_t count; + public SigResult results; + } + + /** Logging Levels */ + [CCode (cname = "alpm_loglevel_t", cprefix = "ALPM_LOG_")] + public enum LogLevel { + ERROR = 1, + WARNING = (1 << 1), + DEBUG = (1 << 2), + FUNCTION = (1 << 3) + } + + /** Log callback */ + [CCode (cname = "alpm_cb_log", has_type_id = false, has_target = false)] + public delegate void LogCallBack(LogLevel level, string fmt, va_list args); + + /** + * Events. + * NULL parameters are passed to in all events unless specified otherwise. + */ + [CCode (cname = "alpm_event_t", cprefix = "ALPM_EVENT_")] + public enum Event { + /** Dependencies will be computed for a package. */ + CHECKDEPS_START = 1, + /** Dependencies were computed for a package. */ + CHECKDEPS_DONE, + /** File conflicts will be computed for a package. */ + FILECONFLICTS_START, + /** File conflicts were computed for a package. */ + FILECONFLICTS_DONE, + /** Dependencies will be resolved for target package. */ + RESOLVEDEPS_START, + /** Dependencies were resolved for target package. */ + RESOLVEDEPS_DONE, + /** Inter-conflicts will be checked for target package. */ + INTERCONFLICTS_START, + /** Inter-conflicts were checked for target package. */ + INTERCONFLICTS_DONE, + /** Package will be installed. + * A pointer to the target package is passed to the callback. + */ + ADD_START, + /** Package was installed. + * A pointer to the new package is passed to the callback. + */ + ADD_DONE, + /** Package will be removed. + * A pointer to the target package is passed to the callback. + */ + REMOVE_START, + /** Package was removed. + * A pointer to the removed package is passed to the callback. + */ + REMOVE_DONE, + /** Package will be upgraded. + * A pointer to the upgraded package is passed to the callback. + */ + UPGRADE_START, + /** Package was upgraded. + * A pointer to the new package, and a pointer to the old package is passed + * to the callback, respectively. + */ + UPGRADE_DONE, + /** Package will be downgraded. + * A pointer to the downgraded package is passed to the callback. + */ + DOWNGRADE_START, + /** Package was downgraded. + * A pointer to the new package, and a pointer to the old package is passed + * to the callback, respectively. + */ + DOWNGRADE_DONE, + /** Package will be reinstalled. + * A pointer to the reinstalled package is passed to the callback. + */ + REINSTALL_START, + /** Package was reinstalled. + * A pointer to the new package, and a pointer to the old package is passed + * to the callback, respectively. + */ + REINSTALL_DONE, + /** Target package's integrity will be checked. */ + INTEGRITY_START, + /** Target package's integrity was checked. */ + INTEGRITY_DONE, + /** Target package will be loaded. */ + LOAD_START, + /** Target package is finished loading. */ + LOAD_DONE, + /** Target delta's integrity will be checked. */ + DELTA_INTEGRITY_START, + /** Target delta's integrity was checked. */ + DELTA_INTEGRITY_DONE, + /** Deltas will be applied to packages. */ + DELTA_PATCHES_START, + /** Deltas were applied to packages. */ + DELTA_PATCHES_DONE, + /** Delta patch will be applied to target package. + * The filename of the package and the filename of the patch is passed to the + * callback. + */ + DELTA_PATCH_START, + /** Delta patch was applied to target package. */ + DELTA_PATCH_DONE, + /** Delta patch failed to apply to target package. */ + DELTA_PATCH_FAILED, + /** Scriptlet has printed information. + * A line of text is passed to the callback. + */ + SCRIPTLET_INFO, + /** Files will be downloaded from a repository. + * The repository's tree name is passed to the callback. + */ + RETRIEVE_START, + /** Disk space usage will be computed for a package */ + DISKSPACE_START, + /** Disk space usage was computed for a package */ + DISKSPACE_DONE, + /** An optdepend for another package is being removed + * The requiring package and its dependency are passed to the callback */ + OPTDEP_REQUIRED, + /** A configured repository database is missing */ + DATABASE_MISSING, + /** Checking keys used to create signatures are in keyring. */ + KEYRING_START, + /** Keyring checking is finished. */ + KEYRING_DONE, + /** Downloading missing keys into keyring. */ + KEY_DOWNLOAD_START, + /** Key downloading is finished. */ + KEY_DOWNLOAD_DONE + } + + /** Event callback */ + [CCode (cname = "alpm_cb_event", has_type_id = false, has_target = false)] + public delegate void EventCallBack (Event event, void *data1, void *data2); + + /** + * Questions. + * Unlike the events or progress enumerations, this enum has bitmask values + * so a frontend can use a bitmask map to supply preselected answers to the + * different types of questions. + */ + [CCode (cname = "alpm_question_t", cprefix = "ALPM_QUESTION_")] + public enum Question { + INSTALL_IGNOREPKG = 1, + REPLACE_PKG = (1 << 1), + CONFLICT_PKG = (1 << 2), + CORRUPTED_PKG = (1 << 3), + REMOVE_PKGS = (1 << 4), + SELECT_PROVIDER = (1 << 5), + IMPORT_KEY = (1 << 6) + } + + /** Question callback */ + [CCode (cname = "alpm_cb_question", has_type_id = false, has_target = false)] + public delegate void QuestionCallBack (Question question, void *data1, void *data2, void *data3, out int response); + + /** Progress */ + [CCode (cname = "alpm_progress_t", cprefix = "ALPM_PROGRESS_")] + public enum Progress { + ADD_START, + UPGRADE_START, + DOWNGRADE_START, + REINSTALL_START, + REMOVE_START, + CONFLICTS_START, + DISKSPACE_START, + INTEGRITY_START, + LOAD_START, + KEYRING_START + } + + /** Progress callback */ + [CCode (cname = "alpm_cb_progress", has_type_id = false, has_target = false)] + public delegate void ProgressCallBack (Progress progress, string pkgname, int percent, uint n_targets, uint current_target); + + /** Type of download progress callbacks. + * @param filename the name of the file being downloaded + * @param xfered the number of transferred bytes + * @param total the total number of bytes to transfer + */ + [CCode (cname = "alpm_cb_download", has_type_id = false, has_target = false)] + public delegate void DownloadCallBack (string filename, uint64 xfered, uint64 total); + + [CCode (cname = "alpm_cb_totaldl", has_type_id = false, has_target = false)] + public delegate void TotalDownloadCallBack (uint64 total); + + /** A callback for downloading files + * @param url the URL of the file to be downloaded + * @param localpath the directory to which the file should be downloaded + * @param force whether to force an update, even if the file is the same + * @return 0 on success, 1 if the file exists and is identical, -1 on + * error. + */ + [CCode (cname = "alpm_cb_fetch", has_type_id = false, has_target = false)] + public delegate int FetchCallBack (string url, string localpath, int force); + + /** Transaction flags */ + [CCode (cname = "alpm_transflag_t", cprefix = "ALPM_TRANS_FLAG_")] + public enum TransFlag { + /** Ignore dependency checks. */ + NODEPS = 1, + /** Ignore file conflicts and overwrite files. */ + FORCE = (1 << 1), + /** Delete files even if they are tagged as backup. */ + NOSAVE = (1 << 2), + /** Ignore version numbers when checking dependencies. */ + NODEPVERSION = (1 << 3), + /** Remove also any packages depending on a package being removed. */ + CASCADE = (1 << 4), + /** Remove packages and their unneeded deps (not explicitly installed). */ + RECURSE = (1 << 5), + /** Modify database but do not commit changes to the filesystem. */ + DBONLY = (1 << 6), + /** Use ALPM_PKG_REASON_DEPEND when installing packages. */ + ALLDEPS = (1 << 8), + /** Only download packages and do not actually install. */ + DOWNLOADONLY = (1 << 9), + /** Do not execute install scriptlets after installing. */ + NOSCRIPTLET = (1 << 10), + /** Ignore dependency conflicts. */ + NOCONFLICTS = (1 << 11), + /** Do not install a package if it is already installed and up to date. */ + NEEDED = (1 << 13), + /** Use ALPM_PKG_REASON_EXPLICIT when installing packages. */ + ALLEXPLICIT = (1 << 14), + /** Do not remove a package if it is needed by another one. */ + UNNEEDED = (1 << 15), + /** Remove also explicitly installed unneeded deps (use with ALPM_TRANS_FLAG_RECURSE). */ + RECURSEALL = (1 << 16), + /** Do not lock the database during the operation. */ + NOLOCK = (1 << 17) + } + + /** + * Errnos + */ + [CCode (cname = "alpm_errno_t", cprefix = "ALPM_ERR_")] + public enum Errno { + MEMORY = 1, + SYSTEM, + BADPERMS, + NOT_A_FILE, + NOT_A_DIR, + WRONG_ARGS, + DISK_SPACE, + /* Interface */ + HANDLE_NULL, + HANDLE_NOT_NULL, + HANDLE_LOCK, + /* Databases */ + DB_OPEN, + DB_CREATE, + DB_NULL, + DB_NOT_NULL, + DB_NOT_FOUND, + DB_INVALID, + DB_INVALID_SIG, + DB_VERSION, + DB_WRITE, + DB_REMOVE, + /* Servers */ + SERVER_BAD_URL, + SERVER_NONE, + /* Transactions */ + TRANS_NOT_NULL, + TRANS_NULL, + TRANS_DUP_TARGET, + TRANS_NOT_INITIALIZED, + TRANS_NOT_PREPARED, + TRANS_ABORT, + TRANS_TYPE, + TRANS_NOT_LOCKED, + /* Packages */ + PKG_NOT_FOUND, + PKG_IGNORED, + PKG_INVALID, + PKG_INVALID_CHECKSUM, + PKG_INVALID_SIG, + PKG_OPEN, + PKG_CANT_REMOVE, + PKG_INVALID_NAME, + PKG_INVALID_ARCH, + PKG_REPO_NOT_FOUND, + /* Signatures */ + SIG_MISSING, + SIG_INVALID, + /* Deltas */ + DLT_INVALID, + DLT_PATCHFAILED, + /* Dependencies */ + UNSATISFIED_DEPS, + CONFLICTING_DEPS, + FILE_CONFLICTS, + /* Misc */ + RETRIEVE, + INVALID_REGEX, + /* External library errors */ + LIBARCHIVE, + LIBCURL, + EXTERNAL_DOWNLOAD, + GPGME + } + +[CCode (cprefix = "alpm_list_", cheader_filename = "alpm_list.h,alpm-util.h", + cname = "alpm_list_t", type_parameters = "G", + free_function = "alpm_list_free")] + [Compact] + public class List { + /* Comparator*/ + [CCode (cname = "alpm_list_fn_cmp", has_target = false)] + public delegate int CompareFunc(G a, G b); + + /* properties */ + public size_t length { + [CCode (cname = "alpm_list_count")] get; + } + + /* item mutators */ + [ReturnsModifiedPointer ()] + public unowned void add(G data); + [ReturnsModifiedPointer ()] + public unowned void join(List list); + [CCode (cname = "alpm_list_sort_data"), ReturnsModifiedPointer ()] + public unowned void sort(CompareFunc fn); + [CCode (cname = "alpm_list_remove_data"), ReturnsModifiedPointer ()] + public unowned void? remove(G data, CompareFunc fn); + public List copy(); + [ReturnsModifiedPointer ()] + public unowned void reverse (); + + /* item accessors */ + public unowned List? first(); + public unowned List? last(); + public unowned List? nth(size_t n); + public unowned List? next(); + public unowned List? previous(); + public unowned G get_data(); + + /* misc */ + public unowned string? find_str(string needle); + /** @return a list containing all items in `this` not present in `list` */ + public unowned List? diff(List? list, CompareFunc fn); + + /* iterator */ + public Iterator iterator(); + + [CCode (cname = "alpm_list_iterator_t", cprefix = "alpm_list_iterator_")] + public struct Iterator { + public unowned G? next_value(); + } + } +} + +/* vim: set ts=2 sw=2 noet: */ diff --git a/vapi/polkit-gobject-1.vapi b/vapi/polkit-gobject-1.vapi new file mode 100644 index 0000000..291dcee --- /dev/null +++ b/vapi/polkit-gobject-1.vapi @@ -0,0 +1,220 @@ +/* polkit-gobject-1.vapi generated by vapigen, do not modify. */ + +[CCode (cprefix = "Polkit", gir_namespace = "Polkit", gir_version = "1.0", lower_case_cprefix = "polkit_")] +namespace Polkit { + [CCode (cheader_filename = "polkit/polkit.h", type_id = "polkit_action_description_get_type ()")] + public class ActionDescription : GLib.Object { + [CCode (has_construct_function = false)] + protected ActionDescription (); + public unowned string get_action_id (); + public unowned string get_annotation (string key); + [CCode (array_length = false, array_null_terminated = true)] + public unowned string[] get_annotation_keys (); + public unowned string get_description (); + public unowned string get_icon_name (); + public Polkit.ImplicitAuthorization get_implicit_active (); + public Polkit.ImplicitAuthorization get_implicit_any (); + public Polkit.ImplicitAuthorization get_implicit_inactive (); + public unowned string get_message (); + public unowned string get_vendor_name (); + public unowned string get_vendor_url (); + } + [CCode (cheader_filename = "polkit/polkit.h", type_id = "polkit_authority_get_type ()")] + public class Authority : GLib.Object, GLib.AsyncInitable, GLib.Initable { + [CCode (has_construct_function = false)] + protected Authority (); + public async bool authentication_agent_response (string cookie, Polkit.Identity identity, GLib.Cancellable? cancellable) throws GLib.Error; + public bool authentication_agent_response_sync (string cookie, Polkit.Identity identity, GLib.Cancellable? cancellable = null) throws GLib.Error; + public async Polkit.AuthorizationResult check_authorization (Polkit.Subject subject, string action_id, Polkit.Details? details, Polkit.CheckAuthorizationFlags flags, GLib.Cancellable? cancellable) throws GLib.Error; + public Polkit.AuthorizationResult check_authorization_sync (Polkit.Subject subject, string action_id, Polkit.Details? details, Polkit.CheckAuthorizationFlags flags, GLib.Cancellable? cancellable = null) throws GLib.Error; + public async GLib.List enumerate_actions (GLib.Cancellable? cancellable) throws GLib.Error; + public GLib.List enumerate_actions_sync (GLib.Cancellable? cancellable = null) throws GLib.Error; + public async GLib.List enumerate_temporary_authorizations (Polkit.Subject subject, GLib.Cancellable? cancellable) throws GLib.Error; + public GLib.List enumerate_temporary_authorizations_sync (Polkit.Subject subject, GLib.Cancellable? cancellable = null) throws GLib.Error; + public static Polkit.Authority @get (); + public static async Polkit.Authority get_async (GLib.Cancellable? cancellable) throws GLib.Error; + public Polkit.AuthorityFeatures get_backend_features (); + public unowned string get_backend_name (); + public unowned string get_backend_version (); + public string get_owner (); + public static Polkit.Authority get_sync (GLib.Cancellable? cancellable = null) throws GLib.Error; + public async bool register_authentication_agent (Polkit.Subject subject, string locale, string object_path, GLib.Cancellable? cancellable) throws GLib.Error; + public bool register_authentication_agent_sync (Polkit.Subject subject, string locale, string object_path, GLib.Cancellable? cancellable = null) throws GLib.Error; + public async bool register_authentication_agent_with_options (Polkit.Subject subject, string locale, string object_path, GLib.Variant? options, GLib.Cancellable? cancellable) throws GLib.Error; + public bool register_authentication_agent_with_options_sync (Polkit.Subject subject, string locale, string object_path, GLib.Variant? options, GLib.Cancellable? cancellable = null) throws GLib.Error; + public async bool revoke_temporary_authorization_by_id (string id, GLib.Cancellable? cancellable) throws GLib.Error; + public bool revoke_temporary_authorization_by_id_sync (string id, GLib.Cancellable? cancellable = null) throws GLib.Error; + public async bool revoke_temporary_authorizations (Polkit.Subject subject, GLib.Cancellable? cancellable) throws GLib.Error; + public bool revoke_temporary_authorizations_sync (Polkit.Subject subject, GLib.Cancellable? cancellable = null) throws GLib.Error; + public async bool unregister_authentication_agent (Polkit.Subject subject, string object_path, GLib.Cancellable? cancellable) throws GLib.Error; + public bool unregister_authentication_agent_sync (Polkit.Subject subject, string object_path, GLib.Cancellable? cancellable = null) throws GLib.Error; + public Polkit.AuthorityFeatures backend_features { get; } + public string backend_name { get; } + public string backend_version { get; } + public string owner { owned get; } + public signal void changed (); + } + [CCode (cheader_filename = "polkit/polkit.h", type_id = "polkit_authorization_result_get_type ()")] + public class AuthorizationResult : GLib.Object { + [CCode (has_construct_function = false)] + public AuthorizationResult (bool is_authorized, bool is_challenge, Polkit.Details? details); + public unowned Polkit.Details get_details (); + public bool get_dismissed (); + public bool get_is_authorized (); + public bool get_is_challenge (); + public bool get_retains_authorization (); + public unowned string get_temporary_authorization_id (); + } + [CCode (cheader_filename = "polkit/polkit.h", type_id = "polkit_details_get_type ()")] + public class Details : GLib.Object { + [CCode (has_construct_function = false)] + public Details (); + [CCode (array_length = false, array_null_terminated = true)] + public string[] get_keys (); + public void insert (string key, string? value); + public unowned string lookup (string key); + } + [CCode (cheader_filename = "polkit/polkit.h", type_id = "polkit_permission_get_type ()")] + public class Permission : GLib.Permission, GLib.AsyncInitable, GLib.Initable { + [CCode (cname = "polkit_permission_new", has_construct_function = false)] + public async Permission (string action_id, Polkit.Subject? subject, GLib.Cancellable? cancellable) throws GLib.Error; + public unowned string get_action_id (); + public unowned Polkit.Subject get_subject (); + [CCode (has_construct_function = false, type = "GPermission*")] + public Permission.sync (string action_id, Polkit.Subject? subject, GLib.Cancellable? cancellable = null) throws GLib.Error; + public string action_id { get; construct; } + public Polkit.Subject subject { get; construct; } + } + [CCode (cheader_filename = "polkit/polkit.h", type_id = "polkit_system_bus_name_get_type ()")] + public class SystemBusName : GLib.Object, Polkit.Subject { + [CCode (has_construct_function = false)] + protected SystemBusName (); + public unowned string get_name (); + public Polkit.Subject get_process_sync (GLib.Cancellable? cancellable = null) throws GLib.Error; + public static Polkit.Subject @new (string name); + public void set_name (string name); + public string name { get; set construct; } + } + [CCode (cheader_filename = "polkit/polkit.h", type_id = "polkit_temporary_authorization_get_type ()")] + public class TemporaryAuthorization : GLib.Object { + [CCode (has_construct_function = false)] + protected TemporaryAuthorization (); + public unowned string get_action_id (); + public unowned string get_id (); + public Polkit.Subject get_subject (); + public uint64 get_time_expires (); + public uint64 get_time_obtained (); + } + [CCode (cheader_filename = "polkit/polkit.h", type_id = "polkit_unix_group_get_type ()")] + public class UnixGroup : GLib.Object, Polkit.Identity { + [CCode (has_construct_function = false)] + protected UnixGroup (); + public int get_gid (); + public static Polkit.Identity @new (int gid); + public static Polkit.Identity new_for_name (string name) throws GLib.Error; + public void set_gid (int gid); + public int gid { get; set construct; } + } + [CCode (cheader_filename = "polkit/polkit.h", type_id = "polkit_unix_netgroup_get_type ()")] + public class UnixNetgroup : GLib.Object, Polkit.Identity { + [CCode (has_construct_function = false)] + protected UnixNetgroup (); + public unowned string get_name (); + public static Polkit.Identity @new (string name); + public void set_name (string name); + public string name { get; set construct; } + } + [CCode (cheader_filename = "polkit/polkit.h", type_id = "polkit_unix_process_get_type ()")] + public class UnixProcess : GLib.Object, Polkit.Subject { + [CCode (has_construct_function = false)] + protected UnixProcess (); + public int get_owner () throws GLib.Error; + public int get_pid (); + public uint64 get_start_time (); + public int get_uid (); + public static Polkit.Subject @new (int pid); + public static Polkit.Subject new_for_owner (int pid, uint64 start_time, int uid); + public static Polkit.Subject new_full (int pid, uint64 start_time); + public void set_pid (int pid); + public void set_start_time (uint64 start_time); + public void set_uid (int uid); + public int pid { get; set construct; } + public uint64 start_time { get; set construct; } + public int uid { get; set construct; } + } + [CCode (cheader_filename = "polkit/polkit.h", type_id = "polkit_unix_session_get_type ()")] + public class UnixSession : GLib.Object, GLib.AsyncInitable, GLib.Initable, Polkit.Subject { + [CCode (has_construct_function = false)] + protected UnixSession (); + public unowned string get_session_id (); + public static Polkit.Subject @new (string session_id); + public static async Polkit.Subject new_for_process (int pid, GLib.Cancellable? cancellable) throws GLib.Error; + public static Polkit.Subject new_for_process_sync (int pid, GLib.Cancellable? cancellable = null) throws GLib.Error; + public void set_session_id (string session_id); + public int pid { construct; } + public string session_id { get; set construct; } + } + [CCode (cheader_filename = "polkit/polkit.h", type_id = "polkit_unix_user_get_type ()")] + public class UnixUser : GLib.Object, Polkit.Identity { + [CCode (has_construct_function = false)] + protected UnixUser (); + public unowned string get_name (); + public int get_uid (); + public static Polkit.Identity @new (int uid); + public static Polkit.Identity new_for_name (string name) throws GLib.Error; + public void set_uid (int uid); + public int uid { get; set construct; } + } + [CCode (cheader_filename = "polkit/polkit.h", type_id = "polkit_identity_get_type ()")] + public interface Identity : GLib.Object { + public abstract bool equal (Polkit.Identity b); + public static Polkit.Identity from_string (string str) throws GLib.Error; + public abstract uint hash (); + public abstract string to_string (); + } + [CCode (cheader_filename = "polkit/polkit.h", type_id = "polkit_subject_get_type ()")] + public interface Subject : GLib.Object { + public abstract bool equal (Polkit.Subject b); + public abstract async bool exists (GLib.Cancellable? cancellable) throws GLib.Error; + public abstract bool exists_sync (GLib.Cancellable? cancellable = null) throws GLib.Error; + public static Polkit.Subject from_string (string str) throws GLib.Error; + public abstract uint hash (); + public abstract string to_string (); + } + [CCode (cheader_filename = "polkit/polkit.h", cprefix = "POLKIT_AUTHORITY_FEATURES_", type_id = "polkit_authority_features_get_type ()")] + [Flags] + public enum AuthorityFeatures { + NONE, + TEMPORARY_AUTHORIZATION + } + [CCode (cheader_filename = "polkit/polkit.h", cprefix = "POLKIT_CHECK_AUTHORIZATION_FLAGS_", type_id = "polkit_check_authorization_flags_get_type ()")] + [Flags] + public enum CheckAuthorizationFlags { + NONE, + ALLOW_USER_INTERACTION + } + [CCode (cheader_filename = "polkit/polkit.h", cprefix = "POLKIT_IMPLICIT_AUTHORIZATION_", type_id = "polkit_implicit_authorization_get_type ()")] + public enum ImplicitAuthorization { + UNKNOWN, + NOT_AUTHORIZED, + AUTHENTICATION_REQUIRED, + ADMINISTRATOR_AUTHENTICATION_REQUIRED, + AUTHENTICATION_REQUIRED_RETAINED, + ADMINISTRATOR_AUTHENTICATION_REQUIRED_RETAINED, + AUTHORIZED; + public static bool from_string (string string, Polkit.ImplicitAuthorization out_implicit_authorization); + public static unowned string to_string (Polkit.ImplicitAuthorization implicit_authorization); + } + [CCode (cheader_filename = "polkit/polkit.h", cprefix = "POLKIT_ERROR_")] + public errordomain Error { + FAILED, + CANCELLED, + NOT_SUPPORTED, + NOT_AUTHORIZED; + public static GLib.Quark quark (); + } + [CCode (cheader_filename = "polkit/polkit.h")] + public static Polkit.Identity identity_from_string (string str) throws GLib.Error; + [CCode (cheader_filename = "polkit/polkit.h")] + public static Polkit.Subject subject_from_string (string str) throws GLib.Error; +}