diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 0000000..46b480c --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,40 @@ +name: PikaOS Package Release + +on: + workflow_dispatch + +jobs: + build: + runs-on: self-hosted + container: + image: ubuntu:22.10 + volumes: + - /proc:/proc + options: --privileged -it + + steps: + - uses: actions/checkout@v3 + + - name: Install needed packages + run: apt update && apt install software-properties-common sudo git bc gpg gpg-agent bison build-essential ccache cpio fakeroot flex git kmod libelf-dev libncurses5-dev libssl-dev lz4 qtbase5-dev rsync schedtool wget zstd tar reprepro dpkg-sig devscripts -y + + - name: Import GPG key + id: import_gpg + uses: crazy-max/ghaction-import-gpg@v5 + with: + gpg_private_key: ${{ secrets.GPG_PRIVATE_KEY }} + passphrase: ${{ secrets.PASSPHRASE }} + + - name: Install SSH key + uses: shimataro/ssh-key-action@v2 + with: + key: ${{ secrets.SSH_KEY }} + name: id_rsa + known_hosts: ${{ secrets.KNOWN_HOSTS }} + if_key_exists: replace + + - name: Build Package + run: ./main.sh + + - name: Release Package + run: ./release.sh diff --git a/archive/.cz.toml b/archive/.cz.toml deleted file mode 100644 index 8b9c8ca..0000000 --- a/archive/.cz.toml +++ /dev/null @@ -1,7 +0,0 @@ -[tool.commitizen] -name = "cz_conventional_commits" -version = "1.5.2" -tag_format = "$version" -version_files = [ - 'repolib/__version__.py:__version__' -] \ No newline at end of file diff --git a/archive/.readthedocs.yml b/archive/.readthedocs.yml deleted file mode 100644 index 07db85f..0000000 --- a/archive/.readthedocs.yml +++ /dev/null @@ -1,20 +0,0 @@ -# .readthedocs.yml -# Read the Docs configuration file -# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details - -# Required -version: 2 - -# Build documentation in the docs/ directory with Sphinx -sphinx: - configuration: docs/conf.py - -# Build documentation with MkDocs -#mkdocs: -# configuration: mkdocs.yml - -# Optionally build your docs in additional formats such as PDF -formats: - - pdf - - epub - - htmlzip diff --git a/archive/.travis.yml b/archive/.travis.yml deleted file mode 100644 index e098634..0000000 --- a/archive/.travis.yml +++ /dev/null @@ -1,13 +0,0 @@ -dist: bionic -addons: - apt: - packages: - - libdbus-1-dev - -language: python -python: "3.8" - -install: - - pip install -r requirements.txt -scripts: - - pytest --pylint diff --git a/archive/LICENSE b/archive/LICENSE deleted file mode 100644 index 01a7a80..0000000 --- a/archive/LICENSE +++ /dev/null @@ -1,675 +0,0 @@ -### GNU GENERAL PUBLIC LICENSE - -Version 3, 29 June 2007 - -Copyright (C) 2007 Free Software Foundation, Inc. - - -Everyone is permitted to copy and distribute verbatim copies of this -license document, but changing it is not allowed. - -### Preamble - -The GNU General Public License is a free, copyleft license for -software and other kinds of works. - -The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom -to share and change all versions of a program--to make sure it remains -free software for all its users. We, the Free Software Foundation, use -the GNU General Public License for most of our software; it applies -also to any other work released this way by its authors. You can apply -it to your programs, too. - -When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - -To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you -have certain responsibilities if you distribute copies of the -software, or if you modify it: responsibilities to respect the freedom -of others. - -For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - -Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - -For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - -Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the -manufacturer can do so. This is fundamentally incompatible with the -aim of protecting users' freedom to change the software. The -systematic pattern of such abuse occurs in the area of products for -individuals to use, which is precisely where it is most unacceptable. -Therefore, we have designed this version of the GPL to prohibit the -practice for those products. If such problems arise substantially in -other domains, we stand ready to extend this provision to those -domains in future versions of the GPL, as needed to protect the -freedom of users. - -Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish -to avoid the special danger that patents applied to a free program -could make it effectively proprietary. To prevent this, the GPL -assures that patents cannot be used to render the program non-free. - -The precise terms and conditions for copying, distribution and -modification follow. - -### TERMS AND CONDITIONS - -#### 0. Definitions. - -"This License" refers to version 3 of the GNU General Public License. - -"Copyright" also means copyright-like laws that apply to other kinds -of works, such as semiconductor masks. - -"The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - -To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of -an exact copy. The resulting work is called a "modified version" of -the earlier work or a work "based on" the earlier work. - -A "covered work" means either the unmodified Program or a work based -on the Program. - -To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - -To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user -through a computer network, with no transfer of a copy, is not -conveying. - -An interactive user interface displays "Appropriate Legal Notices" to -the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - -#### 1. Source Code. - -The "source code" for a work means the preferred form of the work for -making modifications to it. "Object code" means any non-source form of -a work. - -A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - -The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - -The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - -The Corresponding Source need not include anything that users can -regenerate automatically from other parts of the Corresponding Source. - -The Corresponding Source for a work in source code form is that same -work. - -#### 2. Basic Permissions. - -All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - -You may make, run and propagate covered works that you do not convey, -without conditions so long as your license otherwise remains in force. -You may convey covered works to others for the sole purpose of having -them make modifications exclusively for you, or provide you with -facilities for running those works, provided that you comply with the -terms of this License in conveying all material for which you do not -control copyright. Those thus making or running the covered works for -you must do so exclusively on your behalf, under your direction and -control, on terms that prohibit them from making any copies of your -copyrighted material outside their relationship with you. - -Conveying under any other circumstances is permitted solely under the -conditions stated below. Sublicensing is not allowed; section 10 makes -it unnecessary. - -#### 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - -No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - -When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such -circumvention is effected by exercising rights under this License with -respect to the covered work, and you disclaim any intention to limit -operation or modification of the work as a means of enforcing, against -the work's users, your or third parties' legal rights to forbid -circumvention of technological measures. - -#### 4. Conveying Verbatim Copies. - -You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - -You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - -#### 5. Conveying Modified Source Versions. - -You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these -conditions: - -- a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. -- b) The work must carry prominent notices stating that it is - released under this License and any conditions added under - section 7. This requirement modifies the requirement in section 4 - to "keep intact all notices". -- c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. -- d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - -A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - -#### 6. Conveying Non-Source Forms. - -You may convey a covered work in object code form under the terms of -sections 4 and 5, provided that you also convey the machine-readable -Corresponding Source under the terms of this License, in one of these -ways: - -- a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. -- b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the Corresponding - Source from a network server at no charge. -- c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. -- d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. -- e) Convey the object code using peer-to-peer transmission, - provided you inform other peers where the object code and - Corresponding Source of the work are being offered to the general - public at no charge under subsection 6d. - -A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - -A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, -family, or household purposes, or (2) anything designed or sold for -incorporation into a dwelling. In determining whether a product is a -consumer product, doubtful cases shall be resolved in favor of -coverage. For a particular product received by a particular user, -"normally used" refers to a typical or common use of that class of -product, regardless of the status of the particular user or of the way -in which the particular user actually uses, or expects or is expected -to use, the product. A product is a consumer product regardless of -whether the product has substantial commercial, industrial or -non-consumer uses, unless such uses represent the only significant -mode of use of the product. - -"Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to -install and execute modified versions of a covered work in that User -Product from a modified version of its Corresponding Source. The -information must suffice to ensure that the continued functioning of -the modified object code is in no case prevented or interfered with -solely because modification has been made. - -If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - -The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or -updates for a work that has been modified or installed by the -recipient, or for the User Product in which it has been modified or -installed. Access to a network may be denied when the modification -itself materially and adversely affects the operation of the network -or violates the rules and protocols for communication across the -network. - -Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - -#### 7. Additional Terms. - -"Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - -When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - -Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders -of that material) supplement the terms of this License with terms: - -- a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or -- b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or -- c) Prohibiting misrepresentation of the origin of that material, - or requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or -- d) Limiting the use for publicity purposes of names of licensors - or authors of the material; or -- e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or -- f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions - of it) with contractual assumptions of liability to the recipient, - for any liability that these contractual assumptions directly - impose on those licensors and authors. - -All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - -If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - -Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; the -above requirements apply either way. - -#### 8. Termination. - -You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - -However, if you cease all violation of this License, then your license -from a particular copyright holder is reinstated (a) provisionally, -unless and until the copyright holder explicitly and finally -terminates your license, and (b) permanently, if the copyright holder -fails to notify you of the violation by some reasonable means prior to -60 days after the cessation. - -Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - -Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - -#### 9. Acceptance Not Required for Having Copies. - -You are not required to accept this License in order to receive or run -a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - -#### 10. Automatic Licensing of Downstream Recipients. - -Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - -An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - -You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - -#### 11. Patents. - -A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - -A contributor's "essential patent claims" are all patent claims owned -or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - -Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - -In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - -If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - -If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - -A patent license is "discriminatory" if it does not include within the -scope of its coverage, prohibits the exercise of, or is conditioned on -the non-exercise of one or more of the rights that are specifically -granted under this License. You may not convey a covered work if you -are a party to an arrangement with a third party that is in the -business of distributing software, under which you make payment to the -third party based on the extent of your activity of conveying the -work, and under which the third party grants, to any of the parties -who would receive the covered work from you, a discriminatory patent -license (a) in connection with copies of the covered work conveyed by -you (or copies made from those copies), or (b) primarily for and in -connection with specific products or compilations that contain the -covered work, unless you entered into that arrangement, or that patent -license was granted, prior to 28 March 2007. - -Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - -#### 12. No Surrender of Others' Freedom. - -If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under -this License and any other pertinent obligations, then as a -consequence you may not convey it at all. For example, if you agree to -terms that obligate you to collect a royalty for further conveying -from those to whom you convey the Program, the only way you could -satisfy both those terms and this License would be to refrain entirely -from conveying the Program. - -#### 13. Use with the GNU Affero General Public License. - -Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - -#### 14. Revised Versions of this License. - -The Free Software Foundation may publish revised and/or new versions -of the GNU General Public License from time to time. Such new versions -will be similar in spirit to the present version, but may differ in -detail to address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies that a certain numbered version of the GNU General Public -License "or any later version" applies to it, you have the option of -following the terms and conditions either of that numbered version or -of any later version published by the Free Software Foundation. If the -Program does not specify a version number of the GNU General Public -License, you may choose any version ever published by the Free -Software Foundation. - -If the Program specifies that a proxy can decide which future versions -of the GNU General Public License can be used, that proxy's public -statement of acceptance of a version permanently authorizes you to -choose that version for the Program. - -Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - -#### 15. Disclaimer of Warranty. - -THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT -WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT -LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND -PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE -DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR -CORRECTION. - -#### 16. Limitation of Liability. - -IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR -CONVEYS THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES -ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT -NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR -LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM -TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER -PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. - -#### 17. Interpretation of Sections 15 and 16. - -If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - -END OF TERMS AND CONDITIONS - -### How to Apply These Terms to Your New Programs - -If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these -terms. - -To do so, attach the following notices to the program. It is safest to -attach them to the start of each source file to most effectively state -the exclusion of warranty; and each file should have at least the -"copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper -mail. - -If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands \`show w' and \`show c' should show the -appropriate parts of the General Public License. Of course, your -program's commands might be different; for a GUI interface, you would -use an "about box". - -You should also get your employer (if you work as a programmer) or -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. For more information on this, and how to apply and follow -the GNU GPL, see . - -The GNU General Public License does not permit incorporating your -program into proprietary programs. If your program is a subroutine -library, you may consider it more useful to permit linking proprietary -applications with the library. If this is what you want to do, use the -GNU Lesser General Public License instead of this License. But first, -please read . \ No newline at end of file diff --git a/archive/LICENSE.LESSER b/archive/LICENSE.LESSER deleted file mode 100644 index 13fc077..0000000 --- a/archive/LICENSE.LESSER +++ /dev/null @@ -1,157 +0,0 @@ -### GNU LESSER GENERAL PUBLIC LICENSE - -Version 3, 29 June 2007 - -Copyright (C) 2007 Free Software Foundation, Inc. - - -Everyone is permitted to copy and distribute verbatim copies of this -license document, but changing it is not allowed. - -This version of the GNU Lesser General Public License incorporates the -terms and conditions of version 3 of the GNU General Public License, -supplemented by the additional permissions listed below. - -#### 0. Additional Definitions. - -As used herein, "this License" refers to version 3 of the GNU Lesser -General Public License, and the "GNU GPL" refers to version 3 of the -GNU General Public License. - -"The Library" refers to a covered work governed by this License, other -than an Application or a Combined Work as defined below. - -An "Application" is any work that makes use of an interface provided -by the Library, but which is not otherwise based on the Library. -Defining a subclass of a class defined by the Library is deemed a mode -of using an interface provided by the Library. - -A "Combined Work" is a work produced by combining or linking an -Application with the Library. The particular version of the Library -with which the Combined Work was made is also called the "Linked -Version". - -The "Minimal Corresponding Source" for a Combined Work means the -Corresponding Source for the Combined Work, excluding any source code -for portions of the Combined Work that, considered in isolation, are -based on the Application, and not on the Linked Version. - -The "Corresponding Application Code" for a Combined Work means the -object code and/or source code for the Application, including any data -and utility programs needed for reproducing the Combined Work from the -Application, but excluding the System Libraries of the Combined Work. - -#### 1. Exception to Section 3 of the GNU GPL. - -You may convey a covered work under sections 3 and 4 of this License -without being bound by section 3 of the GNU GPL. - -#### 2. Conveying Modified Versions. - -If you modify a copy of the Library, and, in your modifications, a -facility refers to a function or data to be supplied by an Application -that uses the facility (other than as an argument passed when the -facility is invoked), then you may convey a copy of the modified -version: - -- a) under this License, provided that you make a good faith effort - to ensure that, in the event an Application does not supply the - function or data, the facility still operates, and performs - whatever part of its purpose remains meaningful, or -- b) under the GNU GPL, with none of the additional permissions of - this License applicable to that copy. - -#### 3. Object Code Incorporating Material from Library Header Files. - -The object code form of an Application may incorporate material from a -header file that is part of the Library. You may convey such object -code under terms of your choice, provided that, if the incorporated -material is not limited to numerical parameters, data structure -layouts and accessors, or small macros, inline functions and templates -(ten or fewer lines in length), you do both of the following: - -- a) Give prominent notice with each copy of the object code that - the Library is used in it and that the Library and its use are - covered by this License. -- b) Accompany the object code with a copy of the GNU GPL and this - license document. - -#### 4. Combined Works. - -You may convey a Combined Work under terms of your choice that, taken -together, effectively do not restrict modification of the portions of -the Library contained in the Combined Work and reverse engineering for -debugging such modifications, if you also do each of the following: - -- a) Give prominent notice with each copy of the Combined Work that - the Library is used in it and that the Library and its use are - covered by this License. -- b) Accompany the Combined Work with a copy of the GNU GPL and this - license document. -- c) For a Combined Work that displays copyright notices during - execution, include the copyright notice for the Library among - these notices, as well as a reference directing the user to the - copies of the GNU GPL and this license document. -- d) Do one of the following: - - 0) Convey the Minimal Corresponding Source under the terms of - this License, and the Corresponding Application Code in a form - suitable for, and under terms that permit, the user to - recombine or relink the Application with a modified version of - the Linked Version to produce a modified Combined Work, in the - manner specified by section 6 of the GNU GPL for conveying - Corresponding Source. - - 1) Use a suitable shared library mechanism for linking with - the Library. A suitable mechanism is one that (a) uses at run - time a copy of the Library already present on the user's - computer system, and (b) will operate properly with a modified - version of the Library that is interface-compatible with the - Linked Version. -- e) Provide Installation Information, but only if you would - otherwise be required to provide such information under section 6 - of the GNU GPL, and only to the extent that such information is - necessary to install and execute a modified version of the - Combined Work produced by recombining or relinking the Application - with a modified version of the Linked Version. (If you use option - 4d0, the Installation Information must accompany the Minimal - Corresponding Source and Corresponding Application Code. If you - use option 4d1, you must provide the Installation Information in - the manner specified by section 6 of the GNU GPL for conveying - Corresponding Source.) - -#### 5. Combined Libraries. - -You may place library facilities that are a work based on the Library -side by side in a single library together with other library -facilities that are not Applications and are not covered by this -License, and convey such a combined library under terms of your -choice, if you do both of the following: - -- a) Accompany the combined library with a copy of the same work - based on the Library, uncombined with any other library - facilities, conveyed under the terms of this License. -- b) Give prominent notice with the combined library that part of it - is a work based on the Library, and explaining where to find the - accompanying uncombined form of the same work. - -#### 6. Revised Versions of the GNU Lesser General Public License. - -The Free Software Foundation may publish revised and/or new versions -of the GNU Lesser General Public License from time to time. Such new -versions will be similar in spirit to the present version, but may -differ in detail to address new problems or concerns. - -Each version is given a distinguishing version number. If the Library -as you received it specifies that a certain numbered version of the -GNU Lesser General Public License "or any later version" applies to -it, you have the option of following the terms and conditions either -of that published version or of any later version published by the -Free Software Foundation. If the Library as you received it does not -specify a version number of the GNU Lesser General Public License, you -may choose any version of the GNU Lesser General Public License ever -published by the Free Software Foundation. - -If the Library as you received it specifies that a proxy can decide -whether future versions of the GNU Lesser General Public License shall -apply, that proxy's public statement of acceptance of any version is -permanent authorization for you to choose that version for the -Library. \ No newline at end of file diff --git a/archive/README.rst b/archive/README.rst deleted file mode 100644 index be9b897..0000000 --- a/archive/README.rst +++ /dev/null @@ -1,167 +0,0 @@ -======= -RepoLib -======= - -RepoLib is a Python library and CLI tool-set for managing your software -system software repositories. It's currently set up to handle APT repositories -on Debian-based linux distributions. - -RepoLib is intended to operate on DEB822-format sources. It aims to provide -feature parity with software-properties for most commonly used functions. - -Documentation -============= - -Documentation is available online at `Read The Docs `_. - - -Basic CLI Usage ---------------- - -RepoLib includes a CLI program for managing software repositories, -:code:`apt-manage` -. - -Usage is divided into subcommands for most tasks. Currently implemented commands -are: - - apt-manage add # Adds repositories to the system - apt-manage list # Lists configuration details of repositories - -Additional information is available with the built-in help: - - apt-manage --help - - -Add -^^^ - -Apt-manage allows entering a URL for a repository, a complete debian line, or a -Launchpad PPA shortcut (e.g. "ppa:user/repo"). It also adds signing keys for PPA -style repositories automatically. - - -List -^^^^ - -With no options, it outputs a list of the currently configured repositories on -the system (all those found in -:code:`/etc/apt/sources.list.d/` -. With a configured repository as an argument, it outputs the configuration -details of the specified repository. - -Remove -^^^^^^ - -Accepts one repository as an argument. Removes the specified repository. - -NOTE: The system repository (/etc/at/sources.list.d/system.sources) cannot be -removed. - -Source -^^^^^^ - -Allows enabling or disabling source code for the given repository. - -Modify -^^^^^^ - -Allows changing configuration details of a given repository - -Installation -============ - -From System Package Manager ---------------------------- - -If your operating system packages repolib, you can install it by running:: - - sudo apt install python3-repolib - - -Uninstall -^^^^^^^^^ - -To uninstall, simply do:: - - sudo apt remove python3-repolib - - -From PyPI ---------- - -Repolib is available on PyPI. You can install it for your current user with:: - - pip3 install repolib - -Alternatively, you can install it system-wide using:: - - sudo pip3 install repolib - -Uninstall -^^^^^^^^^ - -To uninstall, simply do:: - - sudo pip3 uninstall repolib - -From Git --------- - -First, clone the git repository onto your local system:: - - git clone https://github.com/isantop/repolib - cd repolib - -Debian ------- - -On debian based distributions, you can build a .deb package locally and install -it onto your system. You will need the following build-dependencies: - - * debhelper (>=11) - * dh-python - * python3-all - * python3-setuptools - -You can use this command to install these all in one go:: - - sudo apt install debhelper dh-python python3-all python3-setuptools - -Then build and install the package:: - - debuild -us -uc - cd .. - sudo dpkg -i python3-repolib_*.deb - -Uninstall -^^^^^^^^^ - -To uninstall, simply do:: - - sudo apt remove python3-repolib - -setuptools setup.py -------------------- - -You can build and install the package using python3-setuptools. First, install -the dependencies:: - - sudo apt install python3-all python3-setuptools - -Then build and install the package:: - - sudo python3 ./setup.py install - -Uninstall -^^^^^^^^^ - -You can uninstall RepoLib by removing the following files/directories: - - * /usr/local/lib/python3.7/dist-packages/repolib/ - * /usr/local/lib/python3.7/dist-packages/repolib-\*.egg-info - * /usr/local/bin/apt-manage - -This command will remove all of these for you:: - - sudo rm -r /usr/local/lib/python3.7/dist-packages/repolib* /usr/local/bin/apt-manage diff --git a/archive/SECURITY.md b/archive/SECURITY.md deleted file mode 100644 index d8f441d..0000000 --- a/archive/SECURITY.md +++ /dev/null @@ -1,18 +0,0 @@ -# Security Policy - -## Supported Versions - -The following versions of RepoLib currently receive updates for security: - -| Version | Supported | -| ------- | ------------------------ | -| 1.1.x | :heavy_check_mark: -| 1.0.x | :heavy_exclamation_mark: | - -Please note that only the current supported patch version of each release -is supported. - -## Reporting a Vulnerability - -When Filing an issue for a potential security vulnerability, please be sure -to include a `[SECURITY]` tag in the issue title. diff --git a/archive/TESTING.md b/archive/TESTING.md deleted file mode 100644 index 8979356..0000000 --- a/archive/TESTING.md +++ /dev/null @@ -1,276 +0,0 @@ -## Testing - -The following components of RepoLib should be tested with each revision: - -### CLI - apt-manage command - -The `apt-manage` command should be tested every single revision to ensure that -it is working correctly. This will also generally test that changes to the -underlying library have not affected anything. - -#### Adding repositories - -Adding repositories should be tested. - -1. Test Adding PPAs - -``` -sudo apt-manage -b add ppa:system76/proposed -``` -Verify that the information output and the resulting deb lines (at the end of -the output) appear correct for the given PPA. - -``` -sudo apt-manage add -s ppa:system76/proposed -``` -Verify that the `deb-src` is included in the `Types` field, then remove the -repository: `sudo apt-manage remove ppa-system76-proposed` - -``` -sudo apt-manage add -d ppa:system76/proposed -``` -Verify that the `Enabled` field is set to `no`, then remove the -repository: `sudo apt-manage remove ppa-system76-proposed` - -``` -sudo apt-manage add ppa:system76/proposed -``` -Verify that the command asks for verification before completing and displays -information about the PPA (similar to `add-apt-repository`). Verify that the -command fetches the signing key and adds it to the system. Verify that the -the correct `.list` file is added to `/etc/apt/sources.list.d`, then remove the -repository: `sudo apt-manage remove ppa-system76-proposed` - - -2. Test adding deb repositories - -``` -sudo apt-manage add --format list deb http://example.com/ubuntu focal main -``` -Verify that the added repository matches the given input, and that there is a -commented-out `deb-src` repository with it. Ensure that the added repository -file ends in `.list` and that the contents match legacy Deb format. - -Remove the repository with `sudo apt-manage remove - -3. Test adding URLs - -``` -sudo apt-manage add --format list http://example.com/ubuntu -``` -Verify that the repository is correctly expanded to include the `deb` at the -beginning, and the correct `{RELEASE} main` suites and components, where -{RELEASE} matches the current version codename. Verify that a matching `deb-src` -entry is added as well in the command output. - -4. Test adding Pop Development repositories - -``` -sudo apt-manage add popdev:master -``` - -Verify that the repository details are correct, that the `Signed-by` field -points to `/etc/apt/keyrings/popdev-archive-keyring.gpg`, that the key file -exists at that path. Then, delete the repostiory: -``` -sudo apt-manage remove popdev-master -``` - -#### Test Listing Details - -1. Test that all repos are listed - -``` -apt-manage list -``` -Verify that all configured repositories added to `/etc/apt/sources.list.d` are -printed in the command output. - -2. Test that details for all repositories are listed - -``` -apt-manage list -a -``` - -Verify that the specific configuration for each repository listed in step 1 is -presented in the output. - -3. Test that details for a specific repository are listed - -``` -apt-manage list system -``` - -Verify that the detailed configuration for only the specified repository is -listed in the output. - - -#### Removing repositories - -1. Test cancelling removal - -``` -sudo apt-manage remove example-com-ubuntu -sudo apt-manage remove example-com-ubuntu -sudo apt-manage remove example-com-ubuntu -``` - -On the first run, enter 'n' and press enter. Verify that the source is not -removed using `apt-manage list`. - -On the second run, simply press enter. Verify that the source is not removed by -using `apt-manage list`. - -On the third run, enter 'v' and press enter. Verify that the source is not removed by -using `apt-manage list`. - -2. Test removing sources - -``` -sudo apt-manage remove example-com-ubuntu -``` - -Enter 'y'. Verify that the source is removed using `apt-manage list`. - -3. Verify protection of system sources - -``` -sudo apt-manage remove system -``` - -Verify that the command returns an error and that no action is taken (even if a -system.sources file does not exist) using `apt-manage list` - - -#### Modifying a repository - -##### Setup - -Add a testing repository: - -``` -sudo apt-manage add popdev:master -apt-manage list popdev-master -``` -Verify that the details are correct in the output. - -1. Change Repository Name - -``` -sudo apt-manage modify popdev-master --name 'Testing Repo' -apt-manage list popdev-master -``` - -Verify that the name was updated in the final output to match the given input -`Testing Repo` - -2. Disable Repository - -``` -sudo apt-manage modify popdev-master --disable -apt-manage list popdev-master -``` -Ensure that the repository is now listed as `Enabled: no`. - -3. Add/Remove URI - -``` -sudo apt-manage modify popdev-master --add-uri http://example.com/ -apt-manage list popdev-master -``` -Ensure that the `http://example.com` URI was added to the source. - -``` -sudo apt-manage modify popdev-master --remove-uri http://example.com -apt-manage list popdev-master -``` -Ensure that the `http://example.com` URI was removed. - -4. Add/Remove Suite - -``` -sudo apt-manage modify popdev-master --add-suite xenial -apt-manage list popdev-master -``` -Ensure that the suite `xenial` was added to the source. - -``` -sudo apt-manage modify popdev-master --remove-suite xenial -apt-manage list popdev-master -``` - -Ensure that the suite `xenial` was removed from the source. - -5. Add/Remove Components - -``` -sudo apt-manage modify popdev-master --add-component 'universe multiverse' -apt-manage list popdev-master -``` -Ensure that the components `universe` and `multiverse` were added to the source. - -``` -sudo apt-manage modify popdev-master --remove-component 'main multiverse' -apt-manage list popdev-master -``` -Ensure that the components `main` and `multiverse` were removed from the source. - - -#### Enabling/Disabling Source Code - -##### Setup - -Add a testing repository: - -``` -apt-manage list popdev-master -``` -Verify that the details are correct in the output and that `Types:` is just -`deb`. - -1. Enable source code for one repo - -``` -sudo apt-manage modify --source-enable popdev-master -apt-manage list popdev-master -``` -Verify that the `Types:` is now `deb deb-src`. - -2. Disable source code for one repo - -``` -sudo apt-manage modify --source-disable popdev-master -apt-manage list popdev-master -``` -Verify that the `Types:` is now just `deb`. - -Finally, remove the testing repository: -``` -sudo apt-manage remove popdev-master -``` - -### Installation/upgrading (packaging tests) - -_This section is to test the installation behavior of the Debian package, -and doesn't need to be run for changes to repolib itself._ - -**Confirm add-apt-repository is installed when software-properties-common is not installed:** - -- [ ] Make sure `software-properties-common` is not installed. -- [ ] Remove `python3-repolib` with `sudo dpkg -r --force-all python3-repolib`. -- [ ] Ensure `/usr/bin/add-apt-repository` doesn't exist (if it does, remove it.) -- [ ] Install `python3-repolib` (can be done with `sudo apt install -f`). -- [ ] Ensure `/usr/bin/add-apt-repository` exists and is a link to `/usr/lib/repolib/add-apt-repository`. - -**Confirm add-apt-repository is not installed when software-properties-common is installed:** - -- [ ] Remove `python3-repolib` with `sudo dpkg -r --force-all python3-repolib`. -- [ ] Ensure `/usr/bin/add-apt-repository` doesn't exist (if it does, remove it.) -- [ ] Install `software-properties-common`, confirm `/usr/bin/add-apt-repository` now exists and is not a link. - - Can be done with `apt download software-properties-common python3-software-properties` - followed by `dpkg -i` on the downloaded files. -- [ ] Install `python3-repolib` again, confirm `/usr/bin/add-apt-repository` still isn't a link. - -**Confirm add-apt-repository is installed when software-properties-common is removed:** - -- [ ] Remove `software-properties-common` and confirm that `/usr/bin/add-apt-repository` still exists and is now a link. diff --git a/archive/apt-manage-spec.rst b/archive/apt-manage-spec.rst deleted file mode 100644 index d8d31ea..0000000 --- a/archive/apt-manage-spec.rst +++ /dev/null @@ -1,172 +0,0 @@ -=================== -Spec for apt-manage -=================== - -apt-manage is the CLI interface to manage software sources using RepoLib. It is -written in Python and shipped with RepoLib - -Commands -======== - -There are several commands provided by apt-manage:: - - add - remove - modify - list - source - -add ---- - -The add command is used for adding new software sources to the system. It -requires root. It has the following options:: - - --disable, -d - --source-code, -s - --expand, -e - ---disable -^^^^^^^^^ - -The --disable option (short form -d) will add the source and disable it -immediately - ---source-code -^^^^^^^^^^^^^ - -The --source-code option (short form -s) will enable source code for the -new source as well as binary packages. - ---expand -^^^^^^^^ - -The --expand options (short form -e) will show expanded details about the source -prior to adding it. - -remove ------- - -The remove command will remove the selected source. It has no options. Note that -the system sources cannot be removed. This requires root. - -modify ------- - -The modify command will allow making modifications to the specified repository. -It requires providing a repository to modify. It requires root. It accepts the -following options:: - - --enable, -e - --disable, -d - --add-suite - --remove-suite - --add-component - --remove-component - --add-uri - --remove-uri - --add-option - --remove-option - ---enable -^^^^^^^^ - -The enable option (short form -e) sets the source to be enabled. - ---disable -^^^^^^^^^ - -The disable option (short form -d) sets the source to be disabled. - ---add-suite -^^^^^^^^^^^ - -The --add-suite option attempts to add the specified suite or suites to the -source. If a given suite is already added to the source, it is ignored. Note -that legacy deb sources cannot have multiple suites. - ---remove-suite -^^^^^^^^^^^^^^ - -The --remove-suite option attempts to remove the specified suite or suites from -the source. If a given suite is not added to the source, it is ignored. The last -configured suite on a source cannot be removed. - ---add-component -^^^^^^^^^^^^^^^ - -The --add-component option attempts to add the specified component or components -to the source. If a given component is already added to the source, it is -ignored. - ---remove-component -^^^^^^^^^^^^^^^^^^ - -The --remove-component option attempts to remove the specified component or -components from the source. If a given component is not added to the source, it -is ignored. The last configured component on a source cannot be removed. - ---add-uri -^^^^^^^^^ - -The --add-uri option attempts to add the specified URI or URIs to the source. If -a given URI is already added to the source, it is ignored. Note that legacy deb -sources cannot have multiple URIs. - ---remove-uri -^^^^^^^^^^^^ - -The --remove-uri option attempts to remove the specified URI or URIs from the -source. If a given URI is not added to the source, it is ignored. The last -configured URI on a source cannot be removed. - ---add-option -^^^^^^^^^^^^ -The --add-option option attempts to add the given option or options as well as -values to the source. If a given option is already added to the source, it is -ignored. - ---remove-option -^^^^^^^^^^^^^^^ - -The --remove-option option attempts to remove the given option or options from -the source. If a given option isn't added to the source, it is ignored. - -list ----- - -The list command lists available software sources as well as details about -sources. With no further options, it lists all configured sources. With a -configured source, it lists details about the specified source. It has the -following option:: - - --verbose, -v - --legacy, -l - ---verbose -^^^^^^^^^ - -The --verbose option (short form -v) lists all details for all configured -software sources. It has no effect if a specific source is provided. - -source ------- - -The source command allows enabling or disabling source code in configured -sources. If a configured source is provided, this command will affect that -source. If no sources are provided, this command will affect all sources on the -system. Without options, it will list the status for source code packages. It -also accepts the following options, which require root:: - - --enable, -e - --disable, -d - ---enable -^^^^^^^^ - -The --enable option (short form -e) will enable source code packages. - ---disable -^^^^^^^^^ - -The --disable option (short form -d) will disable source code packages \ No newline at end of file diff --git a/archive/bin/add-apt-repository b/archive/bin/add-apt-repository deleted file mode 100755 index 5c2f26c..0000000 --- a/archive/bin/add-apt-repository +++ /dev/null @@ -1,194 +0,0 @@ -#!/usr/bin/python3 - -""" -Copyright (c) 2019-2020, Ian Santopietro -All rights reserved. - -This file is part of RepoLib. - -RepoLib is free software: you can redistribute it and/or modify -it under the terms of the GNU Lesser General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -RepoLib is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License -along with RepoLib. If not, see . -""" -#pylint: disable=invalid-name -# Pylint will complain about our module name not being snake_case, however this -# is a command rather than a python module, and thus this is correct anyway. - -import argparse -import os -import subprocess - -import repolib - -system_codename = repolib.util.DISTRO_CODENAME - -system_components = [ - 'main', - 'universe', - 'multiverse', - 'restricted' -] - -system_suites = [ - system_codename, - f'{system_codename}-updates', - f'{system_codename}-security', - f'{system_codename}-backports', - f'{system_codename}-proposed', - 'updates', - 'security', - 'backports', - 'proposed', -] - -def get_args(): - parser = argparse.ArgumentParser( - prog='add-apt-repository', - description=( - 'add-apt-repository is a script for adding apt sources.list entries.' - '\nThis command has been deprecated in favor of `apt-manage`. See ' - '`apt-manage --help` for more information.' - ) - ) - - parser.add_argument( - 'sourceline', - metavar='' - ) - - group = parser.add_mutually_exclusive_group() - - group.add_argument( - '-m', - '--massive-debug', - dest='debug', - action='store_true', - help='Print a lot of debug information to the command line' - ) - - group.add_argument( - '-r', - '--remove', - action='store_true', - help='remove repository from sources.list.d directory' - ) - - group.add_argument( - '-s', - '--enable-source', - dest='source', - action='store_true', - help='Allow downloading of source packages from the repository' - ) - - parser.add_argument( - '-y', - '--yes', - action='store_true', - help='Assum yes to all queries' - ) - - parser.add_argument( - '-n', - '--no-update', - dest='noupdate', - action='store_true', - help='Do not update package cache after adding' - ) - - parser.add_argument( - '-u', - '--update', - action='store_true', - help='Update package cache after adding (legacy option)' - ) - - parser.add_argument( - '-k', - '--keyserver', - metavar='KEYSERVER', - help='Legacy option, unused.' - ) - - return parser - -parser = get_args() -args = parser.parse_args() - -command = ['apt-manage'] - -if args.debug: - command.append('-bb') - -sourceline = args.sourceline -run = True -remove = False - -if sourceline in system_components: - command.append('modify') - command.append('system') - if not args.remove: - command.append('--add-component') - else: - command.append('--remove-component') - -elif sourceline in system_suites: - command.append('modify') - command.append('system') - if not args.remove: - command.append('--add-suite') - else: - command.append('--remove-suite') - -else: - - if args.source: - command.append('source') - - elif args.remove: - remove = True - command.append('remove') - - else: - command.append('add') - if not args.yes: - command.append('--expand') - -if not remove: - command.append(sourceline) -else: - sources = repolib.get_all_sources() - comp_source = repolib.DebLine(sourceline) - for source in sources: - if comp_source.uris[0] in source.uris: - name = str(source.filename.name) - name = name.replace(".list", "") - name = name.replace(".sources", "") - command.append(name) - -run = True - -if os.geteuid() != 0: - print('Error: must run as root') - run = False - -if run: - subprocess.run(command) - - if not args.noupdate: - subprocess.run(['apt', 'update']) - -print('NOTE: add-apt-repository is deprecated in Pop!_OS. Use this instead:') -print_command = command.copy() -if '--expand' in print_command: - print_command.remove('--expand') -print(' '.join(print_command)) diff --git a/archive/bin/apt-manage b/archive/bin/apt-manage deleted file mode 100755 index 77ae812..0000000 --- a/archive/bin/apt-manage +++ /dev/null @@ -1,85 +0,0 @@ -#!/usr/bin/python3 - -""" -Copyright (c) 2019-2020, Ian Santopietro -All rights reserved. - -This file is part of RepoLib. - -RepoLib is free software: you can redistribute it and/or modify -it under the terms of the GNU Lesser General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -RepoLib is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License -along with RepoLib. If not, see . -""" -#pylint: disable=invalid-name -# Pylint will complain about our module name not being snake_case, however this -# is a command rather than a python module, and thus this is correct anyway. - -import argparse -import logging -import os -import sys - -import repolib -from repolib import command - -SOURCES_DIR = '/etc/apt/sources.list.d' - -def main(options=None): - """ Main function for apt-manage.""" - # Set up Argument Parsing. - parser = repolib.command.parser - - # Parse options - args = parser.parse_args() - if options: - args = parser.parse_args(options) - - if not args.debug: - args.debug = 0 - - if args.debug > 2: - args.debug = 2 - - verbosity = { - 0 : logging.WARN, - 1 : logging.INFO, - 2 : logging.DEBUG - } - - log = logging.getLogger('apt-manage') - handler = logging.StreamHandler() - formatter = logging.Formatter('%(name)s: %(levelname)s: %(message)s') - handler.setFormatter(formatter) - log.addHandler(handler) - log.setLevel(verbosity[args.debug]) - log.debug('Logging set up!') - repolib.set_logging_level(args.debug) - - if not args.action: - args = parser.parse_args(sys.argv[1:] + ['list']) - - log.debug('Arguments passed: %s', str(args)) - log.debug('Got command: %s', args.action) - - subcommand = args.action.capitalize() - - command = getattr(repolib.command, subcommand)(log, args, parser) - result = command.run() - if not result: - sys.exit(1) - -if __name__ == '__main__': - try: - main() - except KeyboardInterrupt: - print('') - sys.exit(130) diff --git a/archive/data/bash-completion/apt-manage b/archive/data/bash-completion/apt-manage deleted file mode 100755 index f881bc4..0000000 --- a/archive/data/bash-completion/apt-manage +++ /dev/null @@ -1,42 +0,0 @@ -# Debian apt-manage completion - -_apt_manage() -{ - local cur prev words cword package - _init_completion -n ':=' || return - - local special i - i=0 - for (( i=0; i < ${#words[@]}-1; i++ )); do - if [[ ${words[i]} == @(add|list|modify|remove|key) ]]; then - special=${words[i]} - fi - done - - if [[ -n $special ]]; then - case $special in - list|modify|remove|key) - COMPREPLY=( $( compgen -W '$(apt-manage list -n)' -- "$cur" ) ) - return - ;; - *) - ;; - esac - fi - - - if [[ "$cur" == -* ]]; then - return - # COMPREPLY=( $(compgen -W ' - # --help --disable --source-code --expand - # --verbose --legacy --no-names - # --enable --disable --name --add-suite --remove-suite - # --add-component --remove-component --add-uri --remove-uri - # ' -- "$cur") ) - else - COMPREPLY=( $(compgen -W 'add list modify remove key' \ - -- "$cur") ) - fi - -} && -complete -F _apt_manage apt-manage diff --git a/archive/data/org.pop_os.repolib.conf b/archive/data/org.pop_os.repolib.conf deleted file mode 100644 index cadef8b..0000000 --- a/archive/data/org.pop_os.repolib.conf +++ /dev/null @@ -1,20 +0,0 @@ - - - - system - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/archive/data/org.pop_os.repolib.policy b/archive/data/org.pop_os.repolib.policy deleted file mode 100644 index 7a6caef..0000000 --- a/archive/data/org.pop_os.repolib.policy +++ /dev/null @@ -1,20 +0,0 @@ - - - - - Repoman - https://github.com/pop-os/repolib - x-system-software-sources - - - Modifies a Debian Repository in the system software sources. - Authentication is required to change software sources. - - auth_admin_keep - auth_admin_keep - auth_admin_keep - - - \ No newline at end of file diff --git a/archive/data/org.pop_os.repolib.service b/archive/data/org.pop_os.repolib.service deleted file mode 100644 index 2f354e3..0000000 --- a/archive/data/org.pop_os.repolib.service +++ /dev/null @@ -1,4 +0,0 @@ -[D-BUS Service] -Name=org.pop_os.repolib -Exec=/usr/bin/python3 /usr/lib/repolib/service.py -User=root diff --git a/archive/data/service.py b/archive/data/service.py deleted file mode 100755 index b8d79dd..0000000 --- a/archive/data/service.py +++ /dev/null @@ -1,316 +0,0 @@ -#!/usr/bin/python3 -''' - Copyright 2020 Ian Santopietro (ian@system76.com) - - This file is part of Repolib. - - Repolib is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Repolib is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Repolib. If not, see . -''' -#pylint: skip-file - -import shutil -import subprocess - -import gi -from gi.repository import GObject, GLib - -from pathlib import Path -import dbus -import dbus.service -import dbus.mainloop.glib -import time - -import repolib - -class RepolibException(dbus.DBusException): - _dbus_error_name = 'org.pop_os.repolib.RepolibException' - -class PermissionDeniedByPolicy(dbus.DBusException): - _dbus_error_name = 'org.pop_os.repolib.PermissionDeniedByPolicy' - -class AptException(Exception): - pass - -class Repo(dbus.service.Object): - def __init__(self, conn=None, object_path=None, bus_name=None): - dbus.service.Object.__init__(self, conn, object_path, bus_name) - - # These are used by PolKit to check privileges - self.dbus_info = None - self.polkit = None - self.enforce_polkit = True - - try: - self.system_repo = repolib.SystemSource() - except: - self.system_repo = None - - self.source = None - self.sources_dir = Path('/etc/apt/sources.list.d') - self.keys_dir = Path('/etc/apt/trusted.gpg.d') - - @dbus.service.method( - "org.pop_os.repolib.Interface", - in_signature='as', out_signature='', - sender_keyword='sender', connection_keyword='conn' - ) - def add_apt_signing_key(self, cmd, sender=None, conn=None): - self._check_polkit_privilege( - sender, conn, 'org.pop_os.repolib.modifysources' - ) - print(cmd) - key_path = str(cmd.pop(-1)) - with open(key_path, mode='wb') as keyfile: - try: - subprocess.run(cmd, check=True, stdout=keyfile) - except subprocess.CalledProcessError as e: - raise e - - @dbus.service.method( - "org.pop_os.repolib.Interface", - in_signature='ss', out_signature='', - sender_keyword='sender', connection_keyword='conn' - ) - def install_signing_key(self, src, dest, sender=None, conn=None): - self._check_polkit_privilege( - sender, conn, 'org.pop_os.repolib.modifysources' - ) - shutil.copy2(src, dest) - - @dbus.service.method( - "org.pop_os.repolib.Interface", - in_signature='s', out_signature='', - sender_keyword='sender', connection_keyword='conn' - ) - def delete_signing_key(self, src, sender=None, conn=None): - self._check_polkit_privilege( - sender, conn, 'org.pop_os.repolib.modifysources' - ) - key_path = Path(src) - key_path.unlink() - - @dbus.service.method( - "org.pop_os.repolib.Interface", - in_signature='s', out_signature='', - sender_keyword='sender', connection_keyword='conn' - ) - def delete_prefs_file(self, src, sender=None, conn=None): - self._check_polkit_privilege( - sender, conn, 'org.pop_os.repolib.modifysources' - ) - prefs_path = Path(src) - prefs_path.unlink() - - @dbus.service.method( - "org.pop_os.repolib.Interface", - in_signature='ss', out_signature='', - sender_keyword='sender', connection_keyword='conn' - ) - def output_prefs_to_disk(self, path, contents, sender=None, conn=None): - self._check_polkit_privilege( - sender, conn, 'org.pop_os.repolib.modifysources' - ) - full_path = Path(path) - with open(full_path, mode='w') as output_file: - output_file.write(contents) - - @dbus.service.method( - "org.pop_os.repolib.Interface", - in_signature='ss', out_signature='', - sender_keyword='sender', connection_keyword='conn' - ) - def output_file_to_disk(self, filename, source, sender=None, conn=None): - self._check_polkit_privilege( - sender, conn, 'org.pop_os.repolib.modifysources' - ) - full_path = self.sources_dir / filename - with open(full_path, mode='w') as output_file: - output_file.write(source) - - @dbus.service.method( - "org.pop_os.repolib.Interface", - in_signature='ss', out_signature='', - sender_keyword='sender', connection_keyword='conn' - ) - def backup_alt_file(self, alt_file, save_file, sender=None, conn=None): - self._check_polkit_privilege( - sender, conn, 'org.pop_os.repolib.modifysources' - ) - alt_path = self.sources_dir / alt_file - save_path = self.sources_dir / save_file - if alt_path.exists(): - alt_path.rename(save_path) - - @dbus.service.method( - "org.pop_os.repolib.Interface", - in_signature='s', out_signature='', - sender_keyword='sender', connection_keyword='conn' - ) - def delete_source_file(self, filename, sender=None, conn=None): - self._check_polkit_privilege( - sender, conn, 'org.pop_os.repolib.modifysources' - ) - source_file = self.sources_dir / filename - source_file.unlink() - - @dbus.service.method( - "org.pop_os.repolib.Interface", - in_signature='', out_signature='', - sender_keyword='sender', connection_keyword='conn' - ) - def exit(self, sender=None, conn=None): - mainloop.quit() - - @dbus.service.method( - "org.pop_os.repolib.Interface", - in_signature='b', out_signature='b', - sender_keyword='sender', connection_keyword='conn' - ) - def set_system_source_code_enabled(self, enabled, sender=None, conn=None): - """ Enable or disable source code in the system source. - - Arguments: - enabled (bool): The new state to set, True = Enabled. - """ - self._check_polkit_privilege( - sender, conn, 'org.pop_os.repolib.modifysources' - ) - if self.system_repo: - self.system_repo.load_from_file() - new_types = [repolib.util.AptSourceType.BINARY] - if enabled: - new_types.append(repolib.util.AptSourceType.SOURCE) - self.system_repo.types = new_types - self.system_repo.save_to_disk() - return enabled - return False - - @dbus.service.method( - "org.pop_os.repolib.Interface", - in_signature='sb', out_signature='b', - sender_keyword='sender', connection_keyword='conn' - ) - def set_system_comp_enabled(self, comp, enable, sender=None, conn=None): - """ Enable or disable a component in the system source. - - Arguments: - comp (str): the component to set - enable (bool): The new state to set, True = Enabled. - """ - self._check_polkit_privilege( - sender, conn, 'org.pop_os.repolib.modifysources' - ) - if self.system_repo: - self.system_repo.load_from_file() - self.system_repo.set_component_enabled(component=comp, enabled=enable) - self.system_repo.save_to_disk() - return True - return False - - @dbus.service.method( - "org.pop_os.repolib.Interface", - in_signature='sb', out_signature='b', - sender_keyword='sender', connection_keyword='conn' - ) - def set_system_suite_enabled(self, suite, enable, sender=None, conn=None): - """ Enable or disable a suite in the system source. - - Arguments: - suite (str): the suite to set - enable (bool): The new state to set, True = Enabled. - """ - self._check_polkit_privilege( - sender, conn, 'org.pop_os.repolib.modifysources' - ) - if self.system_repo: - self.system_repo.load_from_file() - self.system_repo.set_suite_enabled(suite=suite, enabled=enable) - self.system_repo.save_to_disk() - return True - return False - - @classmethod - def _log_in_file(klass, filename, string): - date = time.asctime(time.localtime()) - ff = open(filename, "a") - ff.write("%s : %s\n" %(date,str(string))) - ff.close() - - @classmethod - def _strip_source_line(self, source): - source = source.replace("#", "# ") - source = source.replace("[", "") - source = source.replace("]", "") - source = source.replace("'", "") - source = source.replace(" ", " ") - return source - - def _check_polkit_privilege(self, sender, conn, privilege): - # from jockey - '''Verify that sender has a given PolicyKit privilege. - sender is the sender's (private) D-BUS name, such as ":1:42" - (sender_keyword in @dbus.service.methods). conn is - the dbus.Connection object (connection_keyword in - @dbus.service.methods). privilege is the PolicyKit privilege string. - This method returns if the caller is privileged, and otherwise throws a - PermissionDeniedByPolicy exception. - ''' - if sender is None and conn is None: - # called locally, not through D-BUS - return - if not self.enforce_polkit: - # that happens for testing purposes when running on the session - # bus, and it does not make sense to restrict operations here - return - - # get peer PID - if self.dbus_info is None: - self.dbus_info = dbus.Interface(conn.get_object('org.freedesktop.DBus', - '/org/freedesktop/DBus/Bus', False), 'org.freedesktop.DBus') - pid = self.dbus_info.GetConnectionUnixProcessID(sender) - - # query PolicyKit - if self.polkit is None: - self.polkit = dbus.Interface(dbus.SystemBus().get_object( - 'org.freedesktop.PolicyKit1', - '/org/freedesktop/PolicyKit1/Authority', False), - 'org.freedesktop.PolicyKit1.Authority') - try: - # we don't need is_challenge return here, since we call with AllowUserInteraction - (is_auth, _, details) = self.polkit.CheckAuthorization( - ('unix-process', {'pid': dbus.UInt32(pid, variant_level=1), - 'start-time': dbus.UInt64(0, variant_level=1)}), - privilege, {'': ''}, dbus.UInt32(1), '', timeout=600) - except dbus.DBusException as e: - if e._dbus_error_name == 'org.freedesktop.DBus.Error.ServiceUnknown': - # polkitd timed out, connect again - self.polkit = None - return self._check_polkit_privilege(sender, conn, privilege) - else: - raise - - if not is_auth: - Repo._log_in_file('/tmp/repolib.log','_check_polkit_privilege: sender %s on connection %s pid %i is not authorized for %s: %s' % - (sender, conn, pid, privilege, str(details))) - raise PermissionDeniedByPolicy(privilege) - -if __name__ == '__main__': - dbus.mainloop.glib.DBusGMainLoop(set_as_default=True) - - bus = dbus.SystemBus() - name = dbus.service.BusName("org.pop_os.repolib", bus) - object = Repo(bus, '/Repo') - - mainloop = GLib.MainLoop() - mainloop.run() \ No newline at end of file diff --git a/archive/data/zsh-completion/_apt-manage b/archive/data/zsh-completion/_apt-manage deleted file mode 100644 index 7ccf75b..0000000 --- a/archive/data/zsh-completion/_apt-manage +++ /dev/null @@ -1,70 +0,0 @@ -#compdef apt-manage -typeset -A opt_args - -typeset -A opt_args - -_arguments -C \ - '1:cmd:->cmds' \ - '2:sources:->source_lists' \ - '*:: :->args' \ -&& ret=0 - -case "$state" in - (cmds) - local commands; commands=( - 'add' - 'list' - 'modify' - 'remove' - 'key' - ) - _describe -t commands 'command' commands && ret=0 - ;; - (source_lists) - local sources - sources=( $(apt-manage list -n)) - _describe -t sources 'source' sources && ret=0 - ;; - (args) - local arguments - arguments=( - # Main command - '--help' - # Add subcommand - '--disable' - '--source-code' - '--terse' - '--name' - '--identifier' - '--format' - '--skip-keys' - # Key Ssbcommand - '--path' - '--url' - '--ascii' - '--fingerprint' - '--keyserver' - '--remove' - # List subcommand - '--legacy' - '--verbose' - '--all' - '--file-names' - # Modify subcommand - '--enable' - '--source-enable' - '--source-disable' - '--add-uri' - '--add-suite' - '--add-component' - '--remove-uri' - '--remove-suite' - '--remove-component' - # Remove subcommand - '--assume-yes' - ) - _describe -t arguments 'argument' arguments && ret=0 - ;; -esac - -return 1 \ No newline at end of file diff --git a/archive/debian/changelog b/archive/debian/changelog deleted file mode 100644 index 980b413..0000000 --- a/archive/debian/changelog +++ /dev/null @@ -1,11 +0,0 @@ -repolib (2.2.0~99pika2) kinetic; urgency=medium - - * Remove stupid post scripts - - -- Ward Nakchbandi Fri, 09 Oct 2022 21:38:00 +0300 - -repolib (2.2.0~99pika1) kinetic; urgency=medium - - * Initial Creation - - -- Ward Nakchbandi Fri, 09 Oct 2022 21:38:00 +0300 diff --git a/archive/docs/Makefile b/archive/docs/Makefile deleted file mode 100644 index 298ea9e..0000000 --- a/archive/docs/Makefile +++ /dev/null @@ -1,19 +0,0 @@ -# Minimal makefile for Sphinx documentation -# - -# You can set these variables from the command line. -SPHINXOPTS = -SPHINXBUILD = sphinx-build -SOURCEDIR = . -BUILDDIR = _build - -# Put it first so that "make" without argument is like "make help". -help: - @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) - -.PHONY: help Makefile - -# Catch-all target: route all unknown targets to Sphinx using the new -# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). -%: Makefile - @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) \ No newline at end of file diff --git a/archive/docs/aptmanage/add.rst b/archive/docs/aptmanage/add.rst deleted file mode 100644 index d2e2121..0000000 --- a/archive/docs/aptmanage/add.rst +++ /dev/null @@ -1,71 +0,0 @@ -============== -Adding Sources -============== - -The ``add`` subcommand is used to add new repositories to the software sources. -You can specify a deb-line to configure into the system or a ``ppa:`` shortcut -to add the new source directly:: - - $ sudo apt-manage add deb http://apt.pop-os.org/ubuntu disco main - $ sudo apt-manage add ppa:system76/pop - -If an internet connection is available, ``apt-manage`` will additionally attempt -to install the signing key for any ``ppa:`` shortcuts added. - - -Options for adding sources -========================== - -Various options control adding sources to the system. - - -Source Code, Details, Disabling Sources ---------------------------------------- - -To enable source code for the added repository, use the ``--source-code`` flag:: - - $ apt-manage add --source-code ppa:system76/pop - -The new source can be disabled upon adding it using the ``--disable`` flag:: - - $ apt-manage add --disable ppa:system76/pop - -Details for the PPA are printed for review prior to adding the source by default. -This will print the generated configuration for the source as well as any -available details fetched for the source (typically only available for PPA -sources). To suppress this output, include ``--terse``. - - -Source File Format ------------------- - -The format which RepoLib saves the repository on disk in depends on the type of -repository being added, but regardless the ``--format`` flag can be used to -force either legacy ``.list`` format or modern ``.sources`` format:: - - apt-manage add popdev:master --format=list - apt-manage add ppa:system76/pop --format=sources - - -Names and Identifiers ---------------------- - -Names for PPA sources are automatically detected from Launchpad if an internet -connection is available. Otherwise they are automatically generated based on the -source type and details. Optionally, a name can be specified when the source is -added:: - - $ apt-manage add ppa:system76/pop --name "PPA for Pop_OS Software" - -System-identifiers determine how the source is subsequently located within RepoLib and -on the system. It matches the filename for the source's configuration file. It -is automatically generated based on the source type, or can be specified -manually upon creation using the ``--identifier`` flag:: - - $ apt-manage add ppa:system76/pop --identifier pop-ppa - -.. note:: - Even though ``apt-manage`` allows modifcation or management of DEB822-format - sources, it does not currently support adding them to the system directly. - DEB822 sources can be manually added or added using third-party tools, and - ``apt-manage`` will correctly operate on them subsequently. diff --git a/archive/docs/aptmanage/aptmanage.rst b/archive/docs/aptmanage/aptmanage.rst deleted file mode 100644 index 2e80cc4..0000000 --- a/archive/docs/aptmanage/aptmanage.rst +++ /dev/null @@ -1,28 +0,0 @@ -========== -Apt Manage -========== - -``apt-manage`` is a command line tool for managing your local software sources -using RepoLib. Run ``apt-manage`` standalone to get a listing of all of the -software repositories currently configured:: - - $ apt-manage - Configured sources: - system - pop-os-apps - ppa-system76-pop - - -``apt-manage`` operates on both DEB822-formated sources (located in the -``/etc/apt/sources.list.d/*.sources`` files) as well as using traditional -one-line format sources (in ``/etc/apt/sources.list.d/*.list`` files). - -.. toctree:: - :maxdepth 1 - :caption: apt-manage Documentation - - add - list - modify - remove - key diff --git a/archive/docs/aptmanage/key.rst b/archive/docs/aptmanage/key.rst deleted file mode 100644 index 88fe9a6..0000000 --- a/archive/docs/aptmanage/key.rst +++ /dev/null @@ -1,78 +0,0 @@ -===================== -Managing Signing Keys -===================== - -Signing keys are an important part of repository security and are generally -required to be used in repositories for all recent versions of APT. As previous -methods of handling Apt keys have been deprecated, Apt Manage provides easy -tools to use for managing signing keys for repositories in the ``key`` -subcommand. - -Most of the tools in the ``key`` subcommand are centered around adding a signing -key to a repository:: - - apt-manage key repo-id --fingerprint 63C46DF0140D738961429F4E204DD8AEC33A7AFF - -Apt Manage supports adding keys from a variety of sources: - - -Existing Keyring Files, --name, --path -====================================== - -``--name`` sets the :ref:`signed_by` value of the existing repository to the -name of a file within the system key configuration directory:: - - apt-manage key popdev-master --name popdev - -``--path`` sets the :ref:`signed_by` value of the existing repository to the -path of a file on disk:: - - apt-manage key popdev-master --path /etc/apt/keyrings/popdev-archive-keyring.gpg - - -Keyring Files Stored on the Internet, --url -=========================================== - -``--url`` will download a key file from the internet and install it into the -system, then set the repository to use that key:: - - apt-manage key popdev-master --url https://example.com/sigining-key.asc - - -Keys Stored on a Public Keyserver -================================= - -``--fingerprint`` will fetch the specified fingerprint from a public keyserver. -By default, keys will be fetched from ``keyserver.ubuntu.com``, but any SKS -keyserver can be specified using the ``--keyserver=`` argument:: - - apt-manage key ppa-system76-pop \ - --fingerprint=E6AC16572ED1AD6F96C7EBE01E5F8BBC5BEB10AE - - apt-manage key popdev-master \ - --fingerprint=63C46DF0140D738961429F4E204DD8AEC33A7AFF \ - --keyserver=https://keyserver.example.com/ - - -Adding ASCII-Armored Keys Directly, --ascii -=========================================== - -``--ascii`` Will take plain ascii data from the command line and add it to a new -keyring file, then set the repository to use that key:: - - apt-manage key popdev-master --ascii "$(/tmp/popdev-key.asc)" - - -Removing Keys -============= - -Generally, manually removing keys is not necessary because removing a source -automatically removes the key (if it is the only source using that key). However, -If there is a need to remove a key manually (e.g. the signing key has changed -and must be re-added), then removal is supported:: - - apt-manage key popdev-master --remove - -This will remove the key from the repository configuration and if no other -sources are using a particular key, it will also remove the keyring file from -disk. diff --git a/archive/docs/aptmanage/list.rst b/archive/docs/aptmanage/list.rst deleted file mode 100644 index 7eacea9..0000000 --- a/archive/docs/aptmanage/list.rst +++ /dev/null @@ -1,79 +0,0 @@ -============================= -Listing Configuration Details -============================= - -To get a list of all of the sources configured on the system, use the ``list`` -subcommand:: - - $ apt-manage list - Configured sources: - system - Pop_OS System Sources - pop-os-apps - Pop_OS Applications - ppa-system76-pop - Pop!_OS PPA - -The sources are listed with the system source (if detected/configured) first, -followed by all DEB822-format sources detected first, then by all one-line -format sources. The system-identifier (used to identify sources in the system) -is listed at the beginning of the line, and the name of the source is listed -after. - -Details of an individual source can be printed by specifying a source's -system-identifier:: - - $ apt-manage list ppa-system76-pop - Details for source ppa-system76-pop: - Name: Pop!_OS PPA - Enabled: yes - Types: deb deb-src - URIs: http://apt.pop-os.org/release - Suites: focal - Components: main - - -Listing all details of all sources at once -========================================== - -Details about all sources can be listed at once using the ``--verbose`` flag:: - - $ apt-manage list --verbose - Configured sources: - system - Pop_OS System Sources - Name: Pop_OS System Sources - Enabled: yes - Types: deb deb-src - URIs: http://us.archive.ubuntu.com/ubuntu/ - Suites: focal focal-security focal-updates focal-backports - Components: main restricted universe multiverse - - pop-os-apps - Pop_OS Applications - Name: Pop_OS Applications - Enabled: yes - Types: deb - URIs: http://apt.pop-os.org/proprietary - Suites: focal - Components: main - - ppa-system76-pop - Pop!_OS PPA - Name: Pop!_OS PPA - Enabled: yes - Types: deb deb-src - URIs: http://apt.pop-os.org/release - Suites: focal - Components: main - -Note -^^^^ - -Passing the ``--verbose`` flag only applies to listing all sources. It has no -effect if a source is specified using the system-identifier; in that case, only -the specified source is printed. Additionally, if there are sources files which -contain errors, the ``--verbose`` flag will print details about them, including -the contents of the files and the stack trace of the exception which caused the -error. - - -Legacy sources.list entries -=========================== - -The contents of the system ``sources.list`` file can be appended to the end of -the output using the ``--legacy`` flag. \ No newline at end of file diff --git a/archive/docs/aptmanage/modify.rst b/archive/docs/aptmanage/modify.rst deleted file mode 100644 index 98a6929..0000000 --- a/archive/docs/aptmanage/modify.rst +++ /dev/null @@ -1,82 +0,0 @@ -================= -Modifying Sources -================= - -Modifications can be made to various configured sources using the ``modify`` -subcommand. - -Enabling/Disabling Sources: --enable | --disable -================================================ - -Sources can be disabled, which prevents software/updates from being installed -from the source but keeps it present in the system configuration for later use -or records for later. To disable a source, use ``--disable``:: - - $ apt-manage modify ppa-system76-pop --disable - -To re-enable a source after it's been disabled, use ``--enable``:: - - $ apt-manage modify ppa-system76-pop --enable - - -Changing names of sources: --name -================================= - -RepoLib allows setting up human-readable names for use in GUIs or other -user-facing contexts. To set or change a name of a source, use ``--name``:: - - $ apt-manage modify ppa-system76-pop --name "Pop_OS PPA" - - -Suites: --add-suite | --remove-suite -==================================== - -Suites for sources can be added or removed from the configuration. In one-line -sources, these are added with multiple lines, since each one-line source can -have only one suite each. DEB822 sources can have multiple suites. - -To add a suite, use ``--add-suite``:: - - $ apt-manage modify ppa-system76-pop --add-suite groovy - -Use ``--remove-suite`` to remove a suite:: - - $ apt-manage modify ppa-system76-pop --remove-suite focal - - -Components: --add-component | --remove-component -================================================ - -Both types of source format can have multiple components for each source. Note -that all components for one-line format sources will share all of a source's -components. - -Components are managed similarly to suites:: - - $ apt-manage modify system --add-component universe - $ apt-manage modify system --remove-component restricted - - -URIs: --add-uri | --remove-uri -============================== - -DEB822 sources may contain an arbitrary number of URIs. One-line sources require -an additional line for each individual URI added. All suites on a source are all -applied to all of the URIs equally. - -URIs are managed similarly to both suites and components:: - - $ apt-manage modify system --add-uri http://apt.pop-os.org/ubuntu - $ apt-manage modify system --remove-uri http://us.archive.ubuntu.com/ubuntu - - -Notes -^^^^^ - -Multiple modifications may be applied on a single ``apt-manage modify`` calls:: - - $ apt-manage modify system --name "Pop_OS 20.10 System Sources" \ - --add-suite groovy \ - --remove-suite focal focal-proposed \ - --add-uri http://apt.pop-os.org/ubuntu \ - --remove-uri http://us.archive.ubuntu.com/ubuntu diff --git a/archive/docs/aptmanage/remove.rst b/archive/docs/aptmanage/remove.rst deleted file mode 100644 index dfe1f03..0000000 --- a/archive/docs/aptmanage/remove.rst +++ /dev/null @@ -1,9 +0,0 @@ -================ -Removing Sources -================ - -To remove a source from the system configuration, use the ``remove`` -subcommand:: - - $ apt-manage remove ppa-system76-pop - \ No newline at end of file diff --git a/archive/docs/conf.py b/archive/docs/conf.py deleted file mode 100644 index ee962e6..0000000 --- a/archive/docs/conf.py +++ /dev/null @@ -1,177 +0,0 @@ -# -*- coding: utf-8 -*- -# -# Configuration file for the Sphinx documentation builder. -# -# This file does only contain a selection of the most common options. For a -# full list see the documentation: -# http://www.sphinx-doc.org/en/master/config -#pylint: skip-file - -# -- Path setup -------------------------------------------------------------- - -# If extensions (or modules to document with autodoc) are in another directory, -# add these directories to sys.path here. If the directory is relative to the -# documentation root, use os.path.abspath to make it absolute, like shown here. -# -# import os -# import sys -# sys.path.insert(0, os.path.abspath('.')) - -import sphinx_rtd_theme - - -# -- Project information ----------------------------------------------------- - -project = 'RepoLib' -copyright = '2019-2020, Ian Santopietro' -author = 'Ian Santopietro' - -# The short X.Y version -version = '0.0.8' -# The full version, including alpha/beta/rc tags -release = '' - - -# -- General configuration --------------------------------------------------- - -# If your documentation needs a minimal Sphinx version, state it here. -# -# needs_sphinx = '1.0' - -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom -# ones. -extensions = [ -] - -# Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] - -# The suffix(es) of source filenames. -# You can specify multiple suffix as a list of string: -# -# source_suffix = ['.rst', '.md'] -source_suffix = '.rst' - -# The master toctree document. -master_doc = 'index' - -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -# -# This is also used if you do content translation via gettext catalogs. -# Usually you set "language" from the command line for these cases. -language = None - -# List of patterns, relative to source directory, that match files and -# directories to ignore when looking for source files. -# This pattern also affects html_static_path and html_extra_path. -exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] - -# The name of the Pygments (syntax highlighting) style to use. -pygments_style = None - - -# -- Options for HTML output ------------------------------------------------- - -# The theme to use for HTML and HTML Help pages. See the documentation for -# a list of builtin themes. -# -html_theme = 'sphinx_rtd_theme' -html_theme_path = [sphinx_rtd_theme.get_html_theme_path()] - -# Theme options are theme-specific and customize the look and feel of a theme -# further. For a list of options available for each theme, see the -# documentation. -# -# html_theme_options = {} - -# Add any paths that contain custom static files (such as style sheets) here, -# relative to this directory. They are copied after the builtin static files, -# so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] - -# Custom sidebar templates, must be a dictionary that maps document names -# to template names. -# -# The default sidebars (for documents that don't match any pattern) are -# defined by theme itself. Builtin themes are using these templates by -# default: ``['localtoc.html', 'relations.html', 'sourcelink.html', -# 'searchbox.html']``. -# -# html_sidebars = {} - - -# -- Options for HTMLHelp output --------------------------------------------- - -# Output file base name for HTML help builder. -htmlhelp_basename = 'RepoLibdoc' - - -# -- Options for LaTeX output ------------------------------------------------ - -latex_elements = { - # The paper size ('letterpaper' or 'a4paper'). - # - # 'papersize': 'letterpaper', - - # The font size ('10pt', '11pt' or '12pt'). - # - # 'pointsize': '10pt', - - # Additional stuff for the LaTeX preamble. - # - # 'preamble': '', - - # Latex figure (float) alignment - # - # 'figure_align': 'htbp', -} - -# Grouping the document tree into LaTeX files. List of tuples -# (source start file, target name, title, -# author, documentclass [howto, manual, or own class]). -latex_documents = [ - (master_doc, 'RepoLib.tex', 'RepoLib Documentation', - 'Ian Santopietro', 'manual'), -] - - -# -- Options for manual page output ------------------------------------------ - -# One entry per manual page. List of tuples -# (source start file, name, description, authors, manual section). -man_pages = [ - (master_doc, 'repolib', 'RepoLib Documentation', - [author], 1) -] - - -# -- Options for Texinfo output ---------------------------------------------- - -# Grouping the document tree into Texinfo files. List of tuples -# (source start file, target name, title, author, -# dir menu entry, description, category) -texinfo_documents = [ - (master_doc, 'RepoLib', 'RepoLib Documentation', - author, 'RepoLib', 'One line description of project.', - 'Miscellaneous'), -] - - -# -- Options for Epub output ------------------------------------------------- - -# Bibliographic Dublin Core info. -epub_title = project - -# The unique identifier of the text. This can be a ISBN number -# or the project homepage. -# -# epub_identifier = '' - -# A unique identification for the text. -# -# epub_uid = '' - -# A list of files that should not be packed into the epub file. -epub_exclude_files = ['search.html'] diff --git a/archive/docs/deb822-format.rst b/archive/docs/deb822-format.rst deleted file mode 100644 index b01e815..0000000 --- a/archive/docs/deb822-format.rst +++ /dev/null @@ -1,276 +0,0 @@ -.. _deb822-explanation: - -======================================= -Explanation of the DEB822 Source Format -======================================= - -The sources described in ``/etc/apt/sources.list.d/`` on a Debian-based OS are -designed to support any number of different active and inactive sources, as well -as a large variety of source media and transport protocols. The files describe -one or more sources each and contain multiline stanzas defining one or more -sources per stanza, with the most preferred source listed first. Information -about available packages and versions from each source is fetched using the -``apt update`` command, or with an equivalent command from a different frontend. - - -.. _sources-list-d: - -sources.list.d -============== - -APT source information is stored locally within the ``/etc/apt/sources.list.d`` -directory. In this directory are one or more files describing one or more -sources each. For :ref:`deb822-format` sources, each file needs to have the .sources -extension. The filenames may only contain letters, digits, underscore, hyphen, -and period characters. Files with other characters in their filenames will cause -APT to print a notice that it has ignore that file (unless the file matches a -pattern in the ``Dir::Ignore-Files-Silently`` configuration list, which will -force APT to silently ignore the file. - - -.. _one-line-format: - -One-Line-Style Format -===================== - -In order to understand some of the decisions behind using the :ref:`deb822-format` -sources, it is helpful to understand the older :ref:`one-line-format`. - -:ref:`one-line-format` sources occupy one line in a file ending in ``.list``. -The line begins with a type (i.e. ``deb`` or ``deb-src`` followed by options and -arguments for this type. Individual entries cannot be continued onto multiple -lines (hence the "one-line" portion of this format's name). Empty lines in -``.list`` files are ignored, and a ``#`` character anywhere on the line signifies -that the remainder of that line is a comment. Consequently an entry can be -disabled by commenting out that entire line (prefixing it with a ``#``). If -options are provided, they are space-separated and all together are enclosed -within square brackets ( ``[]`` ). Options allowing multiple values should -separate each value with a comma ( ``,`` ) and each option name is separated -from its values by an equals sign ( ``=`` ). - -This is the traditional format and is supported by all current APT versions. -It has the advantage of being relatively compact for single-sources and -relatively easy for humans to parse. - - -.. _one-line-disadvantages: - -Disadvantages -------------- - -Problems with the :ref:`one-line-format` begin when parsing entries via machine. -Traditional, optionless entries are relatively simple to parse, as each -different portion of the entry is separated with a space. With options, however, -this is no longer the case. The presence of options causes there to be no, 1, or -multiple segments of configuration between the type declaration and the URI. -Additionally, APT sources support a variety of URI schemas, with the capability -for extensions to add additional schemas on certain configurations. Thus, -supporting modern, optioned :ref:`one-line-format` source entries requires use -of either regular expressions or multi-level parsing in order to adequately -parse the entry. Further compounding this support is the fact that -:ref:`one-line-format` entries can have one or more components, preventing -parsing of sources backwards from the end towards the front. - -Consider the following examples:: - - deb [] http://example.com.ubuntu disco main restricted multiverse universe - deb [ arch=amd64 ] http://example.com/ubuntu disco main nonfree - deb [lang=en_US] http://example.com/ubuntu disco main restricted universe multiverse - deb [ arch=amd64,armel lang=en_US,en_CA ] http://example.com/ubuntu disco main - -Each of these entries are syntactically valid source entries, each cleanly -splits into eight segments when splitting on spaces. Depending on which entry -being parsed, the URI portion of the entry may be in index 2, 4, or 5 while -options (where present) may be in index 1, 2, or 3. If we want to work backwards, -then the URI is in either index -3, -4, or -6. The only segments guaranteed to -be present at any given index is the type. The situation is even more -complicated when considering that entries may have at a minimum 3 elements, and -at a maximum 12 or more elements. - -In addition to parsing difficulty, :ref:`one-line-format` entries may only -specify a single suite and URI per entry, meaning that having two active mirrors -for a given source requires doubling the number of entries configured. You must -also create an extra set of duplicated entries for each suite you want to -configure. This can make tracking down duplicated entries difficult for users -and leads to longer-than-necessary configuration. - - -.. _deb822-format: - -Deb822-style Format -=================== - -This format addresses the file-length, duplication, and machine-parsability -issues present in the :ref:`one-line-format`. Each source is configured in a -single stanza of configuration, with lines explicitly describing their -function for the source. They also allow for lists of values for most options, -meaning that mirrors or multiple suites can be defined within a single source. A -``#`` character at the beginning of a line marks the entire line as a comment. -Entries can again be disabled by commenting out each line within the stanza; -however, as a convenience this format also brings an ``Enabled:`` field which, -when set to ``no`` disables the entry as well. Removing this field or setting it -to ``yes`` re-enables it. Options have the same format as every other field, -thus a stanza may be parsed by checking the beginning of each line for a fixed -substring, and if the line doesn't match a known substring, it can be assumed -the line is an option and the line can be ignored. Unknown options are ignored -by all versions of APT. This has the unintentional side effect of adding -extensibility to the source; by selecting a carefully namespaced field name, -third-party applications and libraries can add their own fields to sources -without causing breakage by APT. This can include comments, version information, -and (as is the case with :ref:`repolib-module`, pretty, human-readable names. - -From the ``sources.list(5)`` manual page: - - This is a new format supported by apt itself since version 1.1. Previous - versions ignore such files with a notice message as described earlier. It is - intended to make this format gradually the default format, deprecating the - previously described one-line-style format, as it is easier to create, - extend and modify for humans and machines alike especially if a lot of - sources and/or options are involved. - -.. _deb822-technical: - -=================================== -DEB822 Source Format Specifications -=================================== - -Following is a description of each field in the deb822 source format. - - -.. _deb822-field-enabled: - -Enabled: -======== - -Enabled: (value: "yes" or "no", required: No, default: "yes") - Tells APT whether the source is enabled or not. Disabled sources are not - queried for package lists, effectively removing them from the system - sources while still allowing reference or re-enabling at any time. - -.. _deb822-field-types: - -Types: -====== - -Types: (value: "deb" or "deb-src", required: Yes) - Defines which types of packages to look for from a given source; either - binary: ``deb`` or source code: ``deb-src``. The ``deb`` type references a - typical two-level Debian archive providing packages containing pre-compiled - binary data intended for execution on user machines. The ``deb-src`` type - references a Debian distribution's source code in the same form as the ``deb`` - type. A ``deb-src`` line is required to fetch source pacakge indices. - - -.. _deb822-field-uris: - -URIs: -===== - -URIs: (value: string(s), required: Yes) - The URI must specify the base of the Debian distribution archive, from which - APT finds the information it needs. There must be a URI component present in - order for the source to be valid; multipls URIs can be configured - simultaneously by adding a space-separated list of URIs. - - A list of the current built-in URI Schemas supported by APT is available at - the `Debian sources.list manpage `_. - - -.. _deb822-field-suites: - -Suites: -======= - -Suites: (value: strings(s), required: Yes) - The Suite can specify an exact path in relation to the URI(s) provided, in - which case the :ref:`deb822-field-components` **must** be omitted and suite - **must** end with a slash ( ``/`` ). Alternatively, it may take the form of - a distribution version (e.g. a version codename like ``disco`` or ``artful`` - ). If the suite does not specify a path, at least one - :ref:`deb822-field-component` **must** be present. - - -.. _deb822-field-components: - -Components: -=========== - -Components: (value: string(s), required: see :ref:`deb822-field-suites`) - Components specify different sections of one distribution version present in - a Suite. If :ref:`deb822-field-suites` specifies an exact path, then no - Components may be specified. Otherwise, a component **must** be present. - - -.. _deb822-options: - -Options -======= - -Sources may specify a number of options. These options and their values will -generally narrow a set of software to be available from the source or in some -other way control what software is downloaded from it. An exhaustive list of -options can be found at the -`Debian sources.list manpage `_. - - -.. _deb822-fields-repolib: - -RepoLib-Specific Deb822 Fields -============================== - -RepoLib presently defines a single internal-use fields which it adds to deb822 -sources that it modifies. - -X-Repolib-Name: ---------------- - -X-Repolib-Name: (value: string, required: no, default: filename) - This field defines a formatted name for the source which is suitable for - inclusion within a graphical UI or other interface which presents source - information to an end-user. As a :ref:`repolib-module` specific field, this - is silently ignored by APT and other tools operating with deb822 sources and - is only intended to be utilized by :ref:`repolib-module` itself. - - -.. _deb822-examples: - -======== -Examples -======== - -The following specifies a binary and source-code source fetching from the -primary Ubuntu archive with multiple suites for updates as well as several components:: - - Enabled: yes - Types: deb deb-src - URIs: http://archive.ubuntu.com/ubuntu - Suites: disco disco-updates disco-security disco-backports - Components: main universe multiverse restricted - -This is a source for fetching Google's Chrome browser, which specifies a CPU -architecture option and a RepoLib Name:: - - X-Repolib-Name: Google Chrome - Enabled: yes - URIs: http://dl.google.com/linux/chrome/deb - Suites: stable - Components: main - Architectures: amd64 - -This specifies a source for downloading packages for System76's Pop!_OS:: - - X-Repolib-Name: Pop!_OS PPA - Enabled: yes - Types: deb - URIs: http://ppa.launchpad.net/system76/pop/ubuntu - Suites: disco - Components: main - -Following is a PPA source which has been disabled:: - - X-Repolib-Name: ZNC Stable - Enabled: no - Types: deb - URIs: http://ppa.launchpad.net/teward/znc/ubuntu - Suites: disco - Components: main diff --git a/archive/docs/index.rst b/archive/docs/index.rst deleted file mode 100644 index 264d01e..0000000 --- a/archive/docs/index.rst +++ /dev/null @@ -1,182 +0,0 @@ -.. RepoLib documentation master file, created by - sphinx-quickstart on Wed May 1 13:49:01 2019. - You can adapt this file completely to your liking, but it should at least - contain the root `toctree` directive. - -=================================== -Welcome to RepoLib's documentation! -=================================== - -RepoLib is a Python library and CLI tool-set for managing your software -system software repositories. It's currently set up to handle APT repositories -on Debian-based linux distributions. - -RepoLib is intended to operate on DEB822-format sources as well as legacy -one-line format sources. It aims to provide feature parity with -software-properties for most commonly used functions. It also allows for -simple, automated conversion from legacy "one-line" style source to newer -DEB822 format sources. These sources will eventually deprecate the older -one-line sources and are much easier to parse for both human and machine. For a -detailed explanation of the DEB822 Source format, see :ref:`deb822-explanation`. - -RepoLib provides much faster access to a subset of ``SoftwareProperties`` -features than ``SoftwareProperties`` itself does. Its scope is somewhat more -limited because of this, but the performance improvements gained are substantial. -``SoftwareProperties`` also does not yet feature support for managing DEB822 -format sources, and instead only manages one-line sources. - -RepoLib is available under the GNU LGPL. - -.. contents:: Table of Contents - :local: - -.. toctree:: - :maxdepth: 4 - :caption: Developer Documentation - - library/developer - -.. toctree:: - :maxdepth: 1 - :caption: RepoLib Documentation - - deb822-format - -.. toctree:: - :maxdepth: 1 - :caption: apt-manage Documentation - - aptmanage/aptmanage - -============ -Installation -============ - -There are a variety of ways to install RepoLib - -From System Package Manager -^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -If your operating system packages repolib, you can install it by running:: - - sudo apt install python3-repolib - - -Uninstall -""""""""" - -To uninstall, simply do:: - - sudo apt remove python3-repolib - - -From PyPI -^^^^^^^^^ - -Repolib is available on PyPI. You can install it for your current user with:: - - pip3 install repolib - -Alternatively, you can install it system-wide using:: - - sudo pip3 install repolib - -Uninstall -""""""""" - -To uninstall, simply do:: - - sudo pip3 uninstall repolib - -From Git -^^^^^^^^ - -First, clone the git repository onto your local system:: - - git clone https://github.com/isantop/repolib - cd repolib - -Debian -^^^^^^ - -On debian based distributions, you can build a .deb package locally and install -it onto your system. You will need the following build-dependencies: - - * debhelper (>= 11) - * dh-python - * lsb-release - * python3-all - * python3-dbus - * python3-debian - * python3-setuptools - * python3-distutils - * python3-pytest - * python3-gnupg - -You can use this command to install these all in one go:: - - sudo apt install debhelper dh-python python3-all python3-setuptools python3-gnupg - -Then build and install the package:: - - debuild -us -uc - cd .. - sudo dpkg -i python3-repolib_*.deb - -Uninstall -""""""""" - -To uninstall, simply do:: - - sudo apt remove python3-repolib - -setuptools setup.py -^^^^^^^^^^^^^^^^^^^ - -You can build and install the package using python3-setuptools. First, install -the dependencies:: - - sudo apt install python3-all python3-setuptools - -Then build and install the package:: - - sudo python3 ./setup.py install - -Uninstall -""""""""" - -You can uninstall RepoLib by removing the following files/directories: - - * /usr/local/lib/python3.7/dist-packages/repolib/ - * /usr/local/lib/python3.7/dist-packages/repolib-\*.egg-info - * /usr/local/bin/apt-manage - -This command will remove all of these for you:: - - sudo rm -r /usr/local/lib/python3.7/dist-packages/repolib* /usr/local/bin/apt-manage - - -| -| -| -| -| - -Copyright © 2019-2022, Ian Santopietro -All rights reserved. - -This file is part of RepoLib. - -RepoLib is free software: you can redistribute it and/or modify -it under the terms of the GNU Lesser General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -RepoLib is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License -along with RepoLib. If not, see . - diff --git a/archive/docs/installation.rst b/archive/docs/installation.rst deleted file mode 100644 index a8279d1..0000000 --- a/archive/docs/installation.rst +++ /dev/null @@ -1,106 +0,0 @@ -============ -Installation -============ - -There are a variety of ways to install RepoLib - -From System Package Manager -^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -If your operating system packages repolib, you can install it by running:: - - sudo apt install python3-repolib - - -Uninstall -""""""""" - -To uninstall, simply do:: - - sudo apt remove python3-repolib - - -From PyPI -^^^^^^^^^ - -Repolib is available on PyPI. You can install it for your current user with:: - - pip3 install repolib - -Alternatively, you can install it system-wide using:: - - sudo pip3 install repolib - -Uninstall -""""""""" - -To uninstall, simply do:: - - sudo pip3 uninstall repolib - -From Git -^^^^^^^^ - -First, clone the git repository onto your local system:: - - git clone https://github.com/isantop/repolib - cd repolib - -Debian -^^^^^^ - -On debian based distributions, you can build a .deb package locally and install -it onto your system. You will need the following build-dependencies: - - * debhelper (>= 11) - * dh-python - * lsb-release - * python3-all - * python3-dbus - * python3-debian - * python3-setuptools - * python3-distutils - * python3-pytest - * python3-gnupg - -You can use this command to install these all in one go:: - - sudo apt install debhelper dh-python python3-all python3-setuptools python3-gnupg - -Then build and install the package:: - - debuild -us -uc - cd .. - sudo dpkg -i python3-repolib_*.deb - -Uninstall -""""""""" - -To uninstall, simply do:: - - sudo apt remove python3-repolib - -setuptools setup.py -^^^^^^^^^^^^^^^^^^^ - -You can build and install the package using python3-setuptools. First, install -the dependencies:: - - sudo apt install python3-all python3-setuptools - -Then build and install the package:: - - sudo python3 ./setup.py install - -Uninstall -""""""""" - -You can uninstall RepoLib by removing the following files/directories: - - * /usr/local/lib/python3.7/dist-packages/repolib/ - * /usr/local/lib/python3.7/dist-packages/repolib-\*.egg-info - * /usr/local/bin/apt-manage - -This command will remove all of these for you:: - - sudo rm -r /usr/local/lib/python3.7/dist-packages/repolib* /usr/local/bin/apt-manage diff --git a/archive/docs/library/developer.rst b/archive/docs/library/developer.rst deleted file mode 100644 index b7ba6b7..0000000 --- a/archive/docs/library/developer.rst +++ /dev/null @@ -1,335 +0,0 @@ -.. _repolib_module: - -======= -RepoLib -======= - -The :ref:`repolib-module` module simplifies working with APT sources, especially -those stored in the DEB822 format. It translates these sources into Python -Objects for easy reading, parsing, and manipulation of them within Python -programs. The program takes a user-defined sources filename and reads the -contents, parsing it into a Python object which can then be iterated upon and -which uses native data types where practicable. The :ref:`repolib-module` module -also allows easy creation of new DEB822-style sources from user-supplied data. - -.. toctree:: - :maxdepth: 1 - :caption: RepoLib - - source/source - ppa-module - enums - -================== -``repolib`` Module -================== - -The ``repolib`` Module is the main module for the package. It allows interfacing -with the various Classes, Subclasses, and Functions provided by RepoLib. - -Module-level Attributes -======================= - -There are a couple of module-level attributes and functions provided directly in -the module. - -.. _module-version - -``VERSION`` ------------ - -repolib.VERSION - Provides the current version of the library. - -.. _module_log_file_path - -``LOG_FILE_PATH`` ------------------ - -repolib.LOG_FILE_PATH - Stores the current path to the log file - -.. _module_log_level - -repolib.LOG_LEVEL - Stores the current logging level. Note: Change this level using the - :ref:`module_set_logging_level` function. - -.. _module_dirs - -Configuration directories -========================= - -repolib.KEYS_DIR -repolib.SOURCES_DIR - Stores the current :obj:`Pathlib.Path` pointing at the signing key and - sources directories, respectively. Used for building path names and reading - configuration. - -.. _module_distro_codename: - -DISTRO_CODENAME -=============== - -repolib.DISTRO_CODENAME - The current CODENAME field from LSB. If LSB is not available, it will - default to ``linux``. - - -.. _module_clean_chars - -CLEAN_CHARS -=========== - -repolib.CLEAN_CHARS - A ``dict`` which maps invalid characters for the :ref:`ident` attributes - which cannot be used and their replacements. These limitations are based on - invalid characters in unix-compatible filenames. - -.. _module_sources - -sources -======= - -repolib.sources - A :obj:`dict` storing all current sources configured on the system. To save - resources, this list is only loaded/parsed when - :ref:`module_load_all_sources` is called, since many simple operations don't - need the full list of currently-configured sources. - -.. _module_files - -files -===== - -repolib.files - A :obj:`dict` containing any source file objects present in the configured - sources dir (See :ref:`module_dirs`). This list is empty until - :ref:`module_load_all_sources` is called, since many simple operations don't - need the full list of currently-installed config files. - -.. _module_keys - -keys -==== - -repolib.keys - A :obj`dict` containing any installed repository signing keys on the system. - This list is empty until :ref:`module_load_all_sources` is called, since - many simple operations don'tneed the full list of - currently-installed keys. - -.. _module_compare_sources - -compare_sources() ------------------ - -repolib.compare_sources(source1, source2, excl_keys:list) -> bool - Compares two sources based on arbitrary criteria. - - This looks at a given list of keys, and if the given keys between the two - given sources are identical, returns True. - - Returns: :obj:`bool` - `True` if the sources are identical, otherwise `False`. - -source1, source2 -^^^^^^^^^^^^^^^^ -The two source objects to compare. - -excl_keys -^^^^^^^^^ -:obj:`list` A list of DEB822key names to ignore when comparing. Even if these -items don't match, this function still returns true if all other keys match. - -.. _module_combine_sources - -combine_sources() ------------------ - -repolib.combine_sources(source1, source2) -> None - Copies all of the data in `source2` and adds it to `source1`. - - This avoids duplicating data and ensures that all of both sources' data are - present in the unified source - -source1 -^^^^^^^ -The source into which both sources should be merged - -source2 -^^^^^^^ -The source from which to copy to `source1` - - -.. _module_url_validator - -url_validator() ---------------- - -repolib.url_validator(url: str) -> bool - Validates a given URL and attempts to see if it's a valid Debian respository - URL. Returns `True` if the URL appears to be valid and `False` if not. - -url -^^^ -:obj:`str`The url to validate - - -.. _module_validate_debline - -validate_debline() -================== - -repolib.util.validate_debline(line: str) -> bool - Validate if the provided debline ``line`` is valid or not. - - Returns ``True`` if ``line`` is valid, otherwise ``False``. - -line -^^^^ -:obj:`str` The line to validate - - -.. _module_strip_hashes - -strip_hashes() --------------- - -repolib.strip_hashes(line: str) -> str - Strips leading hash (`#`) characters from a line and returns the result. - -line -^^^^ -:obj:`str` The line to strip - -.. _module_load_all_sources - -load_all_sources() ------------------- - -repolib.load_all_sources() -> None - - Loads all sources from the current system configuration. - - -.. _module-set_testing - -set_testing() -------------- - -repolib.set_testing(testing: bool = True) -> None - Enables or disables testing mode in Repolib - - When in testing mode, repolib will operate within a temporary directory - rather tan on your live system configuration. This can be used for testing - out changes to the program without worry about changes to the system config. - It's also used for unit testing. - - -testing -^^^^^^^ -:obj:`bool` - Wether testing mode should be enabled (`True`) or not (`False`) - - -Example -======= - -The following code as a Python program that creates in ``example.sources`` file -in `/etc/apt/sources.list.d` with some sample data, then modifies the suites -used by the source and prints it to the console, before finally saving the new, -modified source to disk:: - - import repolib - source = repolib.Source() - file = repolib.SourceFile(name='example') - - source.ident = 'example-source' - source.name = 'Example Source' - source.types = [repolib.SourceType.BINARY] - source.uris = ['http://example.com/software'] - source.suites = ['focal'] - source.components = ['main'] - file.add_source(source) - - print(source.ui) - - file.save() - -When run with the appropriate arguments, it prints the contents of the source to -console and then saves a new ``example.sources`` file:: - - $ - example-source: - Name: Example Source - Enabled: yes - Types: deb - URIs: http://example.com/software - Suites: focal - Components: main - - $ ls -la /etc/apt/sources.list.d/example.sources - -rw-r--r-- 1 root root 159 May 1 15:21 /etc/apt/sources.list.d/example.sources - -Below is a walkthrough of this example. - -Creating Source and File Objects --------------------------------- - -The first step in using :ref:`repolib_module` is creating :ref:`source_object` -and :ref:`file_object`:: - - source = repolib.Source() - file = repolib.SourceFile(name='example') - -The :ref:`source_object` will hold all of the information for the source to be -created. The :ref:`file_object` represents the output file on disk, and allows -for advanced usage like multiple sources per file. - -Adding and Manipulating Data ----------------------------- - -The :ref:`source_object` contains attributes which describe the connfiguration -aspects of the source required to fetch and install software. Generally, these -attributes are lists of strings which describe different aspects of the source. -They can be set or retrieved like any other attributes:: - - source.uris = ['http://example.com/software'] - source.suites = ['focal'] - -This will add a ``focal`` suite to our source and add a URI from which to -download package lists. - -:ref:`source_object` also presents a dict-like interface for setting and getting -configuration data. Key names are case-insensitive and their order within the -object are preserved. - -Adding the Source to the File ------------------------------ - -Before the :ref:`source_object` can be saved, it needs to be added to a -:ref:`file_object`:: - - file.add_source(source) - -This will add `source` to the `file`'s lists of sources, as well as setting the -`source`'s file attribute to `file`. - -Saving Data to Disk -------------------- - -Once a source has the correct data and has been added to a file object, it can -be saved into the system configuration using :ref:`file-save`:: - - file.save() - -When called, this writes the sources stored in the file to disk. This does not -destroy the object, so that it may be further manipulated by the program. - -.. note:: - While data within the source or file objects can be manipulated after - calling :ref:`file-save`, any subsequent changes will not be automatically - written to disk as well. The :ref:`file-save` method must be called to - commit changes to disk. - -.. _source_object: diff --git a/archive/docs/library/enums.rst b/archive/docs/library/enums.rst deleted file mode 100644 index b83031a..0000000 --- a/archive/docs/library/enums.rst +++ /dev/null @@ -1,45 +0,0 @@ -.. _repolib-enums: - -============= -RepoLib Enums -============= - -RepoLib uses a variety of Enums to help ensure that data values are consistent -when they need to be set to specific string values for compatibility. - -.. _enum_sourceformat - -SourceFormat -============ - -repolib.SourceFormat() - Encodes the two formats of source files, either ``.list`` for legacy format - files or ``.sources`` for DEB822-formatted files. - - * ``DEFAULT`` - DEB822 formatting (value: ``"sources"``) - * ``LEGACY`` - Legacy, one-line formatting (value: ``"list"``) - - -.. _enum_sourcetype - -SourceType -========== - -repolib.SourceType() - Encodes the type of packages the repository provides (binary or source code). - - * ``BINARY`` - Binary package source type (value: ``"deb"``) - * ``SOURCECODE`` - Source code package type (value : ``"deb-src"``) - - -.. _enum_aptsourceenabled: - -AptSourceEnabled -================ - -repolib.AptSourceEnabled() - Used to encode whether the source is enabled or not. - - * ``TRUE`` - The source should be enabled (value: ``"yes"``). - * ``FALSE`` - The source should not be enabled (value: ``"no"``). - \ No newline at end of file diff --git a/archive/docs/library/source/exceptions.rst b/archive/docs/library/source/exceptions.rst deleted file mode 100644 index bf5ddce..0000000 --- a/archive/docs/library/source/exceptions.rst +++ /dev/null @@ -1,50 +0,0 @@ -.. _exceptions - -========== -Exceptions -========== - -RepoLib throws various forms of exceptions to halt execution of code when -incorrect input is detected or deviations from expected norms are encountered. - -.. _exc_repoerror - -RepoError() ------------ - -Repolib.RepoError() - This is base exception thrown by RepoLib. All other exceptions are - subclasses of this exception type. - -.. _exc_sourceerror - -SourceError() -------------- - -Repolib.Source.SourceError() - Raised when errors result from processing within the :obj:`source_object` or - one of it's subclasses. - -.. _exc_debparseerror - -DebParseError() ---------------- - -Repolib.parsedeb.DebParseError() - Raised due to problems parsing legacy Debian one-line repository lines. - -.. _exc_sourcefileerror - -SourceFileError() ------------------ - -Repolib.file.SourceFileError() - Raised due to errors handling :ref:`file_object` objects. - -.. _exc_keyfileerror - -KeyFileError() --------------- - -Repolib.key.KeyFileError() - Raised due to errors loading/finding key files or :ref:`key_object` objects. diff --git a/archive/docs/library/source/file.rst b/archive/docs/library/source/file.rst deleted file mode 100644 index c4f6f9f..0000000 --- a/archive/docs/library/source/file.rst +++ /dev/null @@ -1,172 +0,0 @@ -.. _file_object: - -=========== -File object -=========== - -SourceFile objects are the interface between the OS storage and the repolib -:ref:`source_object` items. Files contain sources and comments and allow for -loading sources from and saving them to disk. They also assign idents to sources -in a way that ensures each source has a unique ident. - -Attributes -========== - -File objects contain the following attributes: - -.. _file-name - -name ----- - -SourceFile.name - The name of the file on disk. This does not include the file extension, as - that is stored in :ref:`file-format`. - -.. _file-path - -path ----- - -SourceFile.path - A ``Pathlib.Path`` object representing this file's actual path on disk. Note - that the file may not actually exist on disk yet. - -.. _file-format - -format ------- - -SourceFile.format - The format this file should be saved in. Saved as a :ref:`enum_sourceformat`. - -.. _file-contents - -contents --------- - -SourceFile.contents - A :obj:`list` containing, in order, every comment line and source in this - file. - -.. _file-sources - -sources -------- - -SourceFile.sources - A :obj:`list` containing, in order, only the sources in this file. - - -Methods -======= - -.. _file-add_source - -add_source() ------------- - -SourceFile.add_source(source) -> None - Adds a given source to the file. This correctly appends the source to both - the :ref:`file-contents` and :ref:`file-sources` lists, and sets the - :ref:`source-file` attribute of the source to this file. - -source -^^^^^^ -The source to add to the file. - -.. _file-remove_source - -remove_source() ---------------- - -SourceFile.remove_source(ident: str) -> None - Removes the source with a specified ident from this file. - -ident -^^^^^ -The ident of the source to remove from the file. - -.. _file-get_source_by_ident - -get_source_by_ident() ---------------------- - -SourceFile.get_source_by_ident(ident: str) -> :obj:`Source` - Finds a source within this file given a specified ident and returns the - :ref:`source_object` matching that ident. If the file does not contain a - Source matching the given ident, raises a :ref:`exc_sourcefileerror`. - -ident -^^^^^ -The ident to look up. - -.. _file-reset_path - -SourceFile.reset_path() -> None - Attempts to detect the full path to the file given the :ref:`file-name` - attribute for this file. If the ``name.sources`` exists on disk, the path - will be set to that, otherwise if the ``name.list`` exists, it will be set - to that instead. Failing both, the path will fallback to ``name.sources`` as - a default. - -.. _file-load - -load() ------- - -SourceFile.load() -> None - Loads the file specified by :ref:`path` from disk, creating sources and - comments and appending them in order to the :ref:`file-contents` and - :ref:`file-sources` lists as appropriate. - -.. _file-save - -save() ------- - -SourceFile.save() -> None - Saves the file and any sources currently configured to disk. This method - must be called to commit changes to disk. If the file currently contains no - sources, then the file will instead be deleted. - - -Output -====== - -There are four attributes which contain the output of the files stored as -strings and which are ready for full output in the specified format. - -.. _file-deb822 - -deb822 ------- - -SourceFile.deb822 - Outputs the entire file as DEB822-formatted sources - -.. _file-legacy - -legacy ------- - -SourceFile.legacy - Outputs the entire file as one-line legacy-formatted deb lines - -.. _file-ui - -ui --- - -SourceFile.ui - Outputs the file in a format for output through a UI (e.g. for preview or - external parsing.) - -.. _file-output - -output ------- - -SourceFile.output - Outputs the entire file in the format matching that configured in - :ref:`file-format`. diff --git a/archive/docs/library/source/key.rst b/archive/docs/library/source/key.rst deleted file mode 100644 index 684f71a..0000000 --- a/archive/docs/library/source/key.rst +++ /dev/null @@ -1,121 +0,0 @@ -.. _key_object: - -========== -Key object -========== - -The SourceKey object is the representation for signing keys used to validate -software packages downloaded from repositories. - - -Attributes -========== - -.. _key-path - -path ----- - -SourceKey.path - A :obj:`Pathlib.Path` object pointing to this key's file location on disk. - -.. _key-gpg - -gpg ---- - -SourceKey.gpg - A :obj:`gnupg.GPG` object used for importing and manipulating GPG data. - -.. _key-data - -data ----- - -SourceKey.data - The binary data stored in this key, used to verify package signatures. - - -Methods -======= - -.. _key-reset_path - -reset_path() ------------- - -SourceKey.reset_path(name:str='', path:str='', suffix:str='archive-keyring') -> None - (Re)sets the path object for this key to the key file specified. If a ``name`` - is given, then the file is expected to be located within the system default - signing key directory ``/etc/apt/keyrings``. If a ``path`` is spefified, - then it is assumed to be the full path to the keyring file on disk. - -name -^^^^ -The name of a keyring file located within the system signing key directory, less -any suffix or file extensions. - -path -^^^^ -The absolute path to a keyring file located at any readable location on disk. - -suffix -^^^^^^ -A suffix to append to the file name before the file extension. (Default: -``'archive-keyring'``) - -.. _key-setup_gpg - -setup_gpg() ------------ - -SourceKey.setup_gpg() -> None - Sets up the :ref:`key-gpg` object for this key and loads key data from disk - (if present). - -.. _key-save_gpg - -save_gpg() ----------- - -SourceKey.save_gpg() -> None - Saves the GPG key data to disk. - -.. _key-delete_key - -delete_key() ------------- - -SourceKey.delete_key() -> None - Deletes the key file from disk. - -.. _key-load_key_data - -load_key_data() ---------------- - -SourceKey.load_key_data(raw=|ascii=|url=|fingerprint=) -> None - Fetches and loads a key from some remote source. Keys can be loaded from one - of: - * Raw internal data (:obj:`bytes`) - * ASCII-armored keys (:obj:`str`) - * Internet URL download (:obj:`str`) - * Public GPG Keyserver Fingerprint (:obj:`str`) - -raw=data (:obj:`bytes`) -^^^^^^^^^^^^^^^^^^^^^^^ -Load a key from raw binary data. This is ideal when importing a key which has -already been loaded from a binary data file or stream. - -ascii=armor (:obj:`str`) -^^^^^^^^^^^^^^^^^^^^^^^^ -Load a key from an ASCII-Armored string. - -url=url (:obj:`str`) -^^^^^^^^^^^^^^^^^^^^ -Download a key over an HTTPS connection. Note that keys should only be downloaded -from secure sources. - -fingerprint=fingerprint (:obj:`str`) -^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Fetch the key specified by ``fingerprint`` from a public keyserver. diff --git a/archive/docs/library/source/shortcuts.rst b/archive/docs/library/source/shortcuts.rst deleted file mode 100644 index 9ba697c..0000000 --- a/archive/docs/library/source/shortcuts.rst +++ /dev/null @@ -1,56 +0,0 @@ -.. _shortcuts - -==================== -Repository Shortcuts -==================== - -Repolib supports adding repositories via abbreviated shortcuts (such as -``ppa:system76/pop`` or ``popdev:master``) where the format of the shortcut is -given in the form of a prefix, and the data required to expand the shortcut into -a full repository is provided, with a colon character separating the two parts. -These function as subclasses of the :ref:`source_object` with specialized -functionality. Currently there is support for Launchpad PPAs and Pop_OS -Development branches automatically. - - -Launchpad PPAs -============== - -repolib.PPASource() - RepoLib has built-in support for adding Launchpad PPA shortcuts, similarly to - ``add-apt-repository``. Launchpad shortcuts take the general form:: - - ppa:owner-name/ppa-name - - If an internet connection is available, RepoLib can automatically fetch the - repository signing key as well as metadata like the description, human-readable - name, etc. - - -Pop_OS Development Branches -=========================== - -repolib.PopdevSource() - RepoLib can automatically add Pop_OS development branches for testing unstable - pre-release software before it is ready for general use. Development branch - shortcuts take the form:: - - popdev:branch-name - - If an internet connection is available, then RepoLib will also add the signing - key for the branch (if it is not already added). - - - -Adding Shortcut Repositories -============================ - -Shortcuts are generally added similarly to loading a different source from data, -the main difference being that in the call to :ref:`load_from_data` the only -element in the ``data`` list should be a string of the shortcut:: - - ppa_source = repolib.PPASource() - ppa_source.load_from_data(['ppa:system76/pop']) - - popdev_source = repolib.PopdevSource() - popdev_source.load_from_data(['popdev:master']) \ No newline at end of file diff --git a/archive/docs/library/source/source.rst b/archive/docs/library/source/source.rst deleted file mode 100644 index bf6b3fe..0000000 --- a/archive/docs/library/source/source.rst +++ /dev/null @@ -1,281 +0,0 @@ -.. _source_object: - -============= -Source object -============= - -The Source object is the base class for all of the sources used within RepoLib. -The Source class itself is a subclass of the deb822() class from the Python -Debian module, which provides a dict-like interface for setting data as well as -several methods for dumping data to files and other helpful functions. - -.. toctree:: - :maxdepth: 2 - :caption: Source - - deb - legacy-deb - ppa-object - system - -class repolib.Source (file=None) - Create a new :ref:`source_object`. - - - The Source object has the following attributes: - - * :ref:`ident` - The system-identifier to use for this source. - * :ref:`name` - The human-readable name of the source. (default: '') - * :ref:`enabled` - Whether the source is enabled or not at creation. - (default: True) - * :ref:`types` - A list of the types that the source should use. - (default: []) - * :ref:`uris` - A list of URIs from which to fetch software or check for - updates. (default: []) - * :ref:`suites` - Suites in which to narrow available software. (default: - []) - * :ref:`components` - Components of the source repository to enable. - (default: []) - * :ref:`signed_by` - The path to the signing key for this source - * :ref:`file` - The :ref:`file_object` for this source - * :ref:`key` - The :ref:`key_object` for this source. - * :ref:`twin_source`: - This source should be saved with both binary and - source code types enabled. - -The following decribe how each of these are used. - -.. _ident: - -ident ------ - -The ``ident`` is the system-identifier for this source. This determines the -filename the source will use on-disk as well as the way to specify a source to -load. - -.. _name: - -name ----- - -This is a human-readable and nicely-formatted name to help a user recognize -what this source is. Any unicode character is allowed in this field. If a -source is opened which doesn't have a name field, the filename will be used. - -:ref:`name` is a string value, set to ``''`` by default. If there is no name in -a loaded source, it will be set to the same as the filename (minus the -extension). - -This field maps to the ``X-Repolib-Name:`` field in the .sources file, which -is ignored by Apt and other standards-compliant sources parsers. - -.. _enabled: - -enabled -------- - -Apt sources can be disbaled without removing them entirely from the system. A -disabled source is excluded from updates and new software installs, but it can -be easily re-enabled at any time. It defaults to ``True``. - -This field maps to the ``Enabled:`` field in the .sources file. This is optional -per the DEB822 standard, however if set to anything other than ``no``, the -source is considered enabled. - -.. _types: - -types ------ - -Debian archives may contain either binary packages or source code packages, and -this value specifies which of those Apt should look for in the source. ``deb`` -is used to look for binary packages, while ``deb-src`` looks for source code -packages. RepoLib stores this value as a list of :ref:`aptsourcetype-enum`s, and -defaults to ``[AptSourceType.BINARY]``. - -This field maps to the ``Types:`` field in the sources file. - -.. _uris: - -uris ----- - -A list of string values describing the URIs from which to fetch package lists -and software for updates and installs. The currently recognized URI types are: - - * file - * cdrom - * http - * ftp - * copy - * rsh - * ssh - -DEB822 sources may directly contain an arbitrary number of URIs. Legacy sources -may also have multiple URIs; however, these require writing a new deb line for -each URI as the one-line format only allows a single URI per source. - -.. note:: - Although these are the currently-recognized official URI types, Apt can be - extended with additional URI schemes through extension packages. Thus it is - **not** recommended to parse URIs by type and instead rely on user input - being correct and to throw exceptions when that isn't the case. - -.. _suites: - -suites ------- - -The Suite, also known as the **distribution** specifies a subdirectory of the -main archive root in which to look for software. This is typically used to -differentiate versions for the same OS, e.g. ``disco`` or ``cosmic`` for Ubuntu, -or ``squeeze`` and ``unstable`` for Debian. - -DEB822 Sources allow specifying an arbitrary number of suites. One-line sources -also support multiple suites, but require an additional repo line for each as -the one-line format only allows a single suite for each source. - -This value maps to the ``Suites:`` field in the sources file. - -.. _components: - -components ----------- - -This value is a list of strings describing the enabled distro components to -download software from. Common values include ``main``, ``restricted``, -``nonfree``, etc. - -.. _signed_by - -signed_by ---------- -The path to the keyring containing the signing key used to verify packages -downloaded from this repository. This should generally match the -:ref:`key-path` attribute for this source's :ref:`key` object. - -.. _source-file - -file ----- -The :ref:`file_object` for the file which contains this source. - -.. _key - -key ---- -The :ref:`key_object` for this source. - -======= -Methods -======= - - -.. _get_description - -Source.get_description() -> str - Returns a :obj:`str` containing a UI-compatible description of the source. - -.. _reset_values: - -reset_values() -------------- - -Source.reset_values() - Initializes the Source's attributes with default data in-order. This is - recommended to ensure that the fields in the underlying deb822 Dict are - in order and correctly capitalized. - -.. _load_from_data - -load_from_data() ----------------- - -Source.load_from_data(data: list) -> None - Loads configuration information from a list of data, rather than using - manual entry. The data can either be a list of strings with DEB822 data, or - a single-element list containing a one-line legacy line. - -data -^^^^ -The data load load into the source. If this contains a legacy-format one-line -repository, it must be a single-element list. Otherwise, it should contain a -list of strings, each being a line from a DEB822 configuration. - -.. _generate_default_ident - -generate_default_ident() ------------------------- - -Source.generate_default_ident(prefix: str = '') -> str - Generates a suitable default ident, optionally with a prefix, and sets it. - The generated ident is also returned for processing convenience. - -prefix -^^^^^^ -The prefix to prepend to the ident. - -.. _generate_default_name - -generate_default_name() -_______________________ - -Source.generate_default_name() -> - Generates a default name for the source and sets it. The generated name is - also returned for convenience. - -.. _load_key - -load_key() -__________ - -Source.load_key(ignore_errors: bool = True) -> None - Finds the signing key for this source spefified in :ref:`signed_by` and - loads a :ref:`key_object` for it. - -ignore_errors -^^^^^^^^^^^^^ -If `False`, raise a :ref:`exc_sourceerror` if the key can't be loaded or doesn't -exist. - -.. _source_save - -save() ------- - -Source.save() - Proxy method for the :ref:`file-save` method for this source's - :ref:`file_object`. - -Output Properties -================= - -There are three output properties which contain the current source data for -output in a variety of formats. - -.. _source_deb822 - -deb822 ------- - -Source.deb822 - A representation of the source data as a DEB822-formatted string - -.. _source_legacy - -legacy ------- - -Source.legacy - A one-line formatted string of the source. It :ref:`twin_source` is ``True``, - then there will additionally be a ``deb-src`` line following the primary - line. - -.. _source_ui - -ui --- - -Source.ui - A representation of the source with certain key names translated to better - represent their use in a UI for display to a user. diff --git a/archive/repolib/__init__.py b/archive/repolib/__init__.py deleted file mode 100644 index 4b4b7e5..0000000 --- a/archive/repolib/__init__.py +++ /dev/null @@ -1,144 +0,0 @@ -#!/usr/bin/python3 - -""" -Copyright (c) 2019-2022, Ian Santopietro -All rights reserved. - -This file is part of RepoLib. - -RepoLib is free software: you can redistribute it and/or modify -it under the terms of the GNU Lesser General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -RepoLib is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License -along with RepoLib. If not, see . -""" - -import logging -import logging.handlers as handlers - -from pathlib import Path - -from . import __version__ - -VERSION = __version__.__version__ - -from .file import SourceFile, SourceFileError -from .source import Source, SourceError -from .shortcuts import PPASource, PopdevSource, shortcut_prefixes -from .key import SourceKey, KeyFileError -from . import util -from . import system - -LOG_FILE_PATH = '/var/log/repolib.log' -LOG_LEVEL = logging.WARNING -KEYS_DIR = util.KEYS_DIR -SOURCES_DIR = util.SOURCES_DIR -TESTING = util.TESTING -KEYSERVER_QUERY_URL = util.KEYSERVER_QUERY_URL -DISTRO_CODENAME = util.DISTRO_CODENAME -PRETTY_PRINT = util.PRETTY_PRINT -CLEAN_CHARS = util.CLEAN_CHARS - -try: - from systemd.journal import JournalHandler - systemd_support = True -except ImportError: - systemd_support = False - -## Setup logging -stream_fmt = logging.Formatter( - '%(name)-21s: %(levelname)-8s %(message)s' -) -file_fmt = logging.Formatter( - '%(asctime)s - %(name)-21s: %(levelname)-8s %(message)s' -) -log = logging.getLogger(__name__) - -console_log = logging.StreamHandler() -console_log.setFormatter(stream_fmt) -console_log.setLevel(LOG_LEVEL) - -# file_log = handlers.RotatingFileHandler( -# LOG_FILE_PATH, maxBytes=(1048576*5), backupCount=5 -# ) -# file_log.setFormatter(file_fmt) -# file_log.setLevel(LOG_LEVEL) - -log.addHandler(console_log) -# log.addHandler(file_log) - -log_level_map:dict = { - 0: logging.WARNING, - 1: logging.INFO, - 2: logging.DEBUG -} - -if systemd_support: - journald_log = JournalHandler() # type: ignore (this is handled by the wrapping if) - journald_log.setLevel(logging.INFO) - journald_log.setFormatter(stream_fmt) - log.addHandler(journald_log) - -log.setLevel(logging.DEBUG) - -def set_testing(testing:bool = True) -> None: - """Puts Repolib into testing mode""" - global KEYS_DIR - global SOURCES_DIR - - util.set_testing(testing=testing) - KEYS_DIR = util.KEYS_DIR - SOURCES_DIR = util.SOURCES_DIR - - -def set_logging_level(level:int) -> None: - """Set the logging level for this current repolib - - Accepts an integer between 0 and 2, with 0 being the default loglevel of - logging.WARNING, 1 being logging.INFO, and 2 being logging.DEBUG. - - Values greater than 2 are clamped to 2. Values less than 0 are clamped to 0. - - Note: This only affects console output. Log file output remains - at logging.INFO - - Arguments: - level(int): A logging level from 0-2 - """ - if level > 2: - level = 2 - if level < 0: - level = 0 - LOG_LEVEL = log_level_map[level] - console_log.setLevel(LOG_LEVEL) - -RepoError = util.RepoError -SourceFormat = util.SourceFormat -SourceType = util.SourceType -AptSourceEnabled = util.AptSourceEnabled - -scrub_filename = util.scrub_filename -url_validator = util.url_validator -prettyprint_enable = util.prettyprint_enable -validate_debline = util.validate_debline -strip_hashes = util.strip_hashes -compare_sources = util.compare_sources -combine_sources = util.combine_sources -sources = util.sources -files = util.files -keys = util.keys -errors = util.errors - -valid_keys = util.valid_keys -options_inmap = util.options_inmap -options_outmap = util.options_outmap -true_values = util.true_values - -load_all_sources = system.load_all_sources diff --git a/archive/repolib/__version__.py b/archive/repolib/__version__.py deleted file mode 100644 index f28f7ec..0000000 --- a/archive/repolib/__version__.py +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/python3 - -""" -Copyright (c) 2019-2022, Ian Santopietro -All rights reserved. - -This file is part of RepoLib. - -RepoLib is free software: you can redistribute it and/or modify -it under the terms of the GNU Lesser General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -RepoLib is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License -along with RepoLib. If not, see . -""" -__version__ = "2.1.1" diff --git a/archive/repolib/command/__init__.py b/archive/repolib/command/__init__.py deleted file mode 100644 index 86f8e6c..0000000 --- a/archive/repolib/command/__init__.py +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/python3 - -""" -Copyright (c) 2022, Ian Santopietro -All rights reserved. - -This file is part of RepoLib. - -RepoLib is free software: you can redistribute it and/or modify -it under the terms of the GNU Lesser General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -RepoLib is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License -along with RepoLib. If not, see . -""" - -from .argparser import get_argparser -from .add import Add -from .list import List -from .remove import Remove -from .modify import Modify -from .key import Key - -parser = get_argparser() diff --git a/archive/repolib/command/add.py b/archive/repolib/command/add.py deleted file mode 100644 index 5ba3f14..0000000 --- a/archive/repolib/command/add.py +++ /dev/null @@ -1,267 +0,0 @@ -#!/usr/bin/python3 - -""" -Copyright (c) 2022, Ian Santopietro -All rights reserved. - -This file is part of RepoLib. - -RepoLib is free software: you can redistribute it and/or modify -it under the terms of the GNU Lesser General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -RepoLib is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License -along with RepoLib. If not, see . -""" - -from httplib2.error import ServerNotFoundError -from urllib.error import URLError - -from .. import util -from ..source import Source, SourceError -from ..file import SourceFile, SourceFileError -from ..shortcuts import ppa, popdev, shortcut_prefixes -from .command import Command, RepolibCommandError - -class Add(Command): - """Add subcommand - - Adds a new source into the system. Requests root, if not present. - - Options: - --disable, d - --source-code, -s - --terse, -t - --name, -n - --identifier, -i - --format, -f - --skip-keys, -k - """ - - @classmethod - def init_options(cls, subparsers): - """ Sets up the argument parser for this command. - - Returns: argparse.subparser - The subparser for this command - """ - - sub = subparsers.add_parser( - 'add', - help='Add a new repository to the system' - ) - - sub.add_argument( - 'deb_line', - nargs='*', - default=['822styledeb'], - help='The deb line of the repository to add' - ) - sub.add_argument( - '-d', - '--disable', - action='store_true', - help='Add the repository and then set it to disabled.' - ) - sub.add_argument( - '-s', - '--source-code', - action='store_true', - help='Also enable source code packages for the repository.' - ) - sub.add_argument( - '-t', - '--terse', - action='store_true', - help='Do not display expanded info about a repository before adding it.' - ) - sub.add_argument( - '-n', - '--name', - default='', - help='A name to set for the new repo' - ) - sub.add_argument( - '-i', - '--identifier', - default='', - help='The filename to use for the new source' - ) - sub.add_argument( - '-f', - '--format', - default='sources', - help='The source format to save as, `sources` or `list`' - ) - sub.add_argument( - '-k', - '--skip-keys', - action='store_true', - help='Skip adding signing keys (not recommended!)' - ) - - return sub - - def finalize_options(self, args): - super().finalize_options(args) - self.deb_line = ' '.join(args.deb_line) - self.terse = args.terse - self.source_code = args.source_code - self.disable = args.disable - self.log.debug(args) - - try: - name = args.name.split() - except AttributeError: - name = args.name - - try: - ident = args.identifier.split() - except AttributeError: - ident = args.identifier - - self.name = ' '.join(name) - pre_ident:str = '-'.join(ident) - self.ident = util.scrub_filename(pre_ident) - self.skip_keys = args.skip_keys - self.format = args.format.lower() - - def run(self) -> bool: - """Run the command, return `True` if successful; otherwise `False`""" - if self.deb_line == '822styledeb': - self.parser.print_usage() - self.log.error('A repository is required') - return False - - repo_is_url = self.deb_line.startswith('http') - repo_is_nospaced = len(self.deb_line.split()) == 1 - - if repo_is_url and repo_is_nospaced: - self.deb_line = f'deb {self.deb_line} {util.DISTRO_CODENAME} main' - - print('Fetching repository information...') - - self.log.debug('Adding line %s', self.deb_line) - - new_source: Source = Source() - - for prefix in shortcut_prefixes: - self.log.debug('Trying prefix %s', prefix) - if self.deb_line.startswith(prefix): - self.log.debug('Line is prefix: %s', prefix) - new_source = shortcut_prefixes[prefix]() - if not new_source.validator(self.deb_line): - self.log.error( - 'The shortcut "%s" is malformed', - self.deb_line - ) - - # Try and get a suggested correction for common errors - try: - if self.deb_line[len(prefix)] != ':': - fixed_debline: str = self.deb_line.replace( - self.deb_line[len(prefix)], - ":", - 1 - ) - print(f'Did you mean "{fixed_debline}"?') - except IndexError: - pass - return False - - try: - new_source.load_from_data([self.deb_line]) - except (URLError, ServerNotFoundError) as err: - import traceback - self.log.debug( - 'Exception info: %s \n %s \n %s', - type(err), - ''.join(traceback.format_exception(err)), - err.args - ) - self.log.error( - 'System is offline. A connection is required to add ' - 'PPA and Popdev sources.' - ) - return False - except Exception as err: - import traceback - self.log.debug( - 'Exception info: %s \n %s \n %s', - type(err), - err.__traceback__, - err - ) - self.log.error('An error ocurred: %s', err) - return False - break - - - if not new_source: - self.log.error( - f'Could not parse line "{self.deb_line}". Double-check the ' - 'spelling.' - ) - valid_shortcuts: str = '' - for shortcut in shortcut_prefixes: - if shortcut.startswith('deb'): - continue - valid_shortcuts += f'{shortcut}, ' - valid_shortcuts = valid_shortcuts.strip(', ') - print(f'Supported repository shortcuts:\n {valid_shortcuts}') - return False - - new_source.twin_source = True - new_source.sourcecode_enabled = self.source_code - - if self.name: - new_source.name = self.name - if self.ident: - new_source.ident = self.ident - if self.disable: - new_source.enabled = False - - if not new_source.ident: - new_source.ident = new_source.generate_default_ident() - - new_file = SourceFile(name=new_source.ident) - new_file.format = new_source.default_format - if self.format: - self.log.info('Setting new source format to %s', self.format) - for format in util.SourceFormat: - if self.format == format.value: - new_file.format = format - self.log.debug('New source format set to %s', format.value) - - new_file.add_source(new_source) - new_source.file = new_file - self.log.debug('File format: %s', new_file.format) - self.log.debug('File path: %s', new_file.path) - - self.log.debug('Sources in file %s:\n%s', new_file.path, new_file.sources) - - if not self.terse: - print( - 'Adding the following source: \n', - new_source.get_description(), - '\n\n', - new_source.ui - ) - try: - input( - 'Press ENTER to continue adding this source or Ctrl+C ' - 'to cancel' - ) - except KeyboardInterrupt: - # Handled here to avoid printing the exception to console - exit(0) - - new_file.save() - util.dbus_quit() - return True diff --git a/archive/repolib/command/argparser.py b/archive/repolib/command/argparser.py deleted file mode 100644 index 182ccd7..0000000 --- a/archive/repolib/command/argparser.py +++ /dev/null @@ -1,65 +0,0 @@ -#!/usr/bin/python3 - -""" -Copyright (c) 2020, Ian Santopietro -All rights reserved. - -This file is part of RepoLib. - -RepoLib is free software: you can redistribute it and/or modify -it under the terms of the GNU Lesser General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -RepoLib is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License -along with RepoLib. If not, see . - -Module for getting an argparser. Used by apt-manage -""" - -import argparse -import inspect - -from repolib import command as cmd - -from .. import __version__ - -def get_argparser(): - """ Get an argument parser with our arguments. - - Returns: - An argparse.ArgumentParser. - """ - parser = argparse.ArgumentParser( - prog='apt-manage', - description='Manage software sources and repositories', - epilog='apt-manage version: {}'.format(__version__.__version__) - ) - - parser.add_argument( - '-b', - '--debug', - action='count', - help=argparse.SUPPRESS - ) - - subparsers = parser.add_subparsers( - help='...', - dest='action', - metavar='COMMAND' - ) - - subcommands = [] - for i in inspect.getmembers(cmd, inspect.isclass): - obj = getattr(cmd, i[0]) - subcommands.append(obj) - - for i in subcommands: - i.init_options(subparsers) - - return parser diff --git a/archive/repolib/command/command.py b/archive/repolib/command/command.py deleted file mode 100644 index b4afa41..0000000 --- a/archive/repolib/command/command.py +++ /dev/null @@ -1,77 +0,0 @@ -""" -Copyright (c) 2020, Ian Santopietro -All rights reserved. - -This file is part of RepoLib. - -RepoLib is free software: you can redistribute it and/or modify -it under the terms of the GNU Lesser General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -RepoLib is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License -along with RepoLib. If not, see . - -Command line application helper class. -""" - -from ..util import SOURCES_DIR - -class RepolibCommandError(Exception): - """ Exceptions generated by Repolib CLIs.""" - - def __init__(self, *args, code=1, **kwargs): - """Exception from a CLI - - Arguments: - code (:obj:`int`, optional, default=1): Exception error code. - """ - super().__init__(*args, **kwargs) - self.code = code - -class Command: - # pylint: disable=no-self-use,too-few-public-methods - # This is a base class for other things to inherit and give other programs - # a standardized interface for interacting with commands. - """ CLI helper class for developing command line applications.""" - - def __init__(self, log, args, parser): - self.log = log - self.parser = parser - self.sources_dir = SOURCES_DIR - self.finalize_options(args) - - def finalize_options(self, args): - """ Base options parsing class. - - Use this class in commands to set up the final options parsing and set - instance variables for later use. - """ - self.verbose = False - self.debug = False - if args.debug: - if args.debug > 1: - self.verbose = True - if args.debug != 0: - self.log.info('Debug mode set, not-saving any changes.') - self.debug = True - - def run(self): - """ The initial base for running the command. - - This needs to have a standardized format, argument list, and return - either True or False depending on whether the command was successful or - not. - - Returns: - True if the command succeeded, otherwise False. - """ - - # Since this is just the base, it should always return True (because - # you shouldn't fail at doing nothing). - return True diff --git a/archive/repolib/command/key.py b/archive/repolib/command/key.py deleted file mode 100644 index f73c5b2..0000000 --- a/archive/repolib/command/key.py +++ /dev/null @@ -1,325 +0,0 @@ -#!/usr/bin/python3 - -""" -Copyright (c) 2022, Ian Santopietro -All rights reserved. - -This file is part of RepoLib. - -RepoLib is free software: you can redistribute it and/or modify -it under the terms of the GNU Lesser General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -RepoLib is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License -along with RepoLib. If not, see . -""" - -from pathlib import Path - -from ..key import SourceKey -from .. import system, util - -from .command import Command - -KEYS_PATH = Path(util.KEYS_DIR) - -class Key(Command): - """Key subcommand. - - Manages signing keys for repositories, allowing adding, removal, and - fetching of remote keys. - - Options: - --name, -n - --path, -p - --url, -u - --ascii, -a - --fingerprint, -f - --keyserver, -s - --remove, -r - """ - - @classmethod - def init_options(cls, subparsers) -> None: - """Sets up this command's options parser""" - - sub = subparsers.add_parser( - 'key', - help='Manage repository signing keys', - epilog=( - 'Note that no verification of key validity is performed when ' - 'managing key using apt-mange. Ensure that keys are valid to ' - 'avoid errors with updates.' - ) - ) - - sub.add_argument( - 'repository', - default=['x-repolib-none'], - help='Which repository to manage keys for.' - ) - - sub_group = sub.add_mutually_exclusive_group( - required=True - ) - - sub_group.add_argument( - '-n', - '--name', - help='The name of an existing key file to set.' - ) - - sub_group.add_argument( - '-p', - '--path', - help='Sets a path on disk to a signing key.' - ) - - sub_group.add_argument( - '-u', - '--url', - help='Download a key over HTTPS' - ) - - sub_group.add_argument( - '-a', - '--ascii', - help='Add an ascii-armored key' - ) - - sub_group.add_argument( - '-f', - '--fingerprint', - help=( - 'Fetch a key via fingerprint from a keyserver. Use --keyserver ' - 'to specify the URL to the keyserver.' - ) - ) - - sub_group.add_argument( - '-r', - '--remove', - action='store_true', - help=( - 'Remove a signing key from the repo. If no other sources use ' - 'this key, its file will be deleted.' - ) - ) - - sub.add_argument( - '-s', - '--keyserver', - help=( - 'The keyserver from which to fetch the given fingerprint. ' - '(Default: keyserver.ubuntu.com)' - ) - ) - - def finalize_options(self, args): - super().finalize_options(args) - self.repo = args.repository - self.keyserver = args.keyserver - - self.actions:dict = {} - self.system_source = False - - for act in [ - 'name', - 'path', - 'url', - 'ascii', - 'fingerprint', - 'remove', - ]: - self.actions[act] = getattr(args, act) - - system.load_all_sources() - - def run(self): - """Run the command""" - self.log.info('Modifying signing key settings for %s', self.repo) - - if not self.repo: - self.log.error('No repository provided') - return False - - try: - self.source = util.sources[self.repo] - if self.repo == 'system': - self.system_source = True - except KeyError: - self.log.error( - 'The repository %s was not found. Check the spelling', - self.repo - ) - return False - - self.log.debug('Actions to take:\n%s', self.actions) - self.log.debug('Source before:\n%s', self.source) - - rets = [] - for action in self.actions: - if self.actions[action]: - self.log.debug('Running action: %s - (%s)', action, self.actions[action]) - ret = getattr(self, action)(self.actions[action]) - rets.append(ret) - - self.log.debug('Results: %s', rets) - self.log.debug('Source after: \n%s', self.source) - - if True in rets: - self.source.file.save() - return True - else: - self.log.warning('No valid changes specified, no actions taken.') - return False - - def name(self, value:str) -> bool: - """Sets the key file to a name in the key file directory""" - if not value: - return False - - key_path = None - - for ext in ['.gpg', '.asc']: - if value.endswith(ext): - path = KEYS_PATH / value - if path.exists(): - key_path = path - break - else: - if 'archive-keyring' not in value: - value += '-archive-keyring' - path = KEYS_PATH / f'{value}{ext}' - if path.exists(): - key_path = path - break - - if not key_path: - self.log.error('The key file %s could not be found', value) - return False - - return self.path(str(key_path)) - - def path(self, value:str) -> bool: - """Sets the key file to the given path""" - if not value: - return False - - key_path = Path(value) - - if not key_path.exists(): - self.log.error( - 'The path %s does not exist', value - ) - return False - - self.source.signed_by = str(key_path) - self.source.load_key() - return True - - def url(self, value:str) -> bool: - """Downloads a key to use from a provided URL.""" - if not value: - return False - - if not value.startswith('https:'): - response = 'n' - self.log.warning( - 'The key is not being downloaded over an encrypted connection, ' - 'and may be tampered with in-transit. Only add keys that you ' - 'trust, from sources which you trust.' - ) - response = input('Do you want to continue? (y/N): ') - if response not in util.true_values: - return False - - key = SourceKey(name=self.source.ident) - key.load_key_data(url=value) - self.source.key = key - self.source.signed_by = str(key.path) - self.source.load_key() - return True - - def ascii(self, value:str) -> bool: - """Loads the key from provided ASCII-armored data""" - if not value: - return False - - response = 'n' - print('Only add signing keys from data you trust.') - response = input('Do you want to continue? (y/N): ') - - if response not in util.true_values: - return False - - key = SourceKey(name=self.source.ident) - key.load_key_data(ascii=value) - self.source.key = key - self.source.signed_by = str(key.path) - self.source.load_key() - return True - - def fingerprint(self, value:str) -> bool: - """Downloads the key with the given fingerprint from a keyserver""" - if not value: - return False - - key = SourceKey(name=self.source.ident) - - if self.keyserver: - key.load_key_data(fingerprint=value, keyserver=self.keyserver) - else: - key.load_key_data(fingerprint=value) - - self.source.key = key - self.source.signed_by = str(key.path) - self.source.load_key() - return True - - def remove(self, value:str) -> bool: - """Removes the key from the source""" - - if not self.source.key: - self.log.error( - 'The source %s does not have a key configured.', - self.repo - ) - return False - - response = 'n' - print( - 'If you remove the key, there may no longer be any verification ' - 'of software packages from this repository, including for future ' - 'updates. This may cause errors with your updates.' - ) - response = input('Do you want to continue? (y/N): ') - if response not in util.true_values: - return False - - old_key = self.source.key - self.source.key = None - self.source.signed_by = '' - - for source in util.sources.values(): - if source.key == old_key: - self.log.info( - 'Key file %s in use with another key, not deleting', - old_key.path - ) - return True - - response = 'n' - print('No other sources were found which use this key.') - response = input('Do you want to remove it? (Y/n): ') - if response in util.true_values: - old_key.delete_key() - - return True - diff --git a/archive/repolib/command/list.py b/archive/repolib/command/list.py deleted file mode 100644 index aad121b..0000000 --- a/archive/repolib/command/list.py +++ /dev/null @@ -1,216 +0,0 @@ -#!/usr/bin/python3 - -""" -Copyright (c) 2022, Ian Santopietro -All rights reserved. - -This file is part of RepoLib. - -RepoLib is free software: you can redistribute it and/or modify -it under the terms of the GNU Lesser General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -RepoLib is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License -along with RepoLib. If not, see . -""" - -import argparse -import textwrap -import traceback - -from ..file import SourceFile, SourceFileError -from ..source import Source, SourceError -from .. import RepoError, util, system - -from .command import Command, RepolibCommandError - -class List(Command): - """List subcommand - - Lists information about currently-configured sources on the system. - - Options: - --legacy, -l - --verbose, -v - --all, -a - --no-names, -n - --file-names, -f - --no-indentation - """ - - @classmethod - def init_options(cls, subparsers): - """Sets up ths argument parser for this command. - - Returns: argparse.subparser: - This command's subparser - """ - - sub = subparsers.add_parser( - 'list', - help=( - 'List information for configured repostiories. If a repository ' - 'name is provided, details about that repository are printed.' - ) - ) - - sub.add_argument( - 'repository', - nargs='*', - default=['x-repolib-all-sources'], - help='The repository for which to list configuration' - ) - sub.add_argument( - '-v', - '--verbose', - action='store_true', - help='Show additional information, if available.' - ) - sub.add_argument( - '-a', - '--all', - action='store_true', - help='Display full configuration for all configured repositories.' - ) - sub.add_argument( - '-l', - '--legacy', - action='store_true', - help='Include repositories configured in legacy sources.list file.' - ) - sub.add_argument( - '-n', - '--no-names', - action='store_true', - dest='skip_names', - help=argparse.SUPPRESS - ) - sub.add_argument( - '-f', - '--file-names', - action='store_true', - dest='print_files', - help="Don't print names of files" - ) - sub.add_argument( - '--no-indentation', - action='store_true', - dest='no_indent', - help=argparse.SUPPRESS - ) - - def finalize_options(self, args): - super().finalize_options(args) - self.repo = ' '.join(args.repository) - self.verbose = args.verbose - self.all = args.all - self.legacy = args.legacy - self.skip_names = args.skip_names - self.print_files = args.print_files - self.no_indent = args.no_indent - - def list_legacy(self, indent) -> None: - """List the contents of the sources.list file. - - Arguments: - list_file(Path): The sources.list file to try and parse. - indent(str): An indentation to append to the output - """ - try: - sources_list_file = util.SOURCES_DIR.parent / 'sources.list' - except FileNotFoundError: - sources_list_file = None - - print('Legacy source.list sources:') - if sources_list_file: - with open(sources_list_file, mode='r') as file: - for line in file: - if 'cdrom' in line: - line = '' - - try: - source = Source() - source.load_from_data([line]) - print(textwrap.indent(source.ui, indent)) - except SourceError: - pass - - def list_all(self): - """List all sources presently configured in the system - - This may include the configuration data for each source as well - """ - - indent = ' ' - if self.no_indent: - indent = '' - - if self.print_files: - print('Configured source files:') - - for file in util.files: - print(f'{file.path.name}:') - - for source in file.sources: - print(textwrap.indent(source.ui, indent)) - - if self.legacy: - self.list_legacy(indent) - - else: - print('Configured Sources:') - for source in util.sources: - output = util.sources[source] - print(textwrap.indent(output.ui, indent)) - - if self.legacy: - self.list_legacy(indent) - - if util.errors: - print('\n\nThe following files contain formatting errors:') - for err in util.errors: - print(err) - if self.verbose or self.debug: - print('\nDetails about failing files:') - for err in util.errors: - print(f'{err}: {util.errors[err].args[0]}') - - return True - - def run(self): - """Run the command""" - system.load_all_sources() - self.log.debug("Current sources: %s", util.sources) - ret = False - - if self.all: - return self.list_all() - - if self.repo == 'x-repolib-all-sources' and not self.all: - if not self.skip_names: - print('Configured Sources:') - for source in util.sources: - line = source - if not self.skip_names: - line += f' - {util.sources[source].name}' - print(line) - - return True - - else: - try: - output = util.sources[self.repo] - print(f'Details for source {output.ui}') - return True - except KeyError: - self.log.error( - "Couldn't find the source file for %s, check the spelling", - self.repo - ) - return False diff --git a/archive/repolib/command/modify.py b/archive/repolib/command/modify.py deleted file mode 100644 index 2738684..0000000 --- a/archive/repolib/command/modify.py +++ /dev/null @@ -1,502 +0,0 @@ -#!/usr/bin/python3 - -""" -Copyright (c) 2022, Ian Santopietro -All rights reserved. - -This file is part of RepoLib. - -RepoLib is free software: you can redistribute it and/or modify -it under the terms of the GNU Lesser General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -RepoLib is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License -along with RepoLib. If not, see . -""" - -from argparse import SUPPRESS - -from .command import Command, RepolibCommandError -from .. import util, system - -class Modify(Command): - """Modify Subcommand - - Makes modifications to the specified repository - - Options: - --enable, -e - --disable, -d - --default-mirror - --name - --add-suite - --remove-suite - --add-component - --remove-component - --add-uri - --remove-uri - - Hidden Options - --add-option - --remove-option - --default-mirror - """ - - @classmethod - def init_options(cls, subparsers): - """ Sets up this command's options parser""" - - sub = subparsers.add_parser( - 'modify', - help='Change a configured repository.' - ) - sub.add_argument( - 'repository', - nargs='*', - default=['system'], - help='The repository to modify. Default is the system repository.' - ) - - modify_enable = sub.add_mutually_exclusive_group( - required=False - ) - modify_enable.add_argument( - '-e', - '--enable', - action='store_true', - help='Enable the repository, if disabled.' - ) - modify_enable.add_argument( - '-d', - '--disable', - action='store_true', - help=( - 'Disable the repository, if enabled. The system repository cannot ' - 'be disabled.' - ) - ) - - modify_source = sub.add_mutually_exclusive_group( - required=False - ) - - modify_source.add_argument( - '--source-enable', - action='store_true', - help='Enable source code for the repository, if disabled.' - ) - modify_source.add_argument( - '--source-disable', - action='store_true', - help='Disable source code for the repository, if enabled.' - ) - - sub.add_argument( - '--default-mirror', - help=SUPPRESS - #help='Sets the default mirror for the system source.' - ) - - # Name - sub.add_argument( - '-n', - '--name', - help='Set the repository name to NAME' - ) - - # Suites - sub.add_argument( - '--add-suite', - metavar='SUITE[,SUITE]', - help=( - 'Add the specified suite(s) to the repository. Multiple ' - 'repositories should be separated with commas. NOTE: Legacy deb ' - 'repositories may only contain one suite.' - ) - ) - sub.add_argument( - '--remove-suite', - metavar='SUITE[,SUITE]', - help=( - 'Remove the specified suite(s) from the repository. Multiple ' - 'repositories should be separated with commas. NOTE: The last ' - 'suite in a repository cannot be removed.' - ) - ) - - # Components - sub.add_argument( - '--add-component', - metavar='COMPONENT[,COMPONENT]', - help=( - 'Add the specified component(s) to the repository. Multiple ' - 'repositories should be separated with commas.' - ) - ) - sub.add_argument( - '--remove-component', - metavar='COMPONENT[,COMPONENT]', - help=( - 'Remove the specified component(s) from the repository. Multiple ' - 'repositories should be separated with commas. NOTE: The last ' - 'component in a repository cannot be removed.' - ) - ) - - # URIs - sub.add_argument( - '--add-uri', - metavar='URI[,URI]', - help=( - 'Add the specified URI(s) to the repository. Multiple ' - 'repositories should be separated with commas. NOTE: Legacy deb ' - 'repositories may only contain one uri.' - ) - ) - sub.add_argument( - '--remove-uri', - metavar='URI[,URI]', - help=( - 'Remove the specified URI(s) from the repository. Multiple ' - 'repositories should be separated with commas. NOTE: The last ' - 'uri in a repository cannot be removed.' - ) - ) - - # Options - sub.add_argument( - '--add-option', - metavar='OPTION=VALUE[,OPTION=VALUE]', - help=SUPPRESS - ) - sub.add_argument( - '--remove-option', - metavar='OPTION=VALUE[,OPTION=VALUE]', - help=SUPPRESS - ) - - def finalize_options(self, args): - super().finalize_options(args) - self.count = 0 - self.repo = ' '.join(args.repository) - self.enable = args.enable - self.disable = args.disable - self.source_enable = args.source_enable - self.source_disable = args.source_disable - - self.actions:dict = {} - - self.actions['endisable'] = None - for i in ['enable', 'disable']: - if getattr(args, i): - self.actions['endisable'] = i - - self.actions['source_endisable'] = None - for i in ['source_enable', 'source_disable']: - if getattr(args, i): - self.actions['source_endisable'] = i - - for arg in [ - 'default_mirror', - 'name', - 'add_uri', - 'add_suite', - 'add_component', - 'remove_uri', - 'remove_suite', - 'remove_component', - ]: - self.actions[arg] = getattr(args, arg) - - system.load_all_sources() - - def run(self): - """Run the command""" - self.log.info('Modifying repository %s', self.repo) - - self.system_source = False - try: - self.source = util.sources[self.repo] - except KeyError: - self.log.error( - 'The source %s could not be found. Check the spelling', - self.repo - ) - return False - - if self.source.ident == 'system': - self.system_source = True - - self.log.debug('Actions to take:\n%s', self.actions) - self.log.debug('Source before:\n%s', self.source) - - rets = [] - for action in self.actions: - ret = getattr(self, action)(self.actions[action]) - rets.append(ret) - - self.log.debug('Results: %s', rets) - self.log.debug('Source after: \n%s', self.source) - - if True in rets: - self.source.file.save() - return True - else: - self.log.warning('No valid changes specified, no actions taken.') - return False - - def default_mirror(self, value:str) -> bool: - """Checks if this is the system source, then set the default mirror""" - if not value: - return False - - if self.system_source: - self.source['X-Repolib-Default-Mirror'] = value - return True - return False - - def name(self, value:str) -> bool: - """Sets the source name""" - if not value: - return False - - self.log.info('Setting name for %s to %s', self.repo, value) - self.source.name = value - return True - - def endisable(self, value:str) -> bool: - """Enable or disable the source""" - if not value: - return False - - self.log.info('%sing source %s', value[:-1], self.repo) - if value == 'disable': - self.source.enabled = False - return True - - self.source.enabled = True - return True - - def source_endisable(self, value:str) -> bool: - """Enable/disable source code for the repo""" - if not value: - return False - - self.log.info('%sing source code for source %s', value[7:-1], self.repo) - if value == 'source_disable': - self.source.sourcecode_enabled = False - return True - - self.source.sourcecode_enabled = True - return True - - def add_uri(self, values:str) -> bool: - """Adds URIs to the source, if not already present.""" - if not values: - return False - - self.log.info('Adding URIs: %s', values) - uris = self.source.uris - - for uri in values.split(): - if not util.url_validator(uri): - raise RepolibCommandError( - f'Cannot add URI {uri} to {self.repo}. The URI is ' - 'malformed' - ) - - if uri not in uris: - uris.append(uri) - self.log.debug('Added URI %s', uri) - - else: - self.log.warning( - 'The URI %s was already present in %s', - uri, - self.repo - ) - - if uris != self.source.uris: - self.source.uris = uris - return True - return False - - def remove_uri(self, values:str) -> bool: - """Remove URIs from the soruce, if they are added.""" - if not values: - return False - - self.log.info('Removing URIs %s from source %s', values, self.repo) - uris = self.source.uris - self.log.debug('Starting uris: %s', uris) - - for uri in values.split(): - try: - uris.remove(uri) - self.log.debug('Removed URI %s', uri) - - except ValueError: - self.log.warning( - 'The URI %s was not present in %s', - uri, - self.repo - ) - - if len(uris) == 0: - self.log.error( - 'Cannot remove the last URI from %s. If you meant to delete the source, try REMOVE instead.', - self.repo - ) - return False - - if uris != self.source.uris: - self.source.uris = uris - return True - - return False - - def add_suite(self, values:str) -> bool: - """Adds a suite to the source""" - if not values: - return False - - self.log.info('Adding suites: %s', values) - suites = self.source.suites - - for suite in values.split(): - if suite not in suites: - suites.append(suite) - self.log.debug('Added suite %s', suite) - - else: - self.log.warning( - 'The suite %s was already present in %s', - suite, - self.repo - ) - - if suites != self.source.suites: - self.source.suites = suites - return True - return False - - def remove_suite(self, values:str) -> bool: - """Remove a suite from the source""" - if not values: - return False - - self.log.info('Removing suites %s from source %s', values, self.repo) - suites = self.source.suites - self.log.debug('Starting suites: %s', suites) - - for suite in values.split(): - try: - suites.remove(suite) - self.log.debug('Removed suite %s', suite) - - except ValueError: - self.log.warning( - 'The suite %s was not present in %s', - suite, - self.repo - ) - - if len(suites) == 0: - self.log.error( - 'Cannot remove the last suite from %s. If you meant to delete the source, try REMOVE instead.', - self.repo - ) - return False - - if suites != self.source.suites: - self.source.suites = suites - return True - - return False - - def add_component(self, values:str) -> bool: - """Adds components to the source""" - if not values: - return False - - self.log.info('Adding components: %s', values) - components = self.source.components - - for component in values.split(): - if component not in components: - components.append(component) - self.log.debug('Added component %s', component) - - else: - self.log.warning( - 'The component %s was already present in %s', - component, - self.repo - ) - - if len(components) > 1: - if self.source.file.format == util.SourceFormat.LEGACY: - self.log.warning( - 'Adding multiple components to a legacy source is not ' - 'supported. Consider converting the source to DEB822 format.' - ) - - if components != self.source.components: - self.source.components = components - return True - return False - - def remove_component(self, values:str) -> bool: - """Removes components from the source""" - if not values: - return False - - self.log.info('Removing components %s from source %s', values, self.repo) - components = self.source.components - self.log.debug('Starting components: %s', components) - - for component in values.split(): - try: - components.remove(component) - self.log.debug('Removed component %s', component) - - except ValueError: - self.log.warning( - 'The component %s was not present in %s', - component, - self.repo - ) - - if len(components) == 0: - self.log.error( - 'Cannot remove the last component from %s. If you meant to delete the source, try REMOVE instead.', - self.repo - ) - return False - - if components != self.source.components: - self.source.components = components - return True - - return False - - def add_option(self, values) -> bool: - """TODO: Support options""" - raise NotImplementedError( - 'Options have not been implemented in this version of repolib yet. ' - f'Please edit the file {self.source.file.path} manually.' - ) - - - def remove_option(self, values) -> bool: - """TODO: Support options""" - raise NotImplementedError( - 'Options have not been implemented in this version of repolib yet. ' - f'Please edit the file {self.source.file.path} manually.' - ) diff --git a/archive/repolib/command/remove.py b/archive/repolib/command/remove.py deleted file mode 100644 index 851be03..0000000 --- a/archive/repolib/command/remove.py +++ /dev/null @@ -1,128 +0,0 @@ -#!/usr/bin/python3 - -""" -Copyright (c) 2022, Ian Santopietro -All rights reserved. - -This file is part of RepoLib. - -RepoLib is free software: you can redistribute it and/or modify -it under the terms of the GNU Lesser General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -RepoLib is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License -along with RepoLib. If not, see . -""" - -from .. import util, system -from .command import Command - -class Remove(Command): - """Remove subcommand - - Removes configured sources from the system - - Options: - --assume-yes, -y - """ - - @classmethod - def init_options(cls, subparsers): - """Sets up the argument parser for this command - - Returns: argparse.subparser - This command's subparser - """ - - sub = subparsers.add_parser( - 'remove', - help='Remove a configured repository' - ) - - sub.add_argument( - 'repository', - help='The identifier of the repository to remove. See LIST' - ) - sub.add_argument( - '-y', - '--assume-yes', - action='store_true', - help='Remove without prompting for confirmation' - ) - - def finalize_options(self, args): - super().finalize_options(args) - system.load_all_sources() - self.source_name = args.repository - self.assume_yes = args.assume_yes - self.source = None - - def run(self): - """Run the command""" - - self.log.info('Looking up %s for removal', self.source_name) - - if self.source_name == 'system': - self.log.error('You cannot remove the system sources') - return False - - if self.source_name not in util.sources: - self.log.error( - 'Source %s was not found. Double-check the spelling', - self.source_name - ) - source_list:list = [] - for source in util.sources: - source_list.append(source) - suggested_source:str = self.source_name.replace(':', '-') - suggested_source = suggested_source.translate(util.CLEAN_CHARS) - if not suggested_source in source_list: - return False - - response:str = input(f'Did you mean "{suggested_source}"? (Y/n) ') - if not response: - response = 'y' - if response not in util.true_values: - return False - self.source_name = suggested_source - - self.source = util.sources[self.source_name] - self.key = self.source.key - self.file = self.source.file - - print(f'This will remove the source {self.source_name}') - print(self.source.ui) - response:str = 'n' - if self.assume_yes: - response = 'y' - else: - response = input('Are you sure you want to do this? (y/N) ') - - if response in util.true_values: - self.file.remove_source(self.source_name) - self.file.save() - - system.load_all_sources() - for source in util.sources.values(): - self.log.debug('Checking key for %s', source.ident) - try: - if source.key.path == self.key.path: - self.log.info('Source key in use with another source') - return True - except AttributeError: - pass - - self.log.info('No other sources found using key, deleting key') - if self.key: - self.key.delete_key() - return True - - else: - print('Canceled.') - return False diff --git a/archive/repolib/file.py b/archive/repolib/file.py deleted file mode 100644 index 5541a56..0000000 --- a/archive/repolib/file.py +++ /dev/null @@ -1,544 +0,0 @@ -#!/usr/bin/python3 - -""" -Copyright (c) 2022, Ian Santopietro -All rights reserved. - -This file is part of RepoLib. - -RepoLib is free software: you can redistribute it and/or modify -it under the terms of the GNU Lesser General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -RepoLib is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License -along with RepoLib. If not, see . -""" -import logging - -from pathlib import Path - -import dbus - -from .source import Source, SourceError -from . import util - -FILE_COMMENT = "## Added/managed by repolib ##" - -class SourceFileError(util.RepoError): - """ Exception from a source file.""" - - def __init__(self, *args, code:int = 1, **kwargs): - """Exception with a source file - - Arguments: - :code int, optional, default=1: Exception error code. - """ - super().__init__(*args, **kwargs) - self.code: int = code - -class SourceFile: - """ A Source File on disk - - Attributes: - path(Pathlib.Path): the path for this file on disk - name(str): The name for this source (filename less the extension) - format(SourceFormat): The format used by this source file - contents(list): A list containing all of this file's contents - """ - - def __init__(self, name:str='') -> None: - """Initialize a source file - - Arguments: - name(str): The filename within the sources directory to load - """ - self.log = logging.getLogger(__name__) - self.name:str = '' - self.path:Path = Path() - self.alt_path:Path = Path() - self.format:util.SourceFormat = util.SourceFormat.DEFAULT - self.contents:list = [] - self.sources:list = [] - - self.contents.append(FILE_COMMENT) - self.contents.append('#') - - if name: - self.name = name - self.reset_path() - - if self.path.exists(): - self.contents = [] - self.load() - - def __str__(self): - return self.output - - def __repr__(self): - return f'SourceFile(name={self.name})' - - def add_source(self, source:Source) -> None: - """Adds a source to the file - - Arguments: - source(Source): The source to add - """ - if source not in self.sources: - self.contents.append(source) - self.sources.append(source) - source.file = self - - def remove_source(self, ident:str) -> None: - """Removes a source from the file - - Arguments: - ident(str): The ident of the source to remove - """ - source = self.get_source_by_ident(ident) - self.contents.remove(source) - self.sources.remove(source) - self.save() - - ## Remove sources prefs files/pin-priority - prefs_path = source.prefs - try: - if prefs_path.exists() and prefs_path.name: - prefs_path.unlink() - - except AttributeError: - # No prefs path - pass - - except PermissionError: - bus = dbus.SystemBus() - privileged_object = bus.get_object('org.pop_os.repolib', '/Repo') - privileged_object.delete_prefs_file(str(prefs_path)) - - def get_source_by_ident(self, ident: str) -> Source: - """Find a source within this file by its ident - - Arguments: - ident(str): The ident to search for - - Returns: Source - The located source - """ - self.log.debug(f'Looking up ident {ident} in {self.name}') - for source in self.sources: - if source.ident == ident: - self.log.debug(f'{ident} found') - return source - raise SourceFileError( - f'The file {self.path} does not contain the source {ident}' - ) - - def reset_path(self) -> None: - """Attempt to detect the correct path for this File. - - We default to DEB822 .sources format files, but if that file doesn't - exist, fallback to legacy .list format. If this also doesn't exist, we - swap back to DEB822 format, as this is likely a new file.""" - self.log.debug('Resetting path') - - default_path = util.SOURCES_DIR / f'{self.name}.sources' - legacy_path = util.SOURCES_DIR / f'{self.name}.list' - - if default_path.exists(): - self.path = default_path - self.alt_path = legacy_path - self.format = util.SourceFormat.DEFAULT - - elif legacy_path.exists(): - self.path = legacy_path - self.alt_path = default_path - self.format = util.SourceFormat.LEGACY - - else: - self.path = default_path - self.alt_path = legacy_path - - return - - def find_unique_ident(self, source1:Source, source2:Source) -> bool: - """Takes two sources with identical idents, and finds a new, unique - idents for them. - - The rules for this are mildly complicated, and vary depending on the - situation: - - * (DEB822) If the sources are identical other than some portion of - data, then the two will be combined into a single source. - * (legacy) If the two sources are identical other than source type - (common with legacy-format PPAs with source code) then the second - source will be dropped until export. - * (legacy) If the sources differ by URIs, Components, or Suites, then - the differing data will be appended to the sources' idents. - * (Either) If no other rules can be determined, then the sources will - have a number appended to them - - Arguments: - source1(Source): The original source with the ident - source2(Source): The new colliding source with the ident - - Returns: bool - `True` if the two sources were successfully deduped, `False` if the - second source should be discarded. - """ - ident_src1:str = source1.ident - ident_src2:str = source2.ident - - self.log.debug(f'Idents {ident_src1} and {ident_src2} conflict') - - if self.format == util.SourceFormat.DEFAULT: - util.combine_sources(source1, source2) - ident_src2 = '' - - else: - excl_keys = [ - 'X-Repolib-Name', - 'X-Repolib-ID', - 'X-Repolib-Comment', - 'Enabled', - 'Types' - ] - if len(source1.types) == 1 and len(source2.types) == 1: - if util.compare_sources(source1, source2, excl_keys): - util.combine_sources(source1, source2) - source1.types = [ - util.SourceType.BINARY, util.SourceType.SOURCECODE - ] - source1.twin_source = True - source1.sourcecode_enabled = source2.enabled - ident_src2 = '' - diffs = util.find_differences_sources(source1, source2, excl_keys) - if diffs: - for key in diffs: - raw_diffs:tuple = diffs[key] - diff1_list = raw_diffs[0].strip().split() - diff2_list = raw_diffs[1].strip().split() - for i in diff1_list: - if i not in diff2_list: - ident_src1 += f'-{i}' - break - for i in diff2_list: - if i not in diff1_list: - ident_src2 += f'-{i}' - break - if ident_src1 != ident_src2: - break - if ident_src2 and ident_src1 != ident_src2: - source1.ident = ident_src1 - source2.ident = ident_src2 - return True - - elif ident_src2 and ident_src1 == ident_src2: - for source in self.sources: - src_index = self.sources.index(source) - source.ident = f'{self.name}-{src_index}' - return True - - elif not ident_src2: - return False - - return True - - - def load(self) -> None: - """Loads the sources from the file on disk""" - self.log.debug(f'Loading source file {self.path}') - self.contents = [] - self.sources = [] - - if not self.name: - raise SourceFileError('You must provide a filename to load.') - - if not self.path.exists(): - raise SourceFileError(f'The file {self.path} does not exist.') - - with open(self.path, 'r') as source_file: - srcfile_data = source_file.readlines() - - item:int = 0 - raw822:list = [] - parsing_deb822:bool = False - source_name:str = '' - commented:bool = False - idents:dict = {} - - # Main file parsing loop - for line in srcfile_data: - comment_found:str = '' - name_line:bool = 'X-Repolib-Name' in line - - if not parsing_deb822: - commented = line.startswith('#') - - # Find commented out lines - if commented: - # Exclude disabled legacy deblines - valid_legacy = util.validate_debline(line.strip()) - if not valid_legacy and not name_line: - # Found a standard comment - self.contents.append(line.strip()) - - elif valid_legacy: - if self.format != util.SourceFormat.LEGACY: - raise SourceFileError( - f'File {self.path.name} is an updated file, but ' - 'contains legacy-format sources. This is not ' - 'allowed. Please fix the file manually.' - ) - new_source = Source() - new_source.load_from_data([line]) - if source_name: - new_source.name = source_name - if not new_source.ident: - new_source.ident = self.name - to_add:bool = True - if new_source.ident in idents: - old_source = idents[new_source.ident] - idents.pop(old_source.ident) - to_add = self.find_unique_ident(old_source, new_source) - idents[old_source.ident] = old_source - idents[new_source.ident] = new_source - if to_add: - new_source.file = self - self.contents.append(new_source) - self.sources.append(new_source) - - elif name_line: - source_name = ':'.join(line.split(':')[1:]) - source_name = source_name.strip() - - # Active legacy line - elif not commented: - if util.validate_debline(line.strip()): - if self.format != util.SourceFormat.LEGACY: - raise SourceFileError( - f'File {self.path.name} is an updated file, but ' - 'contains legacy-format sources. This is not ' - 'allowed. Please fix the file manually.' - ) - new_source = Source() - new_source.load_from_data([line]) - if source_name: - new_source.name = source_name - if not new_source.ident: - new_source.ident = self.name - to_add:bool = True - if new_source.ident in idents: - old_source = idents[new_source.ident] - idents.pop(old_source.ident) - to_add = self.find_unique_ident(old_source, new_source) - idents[old_source.ident] = old_source - idents[new_source.ident] = new_source - if to_add: - new_source.file = self - self.contents.append(new_source) - self.sources.append(new_source) - - # Empty lines are treated as comments - if line.strip() == '': - self.contents.append('') - - # Find 822 sources - # Valid sources can begin with any key: - for key in util.valid_keys: - if line.startswith(key): - if self.format == util.SourceFormat.LEGACY: - raise SourceFileError( - f'File {self.path.name} is a DEB822-format file, but ' - 'contains legacy sources. This is not allowed. ' - 'Please fix the file manually.' - ) - parsing_deb822 = True - raw822.append(line.strip()) - - item += 1 - - elif parsing_deb822: - # Deb822 sources are terminated with an empty line - if line.strip() == '': - parsing_deb822 = False - new_source = Source() - new_source.load_from_data(raw822) - new_source.file = self - if source_name: - new_source.name = source_name - if not new_source.ident: - new_source.ident = self.name - if new_source.ident in idents: - old_source = idents[new_source.ident] - idents.pop(old_source.ident) - self.find_unique_ident(old_source, new_source) - idents[old_source.ident] = old_source - idents[new_source.ident] = new_source - new_source.file = self - self.contents.append(new_source) - self.sources.append(new_source) - raw822 = [] - item += 1 - self.contents.append('') - else: - raw822.append(line.strip()) - - if raw822: - parsing_deb822 = False - new_source = Source() - new_source.load_from_data(raw822) - new_source.file = self - if source_name: - new_source.name = source_name - if not new_source.ident: - new_source.ident = self.name - if new_source.ident in idents: - old_source = idents[new_source.ident] - idents.pop(old_source.ident) - self.find_unique_ident(old_source, new_source) - idents[old_source.ident] = old_source - idents[new_source.ident] = new_source - new_source.file = self - self.contents.append(new_source) - self.sources.append(new_source) - raw822 = [] - item += 1 - self.contents.append('') - - for source in self.sources: - if not source.has_required_parts: - raise SourceFileError( - f'The file {self.path.name} is malformed and contains ' - 'errors. Maybe it has some extra new-lines?' - ) - - self.log.debug('File %s loaded', self.path) - - def save(self) -> None: - """Saves the source file to disk using the current format""" - self.log.debug(f'Saving source file to {self.path}') - - for source in self.sources: - self.log.debug('New Source %s: \n%s', source.ident, source) - - save_path = util.SOURCES_DIR / f'{self.name}.save' - - for source in self.sources: - if source.key: - source.key.save_gpg() - source.tasks_save() - - if not self.name or not self.format: - raise SourceFileError('There was not a complete filename to save') - - if not util.SOURCES_DIR.exists(): - try: - util.SOURCES_DIR.mkdir(parents=True) - except PermissionError: - self.log.error( - 'Source destination path does not exist and cannot be created ' - 'Failures expected now.' - ) - - if len(self.sources) > 0: - self.log.debug('Saving, Main path %s; Alt path: %s', self.path, self.alt_path) - try: - with open(self.path, mode='w') as output_file: - output_file.write(self.output) - if self.alt_path.exists(): - self.alt_path.rename(save_path) - - except PermissionError: - bus = dbus.SystemBus() - privileged_object = bus.get_object('org.pop_os.repolib', '/Repo') - privileged_object.output_file_to_disk(self.path.name, self.output) - self.log.debug('File %s saved', self.path) - else: - try: - self.path.unlink(missing_ok=True) - self.alt_path.unlink(missing_ok=True) - save_path.unlink(missing_ok=True) - except PermissionError: - bus = dbus.SystemBus() - privileged_object = bus.get_object('org.pop_os.repolib', '/Repo') - privileged_object.delete_source_file(self.path.name) - self.log.debug('File %s removed', self.path) - - - ## Attribute properties - @property - def format(self) -> util.SourceFormat: # type: ignore (We don't use str.format) - """The format of the file on disk""" - return self._format - - @format.setter - def format(self, format:util.SourceFormat) -> None: # type: ignore (We don't use str.format) - """The path needs to be updated when the format changes""" - alt_format:util.SourceFormat = util.SourceFormat.LEGACY - self._format = format - self.path = util.SOURCES_DIR / f'{self.name}.{self._format.value}' - for format_ in util.SourceFormat: - if format != format_: - alt_format = format_ - self.alt_path = util.SOURCES_DIR / f'{self.name}.{alt_format.value}' - - ## Output properties - @property - def legacy(self) -> str: - """Outputs the file in the output_legacy format""" - legacy_output:str = '' - for item in self.contents: - try: - legacy_output += item.legacy - except AttributeError: - legacy_output += item - legacy_output += '\n' - return legacy_output - - @property - def deb822(self) -> str: - """Outputs the file in the output_822 format""" - deb822_output:str = '' - for item in self.contents: - try: - deb822_output += item.deb822 - except AttributeError: - deb822_output += item - deb822_output += '\n' - return deb822_output - - - @property - def ui(self) -> str: - """Outputs the file in the output_ui format""" - ui_output:str = '' - for item in self.contents: - try: - ui_output += item.ui - except AttributeError: - pass # Skip file comments in UI mode - ui_output += '\n' - return ui_output - - - @property - def output(self) -> str: - """Outputs the file in the output format""" - default_output:str = '' - for item in self.contents: - try: - if self.format == util.SourceFormat.DEFAULT: - default_output += item.deb822 - elif self.format == util.SourceFormat.LEGACY: - default_output += item.legacy - default_output += '\n' - except AttributeError: - default_output += item - default_output += '\n' - return default_output - diff --git a/archive/repolib/key.py b/archive/repolib/key.py deleted file mode 100644 index 766881b..0000000 --- a/archive/repolib/key.py +++ /dev/null @@ -1,204 +0,0 @@ -#!/usr/bin/python3 - -""" -Copyright (c) 2022, Ian Santopietro -All rights reserved. - -This file is part of RepoLib. - -RepoLib is free software: you can redistribute it and/or modify -it under the terms of the GNU Lesser General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -RepoLib is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License -along with RepoLib. If not, see . -""" - -import logging -import shutil - -import dbus -import gnupg -from pathlib import Path -from urllib import request - -from . import util - -SKS_KEYSERVER = 'https://keyserver.ubuntu.com/' -SKS_KEYLOOKUP_PATH = 'pks/lookup?op=get&options=mr&exact=on&search=0x' - -class KeyFileError(util.RepoError): - """ Exceptions related to apt key files.""" - - def __init__(self, *args, code=1, **kwargs): - """Exceptions related to apt key files. - - Arguments: - code (:obj:`int`, optional, default=1): Exception error code. - """ - super().__init__(*args, **kwargs) - self.code = code - -class SourceKey: - """A signing key for an apt source.""" - - def __init__(self, name:str = '') -> None: - self.log = logging.getLogger(__name__) - self.tmp_path = Path() - self.path = Path() - self.gpg = gnupg.GPG() - self.data = b'' - - if name: - self.reset_path(name=name) - self.setup_gpg() - - def reset_path(self, name: str = '', path:str = '', suffix: str = 'archive-keyring') -> None: - """Set the path for this key - - Arguments: - suffix(str): The suffix to append to the end of the name to get the - file name (default: 'archive-keyring') - name(str): The name of the source - path(str): The entire path to the key - """ - self.log.info('Setting path') - if not name and not path: - raise KeyFileError('A name is required to set the path for this key') - - if name: - file_name = f'{name}-{suffix}.gpg' - self.tmp_path = util.TEMP_DIR / file_name - self.path = util.KEYS_DIR / file_name - elif path: - self.path = Path(path) - self.tmp_path = util.TEMP_DIR / self.path.name - - self.setup_gpg() - - self.log.debug('Key Path: %s', self.path) - self.log.debug('Temp Path: %s', self.tmp_path) - - def setup_gpg(self) -> None: - """Set up the GPG object for this key.""" - self.log.info('Setting up GPG') - self.log.debug('Copying %s to %s', self.path, self.tmp_path) - try: - shutil.copy2(self.path, self.tmp_path) - - except FileNotFoundError: - pass - - self.gpg = gnupg.GPG(keyring=str(self.tmp_path)) - self.log.debug('GPG Setup: %s', self.gpg.keyring) - - def save_gpg(self) -> None: - """Saves the key to disk.""" - self.log.info('Saving key file %s from %s', self.path, self.tmp_path) - self.log.debug('Key contents: %s', self.gpg.list_keys()) - self.log.debug('Temp key exists? %s', self.tmp_path.exists()) - if not util.KEYS_DIR.exists(): - try: - util.KEYS_DIR.mkdir(parents=True) - except PermissionError: - self.log.error( - 'Key destination path does not exist and cannot be created ' - 'Failures expected now.' - ) - try: - shutil.copy(self.tmp_path, self.path) - - except PermissionError: - bus = dbus.SystemBus() - privileged_object = bus.get_object('org.pop_os.repolib', '/Repo') - privileged_object.install_signing_key( - str(self.tmp_path), - str(self.path) - ) - - def delete_key(self) -> None: - """Deletes the key file from disk.""" - try: - self.tmp_path.unlink() - self.path.unlink() - - except PermissionError: - bus = dbus.SystemBus() - privileged_object = bus.get_object('org.pop_os.repolib', '/Repo') - privileged_object.delete_signing_key(str(self.path)) - - except FileNotFoundError: - pass - - def load_key_data(self, **kwargs) -> None: - """Loads the key data from disk into the object for processing. - - Each of the keyword options specifies one place to look to import key - data. Once one is successfully imported, the method returns, so passing - multiple won't import multiple keys. - - Keyword Arguments: - raw(bytes): Raw data to import to the keyring - ascii(str): ASCII-armored key data to import directly - url(str): A URL to download key data from - fingerprint(str): A key fingerprint to download from `keyserver` - keyserver(str): A keyserver to download from. - keypath(str): The path on the keyserver from which to download. - - NOTE: The keyserver and keypath args only affect the operation of the - `fingerprint` keyword. - """ - - if self.path.exists(): - with open(self.path, mode='rb') as keyfile: - self.data = keyfile.read() - return - - self.tmp_path.touch() - - if 'raw' in kwargs: - self.data = kwargs['raw'] - self.gpg.import_keys(self.data) - return - - if 'ascii' in kwargs: - self.gpg.import_keys(kwargs['ascii']) - if self.tmp_path.exists(): - with open(self.tmp_path, mode='rb') as keyfile: - self.data = keyfile.read() - return - - if 'url' in kwargs: - req = request.Request(kwargs['url']) - with request.urlopen(req) as response: - self.data = response.read().decode('UTF-8') - self.gpg.import_keys(self.data) - return - - if 'fingerprint' in kwargs: - if not 'keyserver' in kwargs: - kwargs['keyserver'] = SKS_KEYSERVER - - if not 'keypath' in kwargs: - kwargs['keypath'] = SKS_KEYLOOKUP_PATH - - key_url = kwargs['keyserver'] + kwargs['keypath'] + kwargs['fingerprint'] - req = request.Request(key_url) - with request.urlopen(req) as response: - self.data = response.read().decode('UTF-8') - self.gpg.import_keys(self.data) - return - - raise TypeError( - f'load_key_data() got an unexpected keyword argument "{kwargs.keys()}', - ' Expected keyword arguments are: [raw, ascii, url, fingerprint]' - ) - - - diff --git a/archive/repolib/parsedeb.py b/archive/repolib/parsedeb.py deleted file mode 100644 index 1e0d992..0000000 --- a/archive/repolib/parsedeb.py +++ /dev/null @@ -1,371 +0,0 @@ -#!/usr/bin/python3 - -""" -Copyright (c) 2022, Ian Santopietro -All rights reserved. - -This file is part of RepoLib. - -RepoLib is free software: you can redistribute it and/or modify -it under the terms of the GNU Lesser General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -RepoLib is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License -along with RepoLib. If not, see . -""" - -import logging - -from . import util - -log = logging.getLogger(__name__) - -class DebParseError(util.RepoError): - """ Exceptions related to parsing deb lines.""" - - def __init__(self, *args, code=1, **kwargs): - """Exceptions related to parsing deb lines. - - Arguments: - code (:obj:`int`, optional, default=1): Exception error code. - """ - super().__init__(*args, **kwargs) - self.code = code - -def debsplit(line:str) -> list: - """ Improved string.split() with support for things like [] options. - - Adapted from python-apt - - Arguments: - line(str): The line to split up. - """ - line = line.strip() - line_list = line.split() - for i in line_list: - if util.url_validator(i): - line_list[line_list.index(i)] = decode_brackets(i) - line = ' '.join(line_list) - pieces:list = [] - tmp:str = "" - # we are inside a [..] block - p_found = False - for char in line: - if char == '[': - p_found = True - tmp += char - elif char == ']': - p_found = False - tmp += char - elif char.isspace() and not p_found: - pieces.append(tmp) - tmp = '' - continue - else: - tmp += char - # append last piece - if len(tmp) > 0: - pieces.append(tmp) - return pieces - -def encode_brackets(word:str) -> str: - """ Encodes any [ and ] brackets into URL-safe form - - Technically we should never be recieving these, and there are other things - which should technically be encoded as well. However, square brackets - actively break the URL parsing, and must be strictly avoided. - - Arguments: - word (str): the string to encode brackets in. - - Returns: - `str`: the encoded string. - """ - word = word.replace('[', '%5B') - word = word.replace(']', '%5D') - return word - -def decode_brackets(word:str) -> str: - """ Un-encodes [ and ] from the input - - Since our downstream libraries should also be encoding these correctly, it - is better to retain these as the user entered, as that ensures they can - recognize it properly. - - Arguments: - word (str): The string to decode. - - Returns: - `str`: the decoded string. - """ - word = word.replace('%5B', '[') - word = word.replace('%5D', ']') - return word - -def parse_name_ident(tail:str) -> tuple: - """ Find a Repolib name within the given comment string. - - The name should be headed with "X-Repolib-Name:" and is not space terminated. - The ident should be headed with "X-Repolib-ID:" and is space terminated. - - Either field ends at the end of a line, or at a subsequent definition of a - different field, or at a subsequent ' #' substring. Additionally, the ident - field ends with a subsequent space. - - Arguments: - tail (str): The comment to search within. - - Returns: tuple(name, ident, comment): - name (str): The detected name, or None - ident (str): The detected ident, or None - comment (str): The string with the name and ident removed - """ - tail = util.strip_hashes(tail) - - # Used for sanity checking later - has_name = 'X-Repolib-Name' in tail - log.debug('Line name found: %s', has_name) - has_ident = 'X-Repolib-ID' in tail - log.debug('Line ident found: %s', has_ident) - - parts: list = tail.split() - name_found = False - ident_found = False - name:str = '' - ident:str = '' - comment:str = '' - for item in parts: - log.debug("Checking line item: %s", item) - item_is_name = item.strip('#').strip().startswith('X-Repolib-Name') - item_is_ident = item.strip('#').strip().startswith('X-Repolib-ID') - - if '#' in item and not item_is_name and not item_is_ident: - name_found = False - ident_found = False - - elif item_is_name: - name_found = True - ident_found = False - continue - - elif item_is_ident: - name_found = False - ident_found = True - continue - - if name_found and not item_is_name: - name += f'{item} ' - continue - - elif ident_found and not item_is_ident: - ident += f'{item}' - ident_found = False - continue - - elif not name_found and not ident_found: - c = item.strip('#') - comment += f'{c} ' - - name = name.strip() - ident = ident.strip() - comment = comment.strip() - - if not name: - if ident: - name = ident - - # Final sanity checking - if has_name and not name: - raise DebParseError( - f'Could not parse repository name from comment {comment}. Make sure ' - 'you have a space between the colon and the Name' - ) - if has_ident and not ident: - raise DebParseError( - f'Could not parse repository ident from comment {comment}. Make sure ' - 'you have a space between the colon and the Ident' - ) - - return name, ident, comment - - -class ParseDeb: - """ Parsing for source entries. - - Contains parsing helpers for one-line format sources. - """ - - def __init__(self, debug:bool = False) -> None: - """ - Arguments: - debug (bool): In debug mode, the structured data is always returned - at the end, instead of checking for sanity (default: `False`) - """ - self.debug = debug - self.last_line: str = '' - self.last_line_valid: bool = False - self.curr_line: str = '' - self.curr_line_valid: bool = False - - def parse_options(self, opt:str) -> dict: - """ Parses a string of options into a dictionary that repolib can use. - - Arguments: - opt(str): The string with options returned from the line parser. - - Returns: - `dict`: The dictionary of options with key:val pairs (may be {}) - """ - opt = opt.strip() - opt = opt[1:-1].strip() # Remove enclosing brackets - options = opt.split() - - parsed_options:dict = {} - - for opt in options: - pre_key, values = opt.split('=') - values = values.split(',') - value:str = ' '.join(values) - try: - key:str = util.options_inmap[pre_key] - except KeyError: - raise DebParseError( - f'Could not parse line {self.curr_line}: option {opt} is ' - 'not a valid debian repository option or is unsupported.' - ) - parsed_options[key] = value - - return parsed_options - - - def parse_line(self, line:str) -> dict: - """ Parse a deb line into its individual parts. - - Adapted from python-apt - - Arguments: - line (str): The line input to parse - - Returns: - (dict): a dict containing the requisite data. - """ - self.last_line = self.curr_line - self.last_line_valid = self.curr_line_valid - self.curr_line = line.strip() - parts:list = [] - - line_is_comment = self.curr_line == '#' - line_is_empty = self.curr_line == '' - if line_is_comment or line_is_empty: - raise DebParseError(f'Current line "{self.curr_line}" is empty') - - line_parsed: dict = {} - line_parsed['enabled'] = True - line_parsed['name'] = '' - line_parsed['ident'] = '' - line_parsed['comments'] = [] - line_parsed['repo_type'] = '' - line_parsed['uri'] = '' - line_parsed['suite'] = '' - line_parsed['components'] = [] - line_parsed['options'] = {} - - if line.startswith('#'): - line_parsed['enabled'] = False - line = util.strip_hashes(line) - parts = line.split() - if not parts[0] in ('deb', 'deb-src'): - raise DebParseError(f'Current line "{self.curr_line}" is invalid') - - comments_index = line.find('#') - if comments_index > 0: - raw_comments:str = line[comments_index + 1:].strip() - ( - line_parsed['name'], - line_parsed['ident'], - comments - ) = parse_name_ident(raw_comments) - line_parsed['comments'].append(comments) - line = line[:comments_index] - - parts = debsplit(line) - if len(parts) < 3: # We need at least a type, a URL, and a component - raise DebParseError( - f'The line "{self.curr_line}" does not have enough pieces to be' - 'valid' - ) - # Determine the type of the repo - repo_type:str = parts.pop(0) - if repo_type in ['deb', 'deb-src']: - line_parsed['repo_type'] = util.SourceType(repo_type) - else: - raise DebParseError(f'The line "{self.curr_line}" is of invalid type.') - - # Determine the properties of our repo line - uri_index:int = 0 - is_cdrom: bool = False - ## The URI index is the vital piece of information we need to parse the - ## deb line, as it's position determines what other components are - ## present and where they are. This determines the location of the URI - ## regardless of where it's at. - for part in parts: - if part.startswith('['): - if 'cdrom' in part: - is_cdrom = True - uri_index = parts.index(part) - else: - uri_index = 1 - - if is_cdrom: - # This could maybe change if the parser now differentiates between - # CDROM URIs and option lists - raise DebParseError('Repolib cannot currently accept CDROM Sources') - - if uri_index != 0: - line_parsed['options'] = self.parse_options(parts.pop(0)) - - if len(line_parsed) < 2: # Should have at minimum a URI and a suite/path - raise DebParseError( - f'The line "{self.curr_line}" does not have enough pieces to be' - 'valid' - ) - - line_uri = parts.pop(0) - if util.url_validator(line_uri): - line_parsed['uri'] = line_uri - - else: - raise DebParseError( - f'The line "{self.curr_line}" has invalid URI: {line_uri}' - ) - - line_parsed['suite'] = parts.pop(0) - - line_components:list = [] - for comp in parts: - line_parsed['components'].append(comp) - - - has_type = line_parsed['repo_type'] - has_uri = line_parsed['uri'] - has_suite = line_parsed['suite'] - - if has_type and has_uri and has_suite: - # if we have these three minimum components, we can proceed and the - # line is valid. Otherwise, error out. - return line_parsed.copy() - - if self.debug: - return line_parsed.copy() - - raise DebParseError( - f'The line {self.curr_line} could not be parsed due to an ' - 'unknown error (Probably missing the repo type, URI, or a ' - 'suite/path).' - ) diff --git a/archive/repolib/shortcuts/__init__.py b/archive/repolib/shortcuts/__init__.py deleted file mode 100644 index 43c1503..0000000 --- a/archive/repolib/shortcuts/__init__.py +++ /dev/null @@ -1,32 +0,0 @@ -#!/usr/bin/python3 - -""" -Copyright (c) 2022, Ian Santopietro -All rights reserved. - -This file is part of RepoLib. - -RepoLib is free software: you can redistribute it and/or modify -it under the terms of the GNU Lesser General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -RepoLib is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License -along with RepoLib. If not, see . -""" - -from .popdev import PopdevSource -from .ppa import PPASource -from ..source import Source - -shortcut_prefixes = { - 'deb': Source, - 'deb-src': Source, - ppa.prefix: ppa.PPASource, - popdev.prefix: popdev.PopdevSource -} \ No newline at end of file diff --git a/archive/repolib/shortcuts/popdev.py b/archive/repolib/shortcuts/popdev.py deleted file mode 100644 index f4efc6e..0000000 --- a/archive/repolib/shortcuts/popdev.py +++ /dev/null @@ -1,171 +0,0 @@ -#!/usr/bin/python3 - -""" -Copyright (c) 2022, Ian Santopietro -All rights reserved. - -This file is part of RepoLib. - -RepoLib is free software: you can redistribute it and/or modify -it under the terms of the GNU Lesser General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -RepoLib is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License -along with RepoLib. If not, see . -""" - -import logging -from pathlib import Path - -import dbus - -from repolib.key import SourceKey - -from ..source import Source, SourceError -from ..file import SourceFile -from .. import util - -BASE_FORMAT = util.SourceFormat.DEFAULT -BASE_URL = 'http://apt.pop-os.org/staging' -BASE_COMPS = 'main' -BASE_KEYURL = 'https://raw.githubusercontent.com/pop-os/pop/master/scripts/.iso.asc' - -DEFAULT_FORMAT = util.SourceFormat.DEFAULT - -prefix = 'popdev' -delineator = ':' - -class PopdevSource(Source): - """ PopDev Source shortcut - - These are given in the format popdev:branchname. - - Arguments: - shortcut (str): The ppa: shortcut to process - """ - prefs_dir = Path('/etc/apt/preferences.d') - default_format = BASE_FORMAT - - @staticmethod - def validator(shortcut:str) -> bool: - """Determine whether a PPA shortcut is valid. - - Arguments: - shortcut(str): The shortcut to validate - - Returns: bool - `True` if the PPA is valid, otherwise False - """ - if '/' in shortcut: - return False - - shortcut_split = shortcut.split(':') - try: - if not shortcut_split[1]: - return False - except IndexError: - return False - - if shortcut.startswith(f'{prefix}:'): - shortlist = shortcut.split(':') - if len(shortlist) > 0: - return True - - return False - - def __init__(self, *args, line='', fetch_data=True, **kwargs): - if line: - if not line.startswith('ppa:'): - raise SourceError(f'The PPA shortcut {line} is malformed') - super().__init__(args, kwargs) - self.log = logging.getLogger(__name__) - self.line = line - self.twin_source:bool = True - self.prefs_path = None - self.branch_name:str = '' - self.branch_url:str = '' - if line: - self.load_from_shortcut(line) - - def tasks_save(self, *args, **kwargs) -> None: - super().tasks_save(*args, **kwargs) - self.log.info('Saving prefs file for %s', self.ident) - prefs_contents = 'Package: *\n' - prefs_contents += f'Pin: release o=pop-os-staging-{self.branch_url}\n' - prefs_contents += 'Pin-Priority: 1002\n' - - self.log.debug('%s prefs for pin priority:\n%s', self.ident, prefs_contents) - - try: - with open(self.prefs, mode='w') as prefs_file: - prefs_file.write(prefs_contents) - except PermissionError: - bus = dbus.SystemBus() - privileged_object = bus.get_object('org.pop_os.repolib', '/Repo') - privileged_object.output_prefs_to_disk(str(self.prefs), prefs_contents) - - self.log.debug('Pin priority saved for %s', self.ident) - - - def get_description(self) -> str: - return f'Pop Development Staging branch' - - - def load_from_data(self, data: list) -> None: - self.log.debug('Loading line %s', data[0]) - self.load_from_shortcut(shortcut=data[0]) - - def load_from_shortcut(self, shortcut:str='', meta:bool=True, get_key:bool=True) -> None: - """Translates the shortcut line into a full repo. - - Arguments: - shortcut(str): The shortcut to load, if one hasn't been loaded yet. - """ - self.reset_values() - if shortcut: - self.line = shortcut - - if not self.line: - raise SourceError('No PPA shortcut provided') - - if not self.validator(self.line): - raise SourceError(f'The line {self.line} is malformed') - - self.log.debug('Loading shortcut %s', self.line) - - self.info_parts = shortcut.split(delineator) - self.branch_url = ':'.join(self.info_parts[1:]) - self.branch_name = util.scrub_filename(name=self.branch_url) - self.log.debug('Popdev branch name: %s', self.branch_name) - - self.ident = f'{prefix}-{self.branch_name}' - if f'{self.ident}.{BASE_FORMAT.value}' not in util.files: - new_file = SourceFile(name=self.ident) - new_file.format = BASE_FORMAT - self.file = new_file - util.files[str(self.file.path)] = self.file - else: - self.file = util.files[str(self.file.path)] - - self.file.add_source(self) - - self.name = f'Pop Development Branch {self.branch_name}' - self.uris = [f'{BASE_URL}/{self.branch_url}'] - self.suites = [util.DISTRO_CODENAME] - self.components = [BASE_COMPS] - - key = SourceKey(name='popdev') - key.load_key_data(url=BASE_KEYURL) - self.key = key - self.signed_by = str(self.key.path) - - self.prefs_path = self.prefs_dir / f'pop-os-staging-{self.branch_name}' - self.prefs = self.prefs_path - - self.enabled = True diff --git a/archive/repolib/shortcuts/ppa.py b/archive/repolib/shortcuts/ppa.py deleted file mode 100644 index 624ac4e..0000000 --- a/archive/repolib/shortcuts/ppa.py +++ /dev/null @@ -1,274 +0,0 @@ -#!/usr/bin/python3 - -""" -Copyright (c) 2022, Ian Santopietro -All rights reserved. - -This file is part of RepoLib. - -RepoLib is free software: you can redistribute it and/or modify -it under the terms of the GNU Lesser General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -RepoLib is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License -along with RepoLib. If not, see . -""" - -import logging - -from repolib.key import SourceKey - -from ..source import Source, SourceError -from ..file import SourceFile -from .. import util - -try: - from launchpadlib.launchpad import Launchpad - from lazr.restfulclient.errors import BadRequest, NotFound, Unauthorized -except ImportError: - raise SourceError( - 'Missing optional dependency "launchpadlib". Try `sudo apt install ' - 'python3-launchpadlib` to install it.' - ) - -BASE_FORMAT = util.SourceFormat.LEGACY -BASE_URL = 'http://ppa.launchpad.net' -BASE_DIST = 'ubuntu' -BASE_COMPS = 'main' - -DEFAULT_FORMAT = util.SourceFormat.LEGACY - -prefix = 'ppa' -delineator = ':' - -class PPASource(Source): - """ PPA Source shortcut - - These are given in the format ppa:owner/name. Much of this code is adapted - from SoftwareProperties. - - Arguments: - shortcut (str): The ppa: shortcut to process - fetch_data (bool): Whether to try and fetch metadata from Launchpad. - """ - - default_format = BASE_FORMAT - - @staticmethod - def validator(shortcut:str) -> bool: - """Determine whether a PPA shortcut is valid. - - Arguments: - shortcut(str): The shortcut to validate - - Returns: bool - `True` if the PPA is valid, otherwise False - """ - - if shortcut.startswith(f'{prefix}:'): - shortlist = shortcut.split('/') - if len(shortlist) > 1: - return True - return False - - def __init__(self, *args, line='', fetch_data=True, **kwargs): - if line: - if not line.startswith('ppa:'): - raise SourceError(f'The PPA shortcut {line} is malformed') - super().__init__(args, kwargs) - self.log = logging.getLogger(__name__) - self.line = line - self.ppa = None - self.twin_source = True - self._displayname = '' - self._description = '' - if line: - self.load_from_shortcut(self.line) - - def get_description(self) -> str: - output:str = '' - output += self.displayname - output += '\n\n' - output += self.description - return output - - def load_from_data(self, data: list) -> None: - self.load_from_shortcut(shortcut=data[0]) - - def load_from_shortcut(self, shortcut:str='', meta:bool=True, key:bool=True) -> None: - """Translates the shortcut line into a full repo. - - Arguments: - shortcut(str): The shortcut to load, if one hasn't been loaded yet. - meta(bool): Whether to fetch repo metadata from Launchpad - key(bool): Whether to fetch and install a signing key - """ - self.reset_values() - if shortcut: - self.line = shortcut - - if not self.line: - raise SourceError('No PPA shortcut provided') - - if not self.validator(self.line): - raise SourceError(f'The line {self.line} is malformed') - - line = self.line.replace(prefix + delineator, '') - self.info_parts = line.split('/') - ppa_owner = self.info_parts[0] - ppa_name = self.info_parts[1] - - self.ident = f'{prefix}-{ppa_owner}-{ppa_name}' - if f'{self.ident}.{BASE_FORMAT.value}' not in util.files: - new_file = SourceFile(name=self.ident) - new_file.format = BASE_FORMAT - self.file = new_file - util.files[str(self.file.path)] = self.file - else: - self.file = util.files[str(self.file.path)] - - self.file.add_source(self) - - self.name = self.ident - self.uris = [f'{BASE_URL}/{ppa_owner}/{ppa_name}/{BASE_DIST}'] - self.suites = [util.DISTRO_CODENAME] - self.components = [BASE_COMPS] - - if meta or key: - self.ppa = get_info_from_lp(ppa_owner, ppa_name) - self.displayname = self.ppa.displayname - self.description = self.ppa.description - - if self.ppa and meta: - self.name = self.ppa.displayname - - if self.ppa and key: - repo_key = SourceKey(name=self.ident) - if str(repo_key.path) not in util.keys: - repo_key.load_key_data(fingerprint=self.ppa.fingerprint) - util.keys[str(repo_key.path)] = repo_key - self.key:SourceKey = repo_key - else: - self.key = util.keys[repo_key.path] - self.signed_by = str(self.key.path) - - self.enabled = True - - @property - def displayname(self) -> str: - """The name of the PPA provided by launchpad""" - if self._displayname: - return self._displayname - if self.ppa: - self._displayname = self.ppa.displayname - return self._displayname - - @displayname.setter - def displayname(self, displayname) -> None: - """Cache this for use without hitting LP""" - self._displayname = displayname - - @property - def description(self) -> str: - """The description of the PPA provided by Launchpad""" - if self._description: - return self._description - if self.ppa: - self._description = self.ppa.description - return self._description - - @description.setter - def description(self, desc) -> None: - """Cache this for use without hitting LP""" - self._description = desc - -class PPA: - """ An object to fetch data from PPAs. - - Portions of this class were adapted from Software Properties - """ - - def __init__(self, teamname, ppaname): - self.teamname = teamname - self.ppaname = ppaname - self._lap = None - self._lpteam = None - self._lpppa = None - self._signing_key_data = None - self._fingerprint = None - - @property - def lap(self): - """ The Launchpad Object.""" - if not self._lap: - self._lap = Launchpad.login_anonymously( - f'{self.__module__}.{self.__class__.__name__}', - service_root='production', - version='devel' - ) - return self._lap - - @property - def lpteam(self): - """ The Launchpad object for the PPA's owner.""" - if not self._lpteam: - try: - self._lpteam = self.lap.people(self.teamname) # type: ignore (This won't actually be unbound because of the property) - except NotFound as err: - msg = f'User/Team "{self.teamname}" not found' - raise SourceError(msg) from err - except Unauthorized as err: - msg = f'Invalid user/team name "{self.teamname}"' - raise SourceError(msg) from err - return self._lpteam - - @property - def lpppa(self): - """ The Launchpad object for the PPA.""" - if not self._lpppa: - try: - self._lpppa = self.lpteam.getPPAByName(name=self.ppaname) - except NotFound as err: - msg = f'PPA "{self.teamname}/{self.ppaname}"" not found' - raise SourceError(msg) from err - except BadRequest as err: - msg = f'Invalid PPA name "{self.ppaname}"' - raise SourceError(msg) from err - return self._lpppa - - @property - def description(self) -> str: - """str: The description of the PPA.""" - return self.lpppa.description or '' - - @property - def displayname(self) -> str: - """ str: the fancy name of the PPA.""" - return self.lpppa.displayname or '' - - @property - def fingerprint(self): - """ str: the fingerprint of the signing key.""" - if not self._fingerprint: - self._fingerprint = self.lpppa.signing_key_fingerprint - return self._fingerprint - - -def get_info_from_lp(owner_name, ppa): - """ Attempt to get information on a PPA from launchpad over the internet. - - Arguments: - owner_name (str): The Launchpad user owning the PPA. - ppa (str): The name of the PPA - - Returns: - json: The PPA information as a JSON object. - """ - ppa = PPA(owner_name, ppa) - return ppa diff --git a/archive/repolib/source.py b/archive/repolib/source.py deleted file mode 100644 index 889221b..0000000 --- a/archive/repolib/source.py +++ /dev/null @@ -1,920 +0,0 @@ -#!/usr/bin/python3 - -""" -Copyright (c) 2022, Ian Santopietro -All rights reserved. - -This file is part of RepoLib. - -RepoLib is free software: you can redistribute it and/or modify -it under the terms of the GNU Lesser General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -RepoLib is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License -along with RepoLib. If not, see . -""" - -import logging -from pathlib import Path - -from debian import deb822 - -from .parsedeb import ParseDeb -from .key import SourceKey -from . import util - -DEFAULT_FORMAT = util.SourceFormat.LEGACY - -class SourceError(util.RepoError): - """ Exception from a source object.""" - - def __init__(self, *args, code=1, **kwargs): - """Exception with a source object - - Arguments: - code (:obj:`int`, optional, default=1): Exception error code. - """ - super().__init__(*args, **kwargs) - self.code = code - -class Source(deb822.Deb822): - """A DEB822 object representing a single software source. - - Attributes: - ident(str): The unique id for this source - name(str): The user-readable name for this source - enabled(bool): Whether or not the source is enabled - types([SourceType]): A list of repository types for this source - uris([str]): A list of possible URIs for this source - suites([str]): A list of enabled suites for this source - components([str]): A list of enabled components for this source - comments(str): Comments for this source - signed_by(Path): The path to this source's key file - file(SourceFile): The file this source belongs to - key(SourceKey): The key which signs this source - """ - - default_format = DEFAULT_FORMAT - - @staticmethod - def validator(shortcut:str) -> bool: - """Determine whether a deb line is valid. - - Arguments: - shortcut(str): The shortcut to validate - - Returns: bool - `True` if the PPA is valid, otherwise False - """ - shortcut_list:list = shortcut.split() - - if not shortcut.startswith('deb'): - return False - - if not len(shortcut_list) > 3: - return False - - if not util.validate_debline: - return False - - if len(shortcut_list) == 3 and '/' not in shortcut_list[-1]: - return False - - return True - - def __init__(self, *args, file=None, **kwargs) -> None: - """Initialize this source object""" - self.log = logging.getLogger(__name__) - super().__init__(*args, **kwargs) - self.reset_values() - self.file = file - self.twin_source = False - self.twin_enabled = False - - def __repr__(self): - """type: () -> str""" - # Append comments to the item - # if self.options: - - if self.comments: - self['Comments'] = '# ' - self['Comments'] += ' # '.join(self.comments) - - rep:str = '{%s}' % ', '.join(['%r: %r' % (k, v) for k, v in self.items()]) - - rep:str = '{' - for key in self: - rep += f"{util.PRETTY_PRINT}'{key}': '{self[key]}', " - - rep = rep[:-2] - rep += f"{util.PRETTY_PRINT.replace(' ', '')}" - rep += '}' - - if self.comments: - self.pop('Comments') - - return rep - - def __bool__(self) -> bool: - has_uri:bool = len(self.uris) > 0 - has_suite:bool = len(self.suites) > 0 - has_component:bool = len(self.components) > 0 - - if has_uri and has_suite and has_component: - return True - return False - - - def get_description(self) -> str: - """Get a UI-compatible description for a source. - - Returns: (str) - The formatted description. - """ - return self.name - - def reset_values(self) -> None: - """Reset the default values for all attributes""" - self.log.info('Resetting source info') - self.ident = '' - self.name = '' - self.enabled = True - self.types = [util.SourceType.BINARY] - self.uris = [] - self.suites = [] - self.components = [] - self.comments = [] - self.signed_by = None - self.architectures = '' - self.languages = '' - self.targets = '' - self.pdiffs = '' - self.by_hash = '' - self.allow_insecure = '' - self.allow_weak = '' - self.allow_downgrade_to_insecure = '' - self.trusted = '' - self.signed_by = '' - self.check_valid_until = '' - self.valid_until_min = '' - self.valid_until_max = '' - self.prefs = '' - self._update_legacy_options() - self.file = None - self.key = None - - def load_from_data(self, data:list) -> None: - """Loads source information from the provided data - - Should correctly load either a lecagy Deb line (optionally with - preceeding comment) or a DEB822 source. - - Arguments: - data(list): the data to load into the source. - """ - self.log.info('Loading source from data') - self.reset_values() - - if util.validate_debline(data[0]): # Legacy Source - if len(data) > 1: - raise SourceError( - f'The source is a legacy source but contains {len(data)} entries. ' - 'It may only contain one entry.' - ) - deb_parser = ParseDeb() - parsed_debline = deb_parser.parse_line(data[0]) - self.ident = parsed_debline['ident'] - self.name = parsed_debline['name'] - self.enabled = parsed_debline['enabled'] - self.types = [parsed_debline['repo_type']] - self.uris = [parsed_debline['uri']] - self.suites = [parsed_debline['suite']] - self.components = parsed_debline['components'] - for key in parsed_debline['options']: - self[key] = parsed_debline['options'][key] - self._update_legacy_options() - for comment in parsed_debline['comments']: - self.comments.append(comment) - if self.comments == ['']: - self.comments = [] - - if not self.name: - self.name = self.generate_default_name() - - if self.signed_by: - self.load_key() - return - - # DEB822 Source - super().__init__(sequence=data) - if self.signed_by: - self.load_key() - return - - @property - def sourcecode_enabled(self) -> bool: - """`True` if this source also provides source code, otherwise `False`""" - if util.SourceType.SOURCECODE in self.types: - return True - return False - - @sourcecode_enabled.setter - def sourcecode_enabled(self, enabled) -> None: - """Accept a variety of input values""" - types = [util.SourceType.BINARY] - if enabled in util.true_values: - types.append(util.SourceType.SOURCECODE) - self.types = types - - - def generate_default_ident(self, prefix='') -> str: - """Generates a suitable ID for the source - - Returns: str - A sane default-id - """ - ident:str = '' - if len(self.uris) > 0: - uri:str = self.uris[0].replace('/', ' ') - uri_list:list = uri.split() - uri_str:str = '-'.join(uri_list[1:]) - branch_name:str = util.scrub_filename(uri_str) - ident = f'{prefix}{branch_name}' - ident += f'-{self.types[0].ident()}' - try: - if not self['X-Repolib-ID']: - self['X-Repolib-ID'] = ident - except KeyError: - self['X-Repolib-ID'] = ident - return ident - - def generate_default_name(self) -> str: - """Generate a default name based on the ident - - Returns: str - A name based on the ident - """ - name:str = self.ident - try: - name = self['X-Repolib-Name'] - except KeyError: - self['X-Repolib-Name'] = self.ident - return self['X-Repolib-Name'] - - if not name: - self['X-Repolib-Name'] = self.ident - - return self['X-Repolib-Name'] - - def load_key(self, ignore_errors:bool = True) -> None: - """Finds and loads the signing key from the system - - Arguments: - ignore_errors(bool): If `False`, throw a SourceError exception if - the key can't be found/doesn't exist (Default: `True`) - """ - self.log.info('Finding key for source %s', self.ident) - if not self.signed_by: - if ignore_errors: - self.log.warning('No key configured for source %s', self.ident) - else: - raise SourceError('No key configured for source {self.ident}') - - if self.signed_by not in util.keys: - new_key = SourceKey() - new_key.reset_path(path=self.signed_by) - self.key = new_key - util.keys[str(new_key.path)] = new_key - else: - self.key = util.keys[self.signed_by] - - def save(self) -> None: - """Proxy method to save the source""" - if not self.file == None: - self.file.save() - - def output_legacy(self) -> str: - """Outputs a legacy representation of this source - - Note: this is expected to fail if there is more than one type, URI, or - Suite; the one-line format does not support having multiple of these - properties. - - Returns: str - The source output formatted as Legacy - """ - return self.legacy - - def output_822(self) -> str: - """Outputs a DEB822 representation of this source - - Returns: str - The source output formatted as Deb822 - """ - return self.deb822 - - def output_ui(self) -> str: - """Outputs a string representation of this source for use in UIs - - Returns: str - The source output string - """ - return self.ui - - def prop_append(self, prop:list, item:str) -> None: - """Appends an item to a list property of this source. - NOTE: List properties are `types`, `uris`, `suites`, and `components`. - - Arguments: - prop(list): The property on which to append the item. - item(str): The item to append to the propery - """ - _list = prop - _list.append(item) - prop = _list - - def tasks_save(self, *args, **kwargs) -> None: - """Extra tasks to perform when saving a source""" - return - - ## Properties are stored/retrieved from the underlying Deb822 dict - @property - def has_required_parts(self) -> bool: - """(RO) True if all required attributes are set, otherwise false.""" - required_parts = ['uris', 'suites', 'ident'] - - for attr in required_parts: - if len(getattr(self, attr)) < 1: - return False - - return True - - - @property - def ident(self) -> str: - """The ident for this source within the file""" - try: - return self['X-Repolib-ID'] - except KeyError: - return '' - - - @ident.setter - def ident(self, ident: str) -> None: - ident = util.scrub_filename(ident) - self['X-Repolib-ID'] = ident - - - @property - def name(self) -> str: - """The human-friendly name for this source""" - try: - _name = self['X-Repolib-Name'] - except KeyError: - _name = '' - - if not _name: - self.generate_default_name() - return self['X-Repolib-Name'] - - @name.setter - def name(self, name: str) -> None: - self['X-Repolib-Name'] = name - - - @property - def enabled(self) -> util.AptSourceEnabled: - """Whether or not the source is enabled/active""" - try: - enabled = self['Enabled'] in util.true_values - except KeyError: - return util.AptSourceEnabled.FALSE - - if enabled and self.has_required_parts: - return util.AptSourceEnabled.TRUE - return util.AptSourceEnabled.FALSE - - @enabled.setter - def enabled(self, enabled) -> None: - """For convenience, accept a wide varietry of input value types""" - self['Enabled'] = 'no' - if enabled in util.true_values: - self['Enabled'] = 'yes' - - - @property - def types(self) -> list: - """The list of source types for this source""" - _types:list = [] - try: - for sourcetype in self['types'].split(): - _types.append(util.SourceType(sourcetype)) - except KeyError: - pass - return _types - - @types.setter - def types(self, types: list) -> None: - """Turn this list into a string of values for storage""" - self['Types'] = '' - _types:list = [] - for sourcetype in types: - if sourcetype not in _types: - _types.append(sourcetype) - for sourcetype in _types: - self['Types'] += f'{sourcetype.value} ' - self['Types'] = self['Types'].strip() - - - @property - def uris(self) -> list: - """The list of URIs for this source""" - try: - return self['URIs'].split() - except KeyError: - return [] - - @uris.setter - def uris(self, uris: list) -> None: - self['URIs'] = ' '.join(uris).strip() - - - @property - def suites(self) -> list: - """The list of URIs for this source""" - try: - return self['Suites'].split() - except KeyError: - return [] - - @suites.setter - def suites(self, suites: list) -> None: - self['Suites'] = ' '.join(suites).strip() - - - @property - def components(self) -> list: - """The list of URIs for this source""" - try: - return self['Components'].split() - except KeyError: - return [] - - @components.setter - def components(self, components: list) -> None: - self['Components'] = ' '.join(components).strip() - - - @property - def options(self) -> dict: - """The options for this source""" - return self._options - - @options.setter - def options(self, options:dict) -> None: - if 'Signed-By' in options: - self.signed_by = options['Signed-By'] - if self.signed_by: - options.pop('Signed-By') - self._options = options - - @property - def prefs(self): - """The path to any apt preferences files for this source.""" - try: - prefs = self['X-Repolib-Prefs'] - except KeyError: - prefs = '' - - if prefs: - return Path(prefs) - return Path() - - @prefs.setter - def prefs(self, prefs): - """Accept a str or a Path-like object""" - try: - del self['X-Repolib-Prefs'] - except KeyError: - pass - - if prefs: - prefs_str = str(prefs) - self['X-Repolib-Prefs'] = prefs_str - - - ## Option properties - - @property - def architectures (self) -> str: - """architectures option""" - try: - return self['Architectures'] - except KeyError: - return '' - - @architectures.setter - def architectures(self, data) -> None: - try: - self.pop('Architectures') - except KeyError: - pass - - if data: - self['Architectures'] = data - self._update_legacy_options() - - - @property - def languages (self) -> str: - """languages option""" - try: - return self['Languages'] - except KeyError: - return '' - - @languages.setter - def languages(self, data) -> None: - try: - self.pop('Languages') - except KeyError: - pass - - if data: - self['Languages'] = data - self._update_legacy_options() - - - @property - def targets (self) -> str: - """targets option""" - try: - return self['Targets'] - except KeyError: - return '' - - @targets.setter - def targets(self, data) -> None: - try: - self.pop('Targets') - except KeyError: - pass - - if data: - self['Targets'] = data - self._update_legacy_options() - - - @property - def pdiffs (self) -> str: - """pdiffs option""" - try: - return self['Pdiffs'] - except KeyError: - return '' - - @pdiffs.setter - def pdiffs(self, data) -> None: - try: - self.pop('Pdiffs') - except KeyError: - pass - - if data: - self['Pdiffs'] = data - self._update_legacy_options() - - - @property - def by_hash (self) -> str: - """by_hash option""" - try: - return self['By-Hash'] - except KeyError: - return '' - - @by_hash.setter - def by_hash(self, data) -> None: - try: - self.pop('By-Hash') - except KeyError: - pass - - if data: - self['By-Hash'] = data - self._update_legacy_options() - - - @property - def allow_insecure (self) -> str: - """allow_insecure option""" - try: - return self['Allow-Insecure'] - except KeyError: - return '' - - @allow_insecure.setter - def allow_insecure(self, data) -> None: - try: - self.pop('Allow-Insecure') - except KeyError: - pass - - if data: - self['Allow-Insecure'] = data - self._update_legacy_options() - - - @property - def allow_weak (self) -> str: - """allow_weak option""" - try: - return self['Allow-Weak'] - except KeyError: - return '' - - @allow_weak.setter - def allow_weak(self, data) -> None: - try: - self.pop('Allow-Weak') - except KeyError: - pass - - if data: - self['Allow-Weak'] = data - self._update_legacy_options() - - - @property - def allow_downgrade_to_insecure (self) -> str: - """allow_downgrade_to_insecure option""" - try: - return self['Allow-Downgrade-To-Insecure'] - except KeyError: - return '' - - @allow_downgrade_to_insecure.setter - def allow_downgrade_to_insecure(self, data) -> None: - try: - self.pop('Allow-Downgrade-To-Insecure') - except KeyError: - pass - - if data: - self['Allow-Downgrade-To-Insecure'] = data - self._update_legacy_options() - - - @property - def trusted (self) -> str: - """trusted option""" - try: - return self['Trusted'] - except KeyError: - return '' - - @trusted.setter - def trusted(self, data) -> None: - try: - self.pop('Trusted') - except KeyError: - pass - - if data: - self['Trusted'] = data - self._update_legacy_options() - - - @property - def signed_by (self) -> str: - """signed_by option""" - try: - return self['Signed-By'] - except KeyError: - return '' - - @signed_by.setter - def signed_by(self, data) -> None: - try: - self.pop('Signed-By') - except KeyError: - pass - - if data: - self['Signed-By'] = data - self._update_legacy_options() - - - @property - def check_valid_until (self) -> str: - """check_valid_until option""" - try: - return self['Check-Valid-Until'] - except KeyError: - return '' - - @check_valid_until.setter - def check_valid_until(self, data) -> None: - try: - self.pop('Check-Valid-Until') - except KeyError: - pass - - if data: - self['Check-Valid-Until'] = data - self._update_legacy_options() - - - @property - def valid_until_min (self) -> str: - """valid_until_min option""" - try: - return self['Valid-Until-Min'] - except KeyError: - return '' - - @valid_until_min.setter - def valid_until_min(self, data) -> None: - try: - self.pop('Valid-Until-Min') - except KeyError: - pass - - if data: - self['Valid-Until-Min'] = data - self._update_legacy_options() - - - @property - def valid_until_max (self) -> str: - """valid_until_max option""" - try: - return self['Valid-Until-Max'] - except KeyError: - return '' - - @valid_until_max.setter - def valid_until_max(self, data) -> None: - try: - self.pop('Valid-Until-Max') - except KeyError: - pass - - if data: - self['Valid-Until-Max'] = data - self._update_legacy_options() - - @property - def default_mirror(self) -> str: - """The default mirror/URI for the source""" - try: - return self['X-Repolib-Default-Mirror'] - except KeyError: - return '' - - @default_mirror.setter - def default_mirror(self, mirror) -> None: - if mirror: - self['X-Repolib-Default-Mirror'] = mirror - else: - self['X-Repolib-Default-Mirror'] = '' - - - ## Output Properties - @property - def deb822(self) -> str: - """The DEB822 representation of this source""" - self._update_legacy_options() - # comments get handled separately because they're a list, and list - # properties don't support .append() - if self.comments: - self['X-Repolib-Comments'] = '# ' - self['X-Repolib-Comments'] += ' # '.join(self.comments) - _deb822 = self.dump() - if self.comments: - self.pop('X-Repolib-Comments') - if _deb822: - return _deb822 - return '' - - @property - def ui(self) -> str: - """The UI-friendly representation of this source""" - self._update_legacy_options() - _ui_list:list = self.deb822.split('\n') - ui_output: str = f'{self.ident}:\n' - for line in _ui_list: - key = line.split(':')[0] - if key not in util.output_skip_keys: - if line: - ui_output += f'{line}\n' - for key in util.keys_map: - ui_output = ui_output.replace(key, util.keys_map[key]) - return ui_output - - @property - def legacy(self) -> str: - """The legacy/one-line format representation of this source""" - self._update_legacy_options() - - if str(self.prefs) != '.': - raise SourceError( - 'Apt Preferences files can only be used with DEB822-format sources.' - ) - - sourcecode = self.sourcecode_enabled - if len(self.types) > 1: - self.twin_source = True - self.types = [util.SourceType.BINARY] - sourcecode = True - - legacy = '' - - legacy += self._generate_legacy_output() - if self.twin_source: - legacy += '\n' - legacy += self._generate_legacy_output(sourcecode=True, enabled=sourcecode) - - return legacy - - def _generate_legacy_output(self, sourcecode=False, enabled=True) -> str: - """Generate a string of the current source in legacy format""" - legacy = '' - - if len(self.types) > 1: - self.twin_source = True - self.types = [util.SourceType.BINARY] - for attr in ['types', 'uris', 'suites']: - if len(getattr(self, attr)) > 1: - msg = f'The source has too many {attr}.' - msg += f'Legacy-format sources support one {attr[:-1]} only.' - raise SourceError(msg) - - if not self.enabled.get_bool() and not sourcecode: - legacy += '# ' - - if sourcecode and not enabled: - legacy += '# ' - - if sourcecode: - legacy += 'deb-src ' - else: - legacy += self.types[0].value - legacy += ' ' - - options_string = self._legacy_options() - if options_string: - legacy += '[' - legacy += options_string - legacy = legacy.strip() - legacy += '] ' - - legacy += f'{self.uris[0]} ' - legacy += f'{self.suites[0]} ' - - for component in self.components: - legacy += f'{component} ' - - legacy += f' ## X-Repolib-Name: {self.name}' - legacy += f' # X-Repolib-ID: {self.ident}' - if self.comments: - for comment in self.comments: - legacy += f' # {comment}' - - return legacy - - def _legacy_options(self) -> str: - """Turn the current options into a oneline-style string - - Returns: str - The one-line-format options string - """ - options_str = '' - for key in self.options: - if self.options[key] != '': - options_str += f'{key}={self.options[key].replace(" ", ",")} ' - return options_str - - def _update_legacy_options(self) -> None: - """Updates the current set of legacy options""" - self.options = { - 'arch': self.architectures, - 'lang': self.languages, - 'target': self.targets, - 'pdiffs': self.pdiffs, - 'by-hash': self.by_hash, - 'allow-insecure': self.allow_insecure, - 'allow-weak': self.allow_weak, - 'allow-downgrade-to-insecure': self.allow_downgrade_to_insecure, - 'trusted': self.trusted, - 'signed-by': self.signed_by, - 'check-valid-until': self.check_valid_until, - 'valid-until-min': self.valid_until_min, - 'valid-until-max': self.valid_until_max, - } \ No newline at end of file diff --git a/archive/repolib/system.py b/archive/repolib/system.py deleted file mode 100644 index b22ef09..0000000 --- a/archive/repolib/system.py +++ /dev/null @@ -1,73 +0,0 @@ -#!/usr/bin/python3 - -""" -Copyright (c) 2022, Ian Santopietro -All rights reserved. - -This file is part of RepoLib. - -RepoLib is free software: you can redistribute it and/or modify -it under the terms of the GNU Lesser General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -RepoLib is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License -along with RepoLib. If not, see . -""" - -import logging - -from pathlib import Path - -from . import util -from .file import SourceFile -from .source import Source -from .shortcuts import popdev, ppa - - -log = logging.getLogger(__name__) - -def load_all_sources() -> None: - """Loads all of the sources present on the system.""" - log.info('Loading all sources') - - util.sources.clear() - util.files.clear() - util.keys.clear() - util.errors.clear() - - sources_path = Path(util.SOURCES_DIR) - sources_files = sources_path.glob('*.sources') - legacy_files = sources_path.glob('*.list') - - for file in sources_files: - try: - sourcefile = SourceFile(name=file.stem) - log.debug('Loading %s', file) - sourcefile.load() - if file.name not in util.files: - util.files[file.name] = sourcefile - - except Exception as err: - util.errors[file.name] = err - - for file in legacy_files: - try: - sourcefile = SourceFile(name=file.stem) - sourcefile.load() - util.files[file.name] = sourcefile - except Exception as err: - util.errors[file.name] = err - - for f in util.files: - file = util.files[f] - for source in file.sources: - if source.ident in util.sources: - source.ident = f'{file.name}-{source.ident}' - source.file.save() - util.sources[source.ident] = source diff --git a/archive/repolib/unittest/__init__.py b/archive/repolib/unittest/__init__.py deleted file mode 100644 index e69de29..0000000 diff --git a/archive/repolib/unittest/test_key.py b/archive/repolib/unittest/test_key.py deleted file mode 100644 index 977324b..0000000 --- a/archive/repolib/unittest/test_key.py +++ /dev/null @@ -1,142 +0,0 @@ -#!/usr/bin/python3 - -""" -Copyright (c) 2022, Ian Santopietro -All rights reserved. - -This file is part of RepoLib. - -RepoLib is free software: you can redistribute it and/or modify -it under the terms of the GNU Lesser General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -RepoLib is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License -along with RepoLib. If not, see . -""" - -import unittest - -from ..key import SourceKey -from .. import util, system -from .. import set_testing - -# System76 Signing PubKey, for test import -KEY_DATA = ( - '-----BEGIN PGP PUBLIC KEY BLOCK-----\n\nmQINBFlL+3MBEADdNM9Xy2t3EtKU1i3R1o' - '1OCgJqLiDm8OZZq47InYID8oAPKRjd\n0UDVJTrvfsB4oJH97VRi2hGv2xmc19OaFE/NsQBZW/' - '7/3ypLr8eyaNgvscsmG/WN\ncM1cbMZtwd1b0JOr3bNTzp6WKRI3jo9uRw7duM8FwPjKm76Lbo' - 'DQbAR+4Szm3O8x\n/om8Gs1MRPUkY2dVz5KzednFLHwy7qnUXR3WRB5K1L9EBZkFDDNqnyViUI' - 'rE4bTm\nBC9mTg/Xfw/QXUFYz3t/YTYduAU0o1q2yei+8tVAJKh7H9t3PrQ95l3RUUcaAvba\n' - 'A9zlCrI8fonpxu7eSpkqzT4uCkfxdLVwittl1DumKTEkSXDQ5txY21igbSZZQwBA\nZf9MnFhJ' - 'fPsEIq2YHRc1FBcQxiAIpnGizv7FgYY5FxmZQ7592dMQOZ00h+lDSQug\nNMxloHCogaXR038u' - 'IKGTQnQEVcT46FtTRkLMSvbigy+RVSchdu9MEBBPgD3vSv53\nNEobXsLiZ9hF6Hk7XI2WxP5j' - '1zWTPmzxvf9NDOWz2Sw9Z+ilf252LXoxZQaMngp8\nXL32uvw7q+mjB6F1W/qpe3b32uu7eGNr' - 'DWJ5veE808hpXXj803TllmRUfMGUrtY9\nk7uUTQQWtrJ5uZ0QmsTk1oJHCPIUjjuiNtQfq28+' - 'bfg8FEJ/F1N1mB0IvwARAQAB\ntCxQb3AgT1MgKElTTyBTaWduaW5nIEtleSkgPGluZm9Ac3lz' - 'dGVtNzYuY29tPokC\nNwQTAQIAIgUCWUv7cwIbAwYLCQgHAwIGFQgCCQoLBBYCAwECHgECF4AA' - 'CgkQIE3Y\nrsM6ev8kXw/4p/8fOH8wM59ZoU0t1+fv3O8dYaDdTVTVIEno9snrsx5A5tbMu59r' - '\nHoBaxGenv/PB0l8yANhRX+HVmU/l0Sj0lTlEkYzgH/IT2Ne60s1ETgI7DlgSuYyP\nH8wq61' - '85+2DyE2+R/XcXGq0I++QUq1Y6rS+B4KIyYcgpJotcVNFaZiwuJZE31uLg\nkVMZrm1oObHear' - '7P2JQTbgsENMZDJEhQBCGKVdnAfVdKUeUrd07syr0cDe3kwY9o\ncNc00bhIh23cLTJE2omok9' - 'yCsXoeFJlPMyZw8WvEa5oaYWzP4Yw7nF8/27JTzZ70\nDjK2D2xoTkr0cP87LtZulS6FC3lxLu' - 'Z6hSaxsqoBH8Dd1uyYVEzLDsIRMtSHsXk+\n3kLrr1p7/7/vjGShlYkbLtP4jWnlHc6vSxIzm/' - 'MQmQMCfjeo3QH7GGw88mYtXngQ\n/Zna6wz0oL6pGM/4t90SCxTxRqCnoxMxzkcpt9n42bj79g' - 'rESOMH4wm3ExfuPk7I\nDtY+SqzIq0QvoPbC3XJLusWVgwUsRF2FpTTRTHEiWEMjWDKDVEyT4K' - '1k1k3f/gi2\n6LdtXwqDwzUvJJU5HYwVFywt+0jt5F0ZlTlPizz3iHw4gMLOielRShl+gZrU2U' - '0O\naj1Hyts9LymEKMUvRQGwMqCZcXo6sGjs59tTsfeGX16PTOyBri8eoLkCDQRZS/tz\nARAA' - 'pD9IWm4zS1AuBcOTuvh1E/ciKHGIUtW3JftD9ah8loEeckakgG5Xn9he1X6J\nyxPULpsptcCC' - 'cKXlw853ZQK9PLQJX6moWLH+qf2Zo3UAn/YEsWk+KsHoxPXHNUds\nu/j6UKkqEk8c7H92hUo8' - 'aWghO3p4HDVJ9KmGtueQ3jOv8Qun7Eh9cIo0A59cKmMv\njKUiYHLIJw8bkveQ8rVPul1ZHn56' - 'ORiBi58vm3tzjI4UWHQMjiKxXT6H5eG/f5K6\nuaK8lljh6n6jhdnQCpBcdtSIbhE/6YRv2+Ig' - 'L+BRssvprBtx4/sBwKjNNqzWPeGy\nUDHMiF88ETYqZ8DfukQ/e5XuaxjU41g/F8cw8BeVTBMv' - 'eb1YTyOoWcWvTL+hoBfS\nqYc/lvDHmmJ7/IgeMvUE6KoByP4ub5wX52mJTqgMC4GMhA04BC60' - 'B+NfVAXLh2pa\nTRJAHoWTDswOxbR6q9zPEFGZzV04B9Y96EavwMpT5IzG2fOPBwvdT0EDnt+v' - 'Q/iB\nc9O7CvkRTROAV+RoNCLY2XU8yNc/XxuI66PCE4Q96jW4uDzHvi6sPW/glsfRi2NT\nRW' - 'CO15KMVf0aypXeBpSbHIXIYGdXRQRpw980IW6PrElPpqZ5/DGbkXei5CuruF2R\nmltuu3MqYQ' - 'jcUvP9T7s0e5GAFgQFrR/8q29nVULq8IF4vzUAEQEAAYkCHwQYAQIA\nCQUCWUv7cwIbDAAKCR' - 'AgTdiuwzp6/wTGD/9Co4gEmTTOW++FneMMJo5K4WqeWVRg\ng1q5+yoVqgWq3k6lLsEC5kxR30' - '5BAAcvXo9XPKdo62ySYmhIFOpIz/TkeTUxDZaw\nsLtcBxXUME2L5j/1od1V9lxecUvLAgA11o' - '5Kb8TMKn5ZcmGhadtTLslWQcYsKqhw\nLaYQRlcxLDHYT8DXFkHgDhUMMbpt07dU5v5lIjgtGN' - 'HRhdS7/lCmSWOBtYapwpAH\nGYSmahN0zO36VHzOB5uwFue0tSoQiBEvLrCV/8ZtT2S5NkXaSm' - 'isz6B5Vr6DRtWI\nOamW5pMbSL8WQNQ99Kik05ctERjv2NgxI4JQo/a4KKthRrT4JlixXmrfJD' - 'uPyDPp\nRuTu1Elo6snoqWKQNf1sEPKvcv7EviNxBOhbTKivWrJXMnbOme7+UlNLcq7VAFp3\n' - 'x5hxk/ap0WqH/hs7+8jMBC8nS402MoM7EyLS0++kbOuEL/Prf3+JxFRqIu5Df77J\n+bUmTtKI' - 'CV43ikiVWmnP5OuJj2JPSOTR+rLxAQYpyHmo7HKXE63FbH1FVLgsT88+\nEW6VtI01I7EYmKQX' - 'EqQo52yfeHKDrQjGNVBWMKcXj0SVU+QQ1Ue/4yLwA+74VD2d\nfOyJI22NfTI+3SMAsMQ8L+WV' - 'QI+58bu7+iEqoEfHCXikE8BtTbJAN4Oob1lrjfOe\n5utH/lMP9suRWw==\n=NL3f\n-----EN' - 'D PGP PUBLIC KEY BLOCK-----\n' -) - -class KeyTestCase(unittest.TestCase): - def setUp(self): - set_testing() - self.key_data = KEY_DATA - self.keys_dir = util.KEYS_DIR - self.key_id = '204DD8AEC33A7AFF' - self.key_uids = ['Pop OS (ISO Signing Key) '] - self.key_length = '4096' - self.key_date = '1498151795' - - def test_import_ascii(self): - key = SourceKey(name='popdev') - key.load_key_data(ascii=self.key_data) - key_dict = key.gpg.list_keys()[0] - key_path = self.keys_dir / 'popdev-archive-keyring.gpg' - - self.assertEqual(key.path, key_path) - self.assertEqual(len(key.gpg.list_keys()), 1) - self.assertEqual(key_dict['keyid'], self.key_id) - self.assertEqual(key_dict['uids'], self.key_uids) - self.assertEqual(key_dict['length'], self.key_length) - self.assertEqual(key_dict['date'], self.key_date) - - def test_key_save_load(self): - print(self.keys_dir) - key_path = self.keys_dir / 'popdev-archive-keyring.gpg' - if key_path.exists(): - key_path.unlink() - - self.assertFalse(key_path.exists()) - key_save = SourceKey(name='popdev') - key_save.load_key_data(ascii=self.key_data) - key_save.save_gpg() - - self.assertTrue(key_save.path.exists()) - - key_load = SourceKey() - key_load.reset_path(name='popdev') - key_dict = key_load.gpg.list_keys()[0] - - self.assertEqual(key_load.path, key_path) - self.assertEqual(len(key_load.gpg.list_keys()), 1) - self.assertEqual(key_dict['keyid'], self.key_id) - self.assertEqual(key_dict['uids'], self.key_uids) - self.assertEqual(key_dict['length'], self.key_length) - self.assertEqual(key_dict['date'], self.key_date) - - def test_delete_key(self): - key_path = self.keys_dir / 'popdev-archive-keyring.gpg' - if key_path.exists(): - key_path.unlink() - - self.assertFalse(key_path.exists()) - - self.assertFalse(key_path.exists()) - key_save = SourceKey(name='popdev') - key_save.load_key_data(ascii=self.key_data) - - key_save.save_gpg() - - self.assertTrue(key_save.path.exists()) - - key_load = SourceKey() - key_load.reset_path(name='popdev') - key_load.delete_key() - - self.assertFalse(key_load.path.exists()) diff --git a/archive/repolib/unittest/test_parsedeb.py b/archive/repolib/unittest/test_parsedeb.py deleted file mode 100644 index 0a975a0..0000000 --- a/archive/repolib/unittest/test_parsedeb.py +++ /dev/null @@ -1,188 +0,0 @@ -#!/usr/bin/python3 - -""" -Copyright (c) 2019-2022, Ian Santopietro -All rights reserved. - -This file is part of RepoLib. - -RepoLib is free software: you can redistribute it and/or modify -it under the terms of the GNU Lesser General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -RepoLib is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License -along with RepoLib. If not, see . - -This is a library for parsing deb lines into deb822-format data. -""" - -import unittest - -from ..source import Source -from .. import util - -class DebTestCase(unittest.TestCase): - def test_normal_source(self): - source = Source() - source.load_from_data([ - 'deb http://example.com/ suite main' - ]) - source.generate_default_ident() - self.assertEqual(source.types, [util.SourceType.BINARY]) - self.assertTrue(source.enabled.get_bool()) - self.assertEqual(source.uris, ['http://example.com/']) - self.assertEqual(source.suites, ['suite']) - self.assertEqual(source.components, ['main']) - self.assertEqual(source.ident, 'example-com-binary') - - def test_source_with_multiple_components(self): - source = Source() - source.load_from_data([ - 'deb http://example.com/ suite main nonfree' - ]) - source.generate_default_ident() - self.assertEqual(source.suites, ['suite']) - self.assertEqual(source.components, ['main', 'nonfree']) - - def test_source_with_option(self): - source = Source() - source.load_from_data([ - 'deb [ arch=amd64 ] http://example.com/ suite main' - ]) - source.generate_default_ident() - self.assertEqual(source.uris, ['http://example.com/']) - self.assertEqual(source.architectures, 'amd64') - - def test_source_uri_with_brackets(self): - source = Source() - source.load_from_data([ - 'deb http://example.com/[release]/ubuntu suite main' - ]) - source.generate_default_ident() - self.assertEqual(source.uris, ['http://example.com/[release]/ubuntu']) - - def test_source_options_with_colons(self): - source = Source() - source.load_from_data([ - 'deb [ arch=arm:2 ] http://example.com/ suite main' - ]) - source.generate_default_ident() - self.assertEqual(source.uris, ['http://example.com/']) - self.assertEqual(source.architectures, 'arm:2') - - def test_source_with_multiple_option_values(self): - source = Source() - source.load_from_data([ - 'deb [ arch=armel,amd64 ] http://example.com/ suite main' - ]) - source.generate_default_ident() - self.assertEqual(source.uris, ['http://example.com/']) - self.assertEqual(source.architectures, 'armel amd64') - - def test_source_with_multiple_options(self): - source = Source() - source.load_from_data([ - 'deb [ arch=amd64 lang=en_US ] http://example.com/ suite main' - ]) - source.generate_default_ident() - self.assertEqual(source.uris, ['http://example.com/']) - self.assertEqual(source.architectures, 'amd64') - self.assertEqual(source.languages, 'en_US') - - def test_source_with_multiple_options_with_multiple_values(self): - source = Source() - source.load_from_data([ - 'deb [ arch=amd64,armel lang=en_US,en_CA ] ' - 'http://example.com/ suite main' - ]) - source.generate_default_ident() - self.assertEqual(source.uris, ['http://example.com/']) - self.assertEqual(source.architectures, 'amd64 armel') - self.assertEqual(source.languages, 'en_US en_CA') - - def test_source_uri_with_brackets_and_options(self): - source = Source() - source.load_from_data([ - 'deb [ arch=amd64 lang=en_US,en_CA ] ' - 'http://example][.com/[release]/ubuntu suite main' - ]) - source.generate_default_ident() - self.assertEqual(source.uris, ['http://example][.com/[release]/ubuntu']) - self.assertEqual(source.architectures, 'amd64') - self.assertEqual(source.languages, 'en_US en_CA') - - def test_source_uri_with_brackets_and_options_with_colons(self): - source = Source() - source.load_from_data([ - 'deb [ arch=amd64,arm:2 lang=en_US,en_CA ] ' - 'http://example][.com/[release]/ubuntu suite main' - ]) - source.generate_default_ident() - self.assertEqual(source.uris, ['http://example][.com/[release]/ubuntu']) - self.assertEqual(source.architectures, 'amd64 arm:2') - self.assertEqual(source.languages, 'en_US en_CA') - - def test_worst_case_sourcenario(self): - source = Source() - source.load_from_data([ - 'deb [ arch=amd64,arm:2,arm][ lang=en_US,en_CA ] ' - 'http://example][.com/[release:good]/ubuntu suite main restricted ' - 'nonfree not-a-component' - ]) - source.generate_default_ident() - self.assertEqual(source.uris, ['http://example][.com/[release:good]/ubuntu']) - self.assertEqual(source.suites, ['suite']) - self.assertEqual(source.components, [ - 'main', 'restricted', 'nonfree', 'not-a-component' - ]) - source.generate_default_ident() - self.assertEqual(source.architectures, 'amd64 arm:2 arm][') - self.assertEqual(source.languages, 'en_US en_CA') - - def test_source_code_source(self): - source = Source() - source.load_from_data([ - 'deb-src http://example.com/ suite main' - ]) - source.generate_default_ident() - self.assertEqual(source.types, [util.SourceType.SOURCECODE]) - - def test_disabled_source(self): - source = Source() - source.load_from_data([ - '# deb http://example.com/ suite main' - ]) - source.generate_default_ident() - self.assertFalse(source.enabled.get_bool()) - - def test_disabled_source_without_space(self): - source = Source() - source.load_from_data([ - '#deb http://example.com/ suite main' - ]) - source.generate_default_ident() - self.assertFalse(source.enabled.get_bool()) - - def test_source_with_trailing_comment(self): - source = Source() - source.load_from_data([ - 'deb http://example.com/ suite main # This is a comment' - ]) - source.generate_default_ident() - self.assertEqual(source.suites, ['suite']) - self.assertEqual(source.components, ['main']) - - def test_disabled_source_with_trailing_comment(self): - source = Source() - source.load_from_data([ - '# deb http://example.com/ suite main # This is a comment' - ]) - source.generate_default_ident() - self.assertEqual(source.suites, ['suite']) - self.assertEqual(source.components, ['main']) diff --git a/archive/repolib/unittest/test_popdev.py b/archive/repolib/unittest/test_popdev.py deleted file mode 100644 index 8207b09..0000000 --- a/archive/repolib/unittest/test_popdev.py +++ /dev/null @@ -1,43 +0,0 @@ -#!/usr/bin/python3 - -""" -Copyright (c) 2022, Ian Santopietro -All rights reserved. - -This file is part of RepoLib. - -RepoLib is free software: you can redistribute it and/or modify -it under the terms of the GNU Lesser General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -RepoLib is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License -along with RepoLib. If not, see . -""" - -import unittest - -from ..shortcuts import popdev -from .. import util - -class PopdevTestCase(unittest.TestCase): - - def test_ppa(self): - source = popdev.PopdevSource() - - # Verification data - uris_test = ['http://apt.pop-os.org/staging/master'] - signed_test = '/usr/share/keyrings/popdev-archive-keyring.gpg' - source.load_from_shortcut(shortcut='popdev:master') - - self.assertEqual(source.uris, uris_test) - self.assertEqual(source.ident, 'popdev-master') - self.assertEqual(source.suites, [util.DISTRO_CODENAME]) - self.assertEqual(source.components, ['main']) - self.assertEqual(source.types, [util.SourceType.BINARY]) - self.assertTrue(source.signed_by.endswith(signed_test)) \ No newline at end of file diff --git a/archive/repolib/unittest/test_ppa.py b/archive/repolib/unittest/test_ppa.py deleted file mode 100644 index 9b346cf..0000000 --- a/archive/repolib/unittest/test_ppa.py +++ /dev/null @@ -1,42 +0,0 @@ -#!/usr/bin/python3 - -""" -Copyright (c) 2022, Ian Santopietro -All rights reserved. - -This file is part of RepoLib. - -RepoLib is free software: you can redistribute it and/or modify -it under the terms of the GNU Lesser General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -RepoLib is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License -along with RepoLib. If not, see . -""" - -import unittest - -from ..shortcuts import ppa -from .. import util - -class PPATestCase(unittest.TestCase): - - def test_ppa(self): - source = ppa.PPASource() - - # Verification data - uris_test = ['http://ppa.launchpad.net/system76/pop/ubuntu'] - signed_test = '/usr/share/keyrings/ppa-system76-pop-archive-keyring.gpg' - source.load_from_shortcut(shortcut='ppa:system76/pop', meta=False, key=False) - - self.assertEqual(source.uris, uris_test) - self.assertEqual(source.ident, 'ppa-system76-pop') - self.assertEqual(source.suites, [util.DISTRO_CODENAME]) - self.assertEqual(source.components, ['main']) - self.assertEqual(source.types, [util.SourceType.BINARY]) diff --git a/archive/repolib/unittest/test_source.py b/archive/repolib/unittest/test_source.py deleted file mode 100644 index ae7f38e..0000000 --- a/archive/repolib/unittest/test_source.py +++ /dev/null @@ -1,245 +0,0 @@ -#!/usr/bin/python3 - -""" -Copyright (c) 2022, Ian Santopietro -All rights reserved. - -This file is part of RepoLib. - -RepoLib is free software: you can redistribute it and/or modify -it under the terms of the GNU Lesser General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -RepoLib is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License -along with RepoLib. If not, see . -""" - -import unittest - -from .. import file, util, source - -class SourceTestCase(unittest.TestCase): - def setUp(self): - util.set_testing() - self.source = source.Source() - self.source.ident = 'test' - self.source.name = 'Test Source' - self.source.enabled = True - self.source.types = [util.SourceType.BINARY, util.SourceType.SOURCECODE] - self.source.uris = ['http://example.com/ubuntu', 'http://example.com/mirror'] - self.source.suites = ['suite', 'suite-updates'] - self.source.components = ['main', 'contrib', 'nonfree'] - self.source.architectures = 'amd64 armel' - self.source.languages = 'en_US en_CA' - self.file = file.SourceFile(name=self.source.ident) - self.file.add_source(self.source) - self.source.file = self.file - - self.source_legacy = source.Source() - self.source_legacy.ident = 'test-legacy' - self.source_legacy.name = 'Test Legacy Source' - self.source_legacy.enabled = True - self.source_legacy.types = [util.SourceType.BINARY] - self.source_legacy.uris = ['http://example.com/ubuntu'] - self.source_legacy.suites = ['suite'] - self.source_legacy.components = ['main', 'contrib', 'nonfree'] - self.source_legacy.architectures = 'amd64 armel' - self.source_legacy.languages = 'en_US en_CA' - self.source_legacy.file = file.SourceFile(name=self.source_legacy.ident) - self.source_legacy.file.format = util.SourceFormat.LEGACY - - - def test_default_source_data(self): - self.assertEqual(self.source.name, 'Test Source') - self.assertTrue(self.source.enabled.get_bool()) - self.assertEqual( - self.source.types, - [util.SourceType.BINARY, util.SourceType.SOURCECODE] - ) - self.assertTrue(self.source.sourcecode_enabled) - self.assertEqual( - self.source.uris, - ['http://example.com/ubuntu', 'http://example.com/mirror'] - ) - self.assertEqual( - self.source.suites, - ['suite', 'suite-updates'] - ) - self.assertEqual( - self.source.components, - ['main', 'contrib', 'nonfree'] - ) - self.assertEqual(self.source.architectures, 'amd64 armel') - self.assertEqual(self.source.languages, 'en_US en_CA') - self.assertEqual(self.source.file.path.name, 'test.sources') - - def test_output_822(self): - source_string = ( - 'X-Repolib-ID: test\n' - 'X-Repolib-Name: Test Source\n' - 'Enabled: yes\n' - 'Types: deb deb-src\n' - 'URIs: http://example.com/ubuntu http://example.com/mirror\n' - 'Suites: suite suite-updates\n' - 'Components: main contrib nonfree\n' - 'Architectures: amd64 armel\n' - 'Languages: en_US en_CA\n' - ) - legacy_source_string = ( - 'X-Repolib-ID: test-legacy\n' - 'X-Repolib-Name: Test Legacy Source\n' - 'Enabled: yes\n' - 'Types: deb\n' - 'URIs: http://example.com/ubuntu\n' - 'Suites: suite\n' - 'Components: main contrib nonfree\n' - 'Architectures: amd64 armel\n' - 'Languages: en_US en_CA\n' - ) - self.assertEqual(self.source.deb822, source_string) - self.assertEqual(self.source_legacy.deb822, legacy_source_string) - - def test_output_ui(self): - source_string = ( - 'test:\n' - 'Name: Test Source\n' - 'Enabled: yes\n' - 'Types: deb deb-src\n' - 'URIs: http://example.com/ubuntu http://example.com/mirror\n' - 'Suites: suite suite-updates\n' - 'Components: main contrib nonfree\n' - 'Architectures: amd64 armel\n' - 'Languages: en_US en_CA\n' - '' - ) - legacy_source_string = ( - 'test-legacy:\n' - 'Name: Test Legacy Source\n' - 'Enabled: yes\n' - 'Types: deb\n' - 'URIs: http://example.com/ubuntu\n' - 'Suites: suite\n' - 'Components: main contrib nonfree\n' - 'Architectures: amd64 armel\n' - 'Languages: en_US en_CA\n' - ) - self.assertEqual(self.source.ui, source_string) - self.assertEqual(self.source_legacy.ui, legacy_source_string) - - def test_output_legacy(self): - source_string = ( - 'deb [arch=amd64,armel lang=en_US,en_CA] http://example.com/ubuntu suite main contrib nonfree ## X-Repolib-Name: Test Legacy Source # X-Repolib-ID: test-legacy' - ) - self.assertEqual(self.source_legacy.legacy, source_string) - - def test_enabled(self): - self.source.enabled = False - self.assertFalse(self.source.enabled.get_bool()) - - def test_sourcecode_enabled(self): - self.source.sourcecode_enabled = False - self.assertEqual(self.source.types, [util.SourceType.BINARY]) - - def test_dict_access(self): - self.assertEqual(self.source['X-Repolib-ID'], 'test') - self.assertEqual(self.source['X-Repolib-Name'], 'Test Source') - self.assertEqual(self.source['Enabled'], 'yes') - self.assertEqual(self.source['Enabled'], 'yes') - self.assertEqual(self.source['Types'], 'deb deb-src') - self.assertEqual(self.source['URIs'], 'http://example.com/ubuntu http://example.com/mirror') - self.assertEqual(self.source['Suites'], 'suite suite-updates') - self.assertEqual(self.source['Components'], 'main contrib nonfree') - self.assertEqual(self.source['Architectures'], 'amd64 armel') - self.assertEqual(self.source['Languages'], 'en_US en_CA') - - def test_load(self): - load_source = source.Source() - load_source.load_from_data([ - 'X-Repolib-ID: load-test', - 'X-Repolib-Name: Test Source Loading', - 'Enabled: yes', - 'Types: deb', - 'URIs: http://example.com/ubuntu http://example.com/mirror', - 'Suites: suite suite-updates', - 'Components: main contrib nonfree', - 'Architectures: amd64 armel', - 'Languages: en_US en_CA', - ]) - - self.assertEqual(load_source.ident, 'load-test') - self.assertEqual(load_source.name, 'Test Source Loading') - self.assertTrue(load_source.enabled.get_bool()) - self.assertEqual( - load_source.types, - [util.SourceType.BINARY] - ) - self.assertEqual( - load_source.uris, - ['http://example.com/ubuntu', 'http://example.com/mirror'] - ) - self.assertEqual( - load_source.suites, - ['suite', 'suite-updates'] - ) - self.assertEqual( - load_source.components, - ['main', 'contrib', 'nonfree'] - ) - self.assertEqual(load_source.architectures, 'amd64 armel') - self.assertEqual(load_source.languages, 'en_US en_CA') - - load_legacy_source = source.Source() - load_legacy_source.load_from_data( - ['deb [arch=amd64,armel lang=en_US,en_CA] http://example.com/ubuntu suite main contrib nonfree ## X-Repolib-Name: Test Legacy Source Loading # X-Repolib-ID: test-load-legacy'] - ) - - self.assertEqual(load_legacy_source.ident, 'test-load-legacy') - self.assertEqual(load_legacy_source.name, 'Test Legacy Source Loading') - self.assertTrue(load_legacy_source.enabled.get_bool()) - self.assertEqual( - load_legacy_source.types, - [util.SourceType.BINARY] - ) - self.assertEqual( - load_legacy_source.uris, - ['http://example.com/ubuntu'] - ) - self.assertEqual( - load_legacy_source.suites, - ['suite'] - ) - self.assertEqual( - load_legacy_source.components, - ['main', 'contrib', 'nonfree'] - ) - self.assertEqual(load_legacy_source.architectures, 'amd64 armel') - self.assertEqual(load_legacy_source.languages, 'en_US en_CA') - - def test_save_load(self): - self.source.file.save() - load_source_file = file.SourceFile(name='test') - load_source_file.load() - self.assertGreater(len(load_source_file.sources), 0) - self.assertGreater( - len(load_source_file.contents), len(load_source_file.sources) - ) - load_source = load_source_file.sources[0] - - self.assertEqual(load_source.ident, self.source.ident) - self.assertEqual(load_source.name, self.source.name) - self.assertEqual(load_source.enabled, self.source.enabled) - self.assertEqual(load_source.types, self.source.types) - self.assertEqual(load_source.sourcecode_enabled, self.source.sourcecode_enabled) - self.assertEqual(load_source.uris, self.source.uris) - self.assertEqual(load_source.suites, self.source.suites) - self.assertEqual(load_source.components, self.source.components) - self.assertEqual(load_source.architectures, self.source.architectures) - self.assertEqual(load_source.languages, self.source.languages) - self.assertEqual(load_source.file.name, self.source.file.name) - \ No newline at end of file diff --git a/archive/repolib/util.py b/archive/repolib/util.py deleted file mode 100644 index cb303a9..0000000 --- a/archive/repolib/util.py +++ /dev/null @@ -1,455 +0,0 @@ -#!/usr/bin/python3 - -""" -Copyright (c) 2019-2022, Ian Santopietro -All rights reserved. - -This file is part of RepoLib. - -RepoLib is free software: you can redistribute it and/or modify -it under the terms of the GNU Lesser General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -RepoLib is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License -along with RepoLib. If not, see . -""" - -import atexit -import logging -import re -import tempfile - -from enum import Enum -from pathlib import Path -from urllib.parse import urlparse -from urllib import request, error - -import dbus - -SOURCES_DIR = Path('/etc/apt/sources.list.d') -KEYS_DIR = Path('/etc/apt/keyrings/') -TESTING = False -KEYSERVER_QUERY_URL = 'http://keyserver.ubuntu.com/pks/lookup?op=get&search=0x' - -log = logging.getLogger(__name__) - -class RepoError(Exception): - """ Exception from this module.""" - - def __init__(self, *args, code=1, **kwargs): - """Exception with a source object - - Arguments: - code (:obj:`int`, optional, default=1): Exception error code. - """ - super().__init__(*args, **kwargs) - self.code = code - -try: - import distro - DISTRO_CODENAME = distro.codename() -except ImportError: - DISTRO_CODENAME = 'linux' - -class SourceFormat(Enum): - """Enum of SourceFile Formats""" - DEFAULT = "sources" - LEGACY = "list" - -class SourceType(Enum): - """Enum of repository types""" - BINARY = 'deb' - SOURCECODE = 'deb-src' - - def ident(self) -> str: - """Used for getting a version of the format for idents""" - ident = f'{self.value}' - ident = ident.replace('deb-src', 'source') - ident = ident.replace('deb', 'binary') - return ident - -class AptSourceEnabled(Enum): - """ Helper Enum to translate between bool data and the Deb822 format. """ - TRUE = 'yes' - FALSE = 'no' - - def get_bool(self): - """ Return a bool based on the value. """ - # pylint: disable=comparison-with-callable - # This doesnt seem to actually be a callable in this case. - if self.value == "yes": - return True - - return False - -valid_keys = [ - 'X-Repolib-Name:', - 'X-Repolib-ID:', - 'X-Repolib-Default-Mirror:', - 'X-Repolib-Comment', - 'X-Repolib-Prefs', - 'Enabled:', - 'Types:', - 'URIs:', - 'Suites:', - 'Components:', - 'Architectures:', - 'Languages:', - 'Targets:', - 'PDiffs:', - 'By-Hash:', - 'Allow-Insecure:', - 'Allow-Weak:', - 'Allow-Downgrade-To-Insecure:', - 'Trusted:', - 'Signed-By:', - 'Check-Valid-Until:', - 'Valid-Until-Min:', - 'Valid-Until-Max:', -] - -output_skip_keys = [ - 'X-Repolib-Prefs', - 'X-Repolib-ID', -] - -options_inmap = { - 'arch': 'Architectures', - 'lang': 'Languages', - 'target': 'Targets', - 'pdiffs': 'PDiffs', - 'by-hash': 'By-Hash', - 'allow-insecure': 'Allow-Insecure', - 'allow-weak': 'Allow-Weak', - 'allow-downgrade-to-insecure': 'Allow-Downgrade-To-Insecure', - 'trusted': 'Trusted', - 'signed-by': 'Signed-By', - 'check-valid-until': 'Check-Valid-Until', - 'valid-until-min': 'Valid-Until-Min', - 'valid-until-max': 'Valid-Until-Max' -} - -options_outmap = { - 'Architectures': 'arch', - 'Languages': 'lang', - 'Targets': 'target', - 'PDiffs': 'pdiffs', - 'By-Hash': 'by-hash', - 'Allow-Insecure': 'allow-insecure', - 'Allow-Weak': 'allow-weak', - 'Allow-Downgrade-To-Insecure': 'allow-downgrade-to-insecure', - 'Trusted': 'trusted', - 'Signed-By': 'signed-by', - 'Check-Valid-Until': 'check-valid-until', - 'Valid-Until-Min': 'valid-until-min', - 'Valid-Until-Max': 'valid-until-max' -} - -true_values = [ - True, - 'True', - 'true', - 'Yes', - 'yes', - 'YES', - 'y', - 'Y', - AptSourceEnabled.TRUE, - 1 -] - -keys_map = { - 'X-Repolib-Name: ': 'Name: ', - 'X-Repolib-ID: ': 'Ident: ', - 'X-Repolib-Comments: ': 'Comments: ', - 'X-Repolib-Default-Mirror: ': 'Default Mirror: ', -} - -PRETTY_PRINT = '\n ' - -_KEYS_TEMPDIR = tempfile.TemporaryDirectory() -TEMP_DIR = Path(_KEYS_TEMPDIR.name) - -options_re = re.compile(r'[^@.+]\[([^[]+.+)\]\ ') -uri_re = re.compile(r'\w+:(\/?\/?)[^\s]+') - -CLEAN_CHARS = { - 33: None, - 64: 45, - 35: 45, - 36: 45, - 37: 45, - 94: 45, - 38: 45, - 42: 45, - 41: None, - 40: None, - 43: 45, - 61: 45, - 91: None, - 92: None, - 93: None, - 123: None, - 125: None, - 124: 95, - 63: None, - 47: 95, - 46: 45, - 60: 95, - 62: 95, - 44: 95, - 96: None, - 126: None, - 32: 95, - 58: None, - 59: None, -} - -sources:dict = {} -files:dict = {} -keys:dict = {} -errors:dict = {} - - -def scrub_filename(name: str = '') -> str: - """ Clean up a string intended for a filename. - - Arguments: - name (str): The prospective name to scrub. - - Returns: str - The cleaned-up name. - """ - return name.translate(CLEAN_CHARS) - -def set_testing(testing:bool=True) -> None: - """Sets Repolib in testing mode where changes will not be saved. - - Arguments: - testing(bool): Whether testing mode should be enabled or disabled - (Defaul: True) - """ - global KEYS_DIR - global SOURCES_DIR - - testing_tempdir = tempfile.TemporaryDirectory() - - if not testing: - KEYS_DIR = '/usr/share/keyrings' - SOURCES_DIR = '/etc/apt/sources.list.d' - return - - testing_root = Path(testing_tempdir.name) - KEYS_DIR = testing_root / 'usr' / 'share' / 'keyrings' - SOURCES_DIR = testing_root / 'etc' / 'apt' / 'sources.list.d' - - -def _cleanup_temsps() -> None: - """Clean up our tempdir""" - _KEYS_TEMPDIR.cleanup() - # _TESTING_TEMPDIR.cleanup() - -atexit.register(_cleanup_temsps) - -def dbus_quit(): - bus = dbus.SystemBus() - privileged_object = bus.get_object('org.pop_os.repolib', '/Repo') - privileged_object.exit() - -def compare_sources(source1, source2, excl_keys:list) -> bool: - """Compare two sources based on arbitrary criteria. - - This looks at a given list of keys, and if the given keys between the two - given sources are identical, returns True. - - Arguments: - source1, source2(Source): The two sources to compare - excl_keys([str]): Any keys to exclude from the comparison - - Returns: bool - `True` if the sources are identical, otherwise `False`. - """ - for key in source1: - if key in excl_keys: - continue - if key in source2: - if source1[key] != source2[key]: - return False - else: - continue - else: - return False - for key in source2: - if key in excl_keys: - continue - if key in source1: - if source1[key] != source2[key]: - return False - else: - continue - else: - return False - return True - -def find_differences_sources(source1, source2, excl_keys:list) -> dict: - """Find key-value pairs which differ between two sources. - - Arguments: - source1, source2(Source): The two sources to compare - excl_keys([str]): Any keys to exclude from the comparison - - Returns: dict{'key': ('source1[key]','source2[key]')} - The dictionary of different keys, with the key values from each source. - """ - differing_keys:dict = {} - - for key in source1: - if key in excl_keys: - continue - if key in source2: - if source1[key] == source2[key]: - continue - differing_keys[key] = (source1[key], source2[key]) - differing_keys[key] = (source1[key], '') - for key in source2: - if key in excl_keys: - continue - if key in source1: - if source1[key] == source2[key]: - continue - differing_keys[key] = ('', source2[key]) - - return differing_keys - -def combine_sources(source1, source2) -> None: - """Combine the data in two sources into one. - - Arguments: - source1(Source): The source to be merged into - source2(Source): The source to merge from - """ - for key in source1: - if key in ('X-Repolib-Name', 'X-Repolib-ID', 'Enabled', 'Types'): - continue - if key in source2: - source1[key] += f' {source2[key]}' - for key in source2: - if key in ('X-Repolib-Name', 'X-Repolib-ID', 'Enabled', 'Types'): - continue - if key in source1: - source1[key] += f' {source2[key]}' - - # Need to deduplicate the list - for key in source1: - vals = source1[key].strip().split() - newvals = [] - for val in vals: - if val not in newvals: - newvals.append(val) - source1[key] = ' '.join(newvals) - for key in source2: - vals = source2[key].strip().split() - newvals = [] - for val in vals: - if val not in newvals: - newvals.append(val) - source2[key] = ' '.join(newvals) - - -def prettyprint_enable(enabled: bool = True) -> None: - """Easy helper to enable/disable pretty-printing for object reprs. - - Can also be used as an easy way to reset to defaults. - - Arguments: - enabled(bool): Whether or not Pretty Printing should be enabled - """ - global PRETTY_PRINT - if enabled: - PRETTY_PRINT = '\n ' - else: - PRETTY_PRINT = '' - -def url_validator(url): - """ Validate a url and tell if it's good or not. - - Arguments: - url (str): The URL to validate. - - Returns: - `True` if `url` is not malformed, otherwise `False`. - """ - try: - # pylint: disable=no-else-return,bare-except - # A) We want to return false if the URL doesn't contain those parts - # B) We need this to not throw any exceptions, regardless what they are - result = urlparse(url) - if not result.scheme: - return False - if result.scheme == 'x-repolib-name': - return False - if result.netloc: - # We need at least a scheme and a netlocation/hostname or... - return all([result.scheme, result.netloc]) - elif result.path: - # ...a scheme and a path (this allows file:/// URIs which are valid) - return all([result.scheme, result.path]) - return False - except: - return False - -def validate_debline(valid): - """ Basic checks to see if a given debline is valid or not. - - Arguments: - valid (str): The line to validate. - - Returns: - True if the line is valid, False otherwise. - """ - comment:bool = False - if valid.startswith('#'): - comment = True - valid = valid.replace('#', '') - valid = valid.strip() - - if valid.startswith("deb"): - words = valid.split() - for word in words: - if url_validator(word): - return True - - elif valid.startswith("ppa:"): - if "/" in valid: - return True - - else: - if valid.endswith('.flatpakrepo'): - return False - if len(valid.split()) == 1 and not comment: - return url_validator(valid) - return False - -def strip_hashes(line:str) -> str: - """ Strips the leading #'s from the given line. - - Arguments: - line (str): The line to strip. - - Returns: - (str): The input line without any leading/trailing hashes or - leading/trailing whitespace. - """ - while True: - line = line.strip('#') - line = line.strip() - if not line.startswith('#'): - break - - return line diff --git a/archive/requirements.txt b/archive/requirements.txt deleted file mode 100644 index 204fdde..0000000 --- a/archive/requirements.txt +++ /dev/null @@ -1,4 +0,0 @@ -dbus-python -distro -pytest-pylint -python-debian \ No newline at end of file diff --git a/archive/setup.py b/archive/setup.py deleted file mode 100755 index 9a78ce1..0000000 --- a/archive/setup.py +++ /dev/null @@ -1,198 +0,0 @@ -#!/usr/bin/python3 - -""" -Copyright (c) 2019-2020, Ian Santopietro -All rights reserved. - -This file is part of RepoLib. - -RepoLib is free software: you can redistribute it and/or modify -it under the terms of the GNU Lesser General Public License as published by -the Free Software Foundation, either version 3 of the License, or -(at your option) any later version. - -RepoLib is distributed in the hope that it will be useful, -but WITHOUT ANY WARRANTY; without even the implied warranty of -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -GNU Lesser General Public License for more details. - -You should have received a copy of the GNU Lesser General Public License -along with RepoLib. If not, see . -""" -#pylint: skip-file -# We don't need to check these in setup - -import os -import subprocess -from setuptools import setup, find_packages, Command - -def get_version(): - """ Get the program version. """ - #pylint: disable=exec-used - # Just getting the version. - version = {} - with open(os.path.join('repolib', '__version__.py')) as fp: - exec(fp.read(), version) - return version['__version__'] - -with open("README.rst", "r") as fh: - long_description = fh.read() - -classifiers = [ - 'Environment :: Console', - 'Intended Audience :: System Administrators', - 'Intended Audience :: End Users/Desktop', - 'Intended Audience :: Developers', - 'License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)', - 'Natural Language :: English', - 'Operating System :: POSIX :: Linux', - 'Programming Language :: Python :: 3', - 'Topic :: Software Development :: Libraries :: Python Modules', - 'Topic :: System' -] - -class Release(Command): - """ Generate a release and push it to git.""" - description = "Generate a release and push it to git." - - user_options = [ - ('dry-run', None, 'Skip the actual release and do a dry run instead.'), - ('skip-deb', None, 'Skip doing a debian update for this release.'), - ('skip-git', None, 'Skip committing to git at the end.'), - ('prerelease=', None, 'Release a pre-release version (alpha,beta,rc)'), - ('increment=', None, 'Manually specify the desired increment (MAJOR, MINOR, PATCH)') - ] - - def initialize_options(self): - self.dry_run = False - self.skip_deb = False - self.skip_git = False - self.prerelease = None - self.increment = None - - def finalize_options(self): - pass - - def run(self): - cz_command = ['cz', 'bump', '--yes'] - ch_command = ['dch'] - git_command = ['git', 'add', '.'] - - def capture_version(sp_complete): - output = sp_complete.stdout.decode('UTF-8').split('\n') - print('\n'.join(output)) - for line in output: - if 'tag to create' in line: - version_line = line - - try: - return version_line.split()[-1].replace('v', '') - except UnboundLocalError: - stderr = sp_complete.stderr.decode('UTF-8') - print("WARNING: Couldn't get updated version! Using current.") - print(stderr) - return get_version() - - if self.dry_run: - print('Dry run: Not making actual changes') - cz_command.append('--dry-run') - - if self.prerelease: - if self.prerelease.lower() not in ['alpha', 'beta', 'rc']: - raise Exception( - f'{self.prerelease} is not a valid prerelease type. Please ' - 'use one of "alpha", "beta", or "rc".' - ) - cz_command.append('--prerelease') - cz_command.append(self.prerelease.lower()) - - if self.increment: - if self.increment.upper() not in ['MAJOR', 'MINOR', 'PATCH']: - raise Exception( - f'{self.increment} is not a valid increments. Please use ' - 'one of MAJOR, MINOR, or PATCH.' - ) - cz_command.append('--increment') - cz_command.append(self.increment.upper()) - - # We need to get the new version from CZ, as the file hasn't been - # updated yet. - version_command = cz_command.copy() - version_command.append('--dry-run') - version_complete = subprocess.run(version_command, capture_output=True) - - version = capture_version(version_complete) - print(f'Old Version: {get_version()}') - print(f'New version: {version}') - - ch_command.append(f'-v{version}') - if not self.skip_deb: - print(ch_command) - if not self.dry_run: - subprocess.run(ch_command) - subprocess.run(['dch', '-r', '""']) - - if not self.skip_git: - print(git_command) - if not self.dry_run: - subprocess.run(git_command) - - print(' '.join(cz_command)) - if not self.dry_run: - subprocess.run(cz_command) - -class Test(Command): - """ Run pyflakes and pytest""" - description = 'Run pyflakes, pytest, and pylint' - - user_options = [ - ('run-flakes', None, 'Run pyflakes'), - ('skip-test', None, 'Skip running pytest'), - ('skip-lint', None, 'Skip running pylint') - ] - - def initialize_options(self): - self.run_flakes = True - self.skip_test = False - self.skip_lint = False - - def finalize_options(self): - pass - - def run(self): - pytest_command = ['pytest-3'] - flakes_command = ['pyflakes3', 'repolib'] - lint_command = ['pylint', 'repolib'] - - if not self.skip_test: - subprocess.run(pytest_command) - - if not self.run_flakes: - subprocess.run(flakes_command) - - if not self.skip_lint: - subprocess.run(lint_command) - -setup( - name='repolib', - version=get_version(), - author='Ian Santopietro', - author_email='ian@system76.com', - url='https://github.com/pop-os/repolib', - description='Easily manage software sources', - download_url='https://github.com/pop-os/repolib/releases', - long_description=long_description, - tests_require=['pytest'], - license='LGPLv3', - packages=['repolib', 'repolib/command', 'repolib/shortcuts', 'repolib/unittest'], - cmdclass={'release': Release, 'test': Test}, - scripts=['bin/apt-manage'], - data_files=[ - ('share/bash-completion/completions', ['data/bash-completion/apt-manage']), - ('share/zsh/vendor-completions', ['data/zsh-completion/_apt-manage']), - ('/usr/share/dbus-1/system-services', ['data/org.pop_os.repolib.service']), - ('/usr/share/polkit-1/actions', ['data/org.pop_os.repolib.policy']), - ('/etc/dbus-1/system.d/', ['data/org.pop_os.repolib.conf']), - ('/usr/lib/repolib', ['data/service.py', 'bin/add-apt-repository']) - ] -) diff --git a/archive/debian/README.source b/debian/README.source similarity index 100% rename from archive/debian/README.source rename to debian/README.source diff --git a/debian/changelog b/debian/changelog new file mode 100644 index 0000000..390e307 --- /dev/null +++ b/debian/changelog @@ -0,0 +1,5 @@ +repolib (2.2.0~99pika4) kinetic; urgency=medium + + * Initial Creation + + -- Ward Nakchbandi Fri, 09 Oct 2022 21:38:00 +0300 diff --git a/archive/debian/compat b/debian/compat similarity index 100% rename from archive/debian/compat rename to debian/compat diff --git a/archive/debian/control b/debian/control similarity index 100% rename from archive/debian/control rename to debian/control diff --git a/archive/debian/copyright b/debian/copyright similarity index 100% rename from archive/debian/copyright rename to debian/copyright diff --git a/archive/debian/rules b/debian/rules similarity index 100% rename from archive/debian/rules rename to debian/rules diff --git a/archive/debian/source/format b/debian/source/format similarity index 100% rename from archive/debian/source/format rename to debian/source/format diff --git a/archive/debian/source/options b/debian/source/options similarity index 100% rename from archive/debian/source/options rename to debian/source/options diff --git a/archive/debian/triggers b/debian/triggers similarity index 100% rename from archive/debian/triggers rename to debian/triggers diff --git a/main.sh b/main.sh new file mode 100755 index 0000000..90c535f --- /dev/null +++ b/main.sh @@ -0,0 +1,21 @@ +# Add dependent repositories +wget -q -O - https://ppa.pika-os.com/key.gpg | sudo apt-key add - +add-apt-repository https://ppa.pika-os.com +add-apt-repository ppa:pikaos/pika +add-apt-repository ppa:kubuntu-ppa/backports +# Clone Upstream +git clone https://github.com/pop-os/repolib +rm -rvf ./repolib/debian +cp -rvf ./debian ./repolib +cd ./repolib + +# Get build deps +apt-get build-dep ./ -y + +# Build package +dpkg-buildpackage + +# Move the debs to output +cd ../ +mkdir -p ./output +mv ./*.deb ./output/ diff --git a/release.sh b/release.sh new file mode 100755 index 0000000..ce9e316 --- /dev/null +++ b/release.sh @@ -0,0 +1,11 @@ +# Sign the packages +dpkg-sig --sign builder ./output/*.deb + +# Pull down existing ppa repo db files etc +rsync -azP --exclude '*.deb' ferreo@direct.pika-os.com:/srv/www/pikappa/ ./output/repo + +# Add the new package to the repo +reprepro -V --basedir ./output/repo/ includedeb kinetic ./output/*.deb + +# Push the updated ppa repo to the server +rsync -azP ./output/repo/ ferreo@direct.pika-os.com:/srv/www/pikappa/