├── .gitignore ├── Dockerfile ├── LICENSE ├── README.md ├── apacman ├── apacman.8 ├── apacman.conf ├── apacman.conf.5 ├── apacman.install ├── docs ├── apacman.8.html └── apacman.conf.5.html ├── release.sh ├── test.bats └── zsh-completion /.gitignore: -------------------------------------------------------------------------------- 1 | old/ 2 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM vcatechnology/arch-ci:latest 2 | MAINTAINER oshazard 3 | RUN sudo pacman -Syu 4 | RUN sudo pacman -S jshon bash-bats --needed --asdeps --noconfirm 5 | RUN sudo curl -O "https://raw.githubusercontent.com/oshazard/apacman/master/apacman" 6 | RUN sudo bash ./apacman -S apacman --noconfirm 7 | RUN sudo apacman -S apacman-deps proot fuse --needed --asdeps --noconfirm 8 | 9 | # docker build -t "apacman:dockerfile" . 10 | # docker run -t -i "apacman:dockerfile" bats /usr/share/bats/apacman.bats 11 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | GNU GENERAL PUBLIC LICENSE 3 | Version 3, 29 June 2007 4 | 5 | Copyright (C) 2007 Free Software Foundation, Inc. [http://fsf.org/] 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The GNU General Public License is a free, copyleft license for 12 | software and other kinds of works. 13 | 14 | The licenses for most software and other practical works are designed 15 | to take away your freedom to share and change the works. By contrast, 16 | the GNU General Public License is intended to guarantee your freedom to 17 | share and change all versions of a program--to make sure it remains free 18 | software for all its users. We, the Free Software Foundation, use the 19 | GNU General Public License for most of our software; it applies also to 20 | any other work released this way by its authors. You can apply it to 21 | your programs, too. 22 | 23 | When we speak of free software, we are referring to freedom, not 24 | price. Our General Public Licenses are designed to make sure that you 25 | have the freedom to distribute copies of free software (and charge for 26 | them if you wish), that you receive source code or can get it if you 27 | want it, that you can change the software or use pieces of it in new 28 | free programs, and that you know you can do these things. 29 | 30 | To protect your rights, we need to prevent others from denying you 31 | these rights or asking you to surrender the rights. Therefore, you have 32 | certain responsibilities if you distribute copies of the software, or if 33 | you modify it: responsibilities to respect the freedom of others. 34 | 35 | For example, if you distribute copies of such a program, whether 36 | gratis or for a fee, you must pass on to the recipients the same 37 | freedoms that you received. You must make sure that they, too, receive 38 | or can get the source code. And you must show them these terms so they 39 | know their rights. 40 | 41 | Developers that use the GNU GPL protect your rights with two steps: 42 | (1) assert copyright on the software, and (2) offer you this License 43 | giving you legal permission to copy, distribute and/or modify it. 44 | 45 | For the developers' and authors' protection, the GPL clearly explains 46 | that there is no warranty for this free software. For both users' and 47 | authors' sake, the GPL requires that modified versions be marked as 48 | changed, so that their problems will not be attributed erroneously to 49 | authors of previous versions. 50 | 51 | Some devices are designed to deny users access to install or run 52 | modified versions of the software inside them, although the manufacturer 53 | can do so. This is fundamentally incompatible with the aim of 54 | protecting users' freedom to change the software. The systematic 55 | pattern of such abuse occurs in the area of products for individuals to 56 | use, which is precisely where it is most unacceptable. Therefore, we 57 | have designed this version of the GPL to prohibit the practice for those 58 | products. If such problems arise substantially in other domains, we 59 | stand ready to extend this provision to those domains in future versions 60 | of the GPL, as needed to protect the freedom of users. 61 | 62 | Finally, every program is threatened constantly by software patents. 63 | States should not allow patents to restrict development and use of 64 | software on general-purpose computers, but in those that do, we wish to 65 | avoid the special danger that patents applied to a free program could 66 | make it effectively proprietary. To prevent this, the GPL assures that 67 | patents cannot be used to render the program non-free. 68 | 69 | The precise terms and conditions for copying, distribution and 70 | modification follow. 71 | 72 | TERMS AND CONDITIONS 73 | 74 | 0. Definitions. 75 | 76 | "This License" refers to version 3 of the GNU General Public License. 77 | 78 | "Copyright" also means copyright-like laws that apply to other kinds of 79 | works, such as semiconductor masks. 80 | 81 | "The Program" refers to any copyrightable work licensed under this 82 | License. Each licensee is addressed as "you". "Licensees" and 83 | "recipients" may be individuals or organizations. 84 | 85 | To "modify" a work means to copy from or adapt all or part of the work 86 | in a fashion requiring copyright permission, other than the making of an 87 | exact copy. The resulting work is called a "modified version" of the 88 | earlier work or a work "based on" the earlier work. 89 | 90 | A "covered work" means either the unmodified Program or a work based 91 | on the Program. 92 | 93 | To "propagate" a work means to do anything with it that, without 94 | permission, would make you directly or secondarily liable for 95 | infringement under applicable copyright law, except executing it on a 96 | computer or modifying a private copy. Propagation includes copying, 97 | distribution (with or without modification), making available to the 98 | public, and in some countries other activities as well. 99 | 100 | To "convey" a work means any kind of propagation that enables other 101 | parties to make or receive copies. Mere interaction with a user through 102 | a computer network, with no transfer of a copy, is not conveying. 103 | 104 | An interactive user interface displays "Appropriate Legal Notices" 105 | to the extent that it includes a convenient and prominently visible 106 | feature that (1) displays an appropriate copyright notice, and (2) 107 | tells the user that there is no warranty for the work (except to the 108 | extent that warranties are provided), that licensees may convey the 109 | work under this License, and how to view a copy of this License. If 110 | the interface presents a list of user commands or options, such as a 111 | menu, a prominent item in the list meets this criterion. 112 | 113 | 1. Source Code. 114 | 115 | The "source code" for a work means the preferred form of the work 116 | for making modifications to it. "Object code" means any non-source 117 | form of a work. 118 | 119 | A "Standard Interface" means an interface that either is an official 120 | standard defined by a recognized standards body, or, in the case of 121 | interfaces specified for a particular programming language, one that 122 | is widely used among developers working in that language. 123 | 124 | The "System Libraries" of an executable work include anything, other 125 | than the work as a whole, that (a) is included in the normal form of 126 | packaging a Major Component, but which is not part of that Major 127 | Component, and (b) serves only to enable use of the work with that 128 | Major Component, or to implement a Standard Interface for which an 129 | implementation is available to the public in source code form. A 130 | "Major Component", in this context, means a major essential component 131 | (kernel, window system, and so on) of the specific operating system 132 | (if any) on which the executable work runs, or a compiler used to 133 | produce the work, or an object code interpreter used to run it. 134 | 135 | The "Corresponding Source" for a work in object code form means all 136 | the source code needed to generate, install, and (for an executable 137 | work) run the object code and to modify the work, including scripts to 138 | control those activities. However, it does not include the work's 139 | System Libraries, or general-purpose tools or generally available free 140 | programs which are used unmodified in performing those activities but 141 | which are not part of the work. For example, Corresponding Source 142 | includes interface definition files associated with source files for 143 | the work, and the source code for shared libraries and dynamically 144 | linked subprograms that the work is specifically designed to require, 145 | such as by intimate data communication or control flow between those 146 | subprograms and other parts of the work. 147 | 148 | The Corresponding Source need not include anything that users 149 | can regenerate automatically from other parts of the Corresponding 150 | Source. 151 | 152 | The Corresponding Source for a work in source code form is that 153 | same work. 154 | 155 | 2. Basic Permissions. 156 | 157 | All rights granted under this License are granted for the term of 158 | copyright on the Program, and are irrevocable provided the stated 159 | conditions are met. This License explicitly affirms your unlimited 160 | permission to run the unmodified Program. The output from running a 161 | covered work is covered by this License only if the output, given its 162 | content, constitutes a covered work. This License acknowledges your 163 | rights of fair use or other equivalent, as provided by copyright law. 164 | 165 | You may make, run and propagate covered works that you do not 166 | convey, without conditions so long as your license otherwise remains 167 | in force. You may convey covered works to others for the sole purpose 168 | of having them make modifications exclusively for you, or provide you 169 | with facilities for running those works, provided that you comply with 170 | the terms of this License in conveying all material for which you do 171 | not control copyright. Those thus making or running the covered works 172 | for you must do so exclusively on your behalf, under your direction 173 | and control, on terms that prohibit them from making any copies of 174 | your copyrighted material outside their relationship with you. 175 | 176 | Conveying under any other circumstances is permitted solely under 177 | the conditions stated below. Sublicensing is not allowed; section 10 178 | makes it unnecessary. 179 | 180 | 3. Protecting Users' Legal Rights From Anti-Circumvention Law. 181 | 182 | No covered work shall be deemed part of an effective technological 183 | measure under any applicable law fulfilling obligations under article 184 | 11 of the WIPO copyright treaty adopted on 20 December 1996, or 185 | similar laws prohibiting or restricting circumvention of such 186 | measures. 187 | 188 | When you convey a covered work, you waive any legal power to forbid 189 | circumvention of technological measures to the extent such circumvention 190 | is effected by exercising rights under this License with respect to 191 | the covered work, and you disclaim any intention to limit operation or 192 | modification of the work as a means of enforcing, against the work's 193 | users, your or third parties' legal rights to forbid circumvention of 194 | technological measures. 195 | 196 | 4. Conveying Verbatim Copies. 197 | 198 | You may convey verbatim copies of the Program's source code as you 199 | receive it, in any medium, provided that you conspicuously and 200 | appropriately publish on each copy an appropriate copyright notice; 201 | keep intact all notices stating that this License and any 202 | non-permissive terms added in accord with section 7 apply to the code; 203 | keep intact all notices of the absence of any warranty; and give all 204 | recipients a copy of this License along with the Program. 205 | 206 | You may charge any price or no price for each copy that you convey, 207 | and you may offer support or warranty protection for a fee. 208 | 209 | 5. Conveying Modified Source Versions. 210 | 211 | You may convey a work based on the Program, or the modifications to 212 | produce it from the Program, in the form of source code under the 213 | terms of section 4, provided that you also meet all of these conditions: 214 | 215 | a) The work must carry prominent notices stating that you modified 216 | it, and giving a relevant date. 217 | 218 | b) The work must carry prominent notices stating that it is 219 | released under this License and any conditions added under section 220 | 7. This requirement modifies the requirement in section 4 to 221 | "keep intact all notices". 222 | 223 | c) You must license the entire work, as a whole, under this 224 | License to anyone who comes into possession of a copy. This 225 | License will therefore apply, along with any applicable section 7 226 | additional terms, to the whole of the work, and all its parts, 227 | regardless of how they are packaged. This License gives no 228 | permission to license the work in any other way, but it does not 229 | invalidate such permission if you have separately received it. 230 | 231 | d) If the work has interactive user interfaces, each must display 232 | Appropriate Legal Notices; however, if the Program has interactive 233 | interfaces that do not display Appropriate Legal Notices, your 234 | work need not make them do so. 235 | 236 | A compilation of a covered work with other separate and independent 237 | works, which are not by their nature extensions of the covered work, 238 | and which are not combined with it such as to form a larger program, 239 | in or on a volume of a storage or distribution medium, is called an 240 | "aggregate" if the compilation and its resulting copyright are not 241 | used to limit the access or legal rights of the compilation's users 242 | beyond what the individual works permit. Inclusion of a covered work 243 | in an aggregate does not cause this License to apply to the other 244 | parts of the aggregate. 245 | 246 | 6. Conveying Non-Source Forms. 247 | 248 | You may convey a covered work in object code form under the terms 249 | of sections 4 and 5, provided that you also convey the 250 | machine-readable Corresponding Source under the terms of this License, 251 | in one of these ways: 252 | 253 | a) Convey the object code in, or embodied in, a physical product 254 | (including a physical distribution medium), accompanied by the 255 | Corresponding Source fixed on a durable physical medium 256 | customarily used for software interchange. 257 | 258 | b) Convey the object code in, or embodied in, a physical product 259 | (including a physical distribution medium), accompanied by a 260 | written offer, valid for at least three years and valid for as 261 | long as you offer spare parts or customer support for that product 262 | model, to give anyone who possesses the object code either (1) a 263 | copy of the Corresponding Source for all the software in the 264 | product that is covered by this License, on a durable physical 265 | medium customarily used for software interchange, for a price no 266 | more than your reasonable cost of physically performing this 267 | conveying of source, or (2) access to copy the 268 | Corresponding Source from a network server at no charge. 269 | 270 | c) Convey individual copies of the object code with a copy of the 271 | written offer to provide the Corresponding Source. This 272 | alternative is allowed only occasionally and noncommercially, and 273 | only if you received the object code with such an offer, in accord 274 | with subsection 6b. 275 | 276 | d) Convey the object code by offering access from a designated 277 | place (gratis or for a charge), and offer equivalent access to the 278 | Corresponding Source in the same way through the same place at no 279 | further charge. You need not require recipients to copy the 280 | Corresponding Source along with the object code. If the place to 281 | copy the object code is a network server, the Corresponding Source 282 | may be on a different server (operated by you or a third party) 283 | that supports equivalent copying facilities, provided you maintain 284 | clear directions next to the object code saying where to find the 285 | Corresponding Source. Regardless of what server hosts the 286 | Corresponding Source, you remain obligated to ensure that it is 287 | available for as long as needed to satisfy these requirements. 288 | 289 | e) Convey the object code using peer-to-peer transmission, provided 290 | you inform other peers where the object code and Corresponding 291 | Source of the work are being offered to the general public at no 292 | charge under subsection 6d. 293 | 294 | A separable portion of the object code, whose source code is excluded 295 | from the Corresponding Source as a System Library, need not be 296 | included in conveying the object code work. 297 | 298 | A "User Product" is either (1) a "consumer product", which means any 299 | tangible personal property which is normally used for personal, family, 300 | or household purposes, or (2) anything designed or sold for incorporation 301 | into a dwelling. In determining whether a product is a consumer product, 302 | doubtful cases shall be resolved in favor of coverage. For a particular 303 | product received by a particular user, "normally used" refers to a 304 | typical or common use of that class of product, regardless of the status 305 | of the particular user or of the way in which the particular user 306 | actually uses, or expects or is expected to use, the product. A product 307 | is a consumer product regardless of whether the product has substantial 308 | commercial, industrial or non-consumer uses, unless such uses represent 309 | the only significant mode of use of the product. 310 | 311 | "Installation Information" for a User Product means any methods, 312 | procedures, authorization keys, or other information required to install 313 | and execute modified versions of a covered work in that User Product from 314 | a modified version of its Corresponding Source. The information must 315 | suffice to ensure that the continued functioning of the modified object 316 | code is in no case prevented or interfered with solely because 317 | modification has been made. 318 | 319 | If you convey an object code work under this section in, or with, or 320 | specifically for use in, a User Product, and the conveying occurs as 321 | part of a transaction in which the right of possession and use of the 322 | User Product is transferred to the recipient in perpetuity or for a 323 | fixed term (regardless of how the transaction is characterized), the 324 | Corresponding Source conveyed under this section must be accompanied 325 | by the Installation Information. But this requirement does not apply 326 | if neither you nor any third party retains the ability to install 327 | modified object code on the User Product (for example, the work has 328 | been installed in ROM). 329 | 330 | The requirement to provide Installation Information does not include a 331 | requirement to continue to provide support service, warranty, or updates 332 | for a work that has been modified or installed by the recipient, or for 333 | the User Product in which it has been modified or installed. Access to a 334 | network may be denied when the modification itself materially and 335 | adversely affects the operation of the network or violates the rules and 336 | protocols for communication across the network. 337 | 338 | Corresponding Source conveyed, and Installation Information provided, 339 | in accord with this section must be in a format that is publicly 340 | documented (and with an implementation available to the public in 341 | source code form), and must require no special password or key for 342 | unpacking, reading or copying. 343 | 344 | 7. Additional Terms. 345 | 346 | "Additional permissions" are terms that supplement the terms of this 347 | License by making exceptions from one or more of its conditions. 348 | Additional permissions that are applicable to the entire Program shall 349 | be treated as though they were included in this License, to the extent 350 | that they are valid under applicable law. If additional permissions 351 | apply only to part of the Program, that part may be used separately 352 | under those permissions, but the entire Program remains governed by 353 | this License without regard to the additional permissions. 354 | 355 | When you convey a copy of a covered work, you may at your option 356 | remove any additional permissions from that copy, or from any part of 357 | it. (Additional permissions may be written to require their own 358 | removal in certain cases when you modify the work.) You may place 359 | additional permissions on material, added by you to a covered work, 360 | for which you have or can give appropriate copyright permission. 361 | 362 | Notwithstanding any other provision of this License, for material you 363 | add to a covered work, you may (if authorized by the copyright holders of 364 | that material) supplement the terms of this License with terms: 365 | 366 | a) Disclaiming warranty or limiting liability differently from the 367 | terms of sections 15 and 16 of this License; or 368 | 369 | b) Requiring preservation of specified reasonable legal notices or 370 | author attributions in that material or in the Appropriate Legal 371 | Notices displayed by works containing it; or 372 | 373 | c) Prohibiting misrepresentation of the origin of that material, or 374 | requiring that modified versions of such material be marked in 375 | reasonable ways as different from the original version; or 376 | 377 | d) Limiting the use for publicity purposes of names of licensors or 378 | authors of the material; or 379 | 380 | e) Declining to grant rights under trademark law for use of some 381 | trade names, trademarks, or service marks; or 382 | 383 | f) Requiring indemnification of licensors and authors of that 384 | material by anyone who conveys the material (or modified versions of 385 | it) with contractual assumptions of liability to the recipient, for 386 | any liability that these contractual assumptions directly impose on 387 | those licensors and authors. 388 | 389 | All other non-permissive additional terms are considered "further 390 | restrictions" within the meaning of section 10. If the Program as you 391 | received it, or any part of it, contains a notice stating that it is 392 | governed by this License along with a term that is a further 393 | restriction, you may remove that term. If a license document contains 394 | a further restriction but permits relicensing or conveying under this 395 | License, you may add to a covered work material governed by the terms 396 | of that license document, provided that the further restriction does 397 | not survive such relicensing or conveying. 398 | 399 | If you add terms to a covered work in accord with this section, you 400 | must place, in the relevant source files, a statement of the 401 | additional terms that apply to those files, or a notice indicating 402 | where to find the applicable terms. 403 | 404 | Additional terms, permissive or non-permissive, may be stated in the 405 | form of a separately written license, or stated as exceptions; 406 | the above requirements apply either way. 407 | 408 | 8. Termination. 409 | 410 | You may not propagate or modify a covered work except as expressly 411 | provided under this License. Any attempt otherwise to propagate or 412 | modify it is void, and will automatically terminate your rights under 413 | this License (including any patent licenses granted under the third 414 | paragraph of section 11). 415 | 416 | However, if you cease all violation of this License, then your 417 | license from a particular copyright holder is reinstated (a) 418 | provisionally, unless and until the copyright holder explicitly and 419 | finally terminates your license, and (b) permanently, if the copyright 420 | holder fails to notify you of the violation by some reasonable means 421 | prior to 60 days after the cessation. 422 | 423 | Moreover, your license from a particular copyright holder is 424 | reinstated permanently if the copyright holder notifies you of the 425 | violation by some reasonable means, this is the first time you have 426 | received notice of violation of this License (for any work) from that 427 | copyright holder, and you cure the violation prior to 30 days after 428 | your receipt of the notice. 429 | 430 | Termination of your rights under this section does not terminate the 431 | licenses of parties who have received copies or rights from you under 432 | this License. If your rights have been terminated and not permanently 433 | reinstated, you do not qualify to receive new licenses for the same 434 | material under section 10. 435 | 436 | 9. Acceptance Not Required for Having Copies. 437 | 438 | You are not required to accept this License in order to receive or 439 | run a copy of the Program. Ancillary propagation of a covered work 440 | occurring solely as a consequence of using peer-to-peer transmission 441 | to receive a copy likewise does not require acceptance. However, 442 | nothing other than this License grants you permission to propagate or 443 | modify any covered work. These actions infringe copyright if you do 444 | not accept this License. Therefore, by modifying or propagating a 445 | covered work, you indicate your acceptance of this License to do so. 446 | 447 | 10. Automatic Licensing of Downstream Recipients. 448 | 449 | Each time you convey a covered work, the recipient automatically 450 | receives a license from the original licensors, to run, modify and 451 | propagate that work, subject to this License. You are not responsible 452 | for enforcing compliance by third parties with this License. 453 | 454 | An "entity transaction" is a transaction transferring control of an 455 | organization, or substantially all assets of one, or subdividing an 456 | organization, or merging organizations. If propagation of a covered 457 | work results from an entity transaction, each party to that 458 | transaction who receives a copy of the work also receives whatever 459 | licenses to the work the party's predecessor in interest had or could 460 | give under the previous paragraph, plus a right to possession of the 461 | Corresponding Source of the work from the predecessor in interest, if 462 | the predecessor has it or can get it with reasonable efforts. 463 | 464 | You may not impose any further restrictions on the exercise of the 465 | rights granted or affirmed under this License. For example, you may 466 | not impose a license fee, royalty, or other charge for exercise of 467 | rights granted under this License, and you may not initiate litigation 468 | (including a cross-claim or counterclaim in a lawsuit) alleging that 469 | any patent claim is infringed by making, using, selling, offering for 470 | sale, or importing the Program or any portion of it. 471 | 472 | 11. Patents. 473 | 474 | A "contributor" is a copyright holder who authorizes use under this 475 | License of the Program or a work on which the Program is based. The 476 | work thus licensed is called the contributor's "contributor version". 477 | 478 | A contributor's "essential patent claims" are all patent claims 479 | owned or controlled by the contributor, whether already acquired or 480 | hereafter acquired, that would be infringed by some manner, permitted 481 | by this License, of making, using, or selling its contributor version, 482 | but do not include claims that would be infringed only as a 483 | consequence of further modification of the contributor version. For 484 | purposes of this definition, "control" includes the right to grant 485 | patent sublicenses in a manner consistent with the requirements of 486 | this License. 487 | 488 | Each contributor grants you a non-exclusive, worldwide, royalty-free 489 | patent license under the contributor's essential patent claims, to 490 | make, use, sell, offer for sale, import and otherwise run, modify and 491 | propagate the contents of its contributor version. 492 | 493 | In the following three paragraphs, a "patent license" is any express 494 | agreement or commitment, however denominated, not to enforce a patent 495 | (such as an express permission to practice a patent or covenant not to 496 | sue for patent infringement). To "grant" such a patent license to a 497 | party means to make such an agreement or commitment not to enforce a 498 | patent against the party. 499 | 500 | If you convey a covered work, knowingly relying on a patent license, 501 | and the Corresponding Source of the work is not available for anyone 502 | to copy, free of charge and under the terms of this License, through a 503 | publicly available network server or other readily accessible means, 504 | then you must either (1) cause the Corresponding Source to be so 505 | available, or (2) arrange to deprive yourself of the benefit of the 506 | patent license for this particular work, or (3) arrange, in a manner 507 | consistent with the requirements of this License, to extend the patent 508 | license to downstream recipients. "Knowingly relying" means you have 509 | actual knowledge that, but for the patent license, your conveying the 510 | covered work in a country, or your recipient's use of the covered work 511 | in a country, would infringe one or more identifiable patents in that 512 | country that you have reason to believe are valid. 513 | 514 | If, pursuant to or in connection with a single transaction or 515 | arrangement, you convey, or propagate by procuring conveyance of, a 516 | covered work, and grant a patent license to some of the parties 517 | receiving the covered work authorizing them to use, propagate, modify 518 | or convey a specific copy of the covered work, then the patent license 519 | you grant is automatically extended to all recipients of the covered 520 | work and works based on it. 521 | 522 | A patent license is "discriminatory" if it does not include within 523 | the scope of its coverage, prohibits the exercise of, or is 524 | conditioned on the non-exercise of one or more of the rights that are 525 | specifically granted under this License. You may not convey a covered 526 | work if you are a party to an arrangement with a third party that is 527 | in the business of distributing software, under which you make payment 528 | to the third party based on the extent of your activity of conveying 529 | the work, and under which the third party grants, to any of the 530 | parties who would receive the covered work from you, a discriminatory 531 | patent license (a) in connection with copies of the covered work 532 | conveyed by you (or copies made from those copies), or (b) primarily 533 | for and in connection with specific products or compilations that 534 | contain the covered work, unless you entered into that arrangement, 535 | or that patent license was granted, prior to 28 March 2007. 536 | 537 | Nothing in this License shall be construed as excluding or limiting 538 | any implied license or other defenses to infringement that may 539 | otherwise be available to you under applicable patent law. 540 | 541 | 12. No Surrender of Others' Freedom. 542 | 543 | If conditions are imposed on you (whether by court order, agreement or 544 | otherwise) that contradict the conditions of this License, they do not 545 | excuse you from the conditions of this License. If you cannot convey a 546 | covered work so as to satisfy simultaneously your obligations under this 547 | License and any other pertinent obligations, then as a consequence you may 548 | not convey it at all. For example, if you agree to terms that obligate you 549 | to collect a royalty for further conveying from those to whom you convey 550 | the Program, the only way you could satisfy both those terms and this 551 | License would be to refrain entirely from conveying the Program. 552 | 553 | 13. Use with the GNU Affero General Public License. 554 | 555 | Notwithstanding any other provision of this License, you have 556 | permission to link or combine any covered work with a work licensed 557 | under version 3 of the GNU Affero General Public License into a single 558 | combined work, and to convey the resulting work. The terms of this 559 | License will continue to apply to the part which is the covered work, 560 | but the special requirements of the GNU Affero General Public License, 561 | section 13, concerning interaction through a network will apply to the 562 | combination as such. 563 | 564 | 14. Revised Versions of this License. 565 | 566 | The Free Software Foundation may publish revised and/or new versions of 567 | the GNU General Public License from time to time. Such new versions will 568 | be similar in spirit to the present version, but may differ in detail to 569 | address new problems or concerns. 570 | 571 | Each version is given a distinguishing version number. If the 572 | Program specifies that a certain numbered version of the GNU General 573 | Public License "or any later version" applies to it, you have the 574 | option of following the terms and conditions either of that numbered 575 | version or of any later version published by the Free Software 576 | Foundation. If the Program does not specify a version number of the 577 | GNU General Public License, you may choose any version ever published 578 | by the Free Software Foundation. 579 | 580 | If the Program specifies that a proxy can decide which future 581 | versions of the GNU General Public License can be used, that proxy's 582 | public statement of acceptance of a version permanently authorizes you 583 | to choose that version for the Program. 584 | 585 | Later license versions may give you additional or different 586 | permissions. However, no additional obligations are imposed on any 587 | author or copyright holder as a result of your choosing to follow a 588 | later version. 589 | 590 | 15. Disclaimer of Warranty. 591 | 592 | THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY 593 | APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT 594 | HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY 595 | OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, 596 | THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 597 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM 598 | IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF 599 | ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 600 | 601 | 16. Limitation of Liability. 602 | 603 | IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 604 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 605 | THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY 606 | GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE 607 | USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF 608 | DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD 609 | PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), 610 | EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF 611 | SUCH DAMAGES. 612 | 613 | 17. Interpretation of Sections 15 and 16. 614 | 615 | If the disclaimer of warranty and limitation of liability provided 616 | above cannot be given local legal effect according to their terms, 617 | reviewing courts shall apply local law that most closely approximates 618 | an absolute waiver of all civil liability in connection with the 619 | Program, unless a warranty or assumption of liability accompanies a 620 | copy of the Program in return for a fee. 621 | 622 | END OF TERMS AND CONDITIONS 623 | 624 | How to Apply These Terms to Your New Programs 625 | 626 | If you develop a new program, and you want it to be of the greatest 627 | possible use to the public, the best way to achieve this is to make it 628 | free software which everyone can redistribute and change under these terms. 629 | 630 | To do so, attach the following notices to the program. It is safest 631 | to attach them to the start of each source file to most effectively 632 | state the exclusion of warranty; and each file should have at least 633 | the "copyright" line and a pointer to where the full notice is found. 634 | 635 | {one line to give the program's name and a brief idea of what it does.} 636 | Copyright (C) {year} {name of author} 637 | 638 | This program is free software: you can redistribute it and/or modify 639 | it under the terms of the GNU General Public License as published by 640 | the Free Software Foundation, either version 3 of the License, or 641 | (at your option) any later version. 642 | 643 | This program is distributed in the hope that it will be useful, 644 | but WITHOUT ANY WARRANTY; without even the implied warranty of 645 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 646 | GNU General Public License for more details. 647 | 648 | You should have received a copy of the GNU General Public License 649 | along with this program. If not, see [http://www.gnu.org/licenses/]. 650 | 651 | Also add information on how to contact you by electronic and paper mail. 652 | 653 | If the program does terminal interaction, make it output a short 654 | notice like this when it starts in an interactive mode: 655 | 656 | {project} Copyright (C) {year} {fullname} 657 | This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 658 | This is free software, and you are welcome to redistribute it 659 | under certain conditions; type `show c' for details. 660 | 661 | The hypothetical commands `show w' and `show c' should show the appropriate 662 | parts of the General Public License. Of course, your program's commands 663 | might be different; for a GUI interface, you would use an "about box". 664 | 665 | You should also get your employer (if you work as a programmer) or school, 666 | if any, to sign a "copyright disclaimer" for the program, if necessary. 667 | For more information on this, and how to apply and follow the GNU GPL, see 668 | [http://www.gnu.org/licenses/]. 669 | 670 | The GNU General Public License does not permit incorporating your program 671 | into proprietary programs. If your program is a subroutine library, you 672 | may consider it more useful to permit linking proprietary applications with 673 | the library. If this is what you want to do, use the GNU Lesser General 674 | Public License instead of this License. But first, please read 675 | [http://www.gnu.org/philosophy/why-not-lgpl.html]. 676 | 677 | 678 | 679 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | apacman 2 | ================== 3 | 4 | ArchLinux User Repository ([AUR](https://aur.archlinux.org/packages/)) helper and pacman wrapper 5 | 6 | **Chat room:** [![gitter](https://img.shields.io/gitter/room/apacman/gitter.svg?maxAge=2592000)](https://gitter.im/apacman/Lobby) 7 | 8 | **Comments:** [![AUR package](https://img.shields.io/aur/version/apacman.svg?label=AUR%20package&style=plastic)](https://aur.archlinux.org/packages/apacman/) 9 | 10 | ------------ 11 | 12 | **Total:** [![all downloads badge](https://img.shields.io/github/downloads/oshazard/apacman/total.svg)](https://github.com/oshazard/apacman/releases) 13 | 14 | **Previous:** [![previous release badge](https://img.shields.io/github/downloads/oshazard/apacman/v2.6/total.svg)](https://github.com/oshazard/apacman/releases/tag/v2.6) [![previous release badge](https://img.shields.io/github/downloads/oshazard/apacman/v3.0/total.svg)](https://github.com/oshazard/apacman/releases/tag/v3.0) 15 | 16 | **Current:** [![downloads badge](https://img.shields.io/github/downloads/oshazard/apacman/latest/total.svg)](https://github.com/oshazard/apacman/releases/latest) 17 | 18 | **Votes:** [![Votes](https://img.shields.io/aur/votes/apacman.svg)](https://aur.archlinux.org/packages/apacman/) [![Stars](https://img.shields.io/github/stars/oshazard/apacman.svg?style=social)](https://github.com/oshazard/apacman/stargazers) 19 | (if you like this software, please upvote it on AUR) 20 | 21 | 22 | See also 23 | ------------ 24 | 25 | [![apacman-utils](https://img.shields.io/aur/version/apacman-utils.svg?label=apacman-utils)](https://aur.archlinux.org/packages/apacman-utils/) [(AUR uploader)](https://github.com/oshazard/apacman-utils/blob/master/aurpush) [(Migrate wizard for AUR4)](https://github.com/oshazard/apacman-utils/blob/master/apac-migrate) 26 | 27 | [Forked](https://github.com/keenerd/packer/pull/141) from [packer](https://github.com/keenerd/packer) 28 | 29 | 30 | Installation: 31 | ========== 32 | 1. `pacman -S --needed --asdeps jshon` 33 | 2. `curl -O "https://raw.githubusercontent.com/oshazard/apacman/master/apacman"` 34 | 3. `bash ./apacman -S apacman` 35 | 4. `apacman -S apacman-deps` (_optional_) 36 | 37 | 38 | Documentation: 39 | ========== 40 | * [`man 8 apacman`](https://oshazard.github.io/apacman/apacman.8.html) 41 | * [`man 5 apacman.conf`](https://oshazard.github.io/apacman/apacman.conf.5.html) 42 | 43 | 44 | Changelog: 45 | ========== 46 | 47 | Version 3.1 48 | ---------- 49 | * **NEW** Clean build directory and temp directory (fixed #75) 50 | * **NEW** Expanded -G to fetch old AUR package source (`-G foobar~` or `-G foobar==2.0-1`) 51 | * **NEW** Added new exit codes (fixed #72) 52 | * **NEW** Converted manpages to HTML 53 | * **NEW** Fix for progress bar to match `pacman` (pull request #76) 54 | * **NEW** Fix ZSH completion (pull request #74) 55 | * **NEW** Miscellaneous fixes and cleanup 56 | 57 | Version 3.0 58 | ---------- 59 | * Add alternative --flag=parameter syntax for relevant options 60 | * Fix for installing groups and virtual packages 61 | * Fix to allow installing cached packages without Internet 62 | * Implement unit tests using [bats](https://github.com/sstephenson/bats) (WIP) 63 | * Add regex/wildcard support to -S and -Ss 64 | * Return code 1 on errors 65 | * Improve viewing package comments 66 | * Update manpages 67 | * Closed 10+ issues since last release 68 | 69 | Version 2.9 70 | ----------- 71 | * -P parameter uses AUR passthrough for pkgfile 72 | * Save installed AUR package metadata to database 73 | * --nodatabase parameter does not store AUR database 74 | * --gendb parameter to generate AUR database files 75 | * Display remaining packages in queue 76 | * --notify parameter for notify-send notifications 77 | * --noprogress to disable transaction progress 78 | * Enabled terminal title progress by default 79 | * --edit parameter to override 'noedit' option in config file 80 | * fix CLI flag precedence over config file 81 | 82 | Version 2.6 83 | ----------- 84 | * improve -U to display packages removed from AUR as "unresolvable" 85 | * bug fix for --devel 86 | * merged fix that improves curl debugging 87 | * merged fix that removes split package support 88 | * merged pull requests for AUR5 support 89 | * improved virtual package support 90 | * improved -U handling 91 | * -W parameter to view package comments 92 | * sanity checks for curl with debugging 93 | * fixes for ABS 94 | * improved signed package support 95 | * --keepkeys parameter stores PGP keys 96 | * --purgekeys parameter removes trusted PGP keys 97 | * fix for piping output 98 | * fix for yes/no dialog 99 | 100 | Version 2.0 101 | ----------- 102 | * Split package support and shared source 103 | * Improved AUR4 support 104 | * Bug fix for AUR4 -Si 105 | * Bug fix for built/failed 106 | * --legacy flag for AUR3 107 | * Preliminary AUR4 support 108 | * Signed package support 109 | 110 | Version 1.6 111 | ----------- 112 | * Display [installed], [installed: VER], or [local: VER] in -Ss 113 | * --progress parameter sets terminal title to package status 114 | * Add AUR link to -Si info 115 | * Bug fix for saved AUR packages and --cachevcs 116 | * Bug fix for pacmatic 117 | * Build status log 118 | * Override EDITOR for PKGBUILDs in config file 119 | * --buildonly parameter to build but not AUR install packages 120 | * --nofail parameter to quit if a package does not build 121 | * --purgebuild parameter to remove unneeded build depends 122 | * --skiptest to avoid installing unit test packages 123 | 124 | Version 1.0 125 | ----------- 126 | * Config file support (/etc/apacman.conf) 127 | * Cleaned up manpages 128 | * Replacement for pacsysclean (-L list installed packages by size) 129 | * -G now supports ABS + AUR packages 130 | * --noaur parameter to skip AUR packages 131 | * --warn parameter makes errors non-fatal (only enable if you know what you are doing) 132 | * Run as root workaround for Pacman 4.2+ 133 | 134 | Version 0.6 135 | ----------- 136 | * All features from packer 137 | * Saves built AUR packages to /var/cache/apacman/pkg 138 | * Uses AUR package cache directory if applicable 139 | * --needed parameter that does not install up-to-date packages 140 | * --ignorearch parameter that ignores architectures specified in PKGBUILD (useful for ARM devices) 141 | * --skipcache parameter that skips check for pre-built package in cache directory 142 | * --cachevcs parameter installs cached VCS (git, svn, hg) packages newer than AUR PKGBUILDs 143 | * Partial passthrough support for -R, -Q, and -U pacman parameters 144 | -------------------------------------------------------------------------------- /apacman: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ###################################################################### 3 | # apacman - AUR wrapper forked from packer 4 | version="3.1" 5 | # Copyright OS Hazard 6 | # 7 | # New Features: 8 | # * Build old AUR releases from source (pkgname~, pkgname==ver) 9 | # * Merge fix for aurbar length 10 | # * Clean build files 11 | # * Clean temp files 12 | # * --savedir , --savedir= 13 | # * Install AUR packages offline 14 | # * --testing for unit testing purposes only 15 | # * Regex matching for searching packages 16 | # * Regex matching for installing packages 17 | # * -P patched AUR passthrough for pkgfile 18 | # * Save installed AUR package metadata to database 19 | # * Enabled --progress by default 20 | # * Fix CLI switch precedence over config file 21 | # * Improved support for virtual packages 22 | # * Improved -U handling 23 | # * Built-in ABS support (improved) 24 | # * -W View AUR comments (WIP) 25 | # * Signed package support (improved) 26 | # * Split package support 27 | # * AUR4 support 28 | # * Config file support 29 | # * Workaround for running as root 30 | # * Saves AUR packages to /var/cache/apacman/pkg 31 | # * Uses AUR package cache directory if applicable 32 | # * --asdeps install AUR packages non-explicitly 33 | # * --asexplicit install AUR packages explicitly 34 | # * --edit always ask to edit PKGBUILD 35 | # * --gendb generate AUR database files 36 | # * --keepkeys do not remove imported PGP keys 37 | # * --purgekeys remove imported PGP keys 38 | # * --legacy backwards compatability for AUR3 (deprecated) 39 | # * --progress transaction status in terminal titlebar 40 | # * --nodatabase do not store AUR database 41 | # * --nosource for security do not source PKGBUILDs (WIP) 42 | # * --noprogress no transaction status in titlebar 43 | # * --notify transaction status in notification 44 | # * --buildonly create but do not install packages 45 | # * --nofail do not continue if a package fails to build 46 | # * --purgebuild remove unneeded build dependencies 47 | # * --skiptest skips installing check() unit test packages 48 | # * --config specify alternate config file (default: /etc/apacman.conf) 49 | # * --verbose turns on verbose output 50 | # * -L list installed packages by size 51 | # * --noaur do not actions for aur 52 | # * --warn treat errors as non-fatal warnings 53 | # * --needed does not install up-to-date packages 54 | # * --ignorearch ignores architectures specified in PKGBUILD 55 | # * --skipcache skips check for pre-built package in cache directory 56 | # * --cachevcs installs cached VCS (git, svn, hg) packages newer than AUR PKGBUILDs 57 | # * partial passthrough for -R, -Q, -T and -U parameters 58 | ###################################################################### 59 | 60 | # Copyright Matthew Bruenig 61 | # This program is free software: you can redistribute it and/or modify 62 | # it under the terms of the GNU General Public License as published by 63 | # the Free Software Foundation, either version 3 of the License, or 64 | # (at your option) any later version. 65 | 66 | # This program is distributed in the hope that it will be useful, 67 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 68 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 69 | # GNU General Public License for more details. 70 | 71 | # You should have received a copy of the GNU General Public License 72 | # along with this program. If not, see . 73 | 74 | [[ $PACMAN ]] || PACMAN="pacman" 75 | pacmanbin="/usr/bin/pacman" 76 | 77 | makepkgconf='/etc/makepkg.conf' 78 | usermakepkgconf="$HOME/.makepkg.conf" 79 | pacmanconf='/etc/pacman.conf' 80 | apacmanconf='/etc/apacman.conf' 81 | gpgconf='/etc/pacman.d/gnupg/gpg.conf' 82 | downdir='/var/cache/pacman/pkg' 83 | savedir='/var/cache/apacman/pkg' 84 | database='/var/lib/apacman' 85 | pacmandb='/var/lib/pacman/sync/aur.db' 86 | pkgfiledb='/var/cache/pkgfile/aur.files' 87 | localrepo='aur' 88 | builddir="${TMPDIR:-/tmp}/pkgbuild-$UID" 89 | tmpdir="${TMPDIR:-/tmp}/apacmantmp-$UID" 90 | testdir="${TMPDIR:-/tmp}/apacman-testing" 91 | 92 | editor="vi" 93 | [[ $EDITOR ]] && editor="$EDITOR" 94 | 95 | pager="less -R" 96 | [[ $PAGER ]] && pager="$PAGER" 97 | 98 | RPCURL="https://aur.archlinux.org/rpc/?v=5&type" 99 | PKGURL="https://aur.archlinux.org" 100 | WEBURL="https://www.archlinux.org" 101 | ABSURL="rsync.archlinux.org" 102 | legacy="0" 103 | 104 | if [[ -t 1 && ! $COLOR = "NO" ]]; then 105 | COLOR1='\e[1;39m' 106 | COLOR2='\e[1;32m' 107 | COLOR3='\e[1;35m' 108 | COLOR4='\e[1;36m' 109 | COLOR5='\e[1;34m' 110 | COLOR6='\e[1;33m' 111 | COLOR7='\e[1;31m' 112 | ENDCOLOR='\e[0m' 113 | S='\\' 114 | fi 115 | _WIDTH="$(stty size | cut -d ' ' -f 2)" 116 | 117 | trap ctrlc INT 118 | ctrlc() { 119 | echo 120 | exit 1 121 | } 122 | 123 | err() { 124 | echo -e "$1" 125 | [[ "$warn" == 1 ]] || exit 3 126 | } 127 | 128 | dne() { 129 | echo -e "$1" 130 | [[ "$warn" == 1 ]] || exit 5 131 | } 132 | 133 | invalid() { 134 | echo -e "${COLOR7}error:${ENDCOLOR} invalid option \`$1'" 135 | [[ $nofail ]] && exit 2 136 | } 137 | 138 | progress() { 139 | [[ $progress == 1 || $progress == 3 ]] && echo -en "\033]2;$@\007" 140 | [[ $progress == 2 || $progress == 3 ]] && notify-send "$@" 141 | } 142 | 143 | deptest() { 144 | type -p $1 &>/dev/null 145 | } 146 | 147 | version() { 148 | pacver=$($pacmanbin -V 2>/dev/null | grep -o "Pacman v.*") 149 | echo " === = = ===== apacman v${version} - forked from packer" 150 | echo " = = = = = = ${pacver}" 151 | echo ' ===== = = ====' 152 | echo ' = = = = = = This program may be freely redistributed under' 153 | echo ' = = === = = the terms of the GNU General Public License.' 154 | exit 155 | } 156 | 157 | usage() { 158 | echo 'usage: apacman [option] [package] [package] [...]' 159 | echo 'If no operation is specified, searches and installs packages by number' 160 | echo 161 | echo 'OPERATIONS' 162 | echo ' -S - installs package' 163 | echo ' -Syu|-Su - updates all packages, also takes -uu and -yy options' 164 | echo ' -Ss|-Ssq - searches for package' 165 | echo ' -Si - outputs info for package' 166 | echo ' -G - download and extract aur tarball only' 167 | echo ' -L - list installed packages by size' 168 | echo ' -P - passthrough for pkgfile command' 169 | echo ' -W - view web comments for package' 170 | echo 171 | echo 'OPTIONS' 172 | echo ' --asdeps - install AUR packages marked as dependencies' 173 | echo ' --asexplicit - install AUR packages marked as explicit' 174 | echo ' --auronly - only do actions for AUR' 175 | echo ' --buildonly - create but do not install packages' 176 | echo ' --config - specify alternate config file (default: /etc/apacman.conf)' 177 | echo ' --cachevcs - installs cached VCS packages newer than AUR PKGBUILDs' 178 | echo ' --devel - update VCS (git, svn, hg) packages during -Su' 179 | echo ' --edit - always ask to edit PKGBUILD' 180 | echo ' --gendb - generate AUR database files' 181 | echo ' --ignore - takes a comma-separated list of packages to ignore' 182 | echo ' --ignorearch - ignore a missing or incomplete architecture field' 183 | echo ' --keepkeys - do not remove imported PGP keys' 184 | echo ' --legacy - uses AUR3.0 instead of AUR4.0 (deprecated)' 185 | echo ' --needed - do not install up-to-date packages' 186 | echo ' --noaur - do not actions for AUR' 187 | echo ' --noconfirm - do not prompt for any confirmation' 188 | echo ' --nodatabase - do not store AUR database' 189 | echo ' --noedit - do not prompt to edit files' 190 | echo ' --nofail - do not continue if a package fails to build' 191 | echo ' --noprogress - no transaction status in titlebar' 192 | echo ' --nosource - do not source PKGBUILDs (WIP)' 193 | echo ' --notify - transaction status in notification' 194 | echo ' --preview - edit pkgbuild before sourcing' 195 | echo ' --progress - transaction status in terminal titlebar' 196 | echo ' --purgebuild - remove unneeded build dependencies' 197 | echo ' --purgekeys - remove trusted PGP keys' 198 | echo ' --quickcheck - check for updates and exit' 199 | echo ' --quiet - only output package name for searches' 200 | echo ' --savedir - takes a path as the cache directory' 201 | echo ' --skipcache - skips check for pre-built package in cache directory' 202 | echo ' --skipinteg - when using makepkg, do not check md5s' 203 | echo ' --skiptest - when using makepkg, do not parse check() test deps' 204 | echo ' --testing - for unit testing purposes only' 205 | echo ' --warn - treat errors as non-fatal warnings' 206 | echo ' -v - turns on verbose output' 207 | echo ' -V - display version' 208 | echo ' -h - outputs this message' 209 | exit 210 | } 211 | 212 | varstatus() { 213 | val=$(eval echo \$$1) 214 | if [ "$val" == 1 ]; then 215 | echo -e "${COLOR1}$1${ENDCOLOR}" | awk '{printf "%-25s %-40s\n",$1,": yes"}'; 216 | elif [ "$val" == 0 ]; then 217 | echo -e "${COLOR1}$1${ENDCOLOR}" | awk '{printf "%-25s %-40s\n",$1,": no"}'; 218 | elif [ "$val" == 2 ] || [ "$val" == 3 ]; then 219 | echo -e "${COLOR1}$1${ENDCOLOR}" | awk '{printf "%-25s %-40s\n",$1,": alt mode"}'; 220 | elif [[ -r $val ]]; then 221 | echo -e "${COLOR1}$1${ENDCOLOR} $val" | awk '{printf "%-25s %-40s\n",$1,": "$2}'; 222 | fi 223 | } 224 | 225 | infoconf() { 226 | vars="apacmanconf builddir database downdir editor localrepo makepkgconf" 227 | vars="$vars pacmanconf pacmandb pkgfiledb savedir tmpdir usermakepkgconf" 228 | for i in $vars; do 229 | varstatus $i 230 | done 231 | 232 | vars="asdeps asexplicit auronly buildonly cachevcs force gendb ignorearch keepkeys" 233 | vars="$vars legacy needed noaur noconfirm nodatabase noedit nofail preview progress" 234 | vars="$vars purgebuild purgekeys quiet skipcache skipinteg skiptest testing warn" 235 | for j in $vars; do 236 | varstatus $j 237 | done 238 | } 239 | 240 | # Called whenever anything needs to be run as root ($@ is the command) 241 | runasroot() { 242 | if [[ $testing == 1 ]]; then 243 | fakeroot "$@" || code='10' 244 | elif [[ $UID -eq 0 ]]; then 245 | "$@" || code='11' 246 | elif sudo -v &>/dev/null && sudo -l "$@" &>/dev/null; then 247 | sudo -E "$@" || code='12' 248 | else 249 | echo -n "root " 250 | su -c "$(printf '%q ' "$@")" || code='13' 251 | fi 252 | } 253 | 254 | # debugging for curl ($1 is curl exit code, $2 package name) 255 | curlyq() { 256 | if [ $1 -eq 6 ]; then 257 | offline='1' 258 | echo -e "${COLOR7}:: ${COLOR1}No internet connection${ENDCOLOR}" 259 | elif [ $1 -ne 0 -a $1 -ne 7 -a $1 -ne 22 ]; then 260 | echo -e "${COLOR6}notice:${ENDCOLOR} curl exited with code $1 on $2" 261 | if deptest man; then 262 | curlman=$(man curl | sed '1,/^EXIT CODES/d' | grep " $1 ") 263 | curlman=$(echo "$curlman" | awk -F " " '{print $3}' | sed 's/^[ \t]*//') 264 | echo -e "${COLOR3}manpage:${ENDCOLOR} $curlman" 265 | fi 266 | fi 267 | } 268 | 269 | # Extract from AUR4 .info 270 | infoparser() { 271 | pkgname=$(jshon -Qe results < $1 -Qe Name -u) 272 | pkgver=$(jshon -Qe results < $1 -Qe Version -u) 273 | pkgbase=$(jshon -Qe results < $1 -Qe PackageBase -u) 274 | url=$(jshon -Qe results < $1 -Qe URL -u) 275 | licnum=$(($(jshon -Qe results < $1 -a -e License -l)-1)) 276 | license=$(while [ ${licnum} -ge '0' ]; do jshon -e results < $1 -a -e License -e ${licnum} -u ; ((licnum-=1)) ; done) 277 | groups=$(jshon -Qe results < $1 -Qe PackageBase -u) 278 | } 279 | 280 | # FIXME 281 | parser() { 282 | if [ -f "$1" ]; then 283 | if [[ $nosource == 1 ]]; then 284 | unset pkgname pkgver pkgrel arch checkdepends makedepends depends epoch 285 | pkgname=$(grep -o "^pkgname=\S*" "$1" | awk -F = '{print $2}' | tr -dc 'a-z0-9-_.\n'); 286 | pkgver=$(grep -o "^pkgver=\S*" "$1" | awk -F = '{print $2}' | tr -dc 'a-z0-9-_.\n'); 287 | pkgrel=$(grep -o "^pkgrel=\S*" "$1" | awk -F = '{print $2}' | tr -dc 'a-z0-9-_.\n'); 288 | epoch=$(grep -o "^epoch=\S*" "$1" | awk -F = '{print $2}' | tr -dc 'a-z0-9-_.\n'); 289 | _arch=$(grep "^arch=" "$1" | awk -F = '{print $2}' | tr -dc 'a-z0-9-_. \n'); 290 | _checkdepends=$(grep "^checkdepends=" "$1" | awk -F = '{print $2}' | tr -dc 'a-z0-9-_. \n'); 291 | _makedepends=$(grep "^makedepends=" "$1" | awk -F = '{print $2}' | tr -dc 'a-z0-9-_. \n'); 292 | _depends=$(grep "^depends=" "$1" | awk -F = '{print $2}' | tr -dc 'a-z0-9-_. \n'); 293 | 294 | for _machine in $_arch; do arch+=("$_machine"); done 295 | for _pkg in $_checkdepends; do depends+=("$_pkg"); done 296 | for _pkg in $_makedepends; do makedepends+=("$_pkg"); done 297 | for _pkg in $_depends; do depends+=("$_pkg"); done 298 | 299 | echo "==> pkgname: $pkgname" 300 | echo "==> pkgver: $pkgver" 301 | echo "==> pkgrel: $pkgrel" 302 | echo "==> arch: ${arch[@]}" 303 | echo "==> checkdepends: ${checkdepends[@]}" 304 | echo "==> makedepends: ${makedepends[@]}" 305 | echo "==> depends: ${depends[@]}" 306 | return 0 307 | else 308 | . "$1" 309 | fi 310 | else 311 | return 1 312 | fi 313 | } 314 | 315 | # grep PKGBUILD arrays ($1 is array var) 316 | pkgbuildgrep() { 317 | grep "^${1}=" PKGBUILD 2>/dev/null | awk -F = '{print $2}' | tr -dc 'a-z0-9-_. \n'; 318 | } 319 | 320 | # Source apacman.conf file 321 | sourceapacmanconf() { 322 | [[ -r "$apacmanconf" ]] && . "$apacmanconf" 323 | [[ $noconfirm ]] && PACOPTS+=("--noconfirm") 324 | [[ $needed ]] && PACOPTS+=("--needed") 325 | [[ $skiptest ]] && MAKEPKGOPTS+=("--nocheck") 326 | [[ $skipinteg ]] && MAKEPKGOPTS+=("--skipinteg") 327 | [[ $ignorearch ]] && MAKEPKGOPTS+=("--ignorearch") 328 | export keepkeys noconfirm COLOR1 COLOR2 COLOR3 COLOR4 COLOR5 COLOR6 COLOR7 ENDCOLOR 329 | } 330 | 331 | # Source makepkg.conf file 332 | sourcemakepkgconf() { 333 | . "$makepkgconf" 334 | [[ -r "$usermakepkgconf" ]] && . "$usermakepkgconf" 335 | } 336 | 337 | # Parse IgnorePkg and --ignore, put in globally accessible ignoredpackages array 338 | getignoredpackages() { 339 | IFS=',' read -ra ignoredpackages <<< "$ignorearg" 340 | ignoredpackages+=( $(grep '^ *IgnorePkg' "$pacmanconf" | cut -d '=' -f 2-) ) 341 | } 342 | 343 | # Checks to see if $1 is an ignored package 344 | isignored() { 345 | [[ " ${ignoredpackages[@]} " =~ " $1 " ]] 346 | } 347 | 348 | # List installed packages 349 | getlistpackages() { 350 | $pacmanbin -Qi${pacmanarg} | grep -e "^Name " -e "^Installed Size " | \ 351 | awk '{if ($(NF-1) ~ /^[0-9]/) printf $(NF-1); print $NF}' | paste -s -d' \n' | \ 352 | sed -e 's/iB$//' -e 's/\.00K/K/' -e 's/\.00B/B/' | awk '{printf "%-10s %-40s\n",$2,$1}' | sort -h 353 | exit $? 354 | } 355 | 356 | # Tests whether package exists on the aur ($1 is name, $2 is dereferenced variable) 357 | existsinaur() { 358 | chosenpkg=$(echo "$1" | sed 's/\~$//' | awk -F "==" '{print $1}') 359 | val="${!2}" 360 | 361 | regexmatch="$(echo $val | tr -dc '0-9a-z-.\n')" 362 | if [[ $val != $regexmatch ]]; then 363 | matches=$(aurpkglist "$val") 364 | selectprovider "$val" $matches 365 | if [[ $providepkg ]]; then 366 | eval "$2=\"$providepkg\"" 2>/dev/null 367 | chosenpkg="$providepkg" 368 | fi 369 | fi 370 | 371 | rpcinfo "$chosenpkg" 372 | [[ "$(jshon -Qe resultcount -u < "$tmpdir/$chosenpkg.info")" != "0" ]] 373 | } 374 | 375 | # Tests whether $1 exists in pacman 376 | existsinpacman() { 377 | chosenpkg=$1 378 | if [[ $regex = 1 ]]; then 379 | chosenpkg=$(selectprovider) 380 | fi 381 | 382 | $pacmanbin -Si -- "$chosenpkg" &>/dev/null 383 | } 384 | 385 | # Tests whether $1 is provided in pacman, sets globally accessibly providepkg var 386 | providedinpacman() { 387 | unset providepkg 388 | IFS=$'\n' read -rd '' -a providepkg < <($pacmanbin -Ssq -- "^$1$") 389 | selectprovider $1 "${providepkg[@]}" 390 | [[ -n $providepkg ]] 391 | } 392 | 393 | # Select option from numeric choice ($1 is num, $@ is array of choices) 394 | pickone() { 395 | n=1 396 | maxnum=$1 397 | shift 398 | choices=( $(echo $@) ) 399 | 400 | for v in ${choices[@]}; do 401 | echo "${n}) $v"; 402 | n=$((n+1)) 403 | done 404 | echo 405 | echo -n "Enter a selection (default=1): " 406 | read -r 407 | 408 | # Parse answer 409 | if [[ $REPLY ]]; then 410 | for num in $REPLY; do 411 | if [[ $num -le $maxnum ]] && [[ $num -ge 1 ]]; then 412 | num=$((num-1)) 413 | chosenone="${choices[$num]}" 414 | else 415 | err "Number \`$num' is not assigned to any of the options." 416 | fi 417 | done 418 | else 419 | chosenone="$choices" 420 | fi 421 | 422 | echo "$chosenone" 423 | } 424 | 425 | # Prompts options for virtual packages, $1 is package, $@ is array of packages 426 | selectprovider() { 427 | virtpkg=$1 428 | shift 429 | virtual=($@) 430 | virtnum="${#virtual[@]}" 431 | if [[ $virtnum -eq 0 ]]; then 432 | return 1 433 | elif [[ $virtnum -eq 1 ]]; then 434 | providepkg="$virtual" 435 | elif [[ $# -gt 1 ]]; then 436 | # Multiple providers 437 | provmsg="provide" 438 | [[ $regex = 1 ]] && provmsg="match" && unset regex 439 | echo -e "${COLOR5}:: ${COLOR1}There are $virtnum packages that $provmsg $virtpkg:${ENDCOLOR}" 440 | providepkg=$(pickone $virtnum ${virtual[@]}) 441 | fi 442 | } 443 | 444 | # Source old release ($1 is pkgver, $2 is pkgrel) 445 | checkrelease() { 446 | chistory=$(git rev-list --all) 447 | cmatch=$(git grep --all-match -e "pkgver = $1" -e "pkgrel = $2" ${chistory} -- .SRCINFO) 448 | chash=$(echo "$cmatch" | awk NR==1 | awk -F : '{print $1}') 449 | if [[ ! $chash ]]; then 450 | return 1 451 | fi 452 | } 453 | 454 | # Parse AUR4 git repo 455 | relhistory() { 456 | chistory=$(git rev-list --all) 457 | cpkglog=$(git grep -A 1 -e "pkgver =" ${chistory} -- .SRCINFO) 458 | cversions=$(echo "$cpkglog" | awk '{$1=""; print $0}' | sed -e 's/^$/%%%/') 459 | cwtf=$(echo "$cversions" | sed -e 's/ pkgver = //' -e 's/ pkgrel = /-/') 460 | creleases=$(echo "$cwtf" | tr -d '\n' | sed -e 's/$/\n/' -e 's/%%%/\n/g') 461 | echo "$creleases" 462 | } 463 | 464 | # Select AUR package version ($1 is pkgname) 465 | selectrel() { 466 | release=( $(relhistory) ) 467 | relnum=${#release[@]} 468 | echo -e "${COLOR5}:: ${COLOR1}There are $relnum releases for $1:${ENDCOLOR}" 469 | pickone $relnum ${release[@]} 470 | } 471 | 472 | # Build old AUR releases ($1 is package name) 473 | clonehistory() { 474 | if deptest git; then 475 | git clone --quiet "${PKGURL}/${1}.git" 476 | cd "$1" 477 | 478 | if [ -z $2 ]; then 479 | selectrel "$1" 480 | relver="$chosenone" 481 | else 482 | relver="$2" 483 | fi 484 | 485 | if checkrelease ${relver%-*} ${relver##*-}; then 486 | echo -e "${COLOR5}:: ${COLOR1}Checking out $1 ${relver%-*}-${relver##*-}${ENDCOLOR}" 487 | git checkout --quiet "$chash" 488 | ls | sed "s/^/$1\//" 489 | else 490 | err "${COLOR7}error:${ENDCOLOR} package '$1' release '$relver' was not found" 491 | fi 492 | fi 493 | } 494 | 495 | # Tests whether $1 exists in a pacman group 496 | existsinpacmangroup() { 497 | [[ $($pacmanbin -Sgq "$1") ]] 498 | } 499 | 500 | # Tests whether $1 exists locally 501 | existsinlocal() { 502 | $pacmanbin -Qq -- "$1" &>/dev/null 503 | } 504 | 505 | # Scrapes .PKGINFO from local package ($1 is filename) 506 | scrapelocaldeps() { 507 | [[ -f "$1" ]] || err "${COLOR7}error:${ENDCOLOR} '$1': could not access file" 508 | dependencies=( $(pacman -T $(tar -x .PKGINFO -O -f "$1" 2>/dev/null | grep "^depend =" | awk -F " = " '{print $2}')) ) 509 | } 510 | 511 | # Scrapes the aur deps from PKGBUILDS and puts in globally available dependencies array 512 | scrapeaurdeps() { 513 | pkginfo "$1" "$preview" 514 | parser "$tmpdir/$1.PKGBUILD" 515 | [[ $skiptest = 1 ]] && unset checkdepends 516 | IFS=$'\n' 517 | dependencies=( $(echo -e "${depends[*]}\n${makedepends[*]}\n${checkdepends[*]}" | sed -e 's/=.*//' -e 's/>.*//' -e 's/<.*//'| sort -u) ) 518 | purgedepends=( $(echo -e "${makedepends[*]}\n${checkdepends[*]}" | sed -e 's/=.*//' -e 's/>.*//' -e 's/<.*//'| sort -u) ) 519 | unset IFS 520 | } 521 | 522 | # Finds dependencies of package $1 523 | # Sets pacmandeps and aurdeps array, which can be accessed globally after function runs 524 | finddeps() { 525 | # loop through dependencies, if not installed, determine if pacman or aur deps 526 | pacmandeps=() 527 | aurdeps=() 528 | scrapeaurdeps "$1" 529 | [[ $buildonly = 1 || $purgebuild = 1 ]] && purgedeps+=( $($pacmanbin -T "${purgedepends[@]}") ) 530 | missingdeps=( $($pacmanbin -T "${dependencies[@]}") ) 531 | while [[ $missingdeps ]]; do 532 | checkdeps=() 533 | for dep in "${missingdeps[@]}"; do 534 | if [[ " $1 ${aurdeps[@]} ${pacmandeps[@]} " =~ " $dep " ]]; then 535 | continue 536 | fi 537 | if existsinpacman "$dep"; then 538 | pacmandeps+=("$dep") 539 | elif existsinaur "$dep" "dep"; then 540 | if [[ $aurdeps ]]; then 541 | aurdeps=("$dep" "${aurdeps[@]}") 542 | else 543 | aurdeps=("$dep") 544 | fi 545 | checkdeps+=("$dep") 546 | elif providedinpacman "$dep"; then 547 | pacmandeps+=("$providepkg") 548 | else 549 | [[ $option = "install" ]] && dne "Dependency \`$dep' of \`$1' does not exist." 550 | echo "Dependency \`$dep' of \`$1' does not exist." 551 | return 1 552 | fi 553 | done 554 | missingdeps=() 555 | for dep in "${checkdeps[@]}"; do 556 | scrapeaurdeps "$dep" 557 | for depdep in "${dependencies[@]}"; do 558 | [[ $($pacmanbin -T "$depdep") ]] && missingdeps+=("$depdep") 559 | done 560 | done 561 | done 562 | return 0 563 | } 564 | 565 | # Displays a progress bar ($1 is numerator, $2 is denominator, $3 is candy/normal) 566 | aurbar() { 567 | # Delete line 568 | printf "\033[0G" 569 | 570 | # Get vars for output 571 | beginline=" aur" 572 | beginbar="[" 573 | endbar="]" 574 | perc="$(($1*100/$2))" 575 | width="$(stty size)" 576 | width="${width##* }" 577 | infolen="$(($width*6/10))" 578 | [ $infolen -lt 50 ] && infolen=50 579 | 580 | charsbefore="$((${#beginline}+${#1}+${#2}+3))" 581 | spaces="$(($infolen-$charsbefore))" 582 | barchars="$(($width-$infolen-${#beginbar}-${#endbar}-6))" 583 | hashes="$(($barchars*$perc/100))" 584 | dashes="$(($barchars-$hashes))" 585 | 586 | # Print output 587 | printf "$beginline %${spaces}s$1 $2 ${beginbar}" "" 588 | 589 | # ILoveCandy 590 | if [[ $3 = candy ]]; then 591 | for ((n=1; n<$hashes; n++)); do 592 | if (( (n==($hashes-1)) && ($dashes!=0) )); then 593 | (($n%2==0)) && printf "\e[1;33mc\e[0m" || printf "\e[1;33mC\e[0m" 594 | else 595 | printf "-" 596 | fi 597 | done 598 | for ((n=1; n<$dashes; n++)); do 599 | N=$(( $n+$hashes )) 600 | (($hashes>0)) && N=$(($N-1)) 601 | (($N%3==0)) && printf "o" || printf " " 602 | done 603 | else 604 | for ((n=0; n<$hashes; n++)); do 605 | printf "#" 606 | done 607 | for ((n=0; n<$dashes; n++)); do 608 | printf "-" 609 | done 610 | fi 611 | printf "%s %3s%%\r" ${endbar} ${perc} 612 | } 613 | 614 | aurpkglist() { 615 | if ! [[ -f "$tmpdir/packages.lst" ]]; then 616 | curl -Lfs "$PKGURL/packages.gz" | gunzip > "$tmpdir/packages.lst" 617 | fi 618 | 619 | grep -E "$1" "$tmpdir/packages.lst" | sort 620 | } 621 | 622 | rpcinfo() { 623 | if ! [[ -f "$tmpdir/$1.info" ]]; then 624 | curl -LfGs --data-urlencode "arg=$1" "$RPCURL=info" > "$tmpdir/$1.info" 625 | fi 626 | } 627 | 628 | pkglink() { 629 | rpcinfo $1 630 | aurpkgpath=$(jshon -Q -e results -a -e URLPath -u < "$tmpdir/$1.info") 631 | [[ $aurpkgpath ]] && echo "${PKGURL}${aurpkgpath}" 632 | } 633 | 634 | absrepo() { 635 | $pacmanbin -Si -- "$1" 2>/dev/null | grep ^Repository | awk '{print $NF}' | awk NR==1 636 | } 637 | 638 | # find pkgbase name for split packages ($1 is package repository, $2 is package name) 639 | absbase() { 640 | webpkg=$(curl -Lfs "$WEBURL/packages/$1/${makearch}/$2/"); cstatus=$? 641 | if [ $cstatus -eq 22 ]; then 642 | webpkg=$(curl -Lfs "$WEBURL/packages/$1/any/$2/"); cstatus=$? 643 | fi 644 | 645 | if [ $cstatus -eq 0 ]; then 646 | echo "$webpkg" | sed -e 's/<[^>]\+>/ /g' -e 's/^[ \t]*//' -e 's/[ \t]*$//' -e '/^$/d' | grep -A 1 "^Base Package:" | sed '1d' 647 | fi 648 | } 649 | 650 | # downloads source files ($1 is package repository, $2 is package name) 651 | abslink() { 652 | deptest rsync || err "${COLOR7}error:${ENDCOLOR} $option requires \`rsync'" 653 | rflags="-mrt --info=progress2 --no-motd --delete-after --no-p --no-o --no-g" 654 | rsync $rflags --include=/$1{,/$2} --exclude=/{$1/,}* ${ABSURL}::abs/{${makearch},any}/ . 655 | 656 | # try again 657 | if [ ! -d "$1/$2" ]; then 658 | pkgbase=$(absbase "$1" "$2") 659 | if [[ $pkgbase ]]; then 660 | [ -d "$1/$pkgbase" ] && rm -r "$1/$pkgbase" 661 | echo -e "${COLOR5}--> ${COLOR1}selected base: $pkgbase${ENDCOLOR}" 662 | rsync $rflags --include=/$1{,/$pkgbase} --exclude=/{$1/,}* ${ABSURL}::abs/{${makearch},any}/ . 663 | mv "$1/$pkgbase" "$1/$2" 664 | fi 665 | fi 666 | } 667 | 668 | # downloads pkgbuild ($1), edits if $2 is set 669 | pkginfo() { 670 | if ! [[ -f "$tmpdir/$1.PKGBUILD" ]]; then 671 | pkgpath=$(pkglink $1) 672 | basepath=$(echo ${pkgpath##*/} | sed 's/\.tar\.gz$//') 673 | [[ $basepath ]] || err "${COLOR7}error:${ENDCOLOR} package '$package' was not found" 674 | 675 | if [[ $legacy == 1 ]]; then 676 | curl -Lfs "${pkgpath%/*}/PKGBUILD" > "$tmpdir/$1.PKGBUILD" 677 | cstatus=$?; curlyq "$cstatus" "$1" 678 | else 679 | curl -Lfs "${pkgpath%/*/*}/plain/PKGBUILD?h=${basepath}" > "$tmpdir/$1.PKGBUILD" 680 | cstatus=$?; curlyq "$cstatus" "$1" 681 | fi 682 | 683 | if [[ $2 ]]; then 684 | # rename for syntax highlighting 685 | cp "$tmpdir/$1.PKGBUILD" "$tmpdir/PKGBUILD" 686 | confirm_edit "${COLOR6}Edit $1 PKGBUILD with \$editor? [Y/n]${ENDCOLOR} " "$tmpdir/PKGBUILD" 687 | mv "$tmpdir/PKGBUILD" "$tmpdir/$1.PKGBUILD" 688 | fi 689 | fi 690 | } 691 | 692 | # Checks if package is newer on aur ($1 is package name, $2 is local version) 693 | aurversionisnewer() { 694 | package="$1" 695 | rpcinfo "$package" 696 | unset aurversion 697 | if existsinaur "$package" "package"; then 698 | aurversion="$(jshon -Q -e results -a -e Version -u < "$tmpdir/$package.info")" 699 | if [[ "$(LC_ALL=C vercmp "$aurversion" "$2")" -gt 0 ]]; then 700 | return 0 701 | fi 702 | fi 703 | return 1 704 | } 705 | 706 | isoutofdate() { 707 | rpcinfo "$1" 708 | [[ "$(jshon -Q -e results -a -e OutOfDate -u < "$tmpdir/$1.info")" = "1" ]] 709 | } 710 | 711 | # Generate local AUR database 712 | aurgendb() { 713 | savecount=$(ls $savedir 2>/dev/null | wc -l) 714 | echo -e "${COLOR5}::${COLOR1} Generating AUR database... ($savecount)${ENDCOLOR}" 715 | progress "Generating AUR DB ($savecount)" 716 | runasroot mkdir -p ${database}/{local,raw} 717 | savedpkgs=$(ls ${savedir}/*-*-{any,${makearch}}.pkg.{tar,tar.xz} 2>/dev/null) 718 | runasroot repo-add ${database}/raw/aur.db.tar.gz $savedpkgs 719 | runasroot tar -xzf ${database}/raw/aur.files.tar.gz -C ${database}/local/ 720 | runasroot ln -s ${database}/raw/aur.db.tar.gz $pacmandb 2>/dev/null 721 | aurpkgfile 722 | echo -e "${COLOR5}::${COLOR1} Updated AUR database${ENDCOLOR}" 723 | [[ -z $option && -z $packageargs ]] && exit 724 | } 725 | 726 | # Update AUR pkgfile database 727 | aurpkgfile() { 728 | if ! deptest pkgfile; then 729 | return 730 | fi 731 | 732 | pkgdir=$(mktemp -d) 733 | if [[ -d ${database}/local ]]; then 734 | cd ${database}/local 735 | aurlist=$(ls) 736 | for aurpkg in $aurlist; do 737 | grep -v "^%" $aurpkg/files | sed 's/^/\//' > $pkgdir/$aurpkg 738 | done 739 | fi 740 | 741 | cd "$pkgdir" 742 | runasroot tar -czf ${database}/raw/pkgfile.tar.gz * 743 | cd - >/dev/null 744 | rm -r "$pkgdir" 745 | 746 | pkgfiledir=$(dirname "$pkgfiledb" 2>/dev/null) 747 | if [[ -d "$pkgfiledir" ]]; then 748 | runasroot ln -s ${database}/raw/pkgfile.tar.gz "$pkgfiledb" 2>/dev/null 749 | fi 750 | } 751 | 752 | # Update local AUR database ($1 is package, $2 is filename) 753 | aurlocaldb() { 754 | if [[ $nodatabase ]]; then 755 | return 756 | elif [[ ! -d $database ]] || [[ ! -f $pacmandb ]]; then 757 | runasroot mkdir -p ${database}/{local,raw} 758 | echo -e "${COLOR5}::${COLOR1} Checking AUR database${ENDCOLOR}" 759 | savecount=$(ls $savedir 2>/dev/null | wc -l) 760 | if [[ $savecount -gt 0 ]]; then 761 | echo -e "${COLOR7}warning:${ENDCOLOR} need to run ${COLOR1}apacman --gendb${ENDCOLOR} (found $savecount AUR files!)" 762 | else 763 | runasroot repo-add -q ${database}/raw/aur.db.tar.gz 2>/dev/null 764 | runasroot ln -s ${database}/raw/aur.db.tar.gz $pacmandb 2>/dev/null 765 | fi 766 | fi 767 | 768 | runasroot repo-add -q ${database}/raw/aur.db.tar.gz "$2" 2>/dev/null 769 | pkgnamever=$(echo "$2" | awk -F "$savedir/" '{print $2}' | sed "s/-any.pkg.tar.*//g;s/-${makearch}.pkg.tar.*//g") 770 | runasroot tar -C ${database}/local/ -x "$pkgnamever/" -zf ${database}/raw/aur.files.tar.gz && 771 | aurpkgfile 772 | } 773 | 774 | # List bundle package files 775 | listbundle() { 776 | if [[ $bundle ]]; then 777 | echo -e "${COLOR5}==>${ENDCOLOR} Packages to bundle" 778 | echo ${bundle[@]} | sed 's/ /\n/g' | tee "$tmpdir/bundle.lst" 779 | fi 780 | } 781 | 782 | # $1 is prompt, $2 is file 783 | confirm_edit() { 784 | if [[ (! -f "$2") || "$noconfirm" || "$noedit" ]]; then 785 | return 786 | fi 787 | echo -en "$1" 788 | if proceed; then 789 | $editor "$2" 790 | fi 791 | } 792 | 793 | # Output status of aur packages ($1 is 0 for success or 1 for failure) 794 | buildstatus() { 795 | if [[ $1 != 0 ]]; then 796 | echo 797 | echo -e "${COLOR7}==> ERROR:${ENDCOLOR} ${COLOR1}the build failed${ENDCOLOR}" 798 | code='8' 799 | fi 800 | 801 | echo -e "${COLOR5} ->${ENDCOLOR} ${COLOR1}Status${ENDCOLOR}" 802 | [[ $success ]] && echo -e "\t${COLOR4}built (${#success[@]}):${ENDCOLOR} ${success[@]}" 803 | [[ $failure ]] && echo -e "\t${COLOR7}failed (${#failure[@]}):${ENDCOLOR} ${failure[@]}" 804 | [[ $remains ]] && echo -e "\t${COLOR6}remain (${#remains[@]}):${ENDCOLOR} ${remains[@]}" 805 | echo "" 806 | 807 | [[ $nofail = 1 && $1 != 0 ]] && exit 9 808 | } 809 | 810 | # Build install ($1 is package, $2 is dependency or explicit, $3 is filename) 811 | buildinstall() { 812 | if [[ $2 = dependency ]]; then 813 | runasroot $PACMAN ${PACOPTS[@]} --asdeps -U "$3" 814 | aurlocaldb "$1" "$3" 815 | [[ $buildonly = 1 ]] && bundle+=("$3") 816 | [[ $buildonly = 1 ]] && purgedeps+=("$1") 817 | elif [[ $2 = explicit ]]; then 818 | [[ $buildonly = 1 ]] && echo -e "${COLOR6}notice:${ENDCOLOR} $1 built -- not installing" 819 | [[ $buildonly = 1 ]] && bundle+=("$3") 820 | [[ $buildonly != 1 ]] && progress "Installing ${pkgnum}/${totalcount} $1" 821 | [[ $buildonly != 1 ]] && runasroot $PACMAN ${PACOPTS[@]} -U "$3" 822 | [[ $buildonly != 1 ]] && aurlocaldb "$1" "$3" 823 | fi 824 | } 825 | 826 | # Checks if aur cache is newer than aur ($1 is package, $2 is aur version) 827 | checkvcs() { 828 | cachefile=$(ls -t ${savedir}/${1}-*-{any,${makearch}}.pkg.{tar,tar.xz} 2>/dev/null | awk NR==1 | awk -F "${savedir}/${1}-" '{print $2}'); 829 | cachever=$(echo "$cachefile" | sed "s/-any.pkg.tar.*//g;s/-${makearch}.pkg.tar.*//g"); 830 | if [[ "$(LC_ALL=C vercmp "$cachever" "$2")" -gt 0 ]]; then 831 | echo -e "${COLOR7}warning:${ENDCOLOR} $1 -- ${COLOR7}verify cache newer than AUR${ENDCOLOR} ($pkgver-$pkgrel)" 832 | pkgfile="${savedir}/${1}-${cachefile}"; 833 | elif [[ "$(LC_ALL=C vercmp "$cachever" "$2")" -eq 0 ]]; then 834 | pkgfile="${savedir}/${1}-${cachefile}"; 835 | fi 836 | } 837 | 838 | # Checks if packages are in aur cache ($1 is package, $2 is dependency or explicit) 839 | checkcache() { 840 | unset pkgfile; 841 | 842 | if [ "$skipcache" != "1" ]; then 843 | sourcemakepkgconf 844 | pkgfile=$(ls ${savedir}/${1}-${pkgver}-${pkgrel}-{any,${makearch}}.pkg.{tar,tar.xz} 2>/dev/null | awk NR==1); 845 | fi 846 | 847 | if [ "$cachevcs" = "1" ]; then 848 | checkvcs $1 $pkgver-$pkgrel 849 | fi 850 | 851 | pkgnum=$((pkgnum+1)) 852 | if [ -f "$pkgfile" ]; then 853 | #progress "Installing ${pkgnum}/${totalcount} $1" 854 | cacheinstall "$1" "$2" "$pkgfile" 855 | else 856 | progress "Building ${pkgnum}/${totalcount} $1" 857 | aurinstall "$1" "$2" 858 | fi; 859 | } 860 | 861 | # Installs packages from cache ($1 is package, $2 is dependency or explicit, $3 is filename) 862 | cacheinstall() { 863 | if [ "$cachevcs" = "1" ]; then 864 | pkgrelease="$1-$cachever" 865 | else 866 | pkgrelease="$1-$pkgver-$pkgrel" 867 | fi 868 | 869 | if [[ $offline = '1' ]]; then 870 | offlinemsg="${COLOR4} offline${ENDCOLOR}" 871 | fi 872 | 873 | echo -e "${COLOR6}notice:${ENDCOLOR}${offlinemsg} installing $pkgrelease from cache" 874 | remains=(${remains[@]/$1/}) 875 | buildinstall $1 $2 $3 876 | } 877 | 878 | # Retrieve PGP keys ($@ is ${validpgpkeys[@]}) 879 | export gpgconf 880 | checkpgpkeys() { 881 | if [[ $1 ]]; then 882 | gpg --fingerprint $@ 2>/dev/null 883 | fi 884 | }; export -f checkpgpkeys 885 | 886 | # Prompt to import PGP keys ($@ is ${validpgpkeys[@]}) 887 | askpgpkeys() { 888 | echo -e "\n${COLOR6}warning:${ENDCOLOR} One or more PGP signatures unknown" 889 | for pgpkey in $@; do 890 | echo -e "\t${COLOR7}${pgpkey}${ENDCOLOR}" 891 | done 892 | echo -en "${COLOR5}:: ${COLOR1}Verify PGP keys? [Y/n]${ENDCOLOR} " 893 | if ! [[ $noconfirm ]]; then 894 | proceed || exit 895 | else 896 | echo 897 | fi 898 | }; export -f askpgpkeys 899 | 900 | # Import PGP keys ($@ is ${validpgpkeys[@]}) 901 | addpgpkeys() { 902 | [ -f $HOME/.gnupg/gpg.conf ] || cp $gpgconf $HOME/.gnupg/ 903 | for pgpkey in $@; do 904 | echo -e "${COLOR6}trusting:${ENDCOLOR} ${COLOR7}${pgpkey}${ENDCOLOR}" 905 | gpg --recv-key $pgpkey 906 | done 907 | }; export -f addpgpkeys 908 | 909 | # Remove added PGP keys ($@ is ${validpgpkeys[@]}) 910 | removepgpkeys() { 911 | if ! [[ $keepkeys ]]; then 912 | keycheck=$(gpg --fingerprint $@ 2>/dev/null) 913 | if [[ $keycheck ]]; then 914 | echo -e "${COLOR5} -> ${COLOR1}Removed $# trusted keys${ENDCOLOR}" 915 | gpg --batch --yes --delete-keys $@ 916 | fi 917 | fi 918 | }; export -f removepgpkeys 919 | 920 | # Installs cached packages offline ($1 is package, $2 is dependency or explicit) 921 | offlineinstall() { 922 | cachedpkgs=$(ls ${savedir}/*-{any,${makearch}}.pkg.{tar,tar.xz} 2>/dev/null | awk -F "$savedir/" '{print $2}') 923 | cachedpkgs=$(echo "$cachedpkgs" | awk -F "-" '{for(i=1;i<=NF-3;++i) printf $i"-"; print " " $(NF-2) " " $(NF-1) " " $NF}' 2>/dev/null) 924 | cachedarray=$(echo "$cachedpkgs" | sed 's/- / /' | grep "^$1 " | sort -n | tail -n 1) 925 | if [[ $cachedarray ]]; then 926 | pkgver=$(echo "$cachedarray" | awk '{print $2}') 927 | pkgrel=$(echo "$cachedarray" | awk '{print $3}') 928 | pkgext=$(echo "$cachedarray" | awk '{print $4}') 929 | pkgfile=$(ls ${savedir}/${1}-${pkgver}-${pkgrel}-${pkgext} 2>/dev/null) 930 | fi 931 | 932 | if [ -f "$pkgfile" ]; then 933 | cacheinstall "$1" "$2" "$pkgfile" 934 | else 935 | echo "Package \`$1' does not exist in cache." 936 | exit 6 937 | fi 938 | } 939 | 940 | # Sanity check for umask permissions ($1 is build directory) 941 | checkumask() { 942 | otherbits=$(ls -ld "$1" | awk '{print $1}' | cut -c 8,10) 943 | if [[ $otherbits != "rx" ]]; then 944 | mask=$(umask 2>/dev/null) 945 | if [[ $mask != *022 ]]; then 946 | echo -e "${COLOR6}warning:${ENDCOLOR} umask set to ${COLOR4}${mask}${ENDCOLOR} (should be 022)" 947 | fi 948 | rmdir "$1" 949 | err "${COLOR7}error:${COLOR1} no write permission in ${1}${ENDCOLOR}" 950 | fi 951 | } 952 | 953 | # Sanity check for tmpfs free disk space ($1 is build directory) 954 | checkcapacity() { 955 | capacity=$(df -P "$1" 2>/dev/null | tail -n 1 | awk '{print $5}' | tr -dc '[0-9]\n') 956 | if [[ $capacity -ge 99 ]]; then 957 | echo -e "${COLOR7}error:${COLOR1} no free space in ${1}${ENDCOLOR}" 958 | [[ "$warn" == 1 ]] || exit 7 959 | elif [[ $capacity -gt 90 ]]; then 960 | echo -e "${COLOR6}warning:${ENDCOLOR} low disk space in ${1} (tmpfs)" 961 | fi 962 | } 963 | 964 | # Clean package source ($1 is package) 965 | cleanbuild() { 966 | whatlinkshere=$(ls -l --color=never "$builddir" | grep ^l | grep "/${1}$" | awk '{print $(NF-2)}') 967 | if [[ $whatlinkshere ]]; then 968 | echo -e "${COLOR3}notice:${ENDCOLOR} cleaning delayed until finished with $whatlinkshere" 969 | else 970 | [[ $verbose ]] && 971 | echo -e "${COLOR5}::${COLOR1} Cleaning build ${builddir}/$1 ${ENDCOLOR}" 972 | rm -rf "${builddir}/$1" 973 | rm "${tmpdir}/$1.info" "${tmpdir}/$1.PKGBUILD" 974 | fi 975 | } 976 | 977 | # Installs packages from aur ($1 is package, $2 is dependency or explicit) 978 | aurinstall() { 979 | if [[ $offline = '1' ]]; then 980 | offlineinstall "$1" "$2" 981 | else 982 | aurmakepkg "$1" "$2" 983 | fi 984 | } 985 | 986 | # Installs packages from aur ($1 is package, $2 is dependency or explicit) 987 | aurmakepkg() { 988 | unset validpgpkeys 989 | dir="${builddir}/$1" 990 | sourcemakepkgconf 991 | 992 | # Prepare the installation directory 993 | # If there is an old directory and aurversion is not newer, use old directory 994 | if parser "$dir/PKGBUILD" &>/dev/null && ! aurversionisnewer "$1" "$pkgver-$pkgrel"; then 995 | checkumask "$dir" 996 | checkcapacity "$dir" 997 | cd "$dir" 998 | else 999 | [[ -d "$dir" ]] && rm -rf "$dir" 1000 | mkdir -p "$builddir" 1001 | checkumask "$builddir" 1002 | checkcapacity "$builddir" 1003 | cd "$builddir" 1004 | curl -Lfs "$(pkglink $1)" > "$1.tar.gz" 1005 | cstatus=$?; curlyq "$cstatus" "$1" 1006 | mkdir "$1" 1007 | tar -xf "$1.tar.gz" -C "$1" --strip-components=1 1008 | cd "$1" 1009 | if [[ $preview && -s "$tmpdir/$1.PKGBUILD" ]]; then 1010 | cp "$tmpdir/$1.PKGBUILD" PKGBUILD 1011 | fi 1012 | # customizepkg 1013 | if [[ -f "/etc/customizepkg.d/$1" ]] && deptest customizepkg; then 1014 | echo "Applying customizepkg instructions..." 1015 | customizepkg --modify 1016 | fi 1017 | fi 1018 | 1019 | # Check for split PKGBUILD 1020 | pkgbase=($(pkgbuildgrep pkgbase)); 1021 | pkgname=($(pkgbuildgrep pkgname)); 1022 | if [[ "${pkgbase[@]}" ]]; then 1023 | echo -e " ${COLOR5}->${ENDCOLOR}${COLOR1} Split package base: ${pkgbase[@]}${ENDCOLOR}"; 1024 | if [[ "${#pkgname[@]}" -gt 1 ]]; then 1025 | echo -e " ${COLOR5}->${ENDCOLOR}${COLOR1} PKGBUILD contains: ${pkgname[@]}${ENDCOLOR}"; 1026 | for split in ${pkgname[@]}; do 1027 | ln -s "${builddir}/$1" "${builddir}/$split" 2>/dev/null; 1028 | done 1029 | fi 1030 | fi 1031 | 1032 | # Check for missing arch 1033 | arch=($(pkgbuildgrep arch)); 1034 | if [[ ! " ${arch[@]} " =~ " any " ]]; then 1035 | if [[ ! " ${arch[@]} " =~ " ${CARCH} " ]]; then 1036 | echo -e "${COLOR6}warning:$ENDCOLOR $CARCH missing from arch array" 1037 | fi 1038 | fi 1039 | 1040 | # Allow user to edit PKGBUILD 1041 | confirm_edit "${COLOR6}Edit $1 PKGBUILD with \$editor? [Y/n]${ENDCOLOR} " PKGBUILD 1042 | if ! [[ -f PKGBUILD ]]; then 1043 | err "No PKGBUILD found in directory." 1044 | fi 1045 | 1046 | # Allow user to edit .install 1047 | unset install 1048 | parser PKGBUILD 1049 | confirm_edit "${COLOR6}Edit $install with \$editor? [Y/n]${ENDCOLOR} " "$install" 1050 | 1051 | # Installation (makepkg and pacman) 1052 | rm -f *$PKGEXT 1053 | if [[ $UID -eq 0 ]]; then 1054 | id aurbuild >/dev/null 2>/dev/null || useradd -r -d /var/empty aurbuild 1055 | mkdir -p /var/empty/.gnupg 1056 | chown -R aurbuild:aurbuild . /var/empty/.gnupg 1057 | 1058 | if [[ $validpgpkeys ]]; then 1059 | su aurbuild -c "gpg --refresh-keys ${validpgpkeys[*]}" 1060 | keyfound=$(su aurbuild -c "checkpgpkeys ${validpgpkeys[*]}" 2>/dev/null) 1061 | if ! [[ $keyfound ]]; then 1062 | askpgpkeys "${validpgpkeys[*]}" 1063 | su aurbuild -c "addpgpkeys ${validpgpkeys[*]}" 1064 | fi 1065 | su aurbuild -c "makepkg $MAKEPKGOPTS -f"; buildcheck=$? 1066 | [[ $keyfound ]] || su aurbuild -c "removepgpkeys ${validpgpkeys[*]}" 1067 | [[ $purgekeys ]] && [[ $keyfound ]] && su aurbuild -c "removepgpkeys ${validpgpkeys[*]}" 1068 | else 1069 | su aurbuild -c "makepkg $MAKEPKGOPTS -f"; buildcheck=$? 1070 | fi 1071 | else 1072 | if [[ $validpgpkeys ]]; then 1073 | gpg --refresh-keys "${validpgpkeys[@]}" 1074 | keyfound=$(checkpgpkeys "${validpgpkeys[@]}" 2>/dev/null) 1075 | if ! [[ $keyfound ]]; then 1076 | askpgpkeys "${validpgpkeys[@]}" 1077 | addpgpkeys "${validpgpkeys[@]}" 1078 | fi 1079 | makepkg $MAKEPKGOPTS -f; buildcheck=$? 1080 | [[ $keyfound ]] || removepgpkeys "${validpgpkeys[@]}" 1081 | [[ $purgekeys ]] && [[ $keyfound ]] && removepgpkeys "${validpgpkeys[@]}" 1082 | else 1083 | makepkg $MAKEPKGOPTS -f; buildcheck=$? 1084 | fi 1085 | fi 1086 | 1087 | # Build check 1088 | remains=(${remains[@]/$1/}); 1089 | if [[ $buildcheck -ne 0 ]]; then 1090 | failure+=("$1") 1091 | buildstatus 1 1092 | else 1093 | success+=("$1") 1094 | buildstatus 0 1095 | fi 1096 | 1097 | # Reparse PKGBUILD, possibly modified during build 1098 | parser PKGBUILD 1099 | # Save packages 1100 | [ ${epoch} ] && epoch=${epoch}: 1101 | pkgtar=$(ls $1-${epoch}${pkgver}*${PKGEXT} 2>/dev/null | tail -n 1) 1102 | if [[ $pkgtar ]]; then 1103 | [ -d $savedir ] || mkdir -p $savedir 2>/dev/null || runasroot mkdir -p $savedir 1104 | echo -e "${COLOR5} -> ${COLOR1}Saving package:${ENDCOLOR} ${pkgtar}" 1105 | cp ${pkgtar} $savedir/ 2>/dev/null || runasroot cp ${pkgtar} $savedir/ 1106 | echo -e "${COLOR5} -> ${COLOR1}Installing ${1}${ENDCOLOR}" 1107 | buildinstall $1 $2 ${savedir}/$pkgtar 1108 | cleanbuild $1 1109 | elif [[ $nofail ]]; then 1110 | cleanbuild $1 1111 | fi 1112 | } 1113 | 1114 | # Passthrough for pkgfile 1115 | pkgfilehandling() { 1116 | if ! deptest pkgfile; then 1117 | err "${COLOR7}error:${ENDCOLOR} $1 requires \`pkgfile'" 1118 | return 1119 | fi 1120 | 1121 | if [[ ! -f $pacmandb ]]; then 1122 | echo -e "${COLOR7}warning:${ENDCOLOR} need to run ${COLOR1}apacman --gendb${ENDCOLOR}" 1123 | fi 1124 | 1125 | if [[ $1 = -P* ]] && [[ $1 != -P ]]; then 1126 | Parg=$(echo $1 | sed 's/P//g') 1127 | fi 1128 | 1129 | shift 1130 | pkgfile -C <(cat $pacmanconf | sed "$ a [$localrepo]") $Parg "$@" 1131 | exit $? 1132 | } 1133 | 1134 | # Install local packages (-U) 1135 | localhandling() { 1136 | pacmanarg="$1" 1137 | shift 1138 | 1139 | for arg in $@; do 1140 | if [ -f "$arg" ]; then 1141 | localpkg+=("$arg") 1142 | else 1143 | args+=("$arg") 1144 | fi 1145 | done 1146 | 1147 | for pkg in ${localpkg[@]}; do 1148 | scrapelocaldeps $pkg 1149 | echo -e "${COLOR3}notice:${ENDCOLOR} installing dependencies for $pkg" 1150 | if [[ $dependencies ]]; then 1151 | $0 -S "${args[@]}" ${dependencies[@]} --asdeps --localinstall --needed 1152 | fi 1153 | done 1154 | runasroot $pacmanbin $pacmanarg "${localpkg[@]}" 1155 | } 1156 | 1157 | # Goes through all of the install tests and execution ($@ is packages to be installed) 1158 | installhandling() { 1159 | packageargs=("$@") 1160 | getignoredpackages 1161 | sourcemakepkgconf 1162 | # Figure out all of the packages that need to be installed 1163 | for package in "${packageargs[@]}"; do 1164 | # Determine whether package is in pacman repos 1165 | if ! [[ $auronly ]] && existsinpacman "$package"; then 1166 | pacmanpackages+=("$package") 1167 | elif ! [[ $auronly ]] && existsinpacmangroup "$package"; then 1168 | pacmanpackages+=("$package") 1169 | elif ! [[ $auronly ]] && providedinpacman "$package"; then 1170 | pacmanpackages+=("$providepkg") 1171 | elif ! [[ $noaur ]] && existsinaur "$package" "package"; then 1172 | if finddeps "$package"; then 1173 | # here is where dep dupes are created 1174 | aurpackages+=("$package") 1175 | aurdepends=("${aurdeps[@]}" "${aurdepends[@]}") 1176 | pacmandepends+=("${pacmandeps[@]}") 1177 | fi 1178 | else 1179 | dne "Package \`$package' does not exist." 1180 | fi 1181 | done 1182 | 1183 | # Check if any aur target packages are ignored 1184 | for package in "${aurpackages[@]}"; do 1185 | if isignored "$package"; then 1186 | echo -ne "${COLOR5}:: ${COLOR1}$package is in IgnorePkg/IgnoreGroup. Install anyway?${ENDCOLOR} [Y/n] " 1187 | if ! [[ $noconfirm ]]; then 1188 | proceed || continue 1189 | else 1190 | echo 1191 | fi 1192 | fi 1193 | aurtargets+=("$package") 1194 | done 1195 | 1196 | # Check if any aur dependencies are ignored 1197 | for package in "${aurdepends[@]}"; do 1198 | if isignored "$package"; then 1199 | echo -ne "${COLOR5}:: ${COLOR1}$package is in IgnorePkg/IgnoreGroup. Install anyway?${ENDCOLOR} [Y/n] " 1200 | if ! [[ $noconfirm ]]; then 1201 | if ! proceed; then 1202 | echo "Unresolved dependency \`$package'" 1203 | unset aurtargets 1204 | break 1205 | fi 1206 | else 1207 | echo 1208 | fi 1209 | fi 1210 | done 1211 | 1212 | # First install the explicit pacman packages, let pacman prompt 1213 | if [[ $pacmanpackages ]]; then 1214 | echo -e "${COLOR6}Pacman Targets ($((${#pacmanpackages[@]}))):${ENDCOLOR} ${pacmanpackages[@]}" 1215 | echo 1216 | if [[ $buildonly = 1 ]]; then 1217 | downfile=$($PACMAN -Sp -- "${pacmanpackages[@]}" | awk -v dir=$downdir -F "/" '{print dir"/"$NF}') 1218 | bundle+=("${downfile}") 1219 | runasroot $PACMAN "${PACOPTS[@]}" -Sw --cachedir $downdir -- "${pacmanpackages[@]}" 1220 | else 1221 | runasroot $PACMAN "${PACOPTS[@]}" -S -- "${pacmanpackages[@]}" 1222 | fi 1223 | fi 1224 | if [[ -z $aurtargets ]]; then 1225 | listbundle 1226 | exit 1227 | fi 1228 | 1229 | # Test if aurpackages are already installed; echo warning if so 1230 | for pkg in "${aurtargets[@]}"; do 1231 | if existsinlocal "$pkg"; then 1232 | localversion="$($pacmanbin -Qs "$pkg" | grep -F "local/$pkg " | cut -d ' ' -f 2)" 1233 | if ! aurversionisnewer "$pkg" "$localversion"; then 1234 | if [ "$needed" = "1" ]; then 1235 | [[ $localinstall ]] || 1236 | echo -e "${COLOR6}notice:$ENDCOLOR $pkg-$localversion is up to date -- skipping" 1237 | aurtargets=(${aurtargets[@]/$pkg/}); 1238 | else 1239 | echo -e "${COLOR6}warning:$ENDCOLOR $pkg-$localversion is up to date -- reinstalling" 1240 | fi 1241 | fi 1242 | fi 1243 | done 1244 | 1245 | # Echo warning if packages are out of date 1246 | for pkg in "${aurtargets[@]}" "${aurdepends[@]}"; do 1247 | if isoutofdate "$pkg"; then 1248 | echo -e "${COLOR6}warning:$ENDCOLOR $pkg is flagged out of date" 1249 | fi 1250 | done 1251 | 1252 | # Prompt for aur packages and their dependencies 1253 | num="$((${#aurdepends[@]}+${#aurtargets[@]}))" 1254 | if [[ $num -eq 0 ]] && [[ $localinstall ]]; then 1255 | true 1256 | elif [[ $aurdepends ]]; then 1257 | echo 1258 | echo -e "${COLOR6}Aur Targets ($num):${ENDCOLOR} ${aurdepends[@]} ${aurtargets[@]}" 1259 | else 1260 | echo 1261 | echo -e "${COLOR6}Aur Targets ($((${#aurtargets[@]}))):${ENDCOLOR} ${aurtargets[@]}" 1262 | fi 1263 | 1264 | # Prompt for pacman dependencies 1265 | if [[ $pacmandepends ]]; then 1266 | IFS=$'\n' read -rd '' -a pacmandepends < \ 1267 | <(printf "%s\n" "${pacmandepends[@]}" | sort -u) 1268 | echo -e "${COLOR6}Pacman Targets (${#pacmandepends[@]}):${ENDCOLOR} ${pacmandepends[@]}" 1269 | fi 1270 | 1271 | # Sanity check 1272 | pkgnum="${#pacmandepends[@]}" 1273 | totalcount="$((${#aurdepends[@]}+${#aurtargets[@]}+${#pacmandepends[@]}))" 1274 | remains=($(printf "%s\n" "${aurdepends[@]}" "${aurtargets[@]}" | sort -u)) 1275 | if [ "$totalcount" = "0" ]; then 1276 | [[ $localinstall ]] || 1277 | echo -e "${COLOR5}==>$ENDCOLOR nothing to do" 1278 | exit 0 1279 | fi 1280 | 1281 | # Prompt to proceed 1282 | [[ $buildonly = 1 ]] && phrasing="building" || phrasing="installation" 1283 | echo -en "\n${COLOR5}:: ${COLOR1}Proceed with ${phrasing}? [Y/n]${ENDCOLOR} " 1284 | if ! [[ $noconfirm ]]; then 1285 | proceed || exit 1286 | else 1287 | echo 1288 | fi 1289 | 1290 | # Install pacman dependencies 1291 | if [[ $pacmandepends ]]; then 1292 | if [[ $buildonly = 1 ]]; then 1293 | downfile=$($PACMAN -Sp -- "${pacmandepends[@]}" | awk -v dir=$downdir -F "/" '{print dir"/"$NF}') 1294 | bundle+=("${downfile}") 1295 | fi 1296 | progress "Installing ${pkgnum}/${totalcount} packages" 1297 | runasroot $PACMAN --noconfirm --asdeps -S -- "${pacmandepends[@]}" || err "Installation failed." 1298 | fi 1299 | 1300 | # Install aur dependencies 1301 | if [[ $aurdepends ]]; then 1302 | for dep in "${aurdepends[@]}"; do 1303 | checkcache "$dep" "dependency" 1304 | done 1305 | fi 1306 | 1307 | # Install the aur packages 1308 | for package in "${aurtargets[@]}"; do 1309 | scrapeaurdeps "$package" 1310 | if $pacmanbin -T "${dependencies[@]}" &>/dev/null; then 1311 | checkcache "$package" "explicit" 1312 | else 1313 | echo "Dependencies for \`$package' are not met, not building..." 1314 | fi 1315 | done 1316 | 1317 | # Remove build dependencies 1318 | if [[ $buildonly = 1 ]]; then 1319 | purgedeps+=("${pacmandepends[@]}") 1320 | fi 1321 | if [[ $purgedeps ]]; then 1322 | purgedepends=( $(echo -e "${purgedeps[*]}" | sort -u) ) 1323 | progress "Removing ${#purgedepends[@]} build depends" 1324 | runasroot $pacmanbin --noconfirm -Ru -- "${purgedepends[@]}" 2>/dev/null 1325 | fi 1326 | 1327 | listbundle 1328 | exit $code 1329 | } 1330 | 1331 | run_quick_check() { 1332 | bigurl="$RPCURL=multiinfo" 1333 | for p in $($pacmanbin -Qqm); do 1334 | bigurl="$bigurl&arg\[\]=$p" 1335 | done 1336 | parsed_aur="$(curl -s "$bigurl" | \ 1337 | jshon -e results -a -e Name -u -p -e Version -u | \ 1338 | sed 's/^$/-/' | paste -s -d '\t\n' | sort)" 1339 | packages="$(expac -Q '%n\t%v' | sort)" 1340 | comm -23 <(echo "$parsed_aur") <(echo "$packages") | cut -f 1 1341 | if [[ $auronly == 1 ]]; then 1342 | return 1343 | fi 1344 | # see https://mailman.archlinux.org/pipermail/pacman-dev/2011-October/014673.html 1345 | # (note to self, get that merged already...) 1346 | if [[ -z $CHECKUPDATE_DB ]]; then 1347 | CHECKUPDATE_DB="${TMPDIR:-/tmp}/checkup-db-${USER}/" 1348 | fi 1349 | eval $(awk '/DBPath/ {print $1$2$3}' $pacmanconf) 1350 | DBPath="${DBPath:-/var/lib/pacman/}" 1351 | mkdir -p "$CHECKUPDATE_DB" 1352 | ln -s "${DBPath}/local" "$CHECKUPDATE_DB" &> /dev/null 1353 | fakeroot $pacmanbin -Sqy --dbpath "$CHECKUPDATE_DB" &> /dev/null 1354 | $pacmanbin -Qqu --dbpath "$CHECKUPDATE_DB" 2> /dev/null 1355 | } 1356 | 1357 | # proceed with installation prompt 1358 | proceed() { 1359 | read -n 1 1360 | echo 1361 | case "$REPLY" in 1362 | 'Y'|'y'|'') return 0 ;; 1363 | *) return 1 ;; 1364 | esac 1365 | }; export -f proceed 1366 | 1367 | # process busy loop 1368 | nap() { 1369 | while (( $(jobs | wc -l) >= 8 )); do 1370 | jobs > /dev/null 1371 | done 1372 | } 1373 | 1374 | # Parse --config parameter early 1375 | loadconfig() { 1376 | for flag in $@; do 1377 | if [[ $nextflag = 1 ]]; then 1378 | apacmanconf="$flag" 1379 | unset nextflag 1380 | return 1381 | elif [[ $flag = "--config" ]]; then 1382 | nextflag='1' 1383 | elif [[ $flag = --config* ]]; then 1384 | apacmanconf="$flag" 1385 | return 1386 | fi 1387 | done 1388 | } 1389 | 1390 | # Unit testing env 1391 | enabletesting() { 1392 | savedir="$testdir" 1393 | PACOPTS+=("-r" "$testdir") 1394 | PACOPTS+=("--cachedir" "${testdir}/var/cache/pacman/pkg") 1395 | PACOPTS+=("--dbpath" "${testdir}/var/lib/pacman") 1396 | } 1397 | 1398 | 1399 | # Wrap pacman parameters 1400 | pacwrap() { 1401 | if [[ $1 = -Q* ]]; then 1402 | $pacmanbin "$@"; 1403 | elif [[ $1 = -T* ]]; then 1404 | $pacmanbin "$@"; 1405 | elif [[ $1 = -U* ]]; then 1406 | localhandling "$@" 1407 | elif [[ $1 = -P* ]]; then 1408 | pkgfilehandling "$@"; 1409 | elif [[ $1 = --pkgfile ]]; then 1410 | pkgfilehandling "$@"; 1411 | else 1412 | runasroot $pacmanbin "$@"; 1413 | fi; 1414 | exit $? 1415 | } 1416 | 1417 | # Override defaults 1418 | loadconfig $@ 1419 | sourceapacmanconf 1420 | 1421 | # Argument parsing 1422 | [[ $1 ]] || usage 1423 | packageargs=() 1424 | while [[ $1 ]]; do 1425 | case "$1" in 1426 | '-S') option=install ;; 1427 | '-Ss') option=search ;; 1428 | '-Ssq'|'-Sqs') option=search ; quiet='1' ;; 1429 | '-Si') option=info ;; 1430 | -S*u*) option=update ; escaperope='1' ; pacmanarg="$1" ;; 1431 | '-G') option=download ;; 1432 | -L*) option=list ; escaperope='1' ; pacmanarg="${1//-L}" ;; 1433 | -W*) option=web ; pacmanarg="${1//-W}" ;; 1434 | '--asdeps') asdeps='1' PACOPTS+=("--asdeps") ; export asdeps; unset asexplicit ;; 1435 | '--asexplicit') asexplicit='1' PACOPTS+=("--asexplicit"); export asexplicit; unset asdeps ;; 1436 | '--auronly') auronly='1' ; unset noaur ;; 1437 | '--buildonly') buildonly='1' ;; 1438 | '--cachevcs') cachevcs='1' ;; 1439 | '--config') config='1' ; shift ;; 1440 | --config=*) config='1' ; equals+=("--config") ;; 1441 | '--devel') devel='1' ;; 1442 | '--edit') unset noedit ;; 1443 | '--force') force='1' PACOPTS+=("--force");; 1444 | '--gendb') gendb='1' ;; 1445 | '--ignore') ignorearg="$2" ; PACOPTS+=("--ignore" "$2") ; shift ;; 1446 | --ignore=*) ignorearg="$1" ; equals+=("--ignore") ;; 1447 | '--ignorearch') MAKEPKGOPTS+=("--ignorearch");; 1448 | '--keepkeys') keepkeys='1' ; export keepkeys ;; 1449 | '--legacy') legacy='1' ;; 1450 | '--localinstall') localinstall='1' ;; 1451 | '--needed') needed='1' PACOPTS+=("--needed");; 1452 | '--noaur') noaur='1' ; unset auronly ;; 1453 | '--noconfirm') noconfirm='1' PACOPTS+=("--noconfirm") ; export noconfirm ;; 1454 | '--nodatabase') nodatabase='1' ;; 1455 | '--noedit') noedit='1' ;; 1456 | '--nofail') nofail='1' ;; 1457 | '--noprogress') unset progress ;; 1458 | '--nosource') nosource='1' ;; 1459 | '--notify') progress='2' ;; 1460 | '--pkgfile') pacwrap "$@" ;; 1461 | '--preview') preview='1' ;; 1462 | '--progress') progress='1' ;; 1463 | '--purgebuild') purgebuild='1' ;; 1464 | '--purgekeys') purgekeys='1' ;; 1465 | '--quickcheck') quickcheck='1' ;; 1466 | '--quiet') quiet='1' ;; 1467 | '--savedir') savedir="$2" ; shift ;; 1468 | --savedir=*) savedir="$1"; equals+=("--savedir") ;; 1469 | '--skipcache') skipcache='1' ;; 1470 | '--skipinteg') skipinteg='1' ; MAKEPKGOPTS+=("--skipinteg");; 1471 | '--skiptest') skiptest='1' ; MAKEPKGOPTS+=("--nocheck");; 1472 | '--testing') testing='1' ; enabletesting ;; 1473 | '--warn') warn='1' ;; 1474 | '-h'|'--help') usage ;; 1475 | '-v'|'--verbose') verbose='1' ;; 1476 | '-V'|'--version') version ;; 1477 | '--') shift ; packageargs+=("$@") ; break ;; 1478 | -D*) pacwrap "$@" ;; 1479 | -P*) pacwrap "$@" ;; 1480 | -Q*) pacwrap "$@" ;; 1481 | -R*) pacwrap "$@" ;; 1482 | -S*) pacwrap "$@" ;; 1483 | -T*) pacwrap "$@" ;; 1484 | -U*) pacwrap "$@" ;; 1485 | -*) invalid "$@" ;; 1486 | *) packageargs+=("$1") ;; 1487 | esac 1488 | shift 1489 | done 1490 | 1491 | # Handles alternative syntax --flag=parameter 1492 | for eqvar in "${equals[@]}"; do 1493 | if [[ $eqvar = "--config" ]]; then 1494 | apacmanconf=$(echo "$apacmanconf" | awk -F "=" '{print $2}') 1495 | elif [[ $eqvar = "--ignore" ]]; then 1496 | ignorearg=$(echo "$ignorearg" | awk -F "=" '{print $2}') 1497 | PACOPTS+=("--ignore" "$ignorearg") 1498 | elif [[ $eqvar = "--savedir" ]]; then 1499 | savedir=$(echo "$savedir" | awk -F "=" '{print $2}') 1500 | fi 1501 | done 1502 | 1503 | # Set tmpfile stuff, clean tmpdir 1504 | rm -rf "$tmpdir" &>/dev/null 1505 | mkdir -p "$tmpdir" 1506 | olddir="$PWD" 1507 | cd 1508 | 1509 | # Determine architecture 1510 | makearch=$(grep ^CARCH= "$makepkgconf" 2>/dev/null | grep -o -e =.*[0-9A-Za-z] | sed 's/^="//'); 1511 | 1512 | # Check for new packages 1513 | if [[ $quickcheck == 1 ]]; then 1514 | run_quick_check 1515 | exit 1516 | fi 1517 | 1518 | # Verbose mode 1519 | [[ $verbose || $debug ]] && infoconf 1520 | 1521 | # List (-L) handling 1522 | if [[ $option = list ]]; then 1523 | getlistpackages 1524 | fi 1525 | 1526 | # Generate DB (--gendb) handling 1527 | if [[ $gendb = 1 ]]; then 1528 | aurgendb 1529 | fi 1530 | 1531 | # Sanity checks 1532 | [[ $config && -z $apacmanconf ]] && err "${COLOR7}error:${ENDCOLOR} no config file specified (use -h for help)" 1533 | [[ $option ]] || option="searchinstall" 1534 | [[ $escaperope != 1 && -z $packageargs ]] && err "${COLOR7}error:${ENDCOLOR} must specify a package." 1535 | [[ $auronly && $noaur ]] && err "Parameters --auronly and --noaur conflict." 1536 | 1537 | # Install (-S) handling 1538 | if [[ $option = install ]]; then 1539 | for pkg in ${packageargs[@]}; do 1540 | regexmatch="$(echo $pkg | tr -dc '0-9a-z-.\n')" 1541 | if [[ "$pkg" =~ ^/ ]]; then 1542 | err "${COLOR7}error:${ENDCOLOR} invalid package name $pkg" 1543 | elif [[ $regex = 1 ]]; then 1544 | true 1545 | elif [[ "$pkg" != "$regexmatch" ]]; then 1546 | regex='1' 1547 | echo -e "${COLOR6}notice:${ENDCOLOR} enabling regex mode ($pkg)" 1548 | fi 1549 | done 1550 | installhandling "${packageargs[@]}" 1551 | exit $? 1552 | fi 1553 | 1554 | # Update (-Su) handling 1555 | if [[ $option = update ]]; then 1556 | getignoredpackages 1557 | sourcemakepkgconf 1558 | # Pacman update 1559 | if ! [[ $auronly ]]; then 1560 | runasroot $PACMAN "${PACOPTS[@]}" "$pacmanarg" 1561 | fi 1562 | 1563 | # Aur update 1564 | total=0 1565 | if ! [[ $noaur ]]; then 1566 | echo -e "${COLOR5}:: ${COLOR1}Synchronizing aur database...${ENDCOLOR}" 1567 | IFS=$'\n' read -rd '' -a packages < <($pacmanbin -Qm) 1568 | newpackages=() 1569 | checkignores=() 1570 | extinctpkgs=() 1571 | total="${#packages[@]}" 1572 | grep -q '^ *ILoveCandy' "$pacmanconf" && bartype='candy' || bartype='normal' 1573 | fi 1574 | 1575 | if [[ $devel ]]; then 1576 | for ((i=0; i<$total; i++)); do 1577 | aurbar "$((i+1))" "$total" "$bartype" 1578 | pkg="${packages[i]%% *}" 1579 | if isignored "$pkg"; then 1580 | checkignores+=("${packages[i]}") 1581 | continue 1582 | elif ! existsinaur "$pkg" "pkg"; then 1583 | extinctpkgs+=("${packages[i]}") 1584 | continue 1585 | fi 1586 | pkginfo "$pkg" & 1587 | nap 1588 | done 1589 | wait 1590 | for ((i=0; i<$total; i++)); do 1591 | pkg="${packages[i]%% *}" 1592 | ver="${packages[i]##* }" 1593 | if [[ ! -s "$tmpdir/$pkg.PKGBUILD" ]]; then 1594 | continue 1595 | fi 1596 | if isignored "$pkg"; then 1597 | continue 1598 | fi 1599 | unset _darcstrunk _cvsroot _gitroot _svntrunk _bzrtrunk _hgroot 1600 | parser "$tmpdir/$pkg.PKGBUILD" 1601 | if [[ "$(LC_ALL=C vercmp "$pkgver-$pkgrel" "$ver")" -gt 0 ]]; then 1602 | newpackages+=("$pkg") 1603 | elif [[ ${_darcstrunk} || ${_cvsroot} || ${_gitroot} || ${_svntrunk} || ${_bzrtrunk} || ${_hgroot} ]]; then 1604 | newpackages+=("$pkg") 1605 | fi 1606 | done 1607 | else 1608 | for ((i=0; i<$total; i++)); do 1609 | aurbar "$((i+1))" "$total" "$bartype" 1610 | pkg="${packages[i]%% *}" 1611 | rpcinfo "$pkg" & 1612 | nap 1613 | done 1614 | wait 1615 | for ((i=0; i<$total; i++)); do 1616 | pkg="${packages[i]%% *}" 1617 | ver="${packages[i]##* }" 1618 | if isignored "$pkg"; then 1619 | checkignores+=("${packages[i]}") 1620 | elif ! existsinaur "$pkg" "pkg"; then 1621 | extinctpkgs+=("${packages[i]}") 1622 | elif aurversionisnewer "$pkg" "$ver"; then 1623 | newpackages+=("$pkg") 1624 | fi 1625 | done 1626 | fi 1627 | echo 1628 | 1629 | [[ $noaur ]] || echo -e "${COLOR5}:: ${COLOR1}Starting full aur upgrade...${ENDCOLOR}" 1630 | 1631 | # Check and output ignored package update info 1632 | for package in "${checkignores[@]}"; do 1633 | if aurversionisnewer "${package%% *}" "${package##* }"; then 1634 | echo -e "${COLOR6}warning:${ENDCOLOR} ${package%% *}: ignoring package upgrade (${package##* } => $aurversion)" 1635 | fi 1636 | done 1637 | 1638 | # Alert packages no longer in AUR 1639 | if [[ $extinctpkgs ]]; then 1640 | for package in "${extinctpkgs[@]}"; do 1641 | listextinct+=("${package%% *}") 1642 | done 1643 | echo "" 1644 | echo -e "${COLOR6}Unresolvable (${#listextinct[@]}):${ENDCOLOR} ${listextinct[@]}" 1645 | echo "" 1646 | fi 1647 | 1648 | # Now for the installation part 1649 | if [[ $newpackages ]]; then 1650 | auronly='1' 1651 | installhandling "${newpackages[@]}" 1652 | fi 1653 | [[ $noaur ]] || echo " local database is up to date" 1654 | exit $code 1655 | fi 1656 | 1657 | # Download (-G) handling 1658 | if [[ $option = download ]]; then 1659 | cd "$olddir" 1660 | 1661 | for package in "${packageargs[@]}"; do 1662 | if ! [[ $noaur ]] && existsinaur "$package" "package"; then 1663 | pkglist+=("$package") 1664 | elif ! [[ $auronly ]] && existsinpacman "$package"; then 1665 | abslist+=("$package") 1666 | elif [[ $noaur ]]; then 1667 | dne "Package \`$package' does not exist in ABS." 1668 | elif [[ $auronly ]]; then 1669 | dne "Package \`$package' does not exist in AUR." 1670 | else 1671 | dne "Package \`$package' does not exist in ABS+AUR." 1672 | fi 1673 | done 1674 | 1675 | [[ $abslist ]] && echo -e "${COLOR6}notice:$ENDCOLOR sourcing from ${COLOR4}[ABS]$ENDCOLOR" 1676 | for package in "${abslist[@]}"; do 1677 | pkgrepo=$(absrepo "$package") 1678 | abslink "$pkgrepo" "$package" 1679 | [ -d "$package" ] && rm -r "$package" 1680 | if [ -d "$pkgrepo/$package" ]; then 1681 | mv "$pkgrepo/$package" "$package" 1682 | rmdir "$pkgrepo" 1683 | ls "$package" | awk -v package="$package" '{print package"/"$0}' 1684 | else 1685 | err "${COLOR7}error:${ENDCOLOR} failed to retrieve package \`$package'" 1686 | fi 1687 | done 1688 | 1689 | [[ $pkglist ]] && echo -e "${COLOR6}notice:$ENDCOLOR sourcing from ${COLOR3}[AUR]$ENDCOLOR" 1690 | for package in "${pkglist[@]}"; do 1691 | if [[ $package = *~ ]]; then 1692 | pkgname="${package%\~}" 1693 | [ -d "$pkgname" ] && rm -rf "${pkgname}/.git" 1694 | [ -d "$pkgname" ] && rm -r "$pkgname" 1695 | clonehistory "$pkgname" 1696 | if [ ! -f "PKGBUILD" ]; then 1697 | err "${COLOR7}error:${ENDCOLOR} failed to retrieve package \`$pkgname' release $pkgver" 1698 | fi 1699 | elif [[ $package = *==* ]]; then 1700 | pkgname=$(echo "$package" | awk -F "==" '{print $1}') 1701 | pkgver=$(echo "$package" | awk -F "==" '{print $2}') 1702 | [ -d "$pkgname" ] && rm -rf "${pkgname}/.git" 1703 | [ -d "$pkgname" ] && rm -r "$pkgname" 1704 | clonehistory "$pkgname" "$pkgver" 1705 | if [ ! -f "PKGBUILD" ]; then 1706 | err "${COLOR7}error:${ENDCOLOR} failed to retrieve package \`$pkgname' release" 1707 | fi 1708 | else 1709 | curl -Lfs "$(pkglink $package)" > "$package.tar.gz" 1710 | cstatus=$?; curlyq "$cstatus" "$package" 1711 | [ -d "$package" ] && rm -rf "${package}/.git" 1712 | [ -d "$package" ] && rm -r "$package" 1713 | if [ -f "$package.tar.gz" ]; then 1714 | mkdir "$package" 1715 | tar -xzvf "$package.tar.gz" -C "$package" --strip-components=1 1716 | else 1717 | err "${COLOR7}error:${ENDCOLOR} failed to retrieve package \`$package'" 1718 | fi 1719 | fi 1720 | done 1721 | 1722 | exit 1723 | fi 1724 | 1725 | # Search (-Ss) handling 1726 | if [[ $option = search || $option = searchinstall ]]; then 1727 | # Pacman searching 1728 | if ! [[ $auronly ]]; then 1729 | if [[ $quiet ]]; then 1730 | results="$($pacmanbin -Ssq -- "${packageargs[@]}")" 1731 | else 1732 | results="$($pacmanbin -Ss -- "${packageargs[@]}")" 1733 | results="$(sed -r "s|^[^ ][^/]*/|$S${COLOR3}&$S${COLOR1}|" <<< "$results")" 1734 | results="$(sed -r "s|^([^ ]+) ([^ ]+)(.*)$|\1 $S${COLOR2}\2$S${ENDCOLOR}\3|" <<< "$results")" 1735 | results="$(sed -e "s| \[|$S${COLOR4}&|" -e "s|\]|&$S${ENDCOLOR}|" <<< "$results")" 1736 | fi 1737 | if [[ $option = search ]]; then 1738 | echo -e "$results" | fmt -"$_WIDTH" -s 1739 | else # interactive 1740 | echo -e "$results" | fmt -"$_WIDTH" -s | nl -v 0 -w 1 -s ' ' -b 'p^[^ ]' 1741 | fi | sed '/^$/d' 1742 | pacname=( $($pacmanbin -Ssq -- "${packageargs[@]}") ) 1743 | pactotal="${#pacname[@]}" 1744 | else 1745 | pactotal=0 1746 | fi 1747 | 1748 | # Aur searching and tmpfile preparation 1749 | if ! [[ $noaur ]]; then 1750 | for package in "${packageargs[@]}"; do 1751 | curl -LfGs --data-urlencode "arg=$package" "$RPCURL=search" | \ 1752 | jshon -Q -e results -a -e Name -u -p -e Version -u -p -e NumVotes -u -p -e Description -u | \ 1753 | sed 's/^$/-/' | paste -s -d "\t\t\t\n" | sort -nr -k 3 > "$tmpdir/$package.search" & 1754 | done 1755 | wait 1756 | cp "$tmpdir/${packageargs[0]}.search" "$tmpdir/search.results" 1757 | for ((i=1 ; i<${#packageargs[@]} ; i++)); do 1758 | regexmatch="$(echo ${packageargs[$i]} | tr -dc '0-9A-Za-z-.\n')" 1759 | if [[ ${packageargs[$i]} != $regexmatch ]]; then 1760 | echo -e "${COLOR6}notice:${ENDCOLOR} enabling regex mode (${packageargs[$i]})" 1761 | grep --color=always -E "${packageargs[$i]}" "$tmpdir/search.results" > "$tmpdir/search.results-2" 1762 | else 1763 | grep -xFf "$tmpdir/search.results" "$tmpdir/${packageargs[$i]}.search" > "$tmpdir/search.results-2" 1764 | fi 1765 | mv "$tmpdir/search.results-2" "$tmpdir/search.results" 1766 | done 1767 | sed -i '/^$/d' "$tmpdir/search.results" 1768 | 1769 | # Check versioning 1770 | localpkgs=$(pacman -Q) 1771 | for pkg in $(awk '{print $1}' "$tmpdir/search.results"); do 1772 | localver=$(echo "$localpkgs" | grep -E "^${pkg}[[:space:]]" 2>/dev/null | awk '{print $2}'); 1773 | if [ ! -z "$localver" ]; then 1774 | searchver=$(grep -E "^${pkg}[[:space:]]" "$tmpdir/search.results" | awk '{print $2}') 1775 | if [ "$searchver" = "$localver" ]; then 1776 | sed -i "s|$pkg[[:space:]]$searchver|& [installed]|" "$tmpdir/search.results" 1777 | elif [[ "$(LC_ALL=C vercmp "$searchver" "$localver")" -gt 0 ]]; then 1778 | sed -i "s|$pkg[[:space:]]$searchver|& [installed: $localver]|" "$tmpdir/search.results" 1779 | else 1780 | sed -i "s|$pkg[[:space:]]$searchver|& [local: $localver]|" "$tmpdir/search.results" 1781 | fi 1782 | fi 1783 | done 1784 | 1785 | # Prepare tmp file and arrays 1786 | IFS=$'\n' read -rd '' -a aurname < <(cut -f 1 "$tmpdir/search.results") 1787 | aurtotal="${#aurname[@]}" 1788 | alltotal="$(($pactotal+$aurtotal))" 1789 | else 1790 | alltotal="$pactotal" 1791 | fi 1792 | 1793 | # Exit if there are no matches 1794 | if [[ $alltotal = 0 ]]; then 1795 | echo -e "${COLOR5}==>${COLOR7} no matches${ENDCOLOR}" 1796 | exit 4 1797 | fi 1798 | 1799 | # Echo out the -Ss formatted package information 1800 | IFS=$'\t\n' 1801 | if [[ $option = search ]]; then 1802 | if [[ $quiet ]]; then 1803 | printf "%s\n" ${aurname[@]} 1804 | elif [[ -s "$tmpdir/search.results" ]]; then 1805 | resultsaur="$(printf "${COLOR3}aur/${COLOR1}%s ${COLOR2}%s${ENDCOLOR} (%s)\n %s\n" $(cat "$tmpdir/search.results"))" 1806 | resultsaur="$(sed -e "s| \[|$S${COLOR4}&|" -e "s|\]|&$S${ENDCOLOR}|" <<< "$resultsaur")" 1807 | echo -e "$resultsaur" 1808 | fi 1809 | else 1810 | # interactive 1811 | if [[ $quiet ]]; then 1812 | nl -v ${pactotal:-0} -w 1 -s ' ' <(cut -f 1 "$tmpdir/search.results") 1813 | elif [[ -s "$tmpdir/search.results" ]]; then 1814 | resultsaur="$(printf "%d ${COLOR3}aur/${COLOR1}%s ${COLOR2}%s${ENDCOLOR} (%s)\n %s\n" $(nl -v ${pactotal:-0} -w 1 < "$tmpdir/search.results"))" 1815 | resultsaur="$(sed -e "s| \[|$S${COLOR4}&|" -e "s|\] |&$S${ENDCOLOR}|" <<< "$resultsaur")" 1816 | echo -e "$resultsaur" 1817 | fi 1818 | fi | fmt -"$_WIDTH" -s 1819 | unset IFS 1820 | 1821 | # Prompt and install selected numbers 1822 | if [[ $option = searchinstall ]]; then 1823 | pkglist=() 1824 | allpackages=( "${pacname[@]}" "${aurname[@]}" ) 1825 | 1826 | # Prompt for numbers 1827 | echo 1828 | echo -e "${COLOR2}Type numbers to install. Separate each number with a space.${ENDCOLOR}" 1829 | echo -ne "${COLOR2}Numbers: ${ENDCOLOR}" 1830 | read -r 1831 | 1832 | # Parse answer 1833 | if [[ $REPLY ]]; then 1834 | for num in $REPLY; do 1835 | if [[ $num -lt $alltotal ]]; then 1836 | pkglist+=("${allpackages[$num]}") 1837 | else 1838 | err "Number \`$num' is not assigned to any of the packages." 1839 | fi 1840 | done 1841 | fi 1842 | 1843 | # Call installhandling to take care of the packages chosen 1844 | installhandling "${pkglist[@]}" 1845 | fi 1846 | 1847 | # Remove the tmpfiles 1848 | rm -f "$tmpdir/*search" &>/dev/null 1849 | rm -f "$tmpdir/search.results" &>/dev/null 1850 | rm -f "$tmpdir/packages.lst" &>/dev/null 1851 | exit 1852 | fi 1853 | 1854 | # Info (-Si) handling 1855 | if [[ $option = info ]]; then 1856 | # Pacman info check 1857 | sourcemakepkgconf 1858 | for package in "${packageargs[@]}"; do 1859 | if ! [[ $auronly ]] && existsinpacman "$package"; then 1860 | results="$($pacmanbin -Si -- "$package")" 1861 | results="$(sed -r "s|^(Repository[^:]*:)(.*)$|\1$S${COLOR3}\2$S${ENDCOLOR}|" <<< "$results")" 1862 | results="$(sed -r "s|^(Name[^:]*:)(.*)$|\1$S${COLOR1}\2$S${ENDCOLOR}|" <<< "$results")" 1863 | results="$(sed -r "s|^(Version[^:]*:)(.*)$|\1$S${COLOR2}\2$S${ENDCOLOR}|" <<< "$results")" 1864 | results="$(sed -r "s|^(URL[^:]*:)(.*)$|\1$S${COLOR4}\2$S${ENDCOLOR}|" <<< "$results")" 1865 | results="$(sed -r "s|^[^ ][^:]*:|$S${COLOR1}&$S${ENDCOLOR}|" <<< "$results")" 1866 | echo -e "$results" 1867 | exit 1868 | elif ! [[ $noaur ]]; then # Check to see if it is in the aur 1869 | pkginfo "$package" "$preview" 1870 | [[ -s "$tmpdir/$package.PKGBUILD" ]] || err "${COLOR7}error:${ENDCOLOR} package '$package' was not found" 1871 | parser "$tmpdir/$package.PKGBUILD" 1872 | 1873 | # Clean temp files 1874 | [[ $debug ]] || rm "$tmpdir/$package.PKGBUILD" "$tmpdir/$package.info" 1875 | 1876 | # Echo out the -Si formatted package information 1877 | # Retrieve each element in order and echo them immediately 1878 | echo -e "${COLOR1}Repository : ${COLOR3}aur" 1879 | echo -e "${COLOR1}Name : $pkgname" 1880 | echo -e "${COLOR1}Version : ${COLOR2}$pkgver-$pkgrel" 1881 | echo -e "${COLOR1}URL : ${COLOR4}$url" 1882 | echo -e "${COLOR1}AUR : ${COLOR4}$PKGURL/packages/$pkgname/" 1883 | echo -e "${COLOR1}Licenses : ${ENDCOLOR}${license[@]}" 1884 | echo -e "${COLOR1}Groups : ${ENDCOLOR}${groups[@]:-None}" 1885 | echo -e "${COLOR1}Provides : ${ENDCOLOR}${provides[@]:-None}" 1886 | echo -e "${COLOR1}Depends On : ${ENDCOLOR}${depends[@]}" 1887 | echo -e "${COLOR1}Make Depends : ${ENDCOLOR}${makedepends[@]}" 1888 | echo -e -n "${COLOR1}Optional Deps : ${ENDCOLOR}" 1889 | 1890 | len="${#optdepends[@]}" 1891 | if [[ $len -eq 0 ]]; then 1892 | echo "None" 1893 | else 1894 | for ((i=0 ; i<$len ; i++)); do 1895 | if [[ $i = 0 ]]; then 1896 | echo "${optdepends[$i]}" 1897 | else 1898 | echo -e " ${optdepends[$i]}" 1899 | fi 1900 | done 1901 | fi 1902 | 1903 | echo -e "${COLOR1}Conflicts With : ${ENDCOLOR}${conflicts[@]:-None}" 1904 | echo -e "${COLOR1}Replaces : ${ENDCOLOR}${replaces[@]:-None}" 1905 | echo -e "${COLOR1}Architecture : ${ENDCOLOR}${arch[@]}" 1906 | echo -e "${COLOR1}Description : ${ENDCOLOR}$pkgdesc" 1907 | echo 1908 | else 1909 | err "${COLOR7}error:${ENDCOLOR} package '$package' was not found" 1910 | fi 1911 | done 1912 | fi 1913 | 1914 | # Web Comments (-W) handling 1915 | if [[ $option = web ]]; then 1916 | sourcemakepkgconf 1917 | for package in "${packageargs[@]}"; do 1918 | if ! [[ $auronly ]] && existsinpacman "$package"; then 1919 | echo -e "${COLOR7}error:${ENDCOLOR} comments unavailable for non-AUR package '$package'" 1920 | elif ! [[ $noaur ]]; then # Check to see if it is in the aur 1921 | curl -Lfs "$PKGURL/packages/$package/?comments=all" > "$tmpdir/$package.html" 1922 | cstatus=$?; curlyq "$cstatus" "$package" 1923 | [[ -s "$tmpdir/$package.html" ]] || err "${COLOR7}error:${ENDCOLOR} package '$package' was not found" 1924 | 1925 | div="%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%" 1926 | separator="${COLOR3}${div}${div}${ENDCOLOR}" 1927 | header="${COLOR4}*******************************${ENDCOLOR}" 1928 | comments="$(sed '/